zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    Python 爬虫js加密破解(一) 爬取今日头条as cp 算法 解密
    Python 爬虫实例(2)—— 爬取今日头条
    Python 爬虫实例(1)—— 爬取百度图片
    python 操作redis之——HyperLogLog (八)
    python 操作redis之——有序集合(sorted set) (七)
    Python操作redis系列之 列表(list) (五)
    Python操作redis系列以 哈希(Hash)命令详解(四)
    Python操作redis字符串(String)详解 (三)
    How to Install MySQL on CentOS 7
    Linux SSH远程文件/目录 传输
  • 原文地址:https://www.cnblogs.com/rmthy/p/6410287.html
Copyright © 2011-2022 走看看