用C++来读入位图就更加简单了:
BOOL CDib::OpenImage(CString fileName)
{
BITMAPFILEHEADER m_bmfh;
BITMAPINFOHEADER m_bmih;
BYTE *img;
//如果文件名位空,则给出警告并退出
if(!fileName)
{
AfxMessageBox("文件名不能位空");
return false;
}
//建立CFile类的对象dib
CFile dib;
//打开文件
if(!dib.Open(fileName,CFile::modeRead))
{
//打开失败,则给出警告并退出
AfxMessageBox("打开文件失败");
return false;
}
//读取位图文件头
if(dib.Read(&m_bmfh,sizeof(BITMAPFILEHEADER))!=sizeof(BITMAPFILEHEADER))
{
//读取失败,则给出警告并退出
AfxMessageBox("读取位图文件头失败");
return false;
}
//读取位图信息头
if(dib.Read(&m_bmih,sizeof(BITMAPINFOHEADER))!=sizeof(BITMAPINFOHEADER))
{
AfxMessageBox(“读取位图信息头失败”);
return false;
}
//跳过调色板
dib.Seek(m_bmfh.biOffBits,CFile::begin);
//为像素数据分配空间
img=new BYTE[m_bmih.biHeight*((m_bmih.biWidth*m_bmih.biBitCount+31)/32*4)];
//读入像素数据
dib.Read(img, m_bmih.biHeight*((m_bmih.biWidth*m_bmih.biBitCount+31)/32*4));
//关闭文件
dib.Close();
return true;
}
至于显示的话,就是一个StretchDIBits函数而已,不多说了。下面来看看如何用C++来保存位图:
BOOL CDib::SaveImage(CString fileName)
{
//如果文件名位空,则给出警告并退出
if(!fileName)
{
AfxMessageBox("文件名不能位空");
return false;
}
//创建CFile类的对象dib
CFile dib;
//打开要保存的文件
if(!dib.Open(fileName,CFile::modeCreate | CFile::typeBinary | CFile::modeWrite))
{
AfxMessageBox("打开文件失败");
return false;
}
//保存文件头
dib.Write(&m_bmfh,sizeof(BITMAPFILEHEADER));
//保存位图信息头
dib.Write(&m_bmih,sizeof(BITMAPINFOHEADER));
//如果是8位位图,还需要保存调色板内容
if(m_bmih->biBitCount==8)
{
//如果没有用到所有的颜色
if(m_bmih ->biClrUsed!=0)
{
dib.Write(m_lpRgbQuad, m_bmih ->biClrUsed*sizeof(RGBQUAD));
}
else
{
//用到了所有的256种颜色
dib.Write(m_lpRgbQuad,256*sizeof(RGBQUAD));
}
}
//保存像素数据
dib.Write(m_lpDibData,m_bmih ->biHeight*GetLineBytes());
//给出保存成功的提示
AfxMessageBox("保存成功");
//关闭文件
dib.Close();
return true;
}
其中GetLineBytes()函数就是有图像的宽度和位数得到图像每行像素所占的字节数。计算公式如下:lineBytes=(width*bitCount+31)/32*4;为什么要计算图像每行像素所占的字节数?是因为在保存BMP位图的时候,每行所占的字节数必须是4的倍数,如果不是要补齐。这点跟sizeof用在结构体的时候的字节补齐很类似。