VS2010 资源文件中的 PNG 图像在 XP 上使用 GDI 执行奇怪的操作

发布于 2024-11-17 15:23:33 字数 1015 浏览 3 评论 0原文

我在 VS2010 项目中使用了几个 32 位 PNG 文件,并使用 LoadResource/LockResource 等将它们加载到 GDI+ 位图中,并从 IStream 创建。在我的 Win7 开发机器上一切运行良好。

但是,我正在使用 SetColorMatrix/ImageAttributes 进行一些颜色和 alpha 掩码,这在 Win7 上运行良好,但是当我在 XP 上运行它并使用 ImageAttributes 参数调用 Bitmap::DrawImage 时,根本不会绘制 PNG。在任何时候似乎都没有任何错误表明存在问题,只是不可见。

如果我使用直接从文件而不是从资源加载的图像运行相同的代码,它在 XP 和 Win7 上运行良好,但我真的不想在我的安装程序中捆绑 PNG 文件 - 这似乎有点麻烦。为了让生活变得更精彩,我的 XP 机器太慢了,甚至无法考虑运行 VS2010!

有没有人有任何想法可能导致此问题,或建议跟踪问题,因为我在这方面花了很长时间,但我没有灵感。

提前致谢。

更新:

经过加载更多测试后,我还没有完全了解这一点,但有强有力的证据表明,使用 Bitmap(IStream*) 构造函数会以某种方式破坏 PNG 上的透明度通道。我还没有弄清楚究竟发生了什么,但我找到了一个解决方案 - 我现在使用 FreeImage 从资源文件加载 PNG,然后从 FIBITMAP 中的原始图像数据创建 Bitmap 对象。这是完美的,所以证据表明 Bitmap 构造函数存在问题。

更新 2:

我创建的用于使用 FreeImage 从资源加载 PNG 文件的类效果很好,因此为了方便起见,我决定使用它来加载所有图像,但在加载标准 BMP 文件时遇到问题。经过一番调查后,似乎当您将 BMP 文件作为 BITMAP 资源包含时,BMP 文件的前 14 个字节在存储到资源包中之前会被删除,这使得其他任何东西都很难加载它们。无论如何,它很容易解决 - 我只是将“BITMAP”资源的资源类型更改为“BMP”,因此它基本上将其视为未知类型并存储整个文件。所以现在一切都按预期进行。只是想我会发布这个经历,并希望如果其他人尝试做同样的事情,可以节省一个小时。

I'm using several 32 bit PNG files in my VS2010 project and loading them into GDI+ bitmaps using LoadResource/LockResource etc. and creating from an IStream. All is working fine and dandy on my Win7 development machine.

However, I'm doing some colour and alpha masking using SetColorMatrix/ImageAttributes which works fine on Win7, but when I run it on XP and call Bitmap::DrawImage with an ImageAttributes parameter, the PNG isn't drawn at all. There don't appear to be any errors at any point to suggest a problem, it just isn't visible.

If I run the same code with the image loaded directly from file instead of from a resource, it works fine on XP and Win7, but I don't really want to bundle PNG files in my installer - it seems a bit of a bodge. To make life that bit more exciting, my XP machine is too slow to even contemplate running VS2010!

Has anyone got any ideas what could be causing this, or suggestions as to track the problem down because I've spent a long time on this and I'm out of inspiration.

Thanks in advance.

Update :

After a load more testing I haven't entirely got to the bottom of this, but there's strong evidence to suggest that using the Bitmap(IStream*) constructor is somehow mangling the alpha channel on PNGs with transparency. I haven't figured out exactly what's going on, but I have found a solution - I'm now using FreeImage to load the PNG from the resource file, then creating the Bitmap object from the raw image data in the FIBITMAP. This is working perfectly, so the evidence is pointing to a problem with that Bitmap constructor.

Update 2 :

The class I created to use FreeImage to load the PNG files from resources works great so for convenience I decided to use it to load all my images but it was having trouble loading standard BMP files. After a bit of investigating, it seems that when you include BMP files as BITMAP resources, the first 14 bytes of the BMP file are stripped before they're stored in the resource bundle, which makes it tricky for anything else to load them. Anyway, it's easily worked around - I just changed the resource type of the "BITMAP" resources to "BMP" so it basically treats it as an unknown type and stores the whole file. So now it's all working as intended. Just thought I'd post the experience and hopefully save someone else an hour if they try to do the same thing.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

凉月流沐 2024-11-24 15:23:33

放一堆trace语句并在XP上运行,一定会在某个地方返回一些错误代码。尽量不要使用 MFC 包装类并调用原始的底层 win32 API。我与 CImage 和朋友们有过不好的经历;我所做的是将 png 转换为 32 位位图(bmp),使用 ::LoadImage() 加载它们并使用 ::AlphaBlt() 绘制它们。

另外,尝试使用不透明的 png - 我遇到的所有问题都与具有每像素透明度的图像有关。如果这有效,你至少知道从哪个方向开始寻找。

Put a bunch of trace statements and run on XP, there must be some error code returned somewhere. Try to not use the MFC wrapper classes and calling the raw underlying win32 API. I've had bad experiences with CImage and friends; what I do is convert png's to 32-bit bitmaps (bmp's), load those with ::LoadImage() and use ::AlphaBlt() to draw them.

Also, try with a png without transparency - all problems I had were with images with per-pixel transparency. If that works, you at least know in what direction to start looking.

疑心病 2024-11-24 15:23:33

所以我最终自己找到了答案(只是更新这个以便我可以将其标记为已回答)。

在某些情况下,PNG 中似乎存在与 GDI+ 和透明度相关的某种错误。我使用 FreeImage 加载 PNG 解决了这个问题,但这导致了 BMP 的另一个问题。 VS 中的 BITMAP 资源似乎被剥夺了 14 个字节,大概是因为如果您已经告诉 VS 这是一个位图,那么这就是冗余信息。如果您随后使用 LoadImage() 或任何标准 WinAPI 函数加载资源,这通常没问题,但如果您使用另一个库(就像我使用 FreeImage 一样),那么您需要将资源类型更改为 IMAGE(或不是 BITMAP 的类型) ),然后再尝试使用 LoadResource 加载它。

So I found the answer myself in the end (just updating this so that I can mark it as answered).

There appears to be some sort of bug related to GDI+ and transparency in PNGs in some situations. I got around this using FreeImage to load the PNGs, but this caused another problem with BMPs. It seems that BITMAP resources in VS get 14 bytes stripped off them, presumably as this is redundant information if you've already told VS it's a bitmap. This is normally fine if you then load the resource with LoadImage() or any standard WinAPI function, but if you use another library (as I was with FreeImage), then you need to change the resource type to IMAGE (or something that's not BITMAP) before you try and load it using LoadResource.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文