c++ - 图像颜色转换

标签 c++ c image-processing colors

我需要将 24bppRGB 转换为 16bppRGB、8bppRGB、4bppRGB、8bpp 灰度和 4bpp 灰度。有什么好的链接或其他建议吗?

最好使用 Windows/GDI+

[编辑] 速度比质量更重要。源图片是截图 [EDIT1] 需要颜色转换以最小化空间

最佳答案

您最好像其他人所建议的那样,给自己建一个图书馆。除了 ImageMagick,还有其他的,例如 OpenCV .将其留给图书馆的好处是:

  • 为自己节省一些时间 - 通过减少算法的开发和测试时间
  • 速度。大多数库都经过优化,达到了标准开发人员(例如我们自己)无法达到的水平。
  • 符合标准。有许 multimap 像格式,使用库可以解决标准合规性问题。

如果你自己做,那么你的问题可以分为以下子问题:

  1. 简单 color quantization .正如@Alf P. Steinbach 指出的那样,这只是“缩小”了颜色的数量。 RGB24 每个 R、G、B channel 有 8 位。对于 RGB16,您可以执行 a number of conversions :
    • 每个 R、G、B 的位数相同。这通常意味着每个 4 或 5 位。
    • 偏爱绿色 channel (人眼对绿色更敏感)并给它 6 位。 R 和 B 得到 5 位。
    • 您甚至可以对 RGB24 到 RGB8 执行相同的操作,但结果不会像托盘化图像那样漂亮:
    • 4 位绿色、2 位红色、2 位蓝色。
    • 3 位绿色,5 位介于红色和蓝色之间
  2. 码垛(indexed color)。这是为了从 RGB24 到 RGB8 和 RGB4。这是一个很难自己解决的问题。
  3. 颜色到灰度的转换。 非常简单。将 RGB24 转换为 YUV' 色彩空间,并保留 Y' channel 。这将为您提供 8bpp 灰度。如果您想要 4bpp 灰度,那么您要么量化,要么进行托盘化。
  4. 另请务必查看 chroma subsampling .通常,您可以将比特率降低三分之一而不会对图像质量造成明显的损失。

通过这种分解,您可以分而治之。您可以很快解决问题 1 和 2。这将使您能够看到只需进行更粗略的颜色量化即可获得的质量。

是否要解决问题 2 将取决于上面的结果。你说速度更重要,所以如果颜色量化的质量足够好,就不要理会码垛。

最后,您从未提及您这样做的原因。如果这是为了减少存储空间,那么您应该查看 image compression .与单独降低颜色深度相比,即使是无损压缩也会给您带来更好的效果。

编辑

如果您决定使用 PNG 作为最终格式,那么您的选择是 quite limited ,因为 RGB16 和 RGB8 都不是 PNG header 中的有效组合.

所以这意味着:无论位深度如何,如果您想要 RGB 彩色图像低于 24bpp(每 channel 8 位),您将必须切换到索引颜色。这意味着您将能够利用我上面提到的颜色量化和色度抽取——它在 PNG 中不受支持。所以这意味着您将必须解决问题 2 -- 码垛。

但在你考虑之前,还有一些问题:

  • 图片的尺寸是多少?
  • 您想要什么样的理想文件大小?
  • 使用直接 RBG24 + PNG 压缩与理想文件大小有多接近?
  • 您的图像来源是什么?您提到了屏幕截图,但由于您非常关心磁盘空间,我开始怀疑您可能正在处理图像序列(视频)。如果是这样,那么您可以比 PNG 压缩做得更好。

    哦,如果你真的想用 PNG 做事,那么一定要看看 this library .

关于c++ - 图像颜色转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4928276/

相关文章:

php - 添加黑条以创建 16x9 图像

c++ - 可选成员对象

c++ - 如何自动更新状态栏消息?

c++ - MongoDB 2.4 C++ 驱动程序 - 对 `SSL_CTX_use_certificate_chain_file' 的 undefined reference

c++ - 在没有分配和内存复制的情况下从数组中创建 vector

c++ - 使用 SCSI 传递的 ioctrl

c - 如何使用命令提示符运行 .exe 文件?

opencv - SVM代码的学习

c - 使用指针的字符串

image-processing - 提高 OpenCL 图像处理速度