gif文件解析

详细资料:http://blog.csdn.net/wzy198852/article/details/17266507

MD5:98206F88B84CCC399C840C8EEC902CCF

 GIF文件结构定义模块:

  1 #ifndef _GIF_COMMON_H
  2 #define _GIF_COMMON_H
  3 
  4 #ifndef BYTE
  5 #define BYTE unsigned char
  6 #endif
  7 
  8 #ifndef CHAR
  9 #define CHAR char
 10 #endif
 11 
 12 #ifndef SHORT
 13 #define SHORT short
 14 #endif
 15 
 16 #ifndef LONG
 17 #define LONG long
 18 #endif
 19 
 20 typedef struct GIFColor {
 21     BYTE gifRed;
 22     BYTE gifGreen;
 23     BYTE gifBlue;
 24     BYTE gifResv;
 25 }GIFColor;
 26 
 27 typedef struct GIFHeader {
 28     CHAR gifSignature[3];    // GIF署名: "GIF"
 29     CHAR gifVersion[2];        // GIF版本号: "87a" or "89a"
 30     BYTE gifResv[3];        // 保留字段
 31 }GIFHeader;
 32 
 33 typedef struct GIFLSDescriptor {
 34     SHORT gifLSWidth;        // 逻辑屏幕宽度
 35     SHORT gifLSHeight;        // 逻辑屏幕高度
 36 
 37     BYTE gifGlobalColorTableFlg : 1;    // 全局颜色列表标志: 置位表示有全局颜色列表,pixel值有意义
 38     BYTE gifColorResolution : 3;        // 颜色深度: cr + 1
 39     BYTE gifSortFlg : 1;    // 分类标志: 置位表示全局颜色列表分类排序
 40     BYTE gifPixel : 3;        // 全局颜色列表索引数: 2^(pixel+1)
 41     BYTE gifBgColorIdx;        // 背景颜色索引,如果无全局颜色列表,该值无意义
 42     BYTE gifAspectRadio;    // 像素宽高比
 43     BYTE gifResv[2];
 44 }GIFLSDescriptor;
 45 
 46 typedef struct GIFColorTable {
 47     BYTE gifColorTable[256];
 48 }GIFColorTable;
 49 
 50 typedef struct GIFImageDescriptor {
 51     BYTE gifImageFlg;        // 图像标识符开始标志: 0x2c(';')
 52     BYTE gifResv1[3];
 53 
 54     SHORT gifXOffset;        // X方向偏移量
 55     SHORT gifYOffset;        // Y方向偏移量
 56     SHORT gifImageWidth;    // 图像宽度
 57     SHORT gifImageHeight;    // 图像高度
 58 
 59     BYTE gifLocalColorTableFlg : 1;        // 局部颜色列表标志,置位时图像标识符后紧跟一个局部颜色表,
 60                                            供紧跟在它之后的一幅图像使用;值否时使用全局颜色列表,忽略pixel值。
 61     BYTE gifInterlaceFlg : 1;            // 交织标志,置位时图像数据使用交织方式排列,否则使用顺序排列
 62     BYTE gifSortFlg : 1;    // 分类标志,置位表示局部颜色列表分类排序
 63     BYTE gifResv : 2;        // 保留位,必须为 0
 64     BYTE gifPixel;            // 局部颜色列表索引数: 2^(pixel+1)
 65     BYTE gifResv2[3];        
 66 }GIFImageDescriptor;
 67 
 68 typedef struct GIFImageDataSubBlock {
 69     BYTE gifSubBlockSize;    // 块大小
 70     BYTE gifResv[3];
 71     BYTE *gifCodedData;        // 编码数据
 72 }GIFImageDataSubBlock;
 73 
 74 typedef struct GIFImageData {
 75     BYTE gifLZWCodeTableSize;        // LZW初始编码表大小的位数
 76     SHORT gifSubBlockNum;            // 数据块数
 77     BYTE gifResv1;
 78     GIFImageDataSubBlock *gifImageDataSubBlocks;    // 数据块
 79     BYTE gifImageDataEndFlg;        // 数据编码结束: 0
 80     BYTE gifResv2[3];
 81 }GIFImageData;
 82 
 83 typedef struct GIFImageChunk {
 84     /* 图像标识符 */
 85     GIFImageDescriptor gifImageDescriptor;
 86     /* 图像局部颜色列表,gifLocalColorTableFlg=1时有效 */
 87     GIFColorTable gifLocalColorTable;
 88     /* 图像数据 */
 89     GIFImageData gifImageData;
 90 }GIFImageChunk;
 91 
 92 typedef struct GIFStruct {
 93     /* 1 文件头 */
 94     GIFHeader gifHeader;
 95 
 96     /* 2 GIF数据流 */
 97     /* 2.1 逻辑屏幕标志符 */
 98     GIFLSDescriptor gifLSDescriptor;
 99     /* 2.2 全局颜色列表,gifGlobalColorTableFlg=1时有效 */
100     GIFColorTable gifGlobalColorTable;
101     /* 2.3 图像 */
102     SHORT gifImageChunkNum;        // 图像数
103     BYTE gifResv[2];
104     GIFImageChunk *gifImageChunks;
105 
106 
107 
108     /* 3 文件终结器 */
109 };
110 
111 #endif

