JPEG 解码器颜色问题 - 怀疑 DC 系数/霍夫曼解码是原因

问题描述 投票:0回答:2

我正在尝试构建一个 JPEG 解码器,并且我正在灰度图像上测试它以保持简单:

https://commons.wikimedia.org/wiki/File:Grayscale_%28182824419%29.jpeg

代码工作正常,但图像太暗,所以我怀疑 DC 系数存在问题(据我了解,AC 系数不会影响整体亮度,只会影响您看到的图案)。

我在下一页尝试过的详细信息。

我查看了第一个 8x8 MCU,并将其整体亮度与 Python 中的标准解码器进行了比较(matplotlib.image imread):

  • 我看到的第一个量化系数是4
  • 如果我看一下 MCU:
    • 这里的第一件事是 6 个二进制 1,后跟一个零。在 DC Huffman 表中查找,这似乎对应于数字 8(即第一个 DC 系数是 8 位长)。
    • 接下来的八位似乎代表数字241
  • 因此我认为第一个DC系数应该是241*4(乘以量化系数)
  • 为了根据该系数确定整体亮度,我们需要除以 8(根据我对 JPEG ITU 第 27 页 A.3.3 的阅读,因为 Cv 和 Cu 都是 1/sqrt(2) )

因此,我们得到的亮度为 241*4/8=120.5,我认为该亮度不在 255 之内。

如果与 matplotlib.image 进行比较,左上角 8x8 像素的平均亮度为 248.515625。

我做错了什么?与 matplotlib 相比,为什么我左上角 8x8 像素的平均亮度这么暗?

其他问题:

  1. matplotlib.image 如何获得这个数字,其中似乎有 64 次?据我了解,DC系数应该是一个整数,然后除以8得到平均亮度,而不是64。所以我们拥有的最小分数应该是8而不是64?
  2. 我注意到 DC 系数的霍夫曼表“看起来”不是最优的。即值 9 由 11111110(7 个 1 和一个零)编码,而它本来可以由 7 个 1 编码,从而节省了一点。

这是为什么呢?是为了打破 1 的序列,这样看起来我们就不会到达块的末尾吗?或者我解码DC霍夫曼表的方式有错误?

colors jpeg huffman-code
2个回答
0
投票

我注意到 DC 系数的霍夫曼表“看起来”不是最优的。即值 9 由 11111110(7 个 1 和一个零)编码,而它本来可以由 7 个 1 编码,从而节省了一点。

一些编码器使用的 JPEG 标准中有一个示例哈夫曼表(PNG 也是如此)。最佳霍夫曼表需要扫描 DCT 系数两次。在过去,DCT 非常耗时,因此人们以整数形式进行计算,并对数据进行单次扫描。现在 JPEG 最慢的部分通常是读取和写入数据。

matplotlib.image 如何获得这个数字,其中似乎有 64 次?据我了解,DC系数应该是一个整数,然后除以8得到平均亮度,而不是64。所以我们拥有的最小分数应该是8而不是64?

DCT 系数在数学上是实数。使用缩放整数来实现 DCT 是很常见的。对于 32 位整数,您可以将所有内容移位 16 并使用低 16 位作为分数。此方法比使用 8 字节浮点值产生更大的舍入误差,但速度更快。

至于黑暗,正如其他人提到的,听起来你在 DCT 之后没有从颜色值中减去 128。


0
投票

谢谢两位。

事实上,这个问题是通过添加 128 解决的,而 1/64 似乎是四舍五入的结果。

现在彩色 JPEG 可以工作了,接下来我可能会看看 AVIF。 (但该规范似乎比 JPEG ITU 长得多,因此这可能是一项艰巨的工作)。

© www.soinside.com 2019 - 2024. All rights reserved.