回复 楼主 xiaofengzizz
这段代码“似乎”有问题://非24位:解码生成rgb,需要调色板信息
//生成调色板数组,数组的下标,对应bmp文件中有效数据,通过下标对应查找,便可得到该数据对应的颜色
//debug by LiuDong:(unsignedlong long)pow(),pow前的强制类型转换不能转换成unsignedint、unsignedchar等
//因为pow((float)2, info_h.biBitCount)最大值是2^24,unsigned char最大能表示255,unsigned int最大能表示2^32
RGBQUAD *pRGB = (RGBQUAD *)malloc(sizeof(RGBQUAD)*(unsigned int)pow((float)2,info_h->biBitCount));
/*一个单元代表一种颜色
调色板实际上是一个数组,它所包含的元素与位图所具有的颜色数相同,决定于biClrUsed和biBitCount字段。
数组中每个元素的类型是一个RGBQUAD结构。真彩色无调色板部分。
biBitCount;位数/像素,1、2、4、8、24.假如是16位,R占5位,G占5位,B占5位,空出一位,排列组合一共有2^15种颜色,其他位数同理。*/
//读取位图调色板数据
if(!MakePalette(pFile, file_h,info_h,pRGB))
printf("Nopalette!");
//16位:移位操作,从2字节中取出RGB信息,存到3字节中
if (info_h->biBitCount== 16)
{
for(Loop = 0; Loop < height * width; Loop += 2)
{
*rgbDataOut= (Data[Loop] & 0x1F) << 3;//B:用0001 1111取出低字节的右五位,再放到目标字节的高5位(通过右移3位),得到五位的B
*(rgbDataOut+ 1) = ((Data[Loop] & 0xE0) >> 2) + ((Data[Loop + 1] & 0x03)<< 6);//G:11100000取出低字节的左三位,00000011取出高字节的右两位,合并后,放到再放到目标字节的高5位,得到五位的G
*(rgbDataOut+ 2) = (Data[Loop + 1] & 0x7C) << 1; //R:0111 1100取出高字节的中间五位,再放到目标字节的高5位,得到5位的R
rgbDataOut+= 3;
}//RGB都各自位于字节的高5位
}
//1~8位:移位操作,从有限固定位中取出RGB信息,存到3字节中
//循环次数:有效数据字节数
for (Loop =0; Loop<width*height; Loop++)
{
//根据位深设置掩膜
switch(info_h->biBitCount)
{
case 1://1000 0000,1位,黑白双色图
mask = 0x80;
break;
case 2://1100 0000,2位,4色图
mask = 0xC0;
break;
case 4://1111 0000,4位,16色图
mask = 0xF0;
break;
case 8://1111 1111,8位,256色图
mask = 0xFF;
}
shiftCnt = 1;//控制mask的移位,决定取字节中哪些数据
while(mask)//循环一次就是一个字节的解析过程
{
index = mask == 0xFF ? Data[Loop] : ((Data[Loop] & mask) >> (8 -shiftCnt * info_h->biBitCount));
//Loop代表第几个带转换的原始有效数据
//pRGB代表调色板
//8位:mask=1111 1111,index=data[Loop],即index为bmp中原始有效数据,直接对应调色板数组下标,得到相应颜色
//查找调色板,取出对应BGR存入目标buffer:rgbDataOut
*rgbDataOut= pRGB[index].rgbBlue;//B
*(rgbDataOut+ 1) = pRGB[index].rgbGreen;//G
*(rgbDataOut+ 2) = pRGB[index].rgbRed;//R
if(info_h->biBitCount== 8)
mask = 0;//如果是8位bmp,一次性取完一个字节的颜色数据,直接跳出循环即可
else
mask >>= info_h->biBitCount;//若是1位bmp,则一字节取8次数据;若是2位bmp,则一字节取4次数据;若是4位bmp,则一字节取2次数据
//debugby LiuDong
if(Loop == width*height - 1)
{
rgbDataOut= rgbDataOut + 3 - width*height*3;
break;
}
rgbDataOut+= 3;
shiftCnt++;
}
}