C++ GDI无法转换为具有精确调色板的索引颜色? 总结

C++ GDI无法转换为具有精确调色板的索引颜色? 总结,c++,winapi,gdi,C++,Winapi,Gdi,使用Windows GDI将24位颜色转换为索引颜色,GDI似乎选择了“足够接近”的颜色,即使所提供的调色板中存在完全匹配的颜色 有人能确认这是GDI问题吗?或者我在什么地方犯了错误 也许有一个“请检查整个调色板的颜色匹配”的标志,我没有找到 注意:这与量化无关。源是24位的,但包含256种或更少的颜色,因此精确的调色板计算起来很简单。问题是GDI没有使用完整的调色板 变通办法 我自己通过映射颜色解决了这个问题,但我更喜欢使用GDI,因为它应该得到更好的优化。问题是,它似乎“快速但错误” 详细说

使用Windows GDI将24位颜色转换为索引颜色,GDI似乎选择了“足够接近”的颜色,即使所提供的调色板中存在完全匹配的颜色

有人能确认这是GDI问题吗?或者我在什么地方犯了错误

也许有一个“请检查整个调色板的颜色匹配”的标志,我没有找到

注意:这与量化无关。源是24位的,但包含256种或更少的颜色,因此精确的调色板计算起来很简单。问题是GDI没有使用完整的调色板

变通办法 我自己通过映射颜色解决了这个问题,但我更喜欢使用GDI,因为它应该得到更好的优化。问题是,它似乎“快速但错误”

详细说明 我的源图像为24位,但使用256色(或更少)。我为它生成一个精确的调色板,并要求GDI使用该调色板将图像转换为索引位图。对于某些像素,GDI选择相似但不精确的颜色,即使调色板中其他地方有精确的颜色。这会破坏平滑的渐变

此问题发生在:

  • SetDIBitsToDevice
  • 担架障碍物
  • 比特比特
  • 担架
以下情况下不会出现问题:

  • 循环中的SetPixel或SetPixelV(非常慢!)
  • 使用我自己的代码进行映射
我已经在以下方面进行了测试:

  • Windows 7(NVidia硬件/驱动程序)
  • Windows Vista(ATI硬件/驱动程序)
  • Windows 2000(VMware硬件/驱动程序)
每次测试我都得到相同的结果。(不仅是错误的颜色,而且总是相同的错误颜色。)

我不认为问题在于颜色管理(ICM/ICC配置文件/等等),因为大多数API都说他们不使用它,我已经尝试在GDI DC上以及通过V5位图头显式关闭它,我认为它不会应用于我的vanlilla-Win2k VM

测试项目 简单Win32/GDI/VS2008测试项目的代码可在以下位置找到:

Win32UI.cpp中的Test1函数是实际的测试。它有两个RGBquad数组,一个是源图像,另一个是它的精确调色板。它验证调色板是否准确,然后要求GDI使用上述API转换图像,每次都测试结果。对于每个测试,它会告诉你第一个不正确的像素的前后颜色,或告诉你,所有像素都是正确的,如果它工作

谢谢 谢谢你阅读我的问题!抱歉,如果这是我做了一些非常愚蠢的事情的结果!:-)

你在用什么?似乎暗示,在绘制DIB时,仅调用SelectPalette()是不够的,但还需要调用SetDIBColorTable()来设置DIB的调色板:

但是,如果应用程序正在使用 在DIB部分中,您可以创建逻辑 DIB颜色表中的调色板 通常,然后也通过DIB DIB部分的颜色表,带有 调用SetDIBColorTable()。尽管 什么是“平台SDK”文档 RealizePalette()的, RealizePalette()不调整 DIB部分的颜色表


这篇文章包含了一些有关绘制调色板DIB的更多信息,这些信息可能是相关的(请参阅“调色板和DIB部分”一节)。

我模糊地记得,在将调色板选择到DC中之后,您还需要调用
realizepalete(hdc)
。我们很久以前就抛弃了调色板代码,以至于代码不再出现在源代码树中。我从你的代码中看到,你已经尝试过了,但我建议你可能还想再玩一次

我记得调色板代码非常脆弱,我们尽快停止使用它

一些旧的AVI文件将有8位调色板视频,其中嵌入调色板,因此这些文件的播放代码需要加载调色板。我记得realize没有做任何事情,除非你是前台应用,但这应该只适用于屏幕DC,而不是内存DC

如果您搜索可以播放调色板AVI的示例源代码,您可能会找到一些显示使调色板工作的神奇公式的东西


对不起,我帮不上忙了

我遇到了完全相同的问题,最终联系了微软并向他们提供了一个测试用例。在测试用例中,我提供了一个24位DIB中有128种颜色的渐变图像,然后我将其转换为8位DIB,该DIB是使用包含24位图像中所有128种颜色的颜色表创建的。转换后,8位图像仅使用了128种颜色中的65种

总结他们的反应:
这不是一个bug,GDI在向下转换图像的颜色深度时使用了足够接近的计算。这在任何地方都没有记录,确保所有原始颜色准确转换的唯一方法是自己手动操作像素。

在选择DIB后,我尝试在目标DC上设置DIBColorTable,但结果相同。还尝试将SelectPalette调用移动到DIB选择之后,并在两个位置的SelectPalette之后添加回RealizePalette调用,但没有成功。我已经更新了示例代码,以包含SetDIBColorTable调用FWIW。(先前版本的代码移到了GdiIndexColor_old.zip)谢谢您的回复!我会尝试任何想法。+1的答案似乎是正确的。这个问题已经问了将近一年了,但它可能在将来仍然会对某人有所帮助。谢谢里斯!令人失望的是发现事情就是这样,但很高兴知道我没有做错什么。