How to convert an indexed GDI 8-bpp raster file to an RGB bitmap?

I am trying to convert a bitmap with an index of 8 bits to an RGB bitmap, but I did not succeed.

The first problem is that the palette returned by GetPalette() does not contain 256 unique numbers.

This is my code:

 BitmapData bitmapData; int paletteSize =b->GetPaletteSize(); ColorPalette colorPalette; b->GetPalette(&colorPalette,paletteSize/4); b->LockBits(new Gdiplus::Rect(0,0,b->GetWidth(),b->GetHeight()),0,b->GetPixelFormat(),&bitmapData); char* scan0 = (char*)bitmapData.Scan0; width = b->GetWidth(); height = b->GetHeight(); stride = bitmapData.Width*4; pBitmapData = new char[stride*height]; DWORD B = 0x00FF0000; DWORD G =0x0000FF00; DWORD R = 0x000000FF; int currentIndex=0; for(int i = 0 ; i < height; i++) { for(int j =0 ; j < width; j++) { std::stringstream ss; currentIndex = i*stride+j*3; pBitmapData[currentIndex+1]= (colorPalette.Entries[scan0[i*width+j]]&&B)>>16; pBitmapData[currentIndex+2]= (colorPalette.Entries[scan0[i*width+j]]&&G)>>8; pBitmapData[currentIndex+3]= (colorPalette.Entries[scan0[i*width+j]]&&R); } } b->UnlockBits(&bitmapData); 

How can i fix this?

+4
source share
3 answers

It does not follow:

 currentIndex = i*stride+j*3; 

be:

 currentIndex = i*stride+j*4; 

considering that:

 stride = bitmapData.Width*4; 

and

 (colorPalette.Entries[scan0[i*width+j]]&&B)>>16; 

it should be:

 (colorPalette.Entries[scan0[i*width+j]] & B)>>16; 

Double && means "if the left and right sides are true," single & means "bitwise and."

+1
source

Why hazel? When you use LockBits, you can use PixelFormat24bppRGB as a parameter for three LockBits, since the system copies data anyway (you never had direct access to image data in GDI +).

Here are some of the errors I found (for now):

 int paletteSize =b->GetPaletteSize(); ColorPalette colorPalette; b->GetPalette(&colorPalette,paletteSize/4); 

Why division by four? GetPaletteSize returns the size in bytes, and GetPalette expects the size in bytes. ColorPalette is a placeholder definition, one of the darkest that Microsoft developers have done with us. It only defines the first color entry!

use a byte pointer, for example:

 void *palette=new char[paletteSize]; b->GetPalette((ColorPalette *)palette,paletteSize); 

Using

 ((ColorPalette *)palette)->Entries[i] 

When you need to access the color.

Sorry, this is really as ugly as it seems when you use palettes directly. Remember to free the palette and ... ... good luck.

+1
source

It is very important that you correctly fill and align parts of the BITMAP RIFF format. The raster type of the palette type should not contain 256 entries: http://msdn.microsoft.com/en-us/library/windows/desktop/dd183376%28v=vs.85%29.aspx

"8 The bitmap has a maximum of 256 colors, and the bmiColors BITMAPINFO member contains up to 256 entries. In this case, each byte in the array represents one pixel." p>

However, it is important that if less than 256 entries remain in the palette, then the bitmap should not be indexed from the palette structure. Otherwise, the source is not formatted correctly.

You want to convert a 24 bit / s bitmap. This is slightly different from 8bpp. I advise you to open the existing 24bpp and 8bpp bitmap files in a hex editor and see how exactly the structures are aligned and what is there, and compare them with the memory layout.

+1
source

Source: https://habr.com/ru/post/1500191/


All Articles