gif jumper
gif支持多帧动画,但是没有存储总帧数,解析gif直到结束才能知道总帧数。
所以gif解析代码,要么采用链表,要么不停realloc()分配内存,stb_image的代码就是如此。
出于本人的强迫症,于是写了一段代码,迅速“跳过”解析过程,返回总帧数,聊胜于无,仅供参考:
同时也可以作为gif格式的帮助文档,毕竟最好的文档就是代码。
格式
- GIF文件头(Header)
- 逻辑屏幕描述块(Logical Screen Descriptor)
- 全局彩色表(GlobalColor Table)
- 图像描述块(Image Descriptor)
- 局部彩色表(Local Color Table)
- 图形控制扩展块(Graphic Control Extension)
- 注释扩展块(Comment Extension)
- 应用扩展块(Application Extension)
- 无格式文本扩展块(PlainText Extension)
- 文件结束块(Trailer)
源码
#define JUMP(c, offset) c+=offset #define INT8(n, offset) n=*offset #define INT8_BIT(n, offset, s, e) n=(unsigned char)((*offset)<<s)>>(s+7-e) static int gif_jumper(unsigned char *start, unsigned char *end) { int num=0; int frames=0; unsigned char *cur=start; JUMP(cur, 6); // Header(6bytes) JUMP(cur, 4); // Logical Screen Descriptor(7bytes) INT8_BIT(num, cur, 0, 0); // Global Color Table Flag if(num) { INT8_BIT(num, cur, 5, 7); // Size of Global Color Table = 2^(pixel+1) JUMP(cur, 3+3*(1 << (num+1))); } else { JUMP(cur, 3); } while(cur<end) { INT8(num, cur); switch(num) { case 0x2C: // Image Descriptor(9bytes) frames++; JUMP(cur, 1+8); INT8_BIT(num, cur, 0, 0); // Local Color Table Flag if(num) { INT8_BIT(num, cur, 5, 7); // Size of Local Color Table = 2^(pixel+1) JUMP(cur, 1+3*(1 << (num+1))); } else { JUMP(cur, 1); } JUMP(cur, 1); // LZW Minimum Code Size while(cur<end) { INT8(num, cur); // Table-Based Image Data JUMP(cur, 1+num); if (num==0) { break; // Block Terminator } } break; case 0x21: // Extension JUMP(cur, 2); // Extension Introducer while(cur<end) { INT8(num, cur); // Table-Based Image Data JUMP(cur, 1+num); if (num==0) { break; // Block Terminator } } break; case 0x3B: // Trailer JUMP(cur, 1); break; default: return 0; } }; return frames; }