GIF文件解析

Java & Swing实现对GIF图像的解析和显示。

有三部分内容: 1 是gif文件解析; 2 是 图像数据解码; 3 是GUI端显示;仅贴出第2部分图像数据解码, 解码也有三部分,1 是基于位的code获取; 2是字典项的维护,3是转换为实际像素。

java 复制代码
​
​// 字典项分为三种:  Value,Clear, End
abstract class Code { }

class ValueCode extends Code {
	
	private final int[] prev; // 前缀
	private final int[] code; // 后缀
	private final int[] val;  // 前缀+后缀 utils
	
	public ValueCode(int[] code) { 
		this(null, code);
	}
	
	public ValueCode(int[] prev, int[] code) { 
		this.prev = prev;
		this.code = code; 
		
		if (prev == null)
			val = code;
		else if (code == null)
			val = prev;
		else {
			val = new int[prev.length + code.length];
			System.arraycopy(prev, 0, val, 0, prev.length);
			System.arraycopy(code, 0, val, prev.length, code.length);
			
		}
	}
	
	public int[] First() {
		return new int[] { val[0] };
	}

    。。。。。。
}
class ClearCode extends Code {
    。。。。。。
}
class EndCode extends Code {
    。。。。。。
}

​

​

字典维护类:

java 复制代码
class Dictionary {
	
	private Vector<Code> table = new Vector<>();
	
	public Dictionary(int[] bs) {
		for (int b : bs) 
			addValueCode(new ValueCode(null, new int[] {b}));
		
		table.add(new ClearCode());
		table.add(new EndCode());
	}

	public Dictionary(int bits) {
     	int len =  1 << bits;
		for (int i=0; i< len ; i++) 
			addValueCode(new ValueCode(null, new int[] { i }));
		
		table.add(new ClearCode());
		table.add(new EndCode());
	}
	
	public int getBitLen() {
		int max = -1;
		int len = table.size();
		for (int i=0; i<12; i++) {
			if ( (len & 1) == 1)
				max = i;
			len = (len >> 1);
		}
		return  max + 1;
	}

    。。。。。。

}

实现解压缩:

java 复制代码
	static int[] uncompress(final Dictionary dict , int[] data) {
		IntArrayBuffer output = new IntArrayBuffer();        
        int ByteOffset = 0;
        int thisBitsOffset  = 0;
        ValueCode lastValue = null;
    	
        while (true) {
        	int code;
        	
//    		if (ByteOffset >=data.length )
//    			break; 
    		
        	int BIT_LEN = dict.getBitLen();
        	{
        		
        		if (ByteOffset == 1125)
        			System.out.println();

	        	int b = data[ ByteOffset ];
	      	
	        	
	        	if (thisBitsOffset + BIT_LEN <= 8) {
	        		code = GetBitsFromRight(b, thisBitsOffset, BIT_LEN);
	        		thisBitsOffset = thisBitsOffset + BIT_LEN;
	        		
	        		if (thisBitsOffset % 8 == 0) {
	        			thisBitsOffset = 0;
	        			ByteOffset = ByteOffset + 1;
	        		}		
	         	}
	        	else {
        			int rBitLen = 8 - thisBitsOffset;	    			
	    			code = GetBitsFromRight(b, thisBitsOffset, rBitLen);
	    			
//	    			if (ByteOffset + 1 >= data.length)
//	    				break;

	    			
	    			int lBitLen = BIT_LEN - rBitLen;
	    			int llBitLen = -1;
	    			
	    			if (lBitLen != 0) {
		       			b = data[ ++ByteOffset ];
		       			
		       			int b2 = GetBitsFromRight(b, 0 , lBitLen > 8 ? 8 : lBitLen);
		       			code = (b2 << rBitLen) | code;
		       			llBitLen = lBitLen - 8;
	    			}
	    			
	    			if (llBitLen > 0) {
		       			b = data[ ++ByteOffset ];
		       			
		       			int b2 = GetBitsFromRight(b, 0 , llBitLen);
		       			code = (b2 << (8+lBitLen) ) | code;
	    			}
	    			
	    			thisBitsOffset = (thisBitsOffset + BIT_LEN) % 8;
	   			
	        		if (thisBitsOffset % 8 == 0) {
	        			thisBitsOffset = 0;
	        			ByteOffset = ByteOffset + 1;
	        		}
	        		
	        	}
	         	
        	}
        	
        	Code _value = dict.getCode(code);
        	
    	    if (_value == null || _value instanceof ValueCode) {
    	    	ValueCode value = (ValueCode) _value ;
    	    	
    	    	if (value == null) {
    	    		
    	    		if (lastValue != null) {
	    	    		value = new ValueCode(lastValue.getValue() , lastValue.First());
		    	    	dict.addValueCode(value);
    	    		}
    	    	}
    	    	else {
        			
        			if (lastValue != null) {
        				ValueCode vv = new ValueCode(lastValue.getValue(), value.First());
        				dict.addValueCode(vv);
        			}
    	    	}
    	    	
    	    	output.Write(value.getValue());
    	    	lastValue = value;
    	    }
         	else if (_value instanceof ClearCode e) {
        		dict.clear();
        	}
        	else if (_value instanceof EndCode) {
        		break ;
        	}
    	    
        }
        
        return output.GetInts();
	}
	

效果如下:

相关推荐
小旭95279 分钟前
Spring Security 实现权限控制(认证 + 授权全流程)
java·后端·spring
金銀銅鐵15 分钟前
[Java] 如何通过 cglib 的 FastClass 调用一个类中的“任意”方法?
java·后端
阿维的博客日记33 分钟前
为什么会增加TreeMap和TreeSet这两类,有什么核心优势吗?可以解决什么核心痛点?
java·treeset·treemap
dllxhcjla41 分钟前
黑马头条1
java
宠友信息1 小时前
一套基于uniapp+springboot完整社区系统是如何实现的?友猫社区源码级功能解析
java·spring boot·后端·微服务·微信·uni-app
humors2211 小时前
各厂商工具包网址
java·数据库·python·华为·sdk·苹果·工具包
无限进步_1 小时前
【C++&string】大数相乘算法详解:从字符串加法到乘法实现
java·开发语言·c++·git·算法·github·visual studio
海兰1 小时前
使用 Spring AI 打造企业级 RAG 知识库第二部分:AI 实战
java·人工智能·spring
历程里程碑2 小时前
二叉树---二叉树的中序遍历
java·大数据·开发语言·elasticsearch·链表·搜索引擎·lua
小信丶2 小时前
Spring Cloud Stream EnableBinding注解详解:定义、应用场景与示例代码
java·spring boot·后端·spring