VC++读取显示保存位图文件
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
【VC++】读取位图文件、显示位图文件、保存位图文件2009年01月05日 12:25作者:彭军 邮件:poonjun at gmail com
用到的几个数据的声明:public:
char* m_pDibData;
int m_nBitCount;
int m_nHeight;
int m_nWidth;
CString m_fileName;
HGLOBAL m_hDIB;//=========================================void CDIPDlg::OnBtnOpenimage()
{
// TODO: Add your control notification handler code here
//打开对话框,并获得要打开的位图的路径,保存在m_fileName中
static char szFilter[]="位图文件(*.bmp;*.dib)|*.bmp;*.dib|All Files(*.*)|*.*||";
CFileDialog dlg(true,"*.bmp",NULL,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,szFilter);
if(dlg.DoModal()==IDOK)
{
UpdateData(true);
m_fileName=dlg.GetPathName();
}
//新建CFile类对象dibFile,并用只读的模式打开位图文件
CFile dibFile;
if(!dibFile.Open(m_fileName,CFile::modeRead))
{
AfxMessageBox("Can't open DIB file...");
return;
}
//接下来要读取位图文件的文件头
//新建一个位图文件头变量
BITMAPFILEHEADER bitmapFileHeader;
//从位图文件中读取与位图文件头大小的字节到文件头变量中
UINT bitmapFileHeaderSize=dibFile.Read((void*)&bitmapFileHeader,sizeof(BITMAPFILEHEADER));
if(bitmapFileHeaderSize!=sizeof(BITMAPFILEHEADER))
{
AfxMessageBox("读取文件头失败");
return;
}
//判断读取的文件是否为位图文件
if(bitmapFileHeader.bfType==0x4d42)
{
//获取整个位图文件的长度
DWORD dwFileLength=dibFile.GetLength();
/**************************************
BMP文件的组成结构
1 位图文件头(14字节)(BITMAPFILEHEADER)
2 位图信息(包含位图信息头和调色板数据)
真彩色的位图是没有调色板数据的,而位图信息头为14字节
其结构体为BITMAPINFOHEADER,位图信息的结构体为BITMAPINFO
3 像素数据
**************************************/
//获取位图信息头和像素数据的大小(文件总长度-位图文件头的长度)
DWORD dwSize=dwFileLength-sizeof(BITMAPFILEHEADER);
//为位图信息头和像素数据分配大小
m_hDIB=(HGLOBAL)::GlobalAlloc(GMEM_MOVEABLE,dwSize);
//锁定分配的内存,将返回指向此内存的指针
BYTE* m_pdib=(BYTE*)::GlobalLock((HGLOBAL)m_hDIB);
//将位图信息头和像素数据一起读入到已分配的内存当中
DWORD dwReadSize=dibFile.Read((void*)m_pdib,dwSize);
//获取位图信息头和位图信息的指针
//位图信息头指针用来获取位图的宽度、高度和每个像素所占字节数
//位图信息指针用来在StretchDIBits中显示位图时的参数
BITMAPINFO *m_pBitmapInfo=(BITMAPINFO*)m_pdib;
BITMAPINFOHEADER *m_pBitmapInfoHeader=(BITMAPINFOHEADER*)m_pdib;
m_nWidth=m_pBitmapInfoHeader->biWidth;
m_nHeight=m_pBitmapInfoHeader->biHeight;
m_nBitCount=m_pBitmapInfoHeader->biBitCount;
if(m_nBitCount<24)
{
AfxMessageBox("
打开的不是大于24位的真彩色图片,不能进行处理,只能显示和保存位图!");
}
//int m_nTotalColor=m_nBitCount<<1;
//m_pDibData=m_pdib+m_pBitmapInfoHeader->biSize+m_nTotalColor*sizeof(RGBQUAD);
//计算像素数据所在的位置(起始位置+位图信息头的大小)
m_pDibData=(char*)m_pdib+m_pBitmapInfoHeader->biSize;
//显示像素数据的内容
CDC* pDC=GetDC(); //得到当前设备的句柄指针
::StretchDIBits(pDC->m_hDC,0,0,m_nWidth,m_nHeight,0,0,m_nWidth,m_nHeight,m_pDibData,m_pBitmapInfo,DIB_RGB_COLORS,SRCCOPY);
::GlobalUnlock((HGLOBAL)m_hDIB);
}
else
{
AfxMessageBox("非位图文件");
return;
}
}//===========================================void CDIPDlg::OnBtnDisplayimage()
{
// TODO: Add your control notification handler code here
CDC* pDC=GetDC();
BYTE* lpdib=(BYTE*)::GlobalLock((HGLOBAL)m_hDIB);
BITMAPINFO* m_pBitmapInfo=(BITMAPINFO*)lpdib;
::StretchDIBits(pDC->m_hDC,0,0,m_nWidth,m_nHeight,0,0,m_nWidth,m_nHeight,m_pDibData,m_pBitmapInfo,DIB_RGB_COLORS,SRCCOPY);
::GlobalUnlock((HGLOBAL)m_hDIB);
}//========================================void CDIPDlg::OnBtnSaveimage()
{
// TODO: Add your control notification handler code here
//生成图像的信息头(包括位图文件头和位图信息)
//位图文件头占14字节,位图信息头占40字节
//真彩色位图没有调色板,所以图像的偏移就为54字节
BITMAPFILEHEADER bf;
bf.bfOffBits=54;
bf.bfReserved1=0;
bf.bfReserved2=0;
//说明文件大小(位图文件头+位图信息头+图片像素所占字节数)
bf.bfSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+m_nHeight*m_nWidth*4;
//说明文件类型为BM
bf.bfType=((WORD)'M'<<8|'B');BITMAPINFOHEADER bi;
//说明每个像素所占字节数,其值为1、4、8、16、24、32
bi.biBitCount=m_nBitCount;
//说明图像显示有重要影响的颜色索引的数目,如果是0,表示都重要
bi.biClrImportant=0;
//说明位图实际使用的彩色表中的颜色索引数(设为0的话,则说明使用所有调色板项)
bi.biClrUsed=0;
//说明图像数据压缩的类型
bi.biCompression=0L;
//说明图像的宽度,以像素为单位
bi.biWidth=m_nWidth;
//说明图像的高度,以像素为单位
bi.biHeight=m_nHeight;
//目标设备说明位面数,其值总是被设为1
bi.biPlanes=1;
//说明BITMAPINFOHEADER结构所需要的字节数
bi.biSize=sizeof(BITMAPINFOHEADER);
//说明图像的大小,以字节为单位。当用BI_RGB格式时,可设置为0
bi.biSizeImage=0;
//说明图像的水平分辨率,用像素/米来表示
bi.biXPelsPerMeter=0;
//说明图像的垂直分辨率,用像素/米来表示
bi.biYPelsPerMeter=0;//打开保存对话框,获取保存路径及文件名
static char szFilter[]="位图文件(*.bmp;*.dib)|*.bmp;*.dib|All Files(*.*)|*.*||";
CFileDialog dlg(false,"*.bmp",NULL,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,szFilter);
if(dlg.DoModal()==ID
OK)
{
UpdateData(true);
m_fileName=dlg.GetPathName();
}
else
{
return;
}//建立CFile对象准备保存图片
CFile file;
if(!file.Open(m_fileName,CFile::modeCreate|CFile::modeWrite|CFile::typeBinary))
{
AfxMessageBox("Can not write BMP file.");
return;
}//写入位图文件头
file.Write(&bf,14);
//写入位图信息头
file.Write(&bi,sizeof(BITMAPINFOHEADER));
//获得图像每一行所占的字节数
long lWidthBytes=(m_nWidth*m_nBitCount+31)/32*4;
//写入整个的像素矩阵中的数据
file.Write(m_pDibData,m_nHeight*lWidthBytes);
//写入完毕,关闭文件
file.Close();
}