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();
	}
	

效果如下:

相关推荐
豆沙沙包?17 分钟前
2025年- H77-Lc185--45.跳跃游戏II(贪心)--Java版
java·开发语言·游戏
年老体衰按不动键盘42 分钟前
快速部署和启动Vue3项目
java·javascript·vue
咖啡啡不加糖1 小时前
Redis大key产生、排查与优化实践
java·数据库·redis·后端·缓存
liuyang-neu1 小时前
java内存模型JMM
java·开发语言
UFIT1 小时前
NoSQL之redis哨兵
java·前端·算法
刘 大 望1 小时前
数据库-联合查询(内连接外连接),子查询,合并查询
java·数据库·sql·mysql
怀旧,1 小时前
【数据结构】6. 时间与空间复杂度
java·数据结构·算法
大春儿的试验田2 小时前
Parameter ‘XXX‘ not found. Available parameters are [list, param1]
java
程序员JerrySUN3 小时前
[特殊字符] 深入理解 Linux 内核进程管理:架构、核心函数与调度机制
java·linux·架构
2302_809798323 小时前
【JavaWeb】Docker项目部署
java·运维·后端·青少年编程·docker·容器