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

效果如下:

相关推荐
想躺平的咸鱼干1 分钟前
Volatile解决指令重排和单例模式
java·开发语言·单例模式·线程·并发编程
hqxstudying29 分钟前
java依赖注入方法
java·spring·log4j·ioc·依赖
·云扬·37 分钟前
【Java源码阅读系列37】深度解读Java BufferedReader 源码
java·开发语言
Bug退退退1232 小时前
RabbitMQ 高级特性之重试机制
java·分布式·spring·rabbitmq
小皮侠2 小时前
nginx的使用
java·运维·服务器·前端·git·nginx·github
Zz_waiting.2 小时前
Javaweb - 10.4 ServletConfig 和 ServletContext
java·开发语言·前端·servlet·servletconfig·servletcontext·域对象
全栈凯哥2 小时前
02.SpringBoot常用Utils工具类详解
java·spring boot·后端
兮动人2 小时前
获取终端外网IP地址
java·网络·网络协议·tcp/ip·获取终端外网ip地址
呆呆的小鳄鱼2 小时前
cin,cin.get()等异同点[面试题系列]
java·算法·面试
独立开阀者_FwtCoder2 小时前
"页面白屏了?别慌!前端工程师必备的排查技巧和面试攻略"
java·前端·javascript