最简GIF解析代码gif_jumper,用于stb_image的小改进
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;
}
参考文档:
最简GIF解析代码gif_jumper,用于stb_image的小改进的更多相关文章
- [webpack]--webpack 如何解析代码模块路径
前言 webpack是如何解析代码模块路径 webpack 中有一个很关键的模块 enhanced-resolve 就是处理依赖模块路径的解析的,这个模块可以说是 Node.js 那一套模块路径解析的 ...
- Delphi汉字简繁体转换代码(分为D7和D2010版本)
//delphi 7 Delphi汉字简繁体转换代码unit ChineseCharactersConvert; interface uses Classes, Windows; type T ...
- UWP 在 WebView 中执行 JavaScript 代码(用于模拟用户输入等) - walterlv
原文:UWP 在 WebView 中执行 JavaScript 代码(用于模拟用户输入等) - walterlv UWP 在 WebView 中执行 JavaScript 代码(用于模拟用户输入等) ...
- Beaver解析代码反向生成语法文件
背景 Beaver是一款LALR的语法生成工具,现在有一个反编译项目的需求,需要将Beaver语法文件编译后的代码反向生成语法文件的需求,不去评论需求多么傻逼,直接干 设计 flowchart 语法文 ...
- QueryDet: Cascaded Sparse Query for Accelerating High-Resolution Small Object Detection(QueryDet:用于加速高分辨率小目标检测的级联稀疏查询)
QueryDet: Cascaded Sparse Query for Accelerating High-Resolution Small Object Detection(QueryDet:用于加 ...
- js 日期计算星座 根据生日的月份和日期,一行代码计算星座的js小函数(转)
本博客根据 开源中国作者清风徐不来 的文章 根据生日的月份和日期,一行代码计算星座的js小函数(转) 原文出自CSDN 无心的专栏 的文章,知识产权归原文作者所有! 点击查看原文:js 日期计算星座
- stl文件格式解析代码--java版
代码是参考three.js中的stlLoader.js写的. 需要注意的地方,java中byte取值-128~127 package test_stl.test_entry; import java. ...
- PE格式文件的解析代码
#include "Global.h" ; //标志,用于表示是否为pe32+文件 ; //标志,用于表示读入的模式,若为0代表是内存读入,不为0,代表是文件打开,此时mode是文 ...
- h264文件分析(纯c解析代码)
参考链接:1. 解析H264的SPS信息 https://blog.csdn.net/lizhijian21/article/details/80982403 2. h.2 ...
- 你一定看得懂的 DDD+CQRS+EDA+ES 核心思想与极简可运行代码示例
前言 随着分布式架构微服务的兴起,DDD(领域驱动设计).CQRS(命令查询职责分离).EDA(事件驱动架构).ES(事件溯源)等概念也一并成为时下的火热概念,我也在早些时候阅读了一些大佬的分析文,学 ...
随机推荐
- Selenium4自动化测试6--控件获取数据--下拉框级联选择、checkbox选择、时间选择器
4-下拉框级联选择 import time from selenium.webdriver.support.select import Select #pip install selenium fro ...
- pageoffice6 版本实现word 文件添加水印
在很多场景下,Word文档正式发文之前,或者说形成最终文档之前,常常需要往Word文件中添加水印,并且会根据文件类型或内容的不同,需要添加的水印也不一样. 添加水印是Word软件里的一个简单功能,直接 ...
- jenkens
[root@mcw01 ~]$ ls .jenkins/ config.xml jenkins.install.UpgradeWizard.state nodeMonitors.xml secret. ...
- docker flannel网络
部署etcd github部署访问链接:https://github.com/etcd-io/etcd/releases/ ETCD_VER=v3.5.1 # choose either URL GO ...
- 用Vue全家桶纯手工搓了一个开源版「抖音」
前言 2018年刚入行前端时,公司使用的还是Angular.Angular什么都好,就是写代码时的体验老糟心了,改一个地方,按下保存之后,要等好几秒刷新后才能看到效果,Webstorm无比好用的自动保 ...
- css圆圈慢慢放大
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8 ...
- LeetCode 40. Combination Sum II 组合总和 II (C++/Java)
题目: Given a collection of candidate numbers (candidates) and a target number (target), find all uniq ...
- sql去重常用的基本方法
1.存在两条完全相同的纪录 select distinct * from table(表名) where (条件) 2.存在部分字段相同的纪录(有主键id即唯一键) 如果是这种情况的话用disti ...
- Go 语言中的异常处理简单实践 panic、recover【GO 基础】
〇.Go 中的异常处理简介 Golang 没有结构化异常,使用 panic 抛出错误,recover 捕获错误. panic.recover 参数类型为 interface{},因此可抛出任何类型对象 ...
- mysql 判断字符串结尾
mysql 判断字符串结尾 CREATE TABLE `tbl_str` ( `id` INT DEFAULT NULL, `Str` VARCHAR(30) DEFAULT NULL) INSERT ...