我正在尝试使用 BitBlt 获取图形区域并将其存储在位图中。 但在这里,我更容易理解我的问题:
Bitmap sourceBitmap = new Bitmap(64, 64, PixelFormat.Format32bppRgb);
Graphics sourceGraphics = Graphics.FromImage(sourceBitmap);
Bitmap destBitmap = new Bitmap(64, 64, PixelFormat.Format32bppRgb);
Graphics destGraphics = Graphics.FromImage(destBitmap);
sourceGraphics.FillRectangle(new SolidBrush(Color.Red), new Rectangle(0, 0, 30, 30));
sourceGraphics.FillRectangle(new SolidBrush(Color.Green), new Rectangle(30, 30, 30, 30));
destGraphics.FillRectangle(new SolidBrush(Color.Blue), new Rectangle(0, 0, 30, 30));
destGraphics.FillRectangle(new SolidBrush(Color.Yellow), new Rectangle(30, 30, 30, 30));
IntPtr destDC = destGraphics.GetHdc();
IntPtr destHB = destBitmap.GetHbitmap();
IntPtr old = SelectObject(destDC, destHB);
IntPtr sourceDC = sourceGraphics.GetHdc();
IntPtr sourceHB = sourceBitmap.GetHbitmap();
old = SelectObject(sourceDC, sourceHB);
int success = BitBlt(
destDC, 0, 0, 64, 64, sourceDC, 0, 0, 0x00CC0020
);
为什么在BitBlt之后我的destBitmap包含蓝色/黄色矩形(目标中的初始位图)而不是应该从源位图blit的红色/绿色矩形?
进口是这样完成的:
[System.Runtime.InteropServices.DllImportAttribute("gdi32.dll")]
private static extern int BitBlt(
IntPtr hdcDest, // handle to destination DC (device context)
int nXDest, // x-coord of destination upper-left corner
int nYDest, // y-coord of destination upper-left corner
int nWidth, // width of destination rectangle
int nHeight, // height of destination rectangle
IntPtr hdcSrc, // handle to source DC
int nXSrc, // x-coordinate of source upper-left corner
int nYSrc, // y-coordinate of source upper-left corner
System.Int32 dwRop // raster operation code
);
[System.Runtime.InteropServices.DllImportAttribute("gdi32.dll")]
public static extern IntPtr SelectObject(IntPtr hdc, IntPtr obj);
[System.Runtime.InteropServices.DllImportAttribute("gdi32.dll")]
public static extern void DeleteObject(IntPtr obj);
最后清理代码和位图流以查看位图内容:
DeleteObject(destHB);
DeleteObject(sourceHB);
destGraphics.ReleaseHdc();
sourceGraphics.ReleaseHdc();
string path = "c:/tmp/dest.png";
destBitmap.Save(path);
答案 0 :(得分:1)
找到一个有效的组合......但我不明白为什么(绝对不是GDI专家):
我添加了使用CreateCompatibleDC()创建兼容DC的调用。
但是请注意,在对BitBlt()的实际调用中,我仍然使用原始DC“destDC”作为目标DC(而不是新的“destCDC”),但新的兼容DC“sourceCDC”为源DC。似乎没有其他组合工作。我仍然,然而,必须为目的地创建一个兼容的DC,即使我没有在BitBlt()调用中使用它:
private const int SRCCOPY = 0xCC0020;
[System.Runtime.InteropServices.DllImportAttribute("gdi32.dll")]
private static extern int BitBlt(
IntPtr hdcDest, // handle to destination DC (device context)
int nXDest, // x-coord of destination upper-left corner
int nYDest, // y-coord of destination upper-left corner
int nWidth, // width of destination rectangle
int nHeight, // height of destination rectangle
IntPtr hdcSrc, // handle to source DC
int nXSrc, // x-coordinate of source upper-left corner
int nYSrc, // y-coordinate of source upper-left corner
int dwRop // raster operation code
);
[System.Runtime.InteropServices.DllImportAttribute("gdi32.dll")]
public static extern IntPtr CreateCompatibleDC(IntPtr hdc);
[System.Runtime.InteropServices.DllImportAttribute("gdi32.dll")]
public static extern IntPtr SelectObject(IntPtr hdc, IntPtr obj);
[System.Runtime.InteropServices.DllImportAttribute("gdi32.dll")]
public static extern void DeleteObject(IntPtr obj);
private void button1_Click(object sender, EventArgs e)
{
Bitmap sourceBitmap = new Bitmap(64, 64, PixelFormat.Format32bppRgb);
Graphics sourceGraphics = Graphics.FromImage(sourceBitmap);
Bitmap destBitmap = new Bitmap(64, 64, PixelFormat.Format32bppRgb);
Graphics destGraphics = Graphics.FromImage(destBitmap);
sourceGraphics.FillRectangle(new SolidBrush(Color.Red), new Rectangle(0, 0, 30, 30));
sourceGraphics.FillRectangle(new SolidBrush(Color.Green), new Rectangle(30, 30, 30, 30));
destGraphics.FillRectangle(new SolidBrush(Color.Blue), new Rectangle(0, 0, 30, 30));
destGraphics.FillRectangle(new SolidBrush(Color.Yellow), new Rectangle(30, 30, 30, 30));
IntPtr destDC = destGraphics.GetHdc();
IntPtr destCDC = CreateCompatibleDC(destDC);
IntPtr destHB = destBitmap.GetHbitmap();
IntPtr oldDest = SelectObject(destCDC, destHB);
IntPtr sourceDC = sourceGraphics.GetHdc();
IntPtr sourceCDC = CreateCompatibleDC(sourceDC);
IntPtr sourceHB = sourceBitmap.GetHbitmap();
IntPtr oldSource = SelectObject(sourceCDC, sourceHB);
int success = BitBlt(
destDC, 0, 0, 64, 64, sourceCDC, 0, 0, SRCCOPY
);
SelectObject(destCDC, oldDest);
SelectObject(sourceCDC, oldSource);
DeleteObject(destCDC);
DeleteObject(sourceCDC);
DeleteObject(destHB);
DeleteObject(sourceHB);
destGraphics.ReleaseHdc();
sourceGraphics.ReleaseHdc();
pictureBox1.Image = sourceBitmap;
pictureBox2.Image = destBitmap;
}
任何人都知道为什么这个组合有效?...