gif文件解析
详细资料:http://blog.csdn.net/wzy198852/article/details/17266507
MD5:98206F88B84CCC399C840C8EEC902CCF
GIF文件结构定义模块:
#ifndef _GIF_COMMON_H
#define _GIF_COMMON_H #ifndef BYTE
#define BYTE unsigned char
#endif #ifndef CHAR
#define CHAR char
#endif #ifndef SHORT
#define SHORT short
#endif #ifndef LONG
#define LONG long
#endif typedef struct GIFColor {
BYTE gifRed;
BYTE gifGreen;
BYTE gifBlue;
BYTE gifResv;
}GIFColor; typedef struct GIFHeader {
CHAR gifSignature[]; // GIF署名: "GIF"
CHAR gifVersion[]; // GIF版本号: "87a" or "89a"
BYTE gifResv[]; // 保留字段
}GIFHeader; typedef struct GIFLSDescriptor {
SHORT gifLSWidth; // 逻辑屏幕宽度
SHORT gifLSHeight; // 逻辑屏幕高度 BYTE gifGlobalColorTableFlg : ; // 全局颜色列表标志: 置位表示有全局颜色列表,pixel值有意义
BYTE gifColorResolution : ; // 颜色深度: cr + 1
BYTE gifSortFlg : ; // 分类标志: 置位表示全局颜色列表分类排序
BYTE gifPixel : ; // 全局颜色列表索引数: 2^(pixel+1)
BYTE gifBgColorIdx; // 背景颜色索引,如果无全局颜色列表,该值无意义
BYTE gifAspectRadio; // 像素宽高比
BYTE gifResv[];
}GIFLSDescriptor; typedef struct GIFColorTable {
BYTE gifColorTable[];
}GIFColorTable; typedef struct GIFImageDescriptor {
BYTE gifImageFlg; // 图像标识符开始标志: 0x2c(';')
BYTE gifResv1[]; SHORT gifXOffset; // X方向偏移量
SHORT gifYOffset; // Y方向偏移量
SHORT gifImageWidth; // 图像宽度
SHORT gifImageHeight; // 图像高度 BYTE gifLocalColorTableFlg : ; // 局部颜色列表标志,置位时图像标识符后紧跟一个局部颜色表,\
供紧跟在它之后的一幅图像使用;值否时使用全局颜色列表,忽略pixel值。
BYTE gifInterlaceFlg : ; // 交织标志,置位时图像数据使用交织方式排列,否则使用顺序排列
BYTE gifSortFlg : ; // 分类标志,置位表示局部颜色列表分类排序
BYTE gifResv : ; // 保留位,必须为 0
BYTE gifPixel; // 局部颜色列表索引数: 2^(pixel+1)
BYTE gifResv2[];
}GIFImageDescriptor; typedef struct GIFImageDataSubBlock {
BYTE gifSubBlockSize; // 块大小
BYTE gifResv[];
BYTE *gifCodedData; // 编码数据
}GIFImageDataSubBlock; typedef struct GIFImageData {
BYTE gifLZWCodeTableSize; // LZW初始编码表大小的位数
SHORT gifSubBlockNum; // 数据块数
BYTE gifResv1;
GIFImageDataSubBlock *gifImageDataSubBlocks; // 数据块
BYTE gifImageDataEndFlg; // 数据编码结束: 0
BYTE gifResv2[];
}GIFImageData; typedef struct GIFImageChunk {
/* 图像标识符 */
GIFImageDescriptor gifImageDescriptor;
/* 图像局部颜色列表,gifLocalColorTableFlg=1时有效 */
GIFColorTable gifLocalColorTable;
/* 图像数据 */
GIFImageData gifImageData;
}GIFImageChunk; typedef struct GIFStruct {
/* 1 文件头 */
GIFHeader gifHeader; /* 2 GIF数据流 */
/* 2.1 逻辑屏幕标志符 */
GIFLSDescriptor gifLSDescriptor;
/* 2.2 全局颜色列表,gifGlobalColorTableFlg=1时有效 */
GIFColorTable gifGlobalColorTable;
/* 2.3 图像 */
SHORT gifImageChunkNum; // 图像数
BYTE gifResv[];
GIFImageChunk *gifImageChunks; /* 3 文件终结器 */
}; #endif
文件读取缓存模块:
#include <stdio.h>
#include <stdlib.h> #ifndef GIF
#define CHAR char
#define BYTE unsigned char
#define SHORT short
#define INT int
#define LONG long
#define GIF #define SUCCESS 0
#define FAILURE 1
#define INVALID -1 #define CHECK_NULL_RET(expr, ret) if(NULL == (expr)) return ret
#define CHECK_RET(expr, ret) if(expr) return ret
#define CHECK_FALSE_RET(expr, ret) if(!(expr)) return ret #endif #define FIRST_BUFF_SIZE 2048
#define SECOND_BUFF_SIZE FIRST_BUFF_SIZE
#define BUFF_SIZE (FIRST_BUFF_SIZE+SECOND_BUFF_SIZE)
#define READ_ONCE_SIZE FIRST_BUFF_SIZE FILE *fin; // 输入文件
BYTE readBuff[BUFF_SIZE]; // 缓存区,分为第一缓存和第二缓存,对应FIRST_BUFF和SECOND_BUFF
INT startIdx; // 有效数据起始索引(包含当前),默认值为INVALID(-1)
INT endIdx; // 有效数据结束索引(包含当前),默认值为INVALID(-1)
INT readIdx; // 下一次读取起始索引(包含当前),默认值为INVALID(-1) #define GET_VALID_SIZE() (endIdx - readIdx + 1) INT RBFillBuff()
{
INT realReadBytes;
INT unusedLen;
CHECK_NULL_RET(fin, FAILURE); if(readIdx <= endIdx) // 有未读数据
{
memmove(readBuff, &readBuff[readIdx], endIdx-readIdx+);
startIdx = readIdx = ;
endIdx = endIdx - readIdx;
}
else // 无未读数据
{
startIdx = endIdx = -;
readIdx = ;
}
CHECK_FALSE_RET(endIdx < FIRST_BUFF_SIZE, SUCCESS); realReadBytes = fread(&readBuff[endIdx+], , READ_ONCE_SIZE, fin);
CHECK_FALSE_RET(realReadBytes > , FAILURE); startIdx = readIdx = ;
endIdx = endIdx + realReadBytes; return SUCCESS;
} VOID RBFreeFile()
{
if(fin != NULL)
{
fclose(fin);
fin = NULL;
}
} /* 缓存模块初始化 */
INT RBModuleInit(CHAR *filePath)
{
startIdx = endIdx = -;
readIdx = ; CHECK_NULL_RET(filePath, FAILURE); fin = fopen(filePath, "rb");
CHECK_NULL_RET(fin, FAILURE);
RBFillBuff();
} INT RBGetBytes(BYTE *buff, int len)
{
INT ret;
CHECK_NULL_RET(buff, FAILURE);
CHECK_FALSE_RET(len > && len < FIRST_BUFF_SIZE, FAILURE);
if(len > GET_VALID_SIZE())
{
if(FAILURE == RBFillBuff())
{
return FAILURE;
}
}
CHECK_FALSE_RET(len <= GET_VALID_SIZE(), FAILURE);
memcpy(buff, &readBuff[readIdx], len);
readIdx += len; return SUCCESS;
} INT RBGetByte(BYTE *value)
{
return RBGetBytes(value, );
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h> typedef struct Elem {
unsigned char value;
int preIdx;
}Elem; int tabSize;
Elem lzwTab[]; #define LZWSIZE 2 int LzwInit(int size)
{
int loop = ;
for(loop = ; loop < size; loop++)
{
lzwTab[loop].value = loop;
lzwTab[loop].preIdx = -;
}
tabSize = size;
return ;
} int AddElement(unsigned char currChar, int lastIdx)
{
lzwTab[tabSize].value = currChar;
lzwTab[tabSize].preIdx = lastIdx;
tabSize++;
return ;
} int SearchStrInTable(unsigned char currChar, int lastIdx)
{
int loop = ;
for(loop = ; loop < tabSize; loop++)
{
if((lzwTab[loop].value == currChar) && (lzwTab[loop].preIdx == lastIdx))
{
return loop;
}
}
return -;
} int LzwEncode(const unsigned char *inStream, int inLen, int *outStream, int *outLen)
{ unsigned char currChar = ;
int lastIdx = -;
int currIdx = -; int readIdx = ;
int writeIdx = ; LzwInit(LZWSIZE); // 初始化编码表 for(readIdx = ; readIdx < inLen; readIdx++) // 遍历输入流
{
currChar = inStream[readIdx]; // 当前字符,与lastIdx组成当前字符串
currIdx = SearchStrInTable(currChar, lastIdx); // 查找当前字符串索引
if(currIdx == -) // 未找到
{
outStream[writeIdx++] = lastIdx; // 输出前缀索引到编码流
AddElement(currChar, lastIdx); // 添加当前字符串到编码表
lastIdx = SearchStrInTable(currChar, -); // 以当前字符的索引作为lastIdx,为下一轮做准备
}
else
{
lastIdx = currIdx;
}
}
outStream[writeIdx++] = lastIdx;
*outLen = writeIdx; return ;
} int SearchCodeInTable(int currCode, unsigned char *strBuff)
{
if(currCode >= tabSize)
{
return ;
}
else
{
int writeIdx = ;
while(currCode >= )
{
strBuff[writeIdx++] = lzwTab[currCode].value;
currCode = lzwTab[currCode].preIdx;
} unsigned char *strHead = strBuff;
unsigned char *strTail = strBuff + writeIdx - ;
unsigned char strTemp;
while(strHead < strTail)
{
strTemp = *strHead;
*strHead = *strTail;
*strTail = strTemp; strHead++;
strTail--;
}
return writeIdx;
}
} int WriteString(unsigned char *outStream, unsigned char *strBuff, int strLen, int *outLen)
{
memcpy(outStream + (*outLen), strBuff, strLen);
*outLen += strLen;
return ;
} int LzwDecode(const int *inStream, int inLen, unsigned char *outStream, int *outLen)
{
int currCode;
int lastCode = -;
int readIdx = ;
int strLen = ;
unsigned char *strBuff = new unsigned char[];
*outLen = ; LzwInit(LZWSIZE); // 初始化编码表 for(readIdx = ; readIdx < inLen; readIdx++)
{
currCode = inStream[readIdx];
strLen = SearchCodeInTable(currCode, strBuff);
if(strLen == ) // 没找到
{
strBuff[strLen++] = strBuff[];
WriteString(outStream, strBuff, strLen, outLen);
if(lastCode != -)
{
AddElement(strBuff[], lastCode);
}
lastCode = currCode;
}
else // 找到
{
WriteString(outStream, strBuff, strLen, outLen);
AddElement(strBuff[], lastCode);
lastCode = currCode;
}
}
return ;
} int test()
{
unsigned char srcData[] = {,,,,,,,,,,,,,,,,,,,,,,};
int encodeData[];
unsigned char decodeData[];
int srcDataLen = ;
int encodeDataLen;
int decodeDataLen; printf("Start encode...\n");
LzwEncode(srcData, srcDataLen, encodeData, &encodeDataLen);
printf("End encode, encodeDataLen=%d.\n", encodeDataLen);
printf("encodeData:");
for(int i=; i<encodeDataLen; i++)
{
printf("%d ", encodeData[i]);
} printf("\nStart decode...\n");
LzwDecode(encodeData, encodeDataLen, decodeData, &decodeDataLen);
printf("End decode, decodeDataLen=%d.\n", decodeDataLen);
printf("decodeData:");
for(int i=; i<decodeDataLen; i++)
{
printf("%d ", decodeData[i]);
}
printf("\n");
return ;
} int main()
{
test(); system("pause");
return ;
}
gif文件解析的更多相关文章
- CocosStudio文件解析工具CsdAnalysis
起因 因为工作需要,所以需要使用CocosStudio来制作界面动画什么的.做完了发现需要找里边对象的时候会有很长一串代码,感觉不是很爽.之前写OC代码的时候可以吧程序中的对象指针跟编辑器中的对象相对 ...
- 通过正则表达式实现简单xml文件解析
这是我通过正则表达式实现的xml文件解析工具,有些XHTML文件中包含特殊符号,暂时还无法正常使用. 设计思路:常见的xml文件都是单根树结构,工具的目的是通过递归的方式将整个文档树装载进一个Node ...
- 八、Android学习第七天——XML文件解析方法(转)
(转自:http://wenku.baidu.com/view/af39b3164431b90d6c85c72f.html) 八.Android学习第七天——XML文件解析方法 XML文件:exten ...
- phpcms V9 首页模板文件解析
在了解了<phpcms V9 URL访问解析>之后,我们已经知道首页最终执行的是content模块下index控制器的init方法. 下面, 我们逐步分析过程如下: 第一.首页默认执行的是 ...
- (转)AVI文件格式解析+AVI文件解析工具
AVI文件解析工具下载地址:http://download.csdn.net/detail/zjq634359531/7556659 AVI(Audio Video Interleaved的缩写)是一 ...
- itextSharp 附pdf文件解析
一.PdfObject: pdf对象 ,有9种,对象是按照对象内涵来分的,如果按照对象的使用规则来说,对象又分为间接对象和直接对象.间接对象是PDF中最常用的对象,如前面对象集合里面的,所有对象都是间 ...
- 《热血传奇2》wix、wil文件解析Java实现
在百度上搜索java+wil只有iteye上一篇有丁点儿内容,不过他说的是错的!或者说是不完整的,我个人认为我对于热血传奇客户端解析还是有一定研究的,请移步: <JMir——Java版热血传奇2 ...
- paper 37 : WINCE的BIB文件解析
WINCE的BIB文件解析 BIB的全称为Binary Image Builder,在Wince编译过程中的最后MakeImage阶段会用到BIB文件,BIB文件的作用是指示构建系统如何构建二进制映像 ...
- 如何让你的Apache支持include文件解析和支持shtml的相关配置
源地址:http://www.itokit.com/2011/0430/65992.html Apache支持include文件解析shtml首先要应该修改Apache配置文件httpd.conf . ...
- android基础知识13:AndroidManifest.xml文件解析
注:本文转载于:http://blog.csdn.net/xianming01/article/details/7526987 AndroidManifest.xml文件解析. 1.重要性 Andro ...
随机推荐
- Ubuntu 11.04 NFS 配置
安装 NFS 相关组件 sudo apt-get install nfs-kernel-server 增加 NFS 目录 sudo gedit /etc/exports #在文件中添加如下内容 /va ...
- 3.1 PCI设备BAR空间的初始化
在PCI Agent设备进行数据传送之前,系统软件需要初始化PCI Agent设备的BAR0~5寄存器和PCI桥的Base.Limit寄存器.系统软件使用DFS算法对PCI总线进行遍历时,完成这些寄存 ...
- 1.4 PCI总线的中断机制
PCI总线使用INTA#.INTB#.INTC#和INTD#信号向处理器发出中断请求.这些中断请求信号为低电平有效,并与处理器的中断控制器连接.在PCI体系结构中,这些中断信号属于边带信号(Sideb ...
- 挖一挖不常用到而又很实用的重载-Trim
这个我想没有那个开发人员说不知道,但是里面有一个重载,这个不知道有多少开发人员知道! 可以看到,我可以去掉字符串前后的指定字符,只要我在char[]中指定即可,而不是仅仅去掉空格,这次为什么要提它,是 ...
- 页面jquery调试的一个宝贵经验(类似于Eclipse中的写出一个对象点它的方法时候用alt加/可以跳出来它所有的方法)
案例讲解 一,html片段 <div class="page-upload"> <div class="tab-wrapper2"> & ...
- Android App性能评测分析-流畅度篇
1.前言 在手机App竞争越来越激烈的今天,Android App的各项性能特别是流畅度不如IOS,安卓基于java虚拟机运行,触控响应的延迟和卡顿比IOS系统严重得多.一些下拉上滑.双指缩放快速打字 ...
- 第三篇:数据可视化 - ggplot2
前言 R语言的强大之处在于统计和作图.其中统计部分的内容很多很强大,因此会在以后的实例中逐步介绍:而作图部分的套路相对来说是比较固定的,现在可以先对它做一个总体的认识. 在上一篇文章中,介绍了使用gr ...
- [HNOI2010]BUS 公交线路
题面 Bzoj Sol 状压很显然 重点在于转移:题目就相当与每\(p\)长度的车站必须有且仅有\(k\)个被经过 那么转移时状压的二进制一定要有\(k\)个一 且两个相邻转移的状态之间必须满足:设为 ...
- 【UVA 11426】gcd之和 (改编)
题面 \(\sum_{i=1}^{n}\sum_{j=1}^m\gcd(i,j)\mod998244353\) \(n,m<=10^7\) Sol 简单的一道莫比乌斯反演题 \(原式=\sum_ ...
- 关于input 的选中,自定义input[type="checkbox"]样式
1.css 呈现 选中后 的input的样式可以用 /*背景图*/ background:url('../pc/images/archives/icon_choosed.png') no ...