文件读取缓存模块:

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 
  4 #ifndef GIF
  5 #define CHAR char
  6 #define BYTE unsigned char
  7 #define SHORT short
  8 #define INT int
  9 #define LONG long
 10 #define GIF
 11 
 12 #define SUCCESS 0
 13 #define FAILURE 1
 14 #define INVALID -1
 15 
 16 #define CHECK_NULL_RET(expr, ret) if(NULL == (expr)) return ret
 17 #define CHECK_RET(expr, ret) if(expr) return ret
 18 #define CHECK_FALSE_RET(expr, ret) if(!(expr)) return ret
 19 
 20 #endif
 21 
 22 #define FIRST_BUFF_SIZE     2048
 23 #define SECOND_BUFF_SIZE     FIRST_BUFF_SIZE
 24 #define BUFF_SIZE             (FIRST_BUFF_SIZE+SECOND_BUFF_SIZE)
 25 #define READ_ONCE_SIZE     FIRST_BUFF_SIZE
 26 
 27 FILE *fin;                     // 输入文件
 28 BYTE readBuff[BUFF_SIZE];    // 缓存区,分为第一缓存和第二缓存,对应FIRST_BUFF和SECOND_BUFF
 29 INT startIdx;                // 有效数据起始索引(包含当前),默认值为INVALID(-1)
 30 INT endIdx;                    // 有效数据结束索引(包含当前),默认值为INVALID(-1)
 31 INT readIdx;                // 下一次读取起始索引(包含当前),默认值为INVALID(-1)
 32 
 33 #define GET_VALID_SIZE() (endIdx - readIdx + 1)
 34 
 35 INT RBFillBuff()
 36 {
 37     INT realReadBytes;
 38     INT unusedLen;
 39     CHECK_NULL_RET(fin, FAILURE);
 40 
 41     if(readIdx <= endIdx) // 有未读数据
 42     {
 43         memmove(readBuff, &readBuff[readIdx], endIdx-readIdx+1);
 44         startIdx = readIdx = 0;
 45         endIdx = endIdx - readIdx;
 46     }
 47     else // 无未读数据
 48     {
 49         startIdx = endIdx = -1;
 50         readIdx = 0;
 51     }
 52     CHECK_FALSE_RET(endIdx < FIRST_BUFF_SIZE, SUCCESS);
 53     
 54     realReadBytes = fread(&readBuff[endIdx+1], 1, READ_ONCE_SIZE, fin);
 55     CHECK_FALSE_RET(realReadBytes > 0, FAILURE);
 56 
 57     startIdx = readIdx = 0;
 58     endIdx = endIdx + realReadBytes;
 59     
 60     return SUCCESS;
 61 }
 62 
 63 VOID RBFreeFile() 
 64 { 
 65     if(fin != NULL) 
 66     { 
 67         fclose(fin); 
 68         fin = NULL; 
 69     } 
 70 }
 71 
 72 /* 缓存模块初始化 */
 73 INT RBModuleInit(CHAR *filePath)
 74 {
 75     startIdx = endIdx = -1;
 76     readIdx = 0;
 77     
 78     CHECK_NULL_RET(filePath, FAILURE);
 79     
 80     fin = fopen(filePath, "rb");
 81     CHECK_NULL_RET(fin, FAILURE);
 82     RBFillBuff();
 83 }
 84 
 85 INT RBGetBytes(BYTE *buff, int len)
 86 {
 87     INT ret;
 88     CHECK_NULL_RET(buff, FAILURE);
 89     CHECK_FALSE_RET(len > 0 && len < FIRST_BUFF_SIZE, FAILURE);
 90     if(len > GET_VALID_SIZE())
 91     {
 92         if(FAILURE == RBFillBuff())
 93         {
 94             return FAILURE;
 95         }
 96     }
 97     CHECK_FALSE_RET(len <= GET_VALID_SIZE(), FAILURE);
 98     memcpy(buff, &readBuff[readIdx], len);
 99     readIdx += len;
100     
101     return SUCCESS;
102 }
103 
104 
105 INT RBGetByte(BYTE *value)
106 {
107     return RBGetBytes(value, 1);
108 }
  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <string.h>
  4 
  5 typedef struct Elem {
  6     unsigned char value;
  7     int preIdx;
  8 }Elem;
  9 
 10 int tabSize;
 11 Elem lzwTab[256];
 12 
 13 #define LZWSIZE 2
 14 
 15 int LzwInit(int size)
 16 {
 17     int loop = 0;
 18     for(loop = 0; loop < size; loop++)
 19     {
 20         lzwTab[loop].value = loop;
 21         lzwTab[loop].preIdx = -1;
 22     }
 23     tabSize = size;
 24     return 1;
 25 }
 26 
 27 int AddElement(unsigned char currChar, int lastIdx)
 28 {
 29     lzwTab[tabSize].value = currChar;
 30     lzwTab[tabSize].preIdx = lastIdx;
 31     tabSize++;
 32     return 1;
 33 }
 34 
 35 int SearchStrInTable(unsigned char currChar, int lastIdx)
 36 {
 37     int loop = 0;
 38     for(loop = 0; loop < tabSize; loop++)
 39     {
 40         if((lzwTab[loop].value == currChar) && (lzwTab[loop].preIdx == lastIdx))
 41         {
 42             return loop;
 43         }
 44     }
 45     return -1;
 46 }
 47 
 48 int LzwEncode(const unsigned char *inStream, int inLen, int *outStream, int *outLen)
 49 {
 50     
 51     unsigned char currChar = 0;
 52     int lastIdx = -1;
 53     int currIdx = -1;
 54 
 55     int readIdx = 0;
 56     int writeIdx = 0;
 57 
 58     LzwInit(LZWSIZE); // 初始化编码表
 59 
 60     for(readIdx = 0; readIdx < inLen; readIdx++) // 遍历输入流
 61     {
 62         currChar = inStream[readIdx]; // 当前字符,与lastIdx组成当前字符串
 63         currIdx = SearchStrInTable(currChar, lastIdx); // 查找当前字符串索引
 64         if(currIdx == -1) // 未找到
 65         {
 66             outStream[writeIdx++] = lastIdx; // 输出前缀索引到编码流
 67             AddElement(currChar, lastIdx);    // 添加当前字符串到编码表
 68             lastIdx = SearchStrInTable(currChar, -1); // 以当前字符的索引作为lastIdx,为下一轮做准备
 69         }
 70         else
 71         {
 72             lastIdx = currIdx;
 73         }
 74     }
 75     outStream[writeIdx++] = lastIdx;
 76     *outLen = writeIdx;
 77 
 78     return 1;
 79 }
 80 
 81 int SearchCodeInTable(int currCode, unsigned char *strBuff)
 82 {
 83     if(currCode >= tabSize)
 84     {
 85         return 0;
 86     }
 87     else
 88     {
 89         int writeIdx = 0;
 90         while(currCode >= 0)
 91         {
 92             strBuff[writeIdx++] = lzwTab[currCode].value;
 93             currCode = lzwTab[currCode].preIdx;
 94         }
 95 
 96         unsigned char *strHead = strBuff;
 97         unsigned char *strTail = strBuff + writeIdx - 1;
 98         unsigned char strTemp;
 99         while(strHead < strTail)
100         {
101             strTemp = *strHead;
102             *strHead = *strTail;
103             *strTail = strTemp;
104 
105             strHead++;
106             strTail--;
107         }
108         return writeIdx;
109     }
110 }
111 
112 int WriteString(unsigned char *outStream, unsigned char *strBuff, int strLen, int *outLen)
113 {
114     memcpy(outStream + (*outLen), strBuff, strLen);
115     *outLen += strLen;
116     return 1;
117 }
118 
119 int LzwDecode(const int *inStream, int inLen, unsigned char *outStream, int *outLen)
120 {
121     int currCode;
122     int lastCode = -1;
123     int readIdx = 0;
124     int strLen = 0;
125     unsigned char *strBuff = new unsigned char[256];
126     *outLen = 0;
127 
128     LzwInit(LZWSIZE); // 初始化编码表
129 
130     for(readIdx = 0; readIdx < inLen; readIdx++)
131     {
132         currCode = inStream[readIdx];
133         strLen = SearchCodeInTable(currCode, strBuff);
134         if(strLen == 0) // 没找到
135         {
136             strBuff[strLen++] = strBuff[0];
137             WriteString(outStream, strBuff, strLen, outLen);
138             if(lastCode != -1)
139             {
140                 AddElement(strBuff[0], lastCode);
141             }
142             lastCode = currCode;
143         }
144         else // 找到
145         {
146             WriteString(outStream, strBuff, strLen, outLen);
147             AddElement(strBuff[0], lastCode);
148             lastCode = currCode;
149         }
150     }
151     return 1;
152 }
153 
154 int test()
155 {
156     unsigned char srcData[] = {1,0,0,1,1,1,0,1,0,1,0,0,0,1,1,0,1,1,0,1,1,0,1};
157     int encodeData[32];
158     unsigned char decodeData[32];
159     int srcDataLen = 23;
160     int encodeDataLen;
161     int decodeDataLen;
162 
163     printf("Start encode...
");
164     LzwEncode(srcData, srcDataLen, encodeData, &encodeDataLen);
165     printf("End encode, encodeDataLen=%d.
", encodeDataLen);
166     printf("encodeData:");
167     for(int i=0; i<encodeDataLen; i++)
168     {
169         printf("%d ", encodeData[i]);
170     }
171 
172     printf("
Start decode...
");
173     LzwDecode(encodeData, encodeDataLen, decodeData, &decodeDataLen);
174     printf("End decode, decodeDataLen=%d.
", decodeDataLen);
175     printf("decodeData:");
176     for(int i=0; i<decodeDataLen; i++)
177     {
178         printf("%d ", decodeData[i]);
179     }
180     printf("
");
181     return 1;
182 }
183 
184 int main()
185 {
186     test();
187 
188     system("pause");
189     return 0;
190 }
原文地址:https://www.cnblogs.com/rmthy/p/6410287.html