我该如何使用LoadImage和StretchDIBits绘制PNG图像?

4

(这与问题如何在Win32/GDI中使用PNG图像(尽可能不使用GDI+)加载PNG图像有关。

大家好,

我想知道,假设你有一个嵌入二进制文件中的PNG资源,其ID为IDB_PNG1,并且有一个LPDRAWITEMSTRUCT用于绘制(这意味着你有HDC和目标矩形),那么如何使用StretchDIBits将该图像绘制到屏幕上?我之前使用过BitBltTransparentBlt,但是StretchDIBits似乎工作方式不同,并且LoadImage不能使用PNG。

谢谢!

(注意:我提供的语言是C++,但这并不太重要... C、C#、Visual Basic等都可以;我只是想弄清楚步骤,而不是所需的确切代码。)


如果您可以将资源保存为PNG格式的图标,那么您能以这种方式加载它吗? - Gabe
2个回答

9
我写了一篇关于使用C++显示启动画面的博客文章,其中包含一个完整的代码示例,该示例从资源中加载PNG并将其转换为HBITMAP(使用WIC)。然后,您可以使用CreateCompatibleDC、SelectObject和BitBlt在目标HDC中显示它。
虽然我从未尝试过,但是如果您将资源中的原始字节加载到内存中,并设置一个BITMAPINFOHEADER结构体,其中包括宽度、高度等信息,如此MSDN示例所示,那么您应该能够使用StretchDIBits直接显示PNG。
由于C#和VB.NET解决方案使用System.Drawing(GDI+的包装器)或System.Windows.Media.Imaging(在WPF应用程序中)来处理图像加载和绘制,因此可能会有所不同。

1
这非常有趣,似乎正是我正在寻找的。关于尝试设置BITMAPINFOHEADER的问题:我如何知道图像的尺寸?我还是必须使用WIC吗?(编辑:看起来这行不通;请参见我在Greg帖子上的评论。但非常感谢您提供博客文章的链接,它肯定会有所帮助...我希望我可以将两个帖子标记为答案。 :) ) - user541686
1
要知道图像的尺寸,您可以编写一个PNG解码器(或使用libpng或WIC)来从PNG文件中读取它们,或将它们存储为单独的资源,该资源与您的PNG资源保持同步。(这也是我从未尝试StretchDIBits方法的部分原因;我一直使用libpng或WIC来处理所有的PNG读取。) - Bradley Grainger

1

我认为位图中的PNG支持只是供打印机驱动程序使用。对于屏幕显示,您可能需要使用一些代码(例如libpng)自行解压PNG数据。


哦...我肯定没有想到这个。显示器和打印机之间有什么区别会导致这种情况呢? - user541686
1
打印机通常(至少在历史上)比显示适配器拥有更多的功能。打印机还可以通过较低的带宽连接,所以在发送数据到打印机时节省位元很重要(最好给具有解码能力的打印机发送压缩的PNG文件,而不是发送所有原始位元)。这也允许打印机在进行自身解压缩时选择最适合的保真度选项。然而,显示硬件和驱动程序通常希望更加确定性,并避免自行进行解压缩。 - Greg Hewgill
2
函数如何知道它是用于打印机还是显示器? - Gabe
1
该函数将您的数据传递给驱动程序。驱动程序可以将其显示出来,或者说“抱歉,不知道如何处理”。 - Greg Hewgill
@Gabe:+1,这正是我所想的! @Greg:这就是我期望的回复。 :) +1,谢谢你提供的信息,我会更深入地了解它。 - user541686
1
是的...根据MSDN的说法:“在某些版本的Microsoft Windows上,StretchDIBits和SetDIBitsToDevice函数允许将JPEG和PNG图像作为源图像传递给打印机设备。” 感谢您的回复! - user541686

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接