首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

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

2013-09-12 
24位bmp图转换为8位灰度图void CMyBmpMatch::OpenFile(CString FileName){ CFile fileCString open_path

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));

热点排行