我正在尝试将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);
我该如何解决这个问题?
答案 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 &&
表示“如果左侧和右侧为真”,则单&
表示“按位和”。