解析GIF栅格数据 - LZW

时间:2013-01-07 20:44:43

标签: algorithm gif decoding lzw

我一直在尝试用PHP解压缩GIF,似乎除了LZW解压缩之外还有其他所有功能。我保存了一张显示的图片:sample image

此图片为3 x 5,如下所示:

Blue  Black Black
Black Blue  Black
Black Black Black
White White White
White White White

我决定在Binary中手动完成并解析此文件。手动解析的结果如下。我仍然坚持如何在这里解码栅格数据。有人可以分解栅格数据如何成为图像吗?我已经能够分解一个图像,但没有别的(不是这个图像)。我已经发布了我应该如何分解的理解,但我显然做错了。

01000111 G
01001001 I
01000110 F
00111000 8
00111001 9
01100001 a

Screen Descriptor
WIDTH
00000011 3
00000000

00000101 5
00000000

10010001 GCM (1), CR (001), BPP (001), CD = 2, COLORS = 4

00000000 BGCOLOR Index

00000000 Aspect Ratio

GCM
BLUE
00110101 | 53
00000000 | 0
11000001 | 193

WHITE
11111111 | 255
11111111 | 255
11111111 | 255

BLACK
00000000 | 0
00000000 | 0
00000000 | 0

00000000 | 0
00000000 | 0
00000000 | 0

Extension
00100001 | 21
Function Code
11111001 | F9
Length
00000100 | 4
00000000
00000000
00000000
00000000
Terminator
00000000

Local Descriptor
00101100 Header
XPOS
00000000 | 0
00000000

YPOS
00000000 | 0
00000000

Width
00000011 | 3
00000000

Height
00000101 | 5
00000000

Flags
00000000 (LCM = 0, Interlaced = 0, Sorted = 0, Reserved = 0, Pixel Bits = 0)

RASTER DATA
Initial Code Size
00000010 | 2
Length
00000101 | 5

Data
10000100
01101110
00100111
11000001
01011101

Terminator
00000000

00111011 | ;
00000000

我的尝试

10000100
01101110
00100111
11000001
01011101

初始代码大小= 3 一次读取2位

10
00
Append last bit to first (010)
String becomes 010 or 2. 2 would be color # 3 or BLACK

此时,我已经错了。第一种颜色应该是蓝色。

我一直在使用的资源:

http://www.daubnet.com/en/file-format-gif http://en.wikipedia.org/wiki/Graphics_Interchange_Format http://www.w3.org/Graphics/GIF/spec-gif87.txt

5 个答案:

答案 0 :(得分:13)

GIF解析器

你说你想编写自己的GIF解析器,以了解它是如何工作的。我建议你查看任何包含GIF阅读器的库的源代码,例如事实上的参考实现GIFLIB。相关的源文件是dgif_lib.c;启动at slurp进行解码,或跳转到LZW decompression implementation

以下是图像解码的方式。

我认为问题在于您错误地将输入字节拆分为LZW代码。

颜色数为(0b001 + 1) * 2 = 4

代码大小从2 + 1 = 3位开始。

所以初始字典是

000 = color 0 = [blue]
001 = color 1 = [white]
010 = color 2 = [black]
011 = color 3 = [black]
100 = clear dictionary
101 = end of data

现在,GIF packs LZW codes into bytes in LSB-first order.因此,第一个代码被存储为第一个字节的3个最低有效位;第二个代码作为接下来的3位;等等。在您的示例中(第一个字节:0x84 = 10000100),前两个代码因此为100(清除)和000(蓝色)。整件事

01011101 11000001 00100111 01101110 10000100

分为代码(在读取最高3位代码111后切换到4位组)

0101 1101 1100 0001 0010 0111 0110 111 010 000 100

这解码为:

     last
code code
 100      clear dictionary
 000      output [blue] (1st pixel)
 010  000 new code in table:
              output 010 = [black]
              add 110 = old + 1st byte of new = [blue black] to table
 111  010 new code not in table:
              output last string followed by copy of first byte, [black black]
              add 111 = [black black] to table
              111 is largest possible 3-bit code, so switch to 4 bits
0110 0111 new code in table:
              output 0110 = [blue black]
              add 1000 = old + 1st byte of new = [black black blue] to table
0111 0110 new code in table:
              output 0111 = [black black]
              add 1001 = old + 1st byte of new = [blue black black] to table
...

所以输出开始(换行到3列):

blue  black black
black blue  black
black black ...

这就是你想要的。

答案 1 :(得分:1)

无需编写自己的GIF阅读器的解决方案

对于非自己启发的用途,请尝试此操作。

一些注释

  • 您的GIF文件是GIF89a。您链接到GIF87a规范; 89a specification is here
  • 您似乎担心使用库来解析图像会损害性能。这毫无意义。这些库通常用优化的C实现;您的手动解决方案将使用PHP(一种解释性语言)编​​写。
  • 你提到了PCX,像imagemagick这样的图书馆支持。

或者只使用PNG

根据ZPL 2 programming manual,支持PNG。例如,~DY(下载图形)命令采用b(格式)参数,除了默认GRF之外,P(PNG)是一个选项。另请参阅Printing PNG images to a zebra network printer

批次用于将GIF转换为PNG的库。您可以使用ImageMagick (PHP binding),或只使用PHP函数imagecreatefromgifimagepng

答案 2 :(得分:0)

我对LZW解码没有帮助,但是从PHP GD扩展中使用像imagecreatefromgif()这样的库函数解析GIF文件并提取图像数据会不会更容易然后你可以转换成你的目标格式?

答案 3 :(得分:0)

如果不使用其他人编写的库,您想知道如何进行LZW。 LZW不会逐像素地解码图像。它在数据流中查找重复块,将它们保存在字典中并引用它们。如果在某处重复100个像素,则仅使用一个代码来再现100个像素,而不是像位图(BMP)图像那样再现100个像素。这就是为什么GIF非常适合图表,你可能会有许多100个白色像素系列,后面跟几个黑色像素来绘制一条线。另一方面,它对于照片来说很糟糕,因为很少有长重复,GIF通常限制在256种颜色,除非你使用一些复杂的技巧。

压缩文件中使用的代码比原始图像中每个像素的颜色代码长。这只是因为长重复块在图表中很常见,因此可以进行大规模压缩。

答案 4 :(得分:0)

该网站是关于GIF格式的优秀资源,并提供了对LZW压缩和解压缩过程的一个很好的解释:

http://www.matthewflickinger.com/lab/whatsinagif/index.html