Skip to main content
 首页 » 编程设计

c#之如何将 System.Drawing.Bitmap 覆盖到现有的 GDI 位图上

2024年01月25日33birdshome

如果我有 .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 指向锁定位图像素数据的开始(即它不' t 指向位图的 header ,也就是位图本身的开始)。

我很确定解决方案看起来像这样:

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+ 格式)的位图。

请您参考如下方法:

我想您已经回答了您自己的问题:使用 LockBits。

见 How to: Use LockBits 和 Bob Powell - Locking Bits .

我使用这种方法在我编写的 .NET(1.1!)程序中快速绘制分形是为了好玩。在我试验过的所有方法中,这是迄今为止最快的。