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

效果如下:

相关推荐
IT_Octopus3 小时前
IntelliJ 本地日志路径自定义:`-DLOG_PATH=./logs` 为什么总“不听话“
java·log4j·intellij-idea
长征coder4 小时前
【无标题】
java·性能优化
新时代牛马4 小时前
PCI与PCIe 硬件原理、配置空间/BAR 与 Linux 驱动完整篇:从 LTSSM、TLP 到 ECAM 与probe
java·linux·服务器
Bs_MoneyMagnet5 小时前
基于springboot+vue的医疗健康便民服务平台的设计与实现 源码+文档
java·vue.js·spring boot·后端·spring
sunshine22 girl5 小时前
Java学习一 环境配置2 Idea的入门使用和maven配置,项目启动脚本配置
java·maven
有点。6 小时前
*C++哈夫曼树与哈夫曼编码
java·c++·servlet
CRMEB系统商城7 小时前
CRMEB标准版系统(Java)v3.1正式发布
java·spring·微信小程序·php·教育电商
写后端的胖头鱼7 小时前
【高频面试题】Java 基础类型 + 包装类 + String 互相转换
java·开发语言
weixin_460443567 小时前
企业考试系统从.NET迁移到Java+Linux:数据库迁移、接口兼容与灰度切换实践
java·煤矿培训考试系统·煤矿在线考试系统·煤矿安全培训·煤矿考试系统·一人一档
香菜TTT8 小时前
Redis的哨兵机制
java·数据库·redis