• gif解析


    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <assert.h>
    //#define DEBUG
    void parseControlExtension(FILE *fp){
     if(fgetc(fp) != 4){
      printf("错误的块大小在偏移 %u 处. ",ftell(fp) -1);
      assert(0);
     }
     size_t buffer[8] = {0};
     fread(buffer,1,1,fp);
     printf("下一个图像块使用的处置方式为:%u. ",(1+2+4)&(*(char*)buffer >> 2));
     printf("下一个图像块%s用户输入。 ",(2&*(char*)buffer)?"期待":"不期待");
     int enabledTransparent = 0;
     printf("在下一个图像块中%s透明色。 ",(1&*(char*)buffer)?
     enabledTransparent = 1,"使用":"不使用");
     printf("读取到了文件偏移:0x%04X. ",ftell(fp));
     memset(buffer,0,sizeof buffer);
     fread(buffer,2,1,fp);
     printf("延迟时间:%.2lf秒。 ",0.01 * *(int*)buffer);
     fread(buffer,1,1,fp);
     if(enabledTransparent){
      printf("透明颜色索引为:%u. ",*(unsigned char*)buffer);
     }
     if(fgetc(fp) == 0)puts("正确的块终结器.");
     else{
      fprintf(stderr,"错误的块终结器%u. ",(fseek(fp,-1,SEEK_CUR),fgetc(fp)));
      exit(-1);
     }
    }
    void parseColorTable(int sizeColorTable, FILE *fp){
     unsigned char rgb[3];
     const unsigned char *red = &rgb[0];
     const unsigned char *green = &rgb[1];
     const unsigned char *blue = &rgb[2];
     puts("Color Table found.");
    #ifdef DEBUG
     printf("开始于0x%04X ",ftell(fp));
    #endif
     int i = 0;
     for(;sizeColorTable > 0; -- sizeColorTable){
      fread(rgb, sizeof rgb, 1, fp);
      //printf("#%02d RGB( %u , %u , %u ) ",++i,*red,*green,*blue);
     }
     puts("color table 读取完毕.");
     printf("读取到了文件偏移:0x%04X. ",ftell(fp));

    }
    void showSubBlocks(FILE *fp){
     size_t buffer[8];
     int sizeBlock = 0;
     for(;;){
      memset(buffer,0,sizeof buffer);
      fread(buffer,1,1,fp);
      printf("遇到了一个%u大小的数据块。 ",sizeBlock = *(int*)buffer);
      if(sizeBlock == 0)break;
      else if(sizeBlock > 8){
       fseek(fp,sizeBlock,SEEK_CUR);
      }
      else{
       unsigned char buf[512];
       for(;sizeBlock > 0; --sizeBlock){
        char c;
        printf("0x%02X ",(unsigned char)(c = fgetc(fp)));
        if(c >= 0x20)printf("(%c)",c);
       }
       putchar(' ');
      }
     }
    }
    void parseImageData(FILE *fp){
     long loc = ftell(fp);
     printf("下面准备从0x%04X处开始处理图像数据. ",loc);
     fseek(fp,0,SEEK_END);
     printf("还差%d字节的数据未处理. ",ftell(fp) - loc);
     fseek(fp,loc,SEEK_SET);
     printf("此图像块的LZW编码长度为%u. ",(unsigned char)fgetc(fp));
     showSubBlocks(fp);
    }
    void parseImageDescriptor(FILE *fp){
     size_t buffer[8] = {0};
     fread(buffer,2,1,fp);
     printf("x方向偏移量为%u,",*(int*)buffer);
     fread(buffer,2,1,fp);
     printf("y方向偏移量为%u. ",*(int*)buffer);
     fread(buffer,2,1,fp);
     printf("图像宽度为%u. ",*(int*)buffer);
     fread(buffer,2,1,fp);
     printf("图像高度为%u. ",*(int*)buffer);
     fread(buffer,1,1,fp);
    #ifdef DEBUG
     fprintf(stderr,"reading 0x%04X. ",ftell(fp) -1);
    #endif
     int enabledLocalColor = 0;
     printf("%s使用局部颜色. ",
     (0x80 & *(char*)buffer)?enabledLocalColor = 1,"":"不");
     printf("%s使用交织方式排列. ",(0x40 & *(char*)buffer)?"":"不");
     printf("分类标志%s. ",(0x20&*(int*)buffer)?"被置位":"未置位");
     int sizeLocalColorTable = 0;
     if(!enabledLocalColor){
      puts("禁用了局部颜色.");
     }
     else{
      printf("局部颜色列表列表大小为%d。 ",(
      ({
      int i = 1 + ((1+2+4)&(*(char*)buffer));
      //后面这个大括号很重要,血泪的教训啊!
      //否则加号的优先级比与号要高!想不到吧!
      sizeLocalColorTable = 1;
      for(;i>0;--i){
       sizeLocalColorTable *= 2;
      }
      }),sizeLocalColorTable));
     }
     if(enabledLocalColor){
      parseColorTable(sizeLocalColorTable,fp);
      parseImageData(fp);
     }
     else{
      parseImageData(fp);
     }
    }
    void parseApplicationExtension(FILE *fp){
     size_t buffer[16] = {0};
     fread(buffer,1,1,fp);
     if(11 == *(char*)buffer){
      puts("正确的应用程序控制块大小.");
     }
     else{
      fprintf(stderr,"错误的应用程序控制块大小在0x%04X.",ftell(fp));
      assert(0);
     }
     memset(buffer,0,sizeof buffer);
     fread(buffer,8,1,fp);
     puts((char*)buffer);
     memset(buffer,0,sizeof buffer);
     fread(buffer,3,1,fp);
     puts((char*)buffer);
     showSubBlocks(fp);
     
    }
    int main(int argc,char *argv[]){
     FILE *fp = NULL;
     if(argc != 2){
      fputs("bad command line.input filename expected.",stderr);
      exit(0);
     }
     fp = fopen(argv[1],"rb");
     char *signature = "GIF89a";
     char buffer[8] = {0};
     int i;
     for(i = 0; i < strlen(signature); ++i){
      if(feof(fp)){
       fputs("file size too small.",stderr);
       exit(0);
      }
      buffer[i] = fgetc(fp);
     }
     if('' == strcmp(buffer,signature)){
      puts("good signature found.");
     }
     else if('' == strcmp("GIF87a",buffer)){
      puts("Version 87a.");
     }
     else{
      fputs("bad signature. ",stderr);
      fprintf(stderr,"expecting %s while meet %s. ",signature,buffer);
      exit(0);
     }
     
     memset(buffer,0,sizeof buffer);
     fread(buffer,2,1,fp);
     printf("image width : %d pixel(s), ",*(int*)buffer);
     fread(buffer,2,1,fp);
     printf("image height : %d pixel(s). ",*(int*)buffer);

     fread(buffer,1,1,fp);
     int enabledGCT = 0;
     printf("Global Color Table %s. ",
     (0x80 & *(char*)buffer)?
     (enabledGCT = 1, "enabled"): "disabled");
     
     printf("Color Resolution: %d bit. ",1+((1+2+4)&(*(char*)buffer >> 4)));
     
     printf("Sort Flag %s. ",
     (0x08 & *(char*)buffer)?
     ({
      fputs("Meet Sort Flag which is not supported...exiting.",stderr);
      exit(0);
     }),
     "enabled"/*null string for syntax*/:"disabled");
     int sizeGCT;
     {
      int i;
      for(i = 0, sizeGCT = 1; i < 1+(*(char*)buffer & (1+2+4)); ++i){
       sizeGCT *= 2;
      }
      printf("The size of Global Color Table: %d. ", sizeGCT);
     }
     fread(buffer,1,1,fp);
     printf("background color : %u. ",*(unsigned char*)buffer);
     fread(buffer,1,1,fp);
     printf("Pixel Aspect Ratio : %u. ",*(unsigned char*)buffer);
     if(enabledGCT){
      puts("parsing global color table...");
      parseColorTable(sizeGCT, fp);
     }
     while(!feof(fp)){
      unsigned char ch = fgetc(fp);
      if(ch == ','){
       printf("读取到一个图像标识符','在0x%04X. ",ftell(fp) -1);
       parseImageDescriptor(fp);
      }
      else if(ch == ';'){
       puts("遇到了文档的结束标志;。");
       long loc = ftell(fp);
       fseek(fp,0,SEEK_END),
       printf("距离文件流的结尾还有%u个字节。 ",ftell(fp) - loc);
       exit(0);
      }
      else if(ch == '!'){
       puts("读取到一个扩展块标识符'!'");
       ch = fgetc(fp);
       if(ch == 0xF9){
        puts("读取到一个图像控制扩展标签.");
        parseControlExtension(fp);
       }
       else if(ch == 0xFF){
        parseApplicationExtension(fp);
       }
       else{
        printf("读取到0x%02X. ",ch);
        puts("还未能处理这种扩展块");
        assert(0);
       }
      }
      else{
       fputs("遇到了未预期的字符.现在退出程序。",stderr);
       fprintf(stderr,"在0x%04X处. ",ftell(fp));
       exit(-1);
      }
     }
     return 0;
    }

  • 相关阅读:
    windows 的文件夹映射实现
    项目管理工具
    SSM(Spring+SpringMVC+MyBatis)高并发优化思路
    高性能高可用高并发技术架构的一些理解
    你懂什么是分布式系统吗?Redis分布式锁都不会?
    使用批处理文件(*.bat)同时打多个cmd窗口
    mysql删除重复数据只保留一条
    native2ascii命令
    利用编辑距离(Edit Distance)计算两个字符串的相似度
    eclipse如何正确部署tomcat7
  • 原文地址:https://www.cnblogs.com/renhl/p/3336207.html
Copyright © 2020-2023  润新知