为什么我用GDI+的DrawImage在窗口画png的图,但是颜色却不正常?

代码非常简单:

hdc = BeginPaint (hwnd, &ps) ;

myGraphics = new Graphics(hdc);
image = new Image(TEXT("0.png"));
myGraphics->DrawImage( image , 0 , 0 );

EndPaint (hwnd, &ps) ;
但是输出的图片却颜色不正常。

可以看出,左边图片浏览器里的蝴蝶明显更加透亮漂亮。而右边窗口里用DrawImage画出的图片很昏暗,偏黑。
请问这是为什么?难道是我的png的问题不够标准?
这是png的下载:http://pan.baidu.com/s/1o6I0G4q
PS:我可以肯定,左边那个透亮的蝴蝶颜色是正常的

(第一次回答问题,希望能拿到分)

PNG的透明效果是通过Alpha混合实现的,通常情况下,Alpha混合使用下面的计算公式:

    Dest = Src * (Alpha/255) + Dest * (1-Alpha/255) 【公式1】

变量说明:

    Dest    目标像素的RGB值

    Src      源像素的RGB值,在这里PNG就是源

    Alpha  源像素的Alpha通道值

在Windows编程中,使用函数AlphaBlend实现Alpha混合,但是该函数的Alpha混合公式为:

    Dest = Src + Dest * (1-Alpha/255) 【公式2】

    (注:实际情况要稍微复杂一点,公式2只是其中一个特例,但也是最常用的一个特例。完整的计算公式参见MSDN中AlphaBlend的帮助)

公式2中,源没有乘以Alpha值,而是直接叠加至目标,显示效果会比公式1亮一些。


因此结论就出来了:

    暗一些的蝴蝶使用了公式1


    亮一些的蝴蝶使用了公式2(AlphaBlend函数)。下图是调用AlphaBlend的效果:



由于AlphaBlend的特立独行,为了实现与大多数软件一致的显示效果,我在使用AlphaBlend前,都要使用工具软件将PNG中透明背景像素的颜色值变成黑色(0),否则透明背景会显示出来。

追问

原来如此!真是一语惊醒梦中人啊!我考虑过了各种情况,但万万没想到居然是Alpha混合方式不同造成的。果然是学的不扎实啊。
对了,那请问我该如何打开那张png并将其绘制到hdc?(因为我只学过SDK。而SDK下的GDI不支持PNG,所以我想到了用GDI+,但用GDI+的话颜色又不对)我现在是把png转成32位的bmp,然后用AlphaBlend来显示PS:追问居然限制字数。打了一大段只能狂删,好蛋疼

追答

我的实现方法就是你提到的:先将PNG转换成32位BMP,然后调用AlphaBlend显示。
PS:为啥没有采纳我的答案呢?我觉得我说的才是正解啊。

追问

不不不,你误会了啦。毫无疑问我肯定会采纳你的答案的,毕竟你解决了困扰我很久的问题,我真的很感谢你。我只是想在你回答我的追问之后再采纳,主要在想是不是除了转为bmp还有其他方法能正常显示。 既然你是和我一样转为bmp那就没关系了。答案肯定是采纳你的,总是真的是非常感谢!

追答

我是使用开源库libpng在内存中转为32位BMP的,不知你是如何转换的?

温馨提示:答案为网友推荐,仅供参考
第1个回答  2014-02-04
一般我们都是先创建一个 Bitmap bmp;
用 Graphics 把 bmp 清空为纯白色或其他色
再把需要画的东西全部都画到 bmp 上
最后把 bmp 画到控件上追问

这是双缓冲吧。和我说的颜色不正常没关系……甚至我就算通过CreateCompatibleDC创建个hdcMem,然后用Graphics在上面画也同样颜色不正常。

追答

之前网页没显示你的问题中的图片,现在终于可以看到了
那么你再研究研究,如果图片有透明度的话,会和背景相溶,多次重绘不清除原图从头绘制,就会层层叠加,看图片,似乎没有拉伸。要么图片参数有设置地方没设置好,要么就是无清除原图重绘了多次同一图片,我只能这么猜了

追问

刚刚我在每次绘图之前都加了个 myGraphics->Clear(Color( 0 , 255 , 255 , 255));
结果还是上图一样问题。
估计应该和绘图的算法无关了。
有可能是Windows的API或者颜色相关的问题。因为我发现如果用windows自带的照片查看器打开那张图的话,显示的颜色和我上面右边的图一样,也是偏暗的。

追答

哦,那就表示没有问题
你换个其他PNG图片试试

追问

不过我确定左边那个效果是正确的颜色。因为这张图是我从游戏里提取出来的,而游戏中的效果就是左边的效果。难道是调色板或icc的问题OTL

追答

默认的话,一般不需要设置的啊
玩C#多了,C++ GDIPlus也有点忘记了
都是GDIPlus啊,记得以前绘图都不需要设置什么,都是以100%原图原质量画出显示的,不用设置什么
你用浏览器看看或C#绘制看看

追问

虽然没有学过C#,但摸了几下拖了图片控件把图片显示出来了。(难怪C#流行,某些方面的确真心挺好用的)


效果还是不正常,放浏览器里也是。最让我感到囧的是,为什么偏偏只有Visual Studio 自带的资源浏览器能正常显示(好蛋疼)。

追答

很多图片查看软件都是显示图片都是灰暗那个,多数都“不正常”,只有一个“正常”

那么初步看,按照常规显示该图片,应该就是灰暗的
至于Resource Editor 为什么显示的偏亮,需要研究下

相似回答