您的位置:首页 > 其它

24位位图转成8位灰度位图

2010-04-21 11:28 309 查看
24位转8位灰度比较简单,先设置调色板,如下样子

(0,0,0,0)(1,1,1,0)(2,2,2,0)……一共256个,用公式gray = (0.114*Blue+0.587*Green+0.299*Red)得到的gray为该像素点在8位位图中调色板的索引,所以,只要把24位中每个像素点中的数据按公式算出索引,再写入,就完成了,代码如下:

void CDib::ConverTo8BitGray()

{

//24位转换为8位灰度

LPBITMAPINFOHEADER lpbi;

if(!hdib)

return;

lpbi = (BITMAPINFOHEADER*)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(lLineBytes24*height);

//使其指向源图像的图像数据起始地址

srcBits = (BYTE*)lpbi+sizeof(BITMAPINFOHEADER);

//转换后的图像数据指针(大小为图片大小和调色板大小之和

int iPaletteSize = sizeof(RGBQUAD)*256;//调色板大小

BYTE* dstBits = (BYTE*)malloc(iPaletteSize+lLineBytes8*height);

RGBQUAD* pRGB = (RGBQUAD *)dstBits;//调色板指针,指向数据部分开始地址

//写入调色板数据

for(int i=0; i<256; i++)

{

pRGB->rgbBlue = pRGB->rgbGreen = pRGB->rgbRed = i;

pRGB->rgbReserved = 0;

pRGB++;

}

for(int y=0; y<height; y++)

{

for(int x=0, n=0; x<lLineBytes24; x+=3)

{

BYTE B = *(srcBits+lLineBytes24*y+x);//蓝

BYTE G = *(srcBits+lLineBytes24*y+x+1);//绿

BYTE R = *(srcBits+lLineBytes24*y+x+2);//红

int gray = (int)(0.114*B+0.587*G+0.299*R);//灰度公式

*(dstBits + iPaletteSize + lLineBytes8*y + n) = gray;//写入灰度值

n++;

}

}

//8位BMP的信息头

BITMAPINFOHEADER bi;

bi.biBitCount=8;

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;

SetBitmapinfoAndBits(bi, dstBits);

CString FileName;

strFileName.Delete(strFileName.GetLength()-4, 4);

FileName.Format("%s的8位灰度图.bmp",strFileName);

//调用保存文件函数

SaveFile(FileName);

//收尾清除指针内存

//free(srcBits);

srcBits = NULL;

free(dstBits);

dstBits = NULL;

AfxMessageBox("已经转换成8位灰度图,另存为:"+FileName);

}

关于读取保存设置等会在别的文章中写
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: