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 ;
}
上一篇:连接mysql数据库实现增删改查(一)


下一篇:C语言第5天