【发布时间】:2011-06-05 08:53:45
【问题描述】:
假设我从本机 Windows 函数中获取了 HBITMAP 对象/句柄。我可以使用 Bitmap.FromHbitmap(nativeHBitmap) 将其转换为托管位图,但如果本机图像具有透明度信息(alpha 通道),则此转换会丢失它。
关于这个问题,Stack Overflow 上有几个问题。使用这个问题的第一个答案 (How to draw ARGB bitmap using GDI+?) 中的信息,我编写了一段我尝试过的代码,它可以工作。
它基本上是通过GetObject和BITMAP结构获取原生的HBitmap宽高和指向像素数据位置的指针,然后调用托管的Bitmap构造函数:
Bitmap managedBitmap = new Bitmap(bitmapStruct.bmWidth, bitmapStruct.bmHeight,
bitmapStruct.bmWidth * 4, PixelFormat.Format32bppArgb, bitmapStruct.bmBits);
据我了解(如果我错了,请纠正我),这不会将实际像素数据从本机 HBitmap 复制到托管位图,它只是将托管位图指向本机 HBitmap 的像素数据。
而且我不会在另一个图形 (DC) 或另一个位图上绘制这里的位图,以避免不必要的内存复制,尤其是对于大型位图。
我可以简单地将这个位图分配给 PictureBox 控件或 Form BackgroundImage 属性。它工作正常,位图正确显示,使用透明度。
当我不再使用位图时,我确保 BackgroundImage 属性不再指向该位图,并且我同时处置托管位图和本机 HBitmap。
问题:你能告诉我这个推理和代码是否正确。我希望我不会得到一些意想不到的行为或错误。我希望我能正确释放所有内存和对象。
private void Example()
{
IntPtr nativeHBitmap = IntPtr.Zero;
/* Get the native HBitmap object from a Windows function here */
// Create the BITMAP structure and get info from our nativeHBitmap
NativeMethods.BITMAP bitmapStruct = new NativeMethods.BITMAP();
NativeMethods.GetObjectBitmap(nativeHBitmap, Marshal.SizeOf(bitmapStruct), ref bitmapStruct);
// Create the managed bitmap using the pointer to the pixel data of the native HBitmap
Bitmap managedBitmap = new Bitmap(
bitmapStruct.bmWidth, bitmapStruct.bmHeight, bitmapStruct.bmWidth * 4, PixelFormat.Format32bppArgb, bitmapStruct.bmBits);
// Show the bitmap
this.BackgroundImage = managedBitmap;
/* Run the program, use the image */
MessageBox.Show("running...");
// When the image is no longer needed, dispose both the managed Bitmap object and the native HBitmap
this.BackgroundImage = null;
managedBitmap.Dispose();
NativeMethods.DeleteObject(nativeHBitmap);
}
internal static class NativeMethods
{
[StructLayout(LayoutKind.Sequential)]
public struct BITMAP
{
public int bmType;
public int bmWidth;
public int bmHeight;
public int bmWidthBytes;
public ushort bmPlanes;
public ushort bmBitsPixel;
public IntPtr bmBits;
}
[DllImport("gdi32", CharSet = CharSet.Auto, EntryPoint = "GetObject")]
public static extern int GetObjectBitmap(IntPtr hObject, int nCount, ref BITMAP lpObject);
[DllImport("gdi32.dll")]
internal static extern bool DeleteObject(IntPtr hObject);
}
【问题讨论】:
-
诸如“请检查此代码,它可以在我的计算机上运行……”之类的内容确实不属于问题或主题标题。
-
你说得对,我改了标题。这是一个问题,但其中也有代码。
标签: c# bitmap gdi alpha-transparency hbitmap