GDI+ does a very poor job of rendering to an 8bit grayscale DIBSection

Louis Solomon / SteelBytes
21/Dec/05

Problem & Method

Take an 8bit grayscale BMP. Load it with GDI+ using GdipCreateBitmapFromStream(stream,&image) (I use the Flat API methods of GDI+). Create an 8bit grayscale DIBSection. Render the GDI+ Bitmap to this DIBSection using GdipCreateFromHDC(mydibsection.hdc,&graphicsobj); GdipDrawImageRectI(graphicsobj,&image,...);

Results

The resultant image is slightly wrong ... white is not white any more! In the following picture, the above senario is the lower left image, and white which should be palindex(255)=rgb(255,255,255) is instead palindex(252)=rgb(252,252,252). So what are the rest of the images? They are testing other related senarios:
Rows
24bit BMP into 24bit DIB Section
24bit BMP into 8bit DIB Section
8bit BMP into 8bit DIB Section
8bit BMP into 8bit DIB Section
Columns
GDI+ and InterpolationModeHighQualityBicubic
GDI+ and InterpolationModeNearestNeighbor
OleLoadPicture and COLORONCOLOR
OleLoadPicture and HALFTONE
my raw BMP reader and tructation during 24->8
my raw BMP reader and rounding during 24->8
Note: system was running in 32bit screen depth ... this does affect OleLoadPicture!

Solution / Workaround

Use GdipBitmapLockBits() to get raw data, and do your own 24->8bit conversion.
Note: GDI+ seems to be converting the 8bit grayscale to an internal 24bit representation, and the problem is in it's 24bit to 8bit conversion routines.