我正在尝试构建一个 JPEG 解码器,并且我正在灰度图像上测试它以保持简单:
https://commons.wikimedia.org/wiki/File:Grayscale_%28182824419%29.jpeg
代码工作正常,但图像太暗,所以我怀疑 DC 系数存在问题(据我了解,AC 系数不会影响整体亮度,只会影响您看到的图案)。
我在下一页尝试过的详细信息。
我查看了第一个 8x8 MCU,并将其整体亮度与 Python 中的标准解码器进行了比较(matplotlib.image imread):
因此,我们得到的亮度为 241*4/8=120.5,我认为该亮度不在 255 之内。
如果与 matplotlib.image 进行比较,左上角 8x8 像素的平均亮度为 248.515625。
我做错了什么?与 matplotlib 相比,为什么我左上角 8x8 像素的平均亮度这么暗?
其他问题:
这是为什么呢?是为了打破 1 的序列,这样看起来我们就不会到达块的末尾吗?或者我解码DC霍夫曼表的方式有错误?
我注意到 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。
谢谢两位。
事实上,这个问题是通过添加 128 解决的,而 1/64 似乎是四舍五入的结果。
现在彩色 JPEG 可以工作了,接下来我可能会看看 AVIF。 (但该规范似乎比 JPEG ITU 长得多,因此这可能是一项艰巨的工作)。