解压缩GIF光栅动画数据

本文关键字:动画 数据 GIF 解压缩 | 更新日期: 2023-09-27 18:29:11

很抱歉发了这么长的帖子,我试图尽可能多地提供信息,我尽了最大努力将所有内容格式化为尽可能容易阅读。我一直在尝试在C#中解压缩GIF,除了LZW解压缩之外,似乎什么都有。我正在阅读Gif中的URL。对于这个例子,我将使用这个动画GIF。我知道它有35帧,但我只想看第一帧。

HEADER: 474946383961
GIF Version: 89a
LOGICAL DESCRIPTOR: 41003D00F60000
Width : 65
Height: 61
Sorted Color Table: False
Global Color Table Size: 128
Background Color Index: 0
Pixel Bits: 0

下面是全局颜色表,我有点困惑,因为它填充了123/128种颜色,其余的是000000s,我在填充代码表时会怀疑这一点吗?

很抱歉这里的格式,只显示关于000000s 的问题

Global Color Table:
141414 181818 1C1C1C 242424 262626 282828 2A2A2A 2C2C28 302C2C 30302C 3430303 434303
434344 030185 030284 03C346 038306 438306 43C305 044245 048245 448285 C50285C 502C5C
542C5C 543054 503860 542C68 50286C 50286C 542870 542870 542C70 582874 582870 582C745
82C745 C2C785 C2C605 830645 830645 C30645 C34685 C307C6 02C6C6 0346C6 438746 434786
030786 838786 C3C006 464806 02C806 42C806 430846 C34886 C348C7 034847 43C887 0388C7 
43C887 83C8C7 83C907 034947 034947 434987 434947 438987 4389C7 8389C7 C38A07 838A07 
C388C7 C40A46 050A48 03C948 048A08 848A08 C48A89 04CA89 44CAC9 44CAC9 850B09 C50B49 
C50B49 C54B4A 054BCA 050B8A 054B8A 454BCA 454BCA 458BCA C5CC0A 454C0A 854C0A 858C4A 
858C4A C58C4A C5CC8A C58C8A C5CC4B 058C8B 058C8B 05CC89 C64C8B 060CCB 460D0B 860D0B 
864D4B C64D4C 068D8C 068D8C 468DCC 468DCC 86CE8D 070ECD 874F0D C78F4D C78F4D C7CF4E 
078F8E 07CF8E 47C000 000000 000000 000000 000000 000000

图形控制扩展

21F9040D03007B00 |Graphics Control Extension
Block Size: 4
Has Transparency: True
Delay: 768
Transparency Color Index: 123

图像描述符

IMAGE DESCRIPTOR: 2C0000000041003D0000
Left: 0
Top: 0
Width : 65
Height: 61
Local Color Table: False
Interlace: False

最后我困惑的地方图像数据

LZW minimum code size: 7
IMAGE DATA SUBBLOCK 1 HEXDATA: 
80 7B 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F 86 06 06 90 94 84 07 
95 86 05 0C 00 98 94 05 01 07 05 9D 7B 05 0B 9B A3 8F 07 0C 0C 02 05 
93 94 07 08 0A 09 9C A8 8D 05 08 B2 04 02 AF A9 09 0B 0A B5 B6 8B 05 
00 C0 AB 01 A2 8E 05 BF C0 C2 C3 8A 07 0A 08 AB 0F 19 CA 8C A5 C0 0B 
CF D0 88 C5 0C 09 0C 08 6E 29 CB 0C 0B A6 DD DE 87 9A E9 4C 67 2A D8 
89 06 0C 0A E9 08 EB EC 85 06 00 BF 58 63 C6 C8 5B 64 40 4B BA 05 B4 
F6 11 03 F0 20 60 18 37 03 E9 85 41 90 4E 43 05 85 C4 AA 9C 39 43 E6 
8C 0C 15 8A 0A 98 E9 58 A6 0A 05 8C 21 29 90 21 33 86 0C 98 88 99 C0 
8C D9 38 E6 22 CA 90 13 58 86 21 23 05 45 81 9F 40 81 5A 09 C8 F2 E4 
CD 94 1D 37 5C D0 93 A7 A9 D3 A6 2A 7C 8C 34 63 F2 28 B1 09 14 EE D8 
A9 B3 B5 8E 57 AE 76 B8 AC 68 49 66 82 D5 6C 75 E2 A8 55 0B 67 6D 1C 

为了所有密集的目的,我们应该看看的前几个二进制位

IMAGE BLOCK BINARY: 
10000000 clearcode, 01111011, 10000010, 10000011, 10000100, 
10000101, 10000110, 10000111, 10001000, 10001001, 10001010, 
10001011, 10001100, 10001101, 10001110, 10001111,
Codes:
1000000, 0011110, 1110000, 01010000... ect 

我的主要问题是,在阅读这些代码时,我如何使用LSB包装顺序,其次,考虑到背景是透明的,这对每个像素来说有什么意义,比如我如何获得第一个不透明像素的索引。最后,在什么时候,我应该将向表中添加代码的代码大小增加到LZW最小代码大小+1(8)。谢谢你的建议。

解压缩GIF光栅动画数据

LSB打包顺序只意味着以小端序读取数据,并在"吃掉"这些位时对数据进行右移。

下面是C中的一个例子,C#使访问内存变得更加痛苦,但逻辑是一样的:

uint32_t ulBits;
unsigned char *pData;
int codelen, code, bitnum;
int mask;
int nextcode;
codelen = 7; // assume 7 bits to start
mask = (1<<(codelen+1)) -1;
clearcode = (mask >> 1) + 1;
nextcode = clearcode + 2;
ulBits = *(uint32_t)pData; // read 32-bits as little endian
bitnum = 0;
#define WORDLEN 32
// To read the variable length codes you would do the following:
while (decoding == true)
{
   if ((bitnum + codelen) > WORDLEN) // need to read more data
   {
      pData += (bitnum >> 3); // adjust source pointer
      ulBits = *(uint32_t)pData; // read another 32-bits
      bitnum &= 7; // reset bit offset
   }
   code = (ulBits >> bitnum);
   code &= mask;
   bitnum += codelen;
   // some logic here to increment the nextcode is beyond the scope of this answer
   <the rest of your logic here>
}

当你解压缩代码时,你会在字典中添加一个新项目,并增加你的"下一个代码"值。当这个值不能适应当前的代码大小时,您可以将它增加一位,直到达到4096,然后通常从一个清晰的代码开始重置字典。有一个很少使用的选项叫做"不同的清晰代码"。在这种情况下,完整的字典将一直使用,直到收到清晰的代码。有很多示例LZW解码器,你可以看看,所以没有必要在这里发布一个完整的。