【发布时间】:2011-02-07 17:25:11
【问题描述】:
如果我有一个.Net Bitmap,我可以通过调用Bitmap 的GetHbitmap() 方法从它创建一个GDI 位图。
Bitmap bmp = new Bitmap(100, 100);
IntPtr gdiBmp = bmp.GetHbitmap();
这很好用,但是每次调用GetHbitmap 时,Windows 都必须分配返回的IntPtr 引用的新内存。
如果可能的话,我想做的是编写一个函数(我知道这里需要 PInvoke),它还会生成 Bitmap 的 GDI 位图副本,但这会覆盖已经引用的现有内存块通过从GetHbitmap 返回的IntPtr,而不是分配新内存。所以它看起来像这样(如果它是Bitmap 的扩展方法):
// desired method signature:
void OverwriteHbitmap(IntPtr gdi)
{
}
// ex:
Bitmap bmp1 = new Bitmap(100, 100);
IntPtr gdi1 = bmp1.GetHbitmap();
Bitmap bmp2 = new Bitmap(100, 100);
bmp2.OverwriteHbitmap(gdi1); // gdi1 is still pointing to the same block
// of memory, which now contains the pixel data from bmp2
我该怎么做?我假设我需要知道 GDI 位图的结构,并且可能我可以使用 LockBits 和 BitmapData,但我不确定具体如何。
赏金猎人的线索:
Bitmap 有一个方法LockBits 将位图锁定在内存中并返回一个BitmapData 对象。 BitmapData 对象有一个 Scan0 属性,它是一个 IntPtr 指向锁定位图像素数据的开始(即它不指向位图的标题,也就是位图本身)。
我很确定解决方案看起来像这样:
Bitmap bmp1 = new Bitmap(100, 100);
IntPtr gdi1 = bmp1.GetHbitmap(); // now we have a pointer to a
// 100x100 GDI bitmap
Bitmap bmp2 = new Bitmap(100, 100);
BitmapData data = bmp2.LockBits();
IntPtr gdi1Data = gdi1 + 68; // magic number = whatever the size
// of a GDI bitmap header is
CopyMemory(data.Scan0, gdi1Data, 40000);
解决方案不必是通用的 - 它只需要适用于像素格式 Format32bppArgb(默认 GDI+ 格式)的位图。
【问题讨论】:
-
到底谁会否决这个问题?