+2  A: 

Use CreateDIBSection to create a 8bpp bitmap, and BitBlt onto that.


Filling in the BITMAPINFO structure is going to be the interesting. You can't use a normal BITMAPINFO struct as it only allocates space for a single palette entry and, with a 8bpp image - you will need the full 256 entries.

If you want to cheat a bit, one can use a anonymous union to declare a BITMAPINFO with enough space for its palette.

union
{
  BITMAPINFO bmi;
  struct {
    BITMAPINFOHEADER bmih;
    RGBQUAD extra[256];
  } dummy;
};

bmi.bmiHeader.biSize = sizeof (bmi.bmiHeader);
bmi.biBitCount = 8;
// and so on.

As to the values to initialize in the color table... I can't think of an easy way to get a default 8bpp palette from GDI when its not in 8bpp mode. I have a suspicion that CreateHalftonePalette isn't going to do anything on a non palette device.

Chris Becke
what about converting to 16-bit? How would that change things?
Jon
With >8 bits you don't need to bother allocating space for a color table. So ignore everything below the ---
Chris Becke
Thanks Chris that is very helpful!
Jon
+1  A: 

I'm pretty sure you'll have to capture a 32-bit bitmap, then convert that to 8-bits on your own. The 8-bit conversion will normally lose a fair amount of data, and there are quite a few different algorithms for how to do it. Unless you really have no choice about it, I'd reconsider doing this at all. It's been a long time since most people had much reason to mess with 8-bit bitmaps -- and they are a mess.

An 8-bit bitmap (at least a typical one) has a "palette", which specifies the 24-bit values of each of the (up to) 256 colors to be used in the bitmap file. Typically, you want to pick colors that are the closest to those in the original bitmap. There have been lots of algorithms invented to do this. Googling for something like "color reduction algorithm" should yield quite a few hits, with quite a few variations on how to do it, trading off execution speed, memory usage, etc. I can't even begin to guess which will be best suited to your particular purpose.

As I said up-front, my first inclination would be to put some time and effort into simply eliminating this requirement. Reducing from 32 to 24 or even 16 bits is pretty easy, and preserves a lot of the original quality. Going to 8 bits is considerably more difficult and loses a lot of quality.

Jerry Coffin