我正在编写一个 C++ 程序来将 BMP 图像转换为 JPEG。
这是我试图遵循的基本算法:
- 将 RGB 颜色空间转换为 Y,Cb,Cr..
- 将 Cb 和 Cr 向下采样 2(这意味着对于 2*2 的每个方形块有 4 个不同的 Y 值,但 1 个 Cb 和 1 个 Cr 值
- 将 DCT 应用于每个 8*8 像素的数据单元...
- 然后使用标准的 Cb 和 Cr 量化表对 DCT 系数进行量化。
- 做之字形排序。
- 使用霍夫曼编码分别对直流和交流系数进行编码。
- 写入正确的标头并将霍夫曼编码值写入文件...
我已经验证我正确地执行了上述操作,但我仍然遇到以下问题:
- 生成的 JPEG 未正确显示。
- 我制作了一个小的 8*8 24 位(颜色深度)bmp 文件,完全填充了颜色值 R=10 B=10 和 G=100...所有 64 个像素都是相同的颜色..
- 我在每一步得到的数据如下......
- BMP 标头大小为 40
- 标头大小 40
- 宽度 8
- 身高 8
- 飞机数量 1
- 每像素位数 24
- 图像尺寸 194
- x 分辨率每米像素 2834
- y 分辨率每米像素 2834
- 颜色数 0
- 小鬼颜色数 0
- (R,B,G)=(10,10,100)的Y Cb Cr换算为(62,-29,-37)
所以让我们首先考虑 Y 分量。
Y 分量的 DCT 系数为:
495 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
在量化之后,对于 Y 分量,我得到的单个数据单元的锯齿形排序是这样的。
30 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
现在上述之字形顺序数组的霍夫曼编码为:
- Y直流编码:00111110
- Y ac 编码:1010(对于 ac 霍夫曼表(亮度 Y)EOB 值为 1010)
- Cb和Cr分量的类似哈夫曼编码如下:
- cb直流编码:11000010
- cb ac 编码:01(对于 ac 霍夫曼表(色度 Cb,Cr)EOB 值为 01)
- cr直流编码:110101110
- cr 交流编码:01
我得到的最终霍夫曼代码是:
001111101010110000100111010111001 长度33
所以为了使它能被8整除,填充1就完成了。
0011111010101100001001110101110011111111 Length 40.
这里每个 0 或 1 实际上是一个位,需要按原样存储在 JPEG 文件中,但由于我们不能逐位写入文件,因此总共取 8 位并转换为基数中的整数值10 并存储到一个 1 字节的字符中。
任何人都可以就我哪里出错提供任何建议吗?