【问题标题】:LZW encoding and the GIF file formatLZW 编码和 GIF 文件格式
【发布时间】:2015-01-07 20:18:50
【问题描述】:

我正在尝试了解如何在 C++ 中创建 .gif 文件。到目前为止,我想除了LZW 编码的工作原理之外,我什么都懂。这是我用标签生成的文件:

47 49 46 38 39 61 -header
0A 00 01 00 91 00 -logical screen descriptor
00 00 FF 00 FF 00 -color table [green,red,yellow,black]
00 FF FF 00 00 00
00 21 F9 04 00 00 -graphics control extension
00 00 00 2C 00 00 -image descriptor
00 00 0A 00 01 00 -(10 pixels wide x 1 pixel tall)
00 02 04 8A 05 00 -encoded image
3B                -terminator

这里再次没有用于复制/粘贴目的的标签:47 49 46 38 39 61 05 00 04 00 91 00 00 00 FF 00 FF 00 00 FF FF 00 00 00 00 21 F9 04 00 00 00 00 00 2C 00 00 00 00 0A 00 01 00 00 02 04 8A 05 00 3B

我很难理解02 04 8A 05 如何转换为图像yryryggyry。我知道02 是最小代码大小,04 是图像块的长度,我想我已经识别出清晰和EOI 代码,但我不明白中间的代码。

8A       05
10001010 00000101
100|01010 00000|101
 ^      ????     ^
 clear code      EOI code

到目前为止,我从.gif 规范中获得了最多的信息: http://www.w3.org/Graphics/GIF/spec-gif89a.txt

这个网站也很有帮助: http://www.matthewflickinger.com/lab/whatsinagif/lzw_image_data.asp

谢谢

编辑*

我观看了 cmets 中链接的 Youtube 视频,并为颜色流“yryryggyry”手动编码了图像:

Color table-012=gry

2   1   2   1   2   0   0   2   1   2
010 001 010 001 010 000 000 010 001 010

current next output dict
010     001  010    21 6
001     010  001    12 7
010     001  -      -
001     010  110    121 8
010     000  010    212 9
000     000  000    00  10
000     010  1010   002 11
010     001  -      -
001     010  110    -
010     -    010    -

outputs-100 010 001 110 010 000 1010 110 010 101

01010101 4th 55
10101000 3rd A8
00101100 2nd 2C
01010100 1st 54

Code-54 2C A8 55

我一定是搞错了,因为这段代码生成的图像是“yr”而不是“yryryggyry”

我将尝试重做工作,看看我是否得到不同的答案

【问题讨论】:

  • 你说你不明白LZW算法是如何工作的,看这个视频:youtube.com/watch?v=j2HSd3HCpDs,希望它能让你明白。这很简单,如果你有具体问题可以在这里问他们。
  • 感谢您的链接,我试图按照编码过程进行操作,但我一定是做错了。我已经编辑了帖子以显示尝试,也许有人可以找到我的错误
  • 为什么一个部分说图片是 5x4 而另一部分说是 10x1?
  • 谢谢,马克。我已更正该部分,使它们都是 10x1
  • 我知道我这样做是正确的,任何人都可以确认数字字符串 01212 编码为 0127 吗?

标签: c++ gif lzw


【解决方案1】:

也许你在第 4 行犯了一个错误: 001 010 110 121 8

在第 3 行,“010”被忽略,所以你必须先将它添加到第 4 行。 在第 4 行,它涉及:

current  next  output    dict
010 001  010   010 001   212   8

这是我的解决方案(也是手动创建的):

LZW for yryryggyry

更新:

终于知道原因了:

在对数据进行编码时,只要写出等于 2^(当前代码大小)-1 的代码,就会增加代码大小。如果要从代码解码到索引,则需要在将等于 2^(当前代码大小)-1 的代码值添加到代码表后立即增加代码大小。也就是说,下次你抓取下一段比特时,你会再抓取一个。

作者的意思是当你即将输出 2^(current code size) - 1 时你应该增加你的 word size,但可能会有不同的解释,这似乎也是合理的:

当您将#(2 ^ current code size) 项添加到代码表时,下一个输出应增加其字长。

在作者的例子中也是正确的,这是我更喜欢的解释。

这是你的例子(“yryryggyry”):

output sequence:
    #4 #2 #1 #6 #2 #0 #0 #8 #5

当您要输出#6 时,将“yry”添加到代码表中,该表的索引为#8。

因为 8 = 2 ^ 当前字长

(current word size = 2(original) + 1(reserved) = 3)

下一个输出应该增加字长,所以#2变成一个4位的字。

而最终的输出序列是:

4   100
2   010
1   001
6   110
2   0010
0   0000
0   0000
8   1000
5   0101

编码后就变成了

54 2C 00 58

所以数据块是

02            -minimum word size     
04            -data length
54 2c 00 58   -data
00            -data block terminator

【讨论】:

  • 感谢您的回复,并纠正我的错误。这意味着新的码流将是 100 010 001 110 010 000 000 1000 101,变成 54 2C 00 0B。不幸的是,虽然这些修正增加了压缩,但它们并没有真正改变图像。由于某种原因,图像仍然只有两个像素宽。
  • 可能是图片太小了?
  • 我不这么认为。解码为 gry 的代码 44 54 工作得很好,只有三个像素宽
  • 我刚刚尝试了 23 像素宽的图像“01212121212121212121212”,它解码为 44 F4 44 E5 BD 02。它不起作用。
  • 谢谢!既然你已经解释过了,我明白了这个过程
猜你喜欢
  • 2019-05-04
  • 2012-10-06
  • 2012-12-21
  • 2012-10-24
  • 1970-01-01
  • 2013-11-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多