gif格式的图片要怎么弄 GIF表情包是如何动起来的( 二 )

  
文章插图  
图片来源:What’s In A GIF  
GIF 格式的文件按块存储 , 整体上分为三部分:  
其中 , 数据流中的文本扩展块、应用扩展块和注释扩展块我们跳过不看 , 让图片“动”起来的秘诀就存在于 图形控制扩展(Graphic Control Extension)中 。下面让我们用一个栗子来一探究竟吧 。  
样例准备  
样例图片  
本文分析数据 , 全部基于以该样例图片.  
十六进制转换器  
传送门  
文件头  
识别一张图是不是 GIF 并不只看图片扩展格式或者图片是否会动 , GIF 文件的前 6 个字节内容是 GIF 的署名和版本号 , 通过控制台打印我们可以得到:  
【gif格式的图片要怎么弄 GIF表情包是如何动起来的】  

gif格式的图片要怎么弄 GIF表情包是如何动起来的
  
文章插图  
对照 ASCII 编码我们可以得到 47 49 46 38 39 61 对应 GIF 89a  
简单!继续往下看↓  
GIF 数据流  
图形控制扩展  
我们通过观察不难发现 , 图片会有瞬间闪烁的效果 , 对比文章开头表情包图 , 为什么有些 GIF 图可以一直循环播放 , 有些却是瞬间闪烁然后定格在第二帧呢?  
在 89a 版本 , GIF 添加了图形控制扩展块 , 放在图像标识符(Image Descriptor)的前面 , 用来控制紧跟在它后面的第一个图象的显示 , 图形控制扩展块的结构如下图所示:  
gif格式的图片要怎么弄 GIF表情包是如何动起来的
  
文章插图  
由上图可见 , 整个扩展块结构如下:  
描述  
长度  
扩展块标识符  
1 字节、固定值 0x21  
扩展块标识  
1 字节、固定值 0xF9  
扩展块子块长度  
1 字节  
保留位  
3 位  
处置方法  
3 位  
用户输入标志  
1 位  
透明颜色标志  
1 位  
延迟时间  
2 字节  
透明颜色索引  
1 字节  
扩展块尾  
1 字节、固定值 0x00  
找到它了!罪魁祸首就是**延迟时间!**延迟时间标记了需要暂停这个延迟时间后再继续往下处理数据流 , 这里可以理解为动图中每一帧的停留时间 , 其单位为 1/100 秒 。  
分析到这里 , 有种茅塞顿开的感觉 , 回到代码中 , 我们通过控制台可以看到原图解析出来的数据是这样的:  
gif格式的图片要怎么弄 GIF表情包是如何动起来的
  
文章插图  
延迟时间:00 00 , 十六进制转换十进制为:0  
我们通过手动设置延迟时间 , 就可以让一闪而过的图片“动”起来:  
gif格式的图片要怎么弄 GIF表情包是如何动起来的
  
文章插图  
手动修改后的延迟时间:32 00 , 十六进制转换十进制为:800  
核心代码如下:  
letp = 0; // 当前 Buffer 处理对应的下标while(notEndOfFile && p < contentBuffer.length) { ... switch(contentBuffer[p++]) { case0xf9: // Graphics Control Extensionif(contentBuffer[p++] !== 0x4|| contentBuffer[p+4] !== 0) thrownewError(\"Invalid graphics extension block.\"); p++; // graphicPackedFiledif(delay) { constdelayArr = numberToByteArr(delay); contentBuffer[p] = delayArr[delayArr.length - 1]; contentBuffer[p+1] = delayArr[delayArr.length - 2] || 0; } p = p + 4; // 略过 delay 2 字节, transparentIndex 1 字节 , 结束符号 1字节break; } } 复制代码 文件结尾  
gif格式的图片要怎么弄 GIF表情包是如何动起来的
  
文章插图  
当所有子图像数据解析完毕 , 就会遇到文件尾 , 这一部分只有一个值为 0 的字节 , 标识一个 GIF 文件结束 。文件尾固定为 0x3B


特别声明:本站内容均来自网友提供或互联网,仅供参考,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。