Is it possible to use BitBlt to copy directly out of a GDI+ bitmap without using GetHBitmap?
GetHBitmap is slow because it makes a new copy of the whole image, in addition to and slower than the BitBlt copy, and the given HBITMAP must be disposed. The image is large.
Is there a way to point BitBlt to use the pixel data of the original GDI+ image?
EDIT: I can get a pointer to where the GDI+ bitmap pixel data is in the memory. Can I create an HBITMAP that points to the GDI+ bitmap pixel data to avoid the extra copy, and BitBlt from that?
After searching for days, it suddenly hit me that the answer had been staring me in the face all the time! I was creating a GDI+ bitmap from a pointer to a byte array. Then trying to create an HBITMAP using the same pointer. But I could just as easily create the HBITMAP first and use the pointer from that to create the GDI+ bitmap.
It works like a charm! You can mix GDI and GDI+ operations however you like. The image is both plain GDI and GDI+ at once. Instead of using DrawImage, you can BitBlt from the exact same pixel data!
Here's the code:
// Create the HBITMAP BITMAPINFO binfo = new BITMAPINFO(); binfo.biSize = (uint)Marshal.SizeOf(typeof(BITMAPINFO)); binfo.biWidth = width; binfo.biHeight = height; binfo.biBitCount = (ushort)Image.GetPixelFormatSize(pixelFormat); binfo.biPlanes = 1; binfo.biCompression = 0; hDC = CreateCompatibleDC(IntPtr.Zero); IntPtr pointer; hBitmap = CreateDIBSection(hDC, ref binfo, 0, out pointer, IntPtr.Zero, 0); // Create the GDI+ bitmap using the pointer returned from CreateDIBSection gdiBitmap = new Bitmap(width, height, width * binfo.biBitCount >> 3, pixelFormat, pointer);