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 }
  • 相关阅读:
    js小案例---1.随机10不重复10数并排序2.一次输入10数并输出和
    23种设计模式-----转载
    类与类之间的关系-----转载
    设计模式六大原则-----转载
    配置JDK时环境变量path和JAVA_HOME的作用是什么?
    安装和配置JDK,并给出安装、配置JDK的步骤。
    1.Java为什么能跨平台运行?请简述原理。
    求圆的周长和面积
    java第一节课
    相关元素操作
  • 原文地址:https://www.cnblogs.com/rmthy/p/6410287.html
Copyright © 2011-2022 走看看