Converting a GDI+ 24-bit RGB Bitmap to an Indexed Format Bitmap

Converting a GDI+ 24-bit RGB Bitmap to an Indexed Format Bitmap

Post by Alain M. D » Fri, 20 Jul 2007 06:25:01


Hello;

Can someone shed some light on how I can (using GDI+ and/or GDI) convert a
Bitmap whose pixel format is PixelFormat24bppRGB to a bitmap with any
variation of the PixelFormatIndexed pixel format? Note that the source
bitmap is "indexed" and converted to 24-bit RGB, then resized. No color
changes are made. Once completed, I'd like to return the bitmap to it's
original pixel format.

In theory, the source bitmap's palette should be reusable. I thought that
it would be a simple matter of iterating through the 24-bit RGB bitmap data,
one pixel at a time, attempting to locate the pixel's color in the source
bitmap's palette. The colors values to not seem to match at all. The color
palette values I see are actually in the source bitmap file. if I save the
24-bit RGB bitmap to disk, the colors that I see as bitmap pixel data (while
stepping througnb the code) are present in the saved bitmap file. The color
values in the palette and in the 24-bit RGB data seem to be incompatible.

Thanks in advance;

Alain.
 
 
 

Converting a GDI+ 24-bit RGB Bitmap to an Indexed Format Bitmap

Post by Michael Ph » Fri, 20 Jul 2007 08:35:33

I would suggest computing a new Palette using one of the many color
reduction algorithms available.
MSDN has the code for the octree quantization algorithm.

Once you have a new palette, create a new bitmap with the same width and
height of your resized image.
Use the original indexed pixel format for this new image.

Since your resized image is 24bpp, you need to translate the 3 colors in
each pixel into an index of your new color palette.
If you create a logical palette via GDI, you may use the function
GetNearestPaletteIndex to get the new index for the pixel.
You use Lockbits, to cycle through each 24bpp pixel and take the index
returned by GetNearestPaletteIndex and set the
corresponding pixel in your indexed image to this index.

.

 
 
 

Converting a GDI+ 24-bit RGB Bitmap to an Indexed Format Bitmap

Post by Grzegorz W » Fri, 20 Jul 2007 18:42:20


If you used any more advanced algorithm than "nearest neighbour" while
computing the final pixel colors in the resized image, then color
changes *are* made. Most likely your resulting image has now more colors
than the original indexed image.


It would work in case of simplest resizing algorithms. So either use
such, or you'll have to run color-reducing algorithm, then build new
palette and assemble new bitmap indexed bitmap.


--
Grzegorz Wrel
http://www.yqcomputer.com/
677265676F727940346E6575726F6E732E636F6D
 
 
 

Converting a GDI+ 24-bit RGB Bitmap to an Indexed Format Bitmap

Post by Alain M. D » Fri, 03 Aug 2007 02:47:21

ello;

Can you point me to a code sample that creates a new Gdipluss::Bitmap using
the Bitmap::FromBITMAPINFO() method?

First, I created and populated a new palette and an array of indexed pixel
data.

Then, I created a BITMAPINFO structure with the imbedded new palette (note
that the bitmap header is a v4 header). I call Bitmap::FromBITMAPINFO()
method to create the new GDI+ "indexed" Bitmap (is successful). However,
when I attempt to save the Bitmap to a file, the Bitmap::Save(WCHAR*
filename, CLSID* clsEncoder) fails; the LastErrorStatus is 7 (Win32Err);
GetLastError is 1784 (ERROR_INVALID_USER_BUFFER, The supplied user buffer is
not valid for the requested operation.).

The BITMAPINFO header is setup as follows:
ZeroMemory(lpBI, cbBI);
lpBI->bmiHeader.bV4Size = sizeof(BITMAPV4HEADER);
lpBI->bmiHeader.bV4Width = pSrcBitmap->GetWidth();
lpBI->bmiHeader.bV4Height = (pLockedBM->Stride < 0) ?
pSrcBitmap->GetHeight() : (pSrcBitmap->GetHeight() * -1);
lpBI->bmiHeader.bV4Planes = 1;
lpBI->bmiHeader.bV4BitCount = 8;
lpBI->bmiHeader.bV4V4Compression = BI_RGB;

Is a stride necessary with indexed pixel data? I currently allocate (Width
x Height) bytes for the Pixel Data array.

Thanks in advance;

Al

"Michael Phillips, Jr." < XXXX@XXXXX.COM > wrote in message
news: XXXX@XXXXX.COM ...


 
 
 

Converting a GDI+ 24-bit RGB Bitmap to an Indexed Format Bitmap

Post by Michael Ph » Thu, 09 Aug 2007 06:13:43

gt; Is a stride necessary with indexed pixel data? I currently allocate

The stride is necessary for all bitmaps regardless of bit depth.

The Windows 3.1 specification states that each scanline must be aligned on a
32 bit boundary.


Why would you want to use this method?
If you have gone to all the trouble of creating a BITMAPINFO structure for
an indexed bitmap,
then you have a memory representation that looks like this:
BITMAPV4HEADER
Color Table(i.e., palette)
DIB's bits

The easiest method of creating a gdiplus bitmap is to create a memory stream
with CreateStreamOnHGlobal
and use the stream's Write method to create the in memory DIB as follows:
1) Create, fill and write the BITMAPFILEHEADER to the stream
2) Write the BITMAPV4HEADER to the stream
3) Write the "Color Table" to the stream
4) Write the DIB's bits to the stream
5) Rewind the stream
6) Use the gdiplus static method Bitmap::FromStream



"Alain M. Dube" < XXXX@XXXXX.COM > wrote in message
news:% XXXX@XXXXX.COM ...