I'm using this code to capture the screen:
public Bitmap CaptureWindow(IntPtr handle)
{
// get te hDC of the target window
IntPtr hdcSrc = User32.GetWindowDC(handle);
// get the size
User32.RECT windowRect = new User32.RECT();
User32.GetWindowRect(handle, ref windowRect);
int width = windowRect.right - windowRect.left;
int height = windowRect.bottom - windowRect.top;
// create a device context we can copy to
IntPtr hdcDest = GDI32.CreateCompatibleDC(hdcSrc);
// create a bitmap we can copy it to,
// using GetDeviceCaps to get the width/height
IntPtr hBitmap = GDI32.CreateCompatibleBitmap(hdcSrc, width, height);
// select the bitmap object
IntPtr hOld = GDI32.SelectObject(hdcDest, hBitmap);
// bitblt over
GDI32.BitBlt(hdcDest, 0, 0, width, height, hdcSrc, 0, 0, GDI32.SRCCOPY);
// restore selection
GDI32.SelectObject(hdcDest, hOld);
// clean up
GDI32.DeleteDC(hdcDest);
User32.ReleaseDC(handle, hdcSrc);
// get a .NET image object for it
Bitmap img = Image.FromHbitmap(hBitmap);
// free up the Bitmap object
GDI32.DeleteObject(hBitmap);
return img;
}
I then want to convert the bitmap to 256 colors (8 bit). I tried this code but get an error about not being able to create an Image from an indexed bitmap format:
Bitmap img8bit = new Bitmap(img.Width,img.Height,
System.Drawing.Imaging.PixelFormat.Format8bppIndexed);
Graphics g = Graphics.FromImage(img8bit);
g.DrawImage(img,new Point(0,0));
I did see some examples to convert bitmaps between different formats, but in my case I'm looking for the best way to do this while capturing from the screen. For example, if there is a method that will work better by creating an 8-bit bitmap to begin with and then blit the screen to that, that would be preferred over caputring screen to comptible bitmap first and then converting it. Unless it's better to capture then convert anyway.
I have a program written in C++ using Borland Builder 6.0 VCL, and I'm trying to memic that. In that case it is a simple matter of setting the pixel format for VCL's TBitmap object. I notice Bitmap.PixelFormat is read-only in .NET, ugh.
Update: In my case I don't think the answer is as complex as some other usage that requires figuring out the best palette entries, because Graphics.GetHalftonePalette using the screen DC should be fine, since my original bitmap comes from the screen, not just any random bitmap that might come from a file/email/download/etc. I beleive there is something that can be done with maybe 20 lines of code that involves DIBs and GetHalftonePalette -- just can't find it yet.