8位位图与24位位图的区别就在于8位的有调色板,而24位的没有。调色板信息是按(BGRA)顺序存放的,每4位是一个调色板项,共有256个调色板,故只能显示256种颜色,其中A始终为0。位图数据区则是存储的调色板索引,比如0,1,2……按索引获取颜色。
24位的则不然,24位位图没有调色板,数据区存储的就是BGR颜色数据,每3位为一个像素点的颜色,所以可以显示2的24次方种颜色。
转换过程很容易,就是按照8位位图索引取出调色板中的数据,把A舍去,把其他的按顺序存储到24位图像的数据区,在数据区前加上位图的头就OK了,代码如下:
void CDib::ConverTo24Bit()
{
LPBITMAPINFOHEADER lpbi;
if(!hdib)
return;
lpbi = (BITMAPINFOHEADER*)hdib;//hdib是成员变量,指向已打开的位图信息首地址
int height = lpbi->biHeight;
//两个宽度
LONG lLineBytes24=((lpbi->biWidth*24+31)/32*4);
LONG lLineBytes8=((lpbi->biWidth*8+31)/32*4);
//源图像的指针,申请一块足够大的内存
BYTE* srcBits ;//= (BYTE*)malloc(lLineBytes8*height);
//使其指向源图像的图像数据起始地址
srcBits = (BYTE*)lpbi+sizeof(BITMAPINFOHEADER)+PaletteSize();
//转换后的图像数据指针
BYTE* dstBits = (BYTE*)malloc(lLineBytes24*height);
//调色板信息
RGBQUAD *pRgb = (RGBQUAD *)((BYTE*)lpbi+sizeof(BITMAPINFOHEADER));
//通过循环,使8位BMP中的颜色信息转换为24位
//因为24位是用三位表示一个颜色(顺序是BGR),没有调色板,而8位的是一位表示一个颜色信息在调色板中的偏移量
for( int i=0; i<height; i++)
{
for(int j=0, n=0; j<lLineBytes8; j++)
{
int num = *(srcBits+lLineBytes8*i+j);//获取8位中调色板信息的偏移量
//将颜色信息写入24位指针指向的地址(为了保证dstBits始终指向首地址,故不写成dst=...)
*(dstBits+lLineBytes24*i+n)=pRgb[num].rgbBlue;
n++;
*(dstBits+lLineBytes24*i+n)=pRgb[num].rgbGreen;
n++;
*(dstBits+lLineBytes24*i+n)=pRgb[num].rgbRed;
n++;
}
}
//24位BMP的信息头
BITMAPINFOHEADER bi;
bi.biBitCount=24;
bi.biClrImportant=0;
bi.biClrUsed=0;
bi.biCompression=0L;
bi.biHeight=Height();
bi.biPlanes=1;
bi.biSize=sizeof(BITMAPINFOHEADER);
bi.biSizeImage=Height()*lLineBytes24;
bi.biWidth=Width();
bi.biXPelsPerMeter=0;
bi.biYPelsPerMeter=0;
//设置BMP信息头和数据信息函数
SetBitmapinfoAndBits(bi, dstBits);//函数功能为把信息头和数据信息合并,存储在hdib指针指向的区域内
CString FileName;
strFileName.Delete(strFileName.GetLength()-4, 4);
FileName.Format("%s的24位图.bmp",strFileName);
SaveFile(FileName);//把hdib指向的区域写入到文件
//收尾清除指针内存
//free(srcBits);
srcBits = NULL;
free(dstBits);
dstBits = NULL;
AfxMessageBox("已经转换成24位,另存为:"+FileName);
}
关于读取和设置信息头,保存部分会写在别的地方