【问题标题】:Need help on BMP to JPEG conversion在 BMP 到 JPEG 转换方面需要帮助
【发布时间】:2009-07-13 17:36:41
【问题描述】:

我正在编写一个 C++ 程序来将 BMP 图像转换为 JPEG。

这是我尝试遵循的基本算法:

  1. 将 RGB 颜色空间转换为 Y,Cb,Cr..
  2. 将 Cb 和 Cr 下采样 2(这意味着对于 2*2 的每个方块,有 4 个不同的 Y 值,但有 1 个 Cb 和 1 个 Cr 值
  3. 对每个 8*8 像素的数据单元应用 DCT...
  4. 然后使用标准的 Cb 和 Cr 量化表对 DCT 系数进行量化。
  5. 进行曲折排序。
  6. 使用霍夫曼编码分别对直流和交流系数进行编码。
  7. 写入正确的标头并将霍夫曼编码值写入文件...

我已确认我执行上述操作是正确的,但我仍然遇到以下问题:

  • 生成的 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
    • imp 颜色数 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 (for ac huffman table(chrominance Cb,Cr) EOB 值为 01)
  • cr 直流编码:110101110
  • cr ac 编码:01
  • 我得到的最终霍夫曼代码是:

    001111101010110000100111010111001 长度33

为了使它能被 8 整除,填充 1 就完成了。

0011111010101100001001110101110011111111 Length 40.

这里每个0或1实际上是需要存储在JPEG文件中的一个位,但是由于我们不能逐位写入文件,所以总共取8位并转换为整数以 10 为底的值并存储为 1 字节字符。

任何人都可以提供任何关于我哪里出错的建议吗?

【问题讨论】:

  • 您似乎需要帮助来撰写帖子和选择合适的标签。
  • 最后是一个很棒的技术问题。谢谢马克。不幸的是,我没有答案,但我希望有人知道。
  • 顺便提一下,将您的代码提炼成其他人可以编译的最短示例可以创造奇迹。提供代码也是一种更有效的方式,可以帮助其他人了解可能缺少的内容。
  • 我投了反对票,因为不清楚您认为结果的哪一部分是错误的以及它们应该是什么,并且您没有包含任何代码来明确可能发生的情况。
  • 你有什么理由不能使用 IJG 的 libjpeg?

标签: jpeg bmp huffman-code dct


【解决方案1】:

要解决您的问题,首先要做的是获取有关 JPEG 标准的 Pennebaker/Mitchel 书籍。

操作顺序为:

1) 色彩空间转换 2) FDCT 3) 量化 4)之字形重新排序 5) 霍夫曼编码

由于您必须遵循许多规则,因此这些操作具有许多复杂性。

a) 您是否正确处理 DC 预测器? b)您是否正确编码 A/C 组件 w.r.t.零的运行? c)您是否尊重有关“填充零”和标记的输出流规则? d) 您的色彩空间转换公式是否正确?它是否包括必须从每个组件中减去的 0x80? e) 您是否根据您选择的二次采样选项以正确的顺序对 MCU 模块进行编码?

【讨论】:

    【解决方案2】:

    不要重新发明轮子。使用 ImageMagick、Magick++ 或 CImg 来完成此操作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-04-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-27
      • 2014-02-06
      • 2017-11-02
      相关资源
      最近更新 更多