如何将GDI 8-bpp索引位图转换为RGB位图?

时间:2013-09-02 17:38:04

标签: c++ gdi

我正在尝试将8-bpp索引位图转换为RGB位图,但我还没有成功。

第一个问题是GetPalette()返回的调色板不包含256个唯一编号。

到目前为止,这是我的代码:

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); 

我该如何解决这个问题?

3 个答案:

答案 0 :(得分:1)

为什么是榛子?当您使用LockBits时,您可以使用PixelFormat24bppRGB作为LockBits的参数三,因为系统无论如何都会复制数据(您从未直接访问GDI +中的图像数据)。

这里发现了一些错误(到目前为止):

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

为什么四分? GetPaletteSize以字节为单位返回大小,GetPalette等待以字节为单位的大小。 ColorPalette是一个占位符定义,是微软开发人员对我们所做的最黑暗的考虑之一。它只定义了第一个颜色条目!

使用字节指针,如:

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

使用

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

当您需要访问颜色时。

抱歉,直接使用调色板时,它看起来很丑陋。 别忘了释放调色板...... 祝你好运。

答案 1 :(得分:1)

正确填写和对齐BITMAP RIFF格式的各个部分非常重要。调色板类型位图的调色板不必包含256个条目: http://msdn.microsoft.com/en-us/library/windows/desktop/dd183376%28v=vs.85%29.aspx

“8位图最多有256种颜色,BITMAPINFO的bmiColors成员包含最多 256个条目。在这种情况下,数组中的每个字节代表一个像素。” p>

但重要的是,如果调色板中的条目少于256个,则位图不应该从调色板结构中索引。否则,源格式不正确。

您想要转换24 bpp位图。这与8bpp略有不同。我建议你用十六进制编辑器打开现有的24bpp和8bpp位图文件,看看结构是如何对齐的,以及它们的内容,并将它与你的内存布局进行比较。

答案 2 :(得分:1)

不应该这样:

currentIndex = i*stride+j*3;

是:

currentIndex = i*stride+j*4;

鉴于:

stride =  bitmapData.Width*4;

也:

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

应该是:

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

Double &&表示“如果左侧和右侧为真”,则单&表示“按位和”。