如果我有.Net Bitmap
,我可以通过调用Bitmap
的{{1}}方法从中创建一个GDI位图。
GetHbitmap()
这很好用,但每次调用Bitmap bmp = new Bitmap(100, 100);
IntPtr gdiBmp = bmp.GetHbitmap();
时,Windows都必须分配返回的GetHbitmap
引用的新内存。
我想做的 - 如果可能的话 - 写一个函数(我知道这里需要PInvoke),它还生成一个IntPtr
的GDI位图副本,但是会覆盖现有的一块内存已经从Bitmap
返回的IntPtr
引用,而不是分配新内存。所以它看起来像这样(如果它是GetHbitmap
的扩展方法):
Bitmap
我该怎么做?我假设我需要知道GDI位图的结构,可能我可以使用// 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
和LockBits
,但我不确定如何。
赏金猎人的线索:
BitmapData
有一个方法Bitmap
,它将位图锁定在内存中并返回一个LockBits
对象。 BitmapData
对象具有BitmapData
属性,该属性是Scan0
指向锁定位图的像素数据的开头(即不指向位图的header又是位图本身的开头。)
我很确定解决方案看起来像这样:
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);
(默认的GDI +格式)的位图。
答案 0 :(得分:3)
我认为您回答了自己的问题:使用LockBits。
请参阅 http://msdn.microsoft.com/en-us/library/ms229672.aspx 和 http://www.bobpowell.net/lockingbits.htm
我使用这种方法在.NET(1.1!)程序中快速绘制分形,我正在写这篇文章以获得乐趣。在我尝试的所有方法中,这是迄今为止最快的方法。
答案 1 :(得分:2)
你不应该假设HANDLE或HBITMAP是指向任何东西的指针。它可以实现为句柄表的索引,哈希表的键等等。
但是,如果调用GDI GetObject函数,则结果BITMAP structure包含指向实数位的指针。
不确定它是否会如此快(我认为在源和目标的像素格式相同的情况下),但SetDIBits应该完全符合您的要求(替换现有HBITMAP中的数据) )。
答案 2 :(得分:2)
使用Graphics.FromHdc从IntPtr创建图形,并使用Graphics.DrawImage将Bitmap粘贴到其中。