读书人

24位bmp图变换为8位灰度图

发布时间: 2013-09-12 22:07:04 作者: rapoo

24位bmp图转换为8位灰度图
void CMyBmpMatch::OpenFile(CString FileName)

{
CFile file;
CString open_path = _T("c:\\Tulip.bmp");
if(!file.Open(open_path,CFile::modeRead))
{
AfxMessageBox(_T("不能打开文件"));
return;
}
BITMAPFILEHEADER BFH;
file.Read(&BFH, sizeof(BITMAPFILEHEADER));
if(BFH.bfType != 'MB')
{
AfxMessageBox(_T("不是BMP位图文件或数据有误!\n"));
return;
}
BITMAPINFOHEADER BIH;
file.Read(&BIH,sizeof(BITMAPINFOHEADER));
nWidth = BIH.biWidth; //图像的宽度
nHeight = BIH.biHeight; //图像的高度
nColorBits = BIH.biBitCount; //图像的颜色数
nByteWidth = (nWidth*nColorBits+31)/32*4; //图像的扫描宽度
nColor = (nColorBits>8) ? 0 : (1<<nColorBits); //调色板中的颜色数
RGBQUAD *pColorTable;//颜色表指针
if(nColorBits==8)
{
//申请颜色表所需要的空间,读颜色表进内存
pColorTable=new RGBQUAD[256];
file.Read(pColorTable,sizeof(RGBQUAD));
}
//申请位图数据所需要的空间,读位图数据进内存
lpBits=new unsigned char[nByteWidth * nHeight];
file.Read(lpBits,nByteWidth * nHeight);
file.Close();
}

void CMyBmpMatch::SaveFile(CString FileName)

{nColorBits=8;
//SaveFile(CString FileName,unsigned char *imgBuf,)
CFile filesave;
CString path = _T("c:\\temp.bmp");
if(!filesave.Open(path,CFile::modeCreate|CFile::modeWrite))
{
AfxMessageBox(_T("不能打开文件"));
return;
}
int lineByte=(nWidth*nColorBits+31)/32*4;
int bmp_size = nWidth*nHeight*(nColorBits/8);
BITMAPFILEHEADER bmfHeader;
bmfHeader.bfType = 0x4D42;
if(nColorBits==8)
{
bmfHeader.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) +sizeof(RGBQUAD)*256+ bmp_size;
bmfHeader.bfOffBits=bmfHeader.bfSize-bmp_size;
}
else
{
bmfHeader.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + bmp_size;
bmfHeader.bfOffBits=bmfHeader.bfSize-bmp_size;
}
bmfHeader.bfReserved1 = bmfHeader.bfReserved2 = 0;


filesave.Write(&bmfHeader,sizeof(BITMAPFILEHEADER));
unsigned long fileLength; //原bmp文件大小
fileLength=(unsigned long)bmfHeader.bfSize;
//保存改变的位图文件数据
BITMAPINFOHEADER bmiHeader;
bmiHeader.biSize = sizeof(bmiHeader); // 本结构所占用字节数,即sizeof(BITMAPINFOHEADER);
bmiHeader.biWidth = nWidth; // 位图宽度(单位:像素)
bmiHeader.biHeight = nHeight; // 位图高度(单位:像素)
bmiHeader.biPlanes = 1; // 目标设备的级别,必须为1
bmiHeader.biBitCount = nColorBits; // 像素的位数(每个像素所需的位数,范围:1、4、8、24、32)
bmiHeader.biCompression = 0; // 压缩类型(0:不压缩 1:BI_RLE8压缩类型 2:BI_RLE4压缩类型)
bmiHeader.biSizeImage = bmp_size; // 位图大小(单位:字节)
bmiHeader.biXPelsPerMeter = 0; // 水平分辨率(像素/米)
bmiHeader.biYPelsPerMeter = 0; // 垂直分辨率(像素/米)
bmiHeader.biClrUsed = 0; // 位图实际使用的彩色表中的颜色索引数
bmiHeader.biClrImportant = 0; // 对图象显示有重要影响的颜色索引的
filesave.Write(&bmiHeader,sizeof(BITMAPINFOHEADER));

/////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////图像变为灰度图像然后保存////////////////////////////////////////////////////////
int i,j;
BYTE *winl;
winl=new BYTE[fileLength];
if(nColorBits==8)
{
RGBQUAD rgbquad[256];
// 计算灰度映射表(保存各个颜色的灰度值)
for (i = 0; i < 256; i ++)
{
rgbquad[i].rgbRed = i; // 更新DIB调色板红色分量
rgbquad[i].rgbGreen = i; // 更新DIB调色板绿色分量


rgbquad[i].rgbBlue = i; // 更新DIB调色板蓝色分量
rgbquad[i].rgbReserved = 0;// 更新DIB调色板保留位
}
filesave.Write(rgbquad,sizeof(RGBQUAD));
}

for(int nCount=0;nCount<nWidth*nHeight*3;nCount+=3)
{
winl[nCount/3]=char(lpBits[nCount]*0.114+lpBits[nCount+1]*0.587+lpBits[nCount+2]*0.299);
}
filesave.Write(winl,fileLength);

delete []winl;
filesave.Close();
}
转换后的图不正确
[解决办法]
下面这句话错了,
颜色表没有全部写进去。

filesave.Write(rgbquad,sizeof(RGBQUAD));
------》
filesave.Write(rgbquad,sizeof(RGBQUAD) *256);
或者
filesave.Write(rgbquad,sizeof(rgbquad));

读书人网 >C++

热点推荐