MFC详解显示BMP格式图片

article/2025/8/28 8:51:17

本文主要是讲述《数字图像处理》系列栏目中的第一篇文章.主要详细介绍了BMP图片格式,同时使用C++和MFC显示BMP格式,主要结合自己的《数字图像处理》课程和以前的项目叙述讲解.

一.BMP图片格式定义

BMP文件格式是Windows操作系统推荐和支持的标准图像文件格式,是一种将内存或显示器的图像数据不经过压缩而直接按位存盘的文件格式,故称位图(bitmap),其扩展名为BMP.BMP图像通常有4个部分组成:位图文件头、位图信息头、颜色表、位图数据.如下图所示:

第一部分为位图文件头BITMAPFILEHEADER.位图文件头结构长度固定为14个字节,包含文件的类型、大小、位图文件保留字、位图数据距文件头的偏移量.其中WORD为无符号16位整数(2byte),DWORD为无符号32位整数(4byte).具体结构体定义如下:

 
  1. //位图文件头

  2. typedef struct tagBITMAPFILEHEADER {

  3. WORD bfType; //位图文件的类型,必须为BM 0x424d 表示.bmp

  4. DWORD bfSize; //位图文件的大小,以字节为单位 包括该14字节

  5. WORD bfReserved1; //位图文件保留字,必须为0

  6. WORD bfReserved2; //位图文件保留字,必须为0

  7. DWORD bfOffBits; //位图数据距文件头的偏移量,以字节为单位 即前三部分和

  8. } BITMAPFILEHEADER;

第二部分为位图信息头BITMAPINFOHEADER,该结构也固定为40个字节,用于说明位图的尺寸、宽高、像素、分辨率、颜色表等信息.具体结构定义如下:

 
  1. //位图信息头

  2. typedef struct tagBITMAPINFOHEADER {

  3. DWORD biSize; //本结构所占用字节数 40字节

  4. LONG biWidth; //位图的宽度,以像素为单位

  5. LONG biHeight; //位图的高度,以像素为单位

  6. WORD biPlanes; //目标设备的级别,必须为1

  7. WORD biBitCount; //每个像素所需的位数,必须是1(双色)、

  8. //4(16色)、8(256色)或24(真彩色)之一

  9. DWORD biCompression; //位图压缩类型,必须是 0(BI_RGB不压缩)、

  10. //1(BI_RLE8压缩类型)或2(BI_RLE压缩类型)之一

  11. DWORD biSizeImage; //位图的大小,以字节为单位

  12. LONG biXPelsPerMeter; //位图水平分辨率,每米像素数

  13. LONG biYPelsPerMeter; //位图垂直分辨率,每米像素数

  14. DWORD biClrUsed; //位图实际使用的颜色表中的颜色数

  15. DWORD biClrImportant; //位图显示过程中重要的颜色数

  16. } BITMAPINFOHEADER;

第三部分为颜色表或调色板(Palette).有些位图需要调色板,有些位图如真彩色图(biBitCount=24)不需要调色板,它们的BITMAPINFOHEADER后面直接是位图数据.调色板实际是一个数组,共有biClrUsed个元素(如果该值为零,则有2的biBitCount次幂个元素).数组中每个元素的类型是一个RGBQUAD结构,占4字节.定义如下:

 
  1. //位图颜色表

  2. typedef struct tagRGBQUAD

  3. {

  4. BYTE rgbBlue; //蓝色的亮度(值范围为0~255)

  5. BYTE rgbGreen; //绿色的亮度(值范围为0~255)

  6. BYTE rgbRed; //红色的亮度(值范围为0~255)

  7. BYTE rgbReserved; //保留,必须为0

  8. } RGBQUAD;

第四部分就是实际的图像数据.对于真彩色图(24位位图 biBitCount=24),图像数据就是实际的RGB值;对于用到调色板的位图,图像数据就是该像素颜色在调色板中的索引值.下面对2色、16色、256色和真彩色位图分别介绍:
(1).2色位图:当biBitCount=1时,用1位就可以表示该像素的颜色(0表示黑,1表示白),所以8个像素占1个字节;
(2).16色位图:当biBitCount=4时,用4为可以表示一个像素的颜色,所以2个像素占1个字节;
(3).256色位图:当biBitCount=8时,用1个字节表示1个像素,1个像素占1个字节;
(4).真彩色图:当biBitCount=24时,此时用3个字节表示1个像素,其中RGB各占1字节,由于没有颜色表,位图信息头后面是位图数据.

同时,注意以下几点:
1.由于Windows规定一个扫描所占的字节数必须是4的倍数(即以long为单位),不足的以0填充.同时注意下面公式,计算只含位图数据的大小:
biSizeImage=(((bi.biWidth*bi.biBitCount)+31)/(32*4))*bi.Height
在后面讲述获取文件的信息时会通过UE软件结合16进制数据进行详细讲解上面各个数据的具体含义.
2.BMP图片格式的数据是从下到上、从左到右读.即文件中最先读到的图像是最下面一行的左边第一个元素,即从左下角开始存储(0,0)点,从左下角到右上角存储数据.尤其是在图像几何变换平移、旋转时,我就犯过这样的错误,本想让图像从左下角向右上移动,结果刚好相反,后面也会通过实例加深大家的印象.
3.如果想使用C语言\C++显示图片,建议自定义个ImageStruct.h的头文件.包含BMP位图的位图文件头结构、位图信息头结构、位图颜色表3个结构,在实例变量操作.而使用MFC,因为在wingdi.h文件中系统已经定义了BMP图像的结构BITMAPFILEHEADER、BITMAPINFOHEADER,直接在View.h中用他俩实例定义即可.

二.显示BMP图片的基本步骤

在MFC工程XXXView.h类中添加成员函数void ShowBitmap(CDC* pDC,CString BmpName);通过自定义函数实现显示BMP格式图像,其中*pDC是CDC句柄,BmpName是图像文件名.具体步骤如下:
1.创建位图并调用函数LoadImage装载图标、光标或位图.
  HBITMAP m_hBitmap; 
  m_hBitmap=(HBITMAP)LoadImage(HINSTANCE hinst,LPCTSTR lpszName,UINT uType,int cxDesired,int cyDesired,UINT fuLoad)
2.定义并创建一个内存设备环境DC,调用函数CreateCompatibleDC创建兼容的DC.
  CDC dcBmp; dcBmp.CreateCompatibleDC(pDC) ;
3.定义BITMAP变量,调用函数GetBitmap将图片载入位图中,该定义是为后去图像的长宽等信息.
  BITMAP m_bmp; m_bitmap.GetBitmap(&m_bmp);
4.调用函数SelectObject将位图选入兼容内存设备环境DC中.
  dcBmp.SelectObject(&m_bitmap);
5.将兼容的DC中的位图填到当前DC中,调用函数BitBlt或strechBlt显示图像.
(1).BitBlt()该函数对指定的源设备环境区域中的像素进行位块(bit_block)转换,以传送到目标设备环境.
  pDC->BitBlt(0,0,m_bmp.bmWidth,m_bmp.bmHeight,&dcBmp,0,0,SRCCOPY);
(2).stretchBlt()该函数从源矩形中复制位图到目标矩形,必要是按目标设备设置的模式进行图像拉伸或压缩.
  pDC->StretchBlt(0,0,m_nDrawWidth,m_nDrawHeight,&dcBmp,0,0,m_bmp.bmWidth,m_bmp.bmHeight,SRCCOPY);
6.恢复临时DC的位图,删除CreateCompatibleDC得到的图片DC,删除内存中的位图及释放系统资源.
  dcBmp.SelectObject(pbmpOld); DeleteObject(&m_bitmap);  dcBmp.DeleteDC();
具体函数代码如下:

 
  1. //****************显示BMP格式图片****************//

  2. void CShowBMPView::ShowBitmap(CDC *pDC, CString BmpName)

  3. {

  4. //定义bitmap指针 调用函数LoadImage装载位图

  5. HBITMAP m_hBitmap;

  6. m_hBitmap = (HBITMAP) LoadImage(NULL,BmpName,IMAGE_BITMAP,0,0,LR_LOADFROMFILE|LR_DEFAULTSIZE|LR_CREATEDIBSECTION);

  7.  
  8. /*************************************************************************/

  9. /* 1.要装载OEM图像,则设此参数值为0 OBM_ OEM位图 OIC_OEM图标 OCR_OEM光标

  10. /* 2.BmpName要装载图片的文件名

  11. /* 3.装载图像类型:

  12. /* IMAGE_BITMAP-装载位图 IMAGE_CURSOR-装载光标 IMAGE_ICON-装载图标

  13. /* 4.指定图标或光标的像素宽度和长度 以像素为单位

  14. /* 5.加载选项:

  15. /* IR_LOADFROMFILE-指明由lpszName指定文件中加载图像

  16. /* IR_DEFAULTSIZE-指明使用图像默认大小

  17. /* LR_CREATEDIBSECTION-当uType参数为IMAGE_BITMAP时,创建一个DIB项

  18. /**************************************************************************/

  19.  
  20. if( m_bitmap.m_hObject )

  21. {

  22. m_bitmap.Detach(); //切断CWnd和窗口联系

  23. }

  24. m_bitmap.Attach(m_hBitmap); //将句柄HBITMAP m_hBitmap与CBitmap m_bitmap关联

  25.  
  26. //边界

  27. CRect rect;

  28. GetClientRect(&rect);

  29.  
  30. //图片显示(x,y)起始坐标

  31. int m_showX=0;

  32. int m_showY=0;

  33. int m_nWindowWidth = rect.right - rect.left; //计算客户区宽度

  34. int m_nWindowHeight = rect.bottom - rect.top; //计算客户区高度

  35.  
  36. //定义并创建一个内存设备环境DC

  37. CDC dcBmp;

  38. if( !dcBmp.CreateCompatibleDC(pDC) ) //创建兼容性的DC

  39. return;

  40.  
  41. BITMAP m_bmp; //临时bmp图片变量

  42. m_bitmap.GetBitmap(&m_bmp); //将图片载入位图中

  43.  
  44. CBitmap *pbmpOld = NULL;

  45. dcBmp.SelectObject(&m_bitmap); //将位图选入临时内存设备环境

  46.  
  47. //图片显示调用函数stretchBlt

  48. pDC->StretchBlt(0,0,m_bmp.bmWidth,m_bmp.bmHeight,&dcBmp,0,0,m_bmp.bmWidth,m_bmp.bmHeight,SRCCOPY);

  49.  
  50. /*******************************************************************************/

  51. /* BOOL StretchBlt(int x,int y,int nWidth,int nHeight,CDC* pSrcDC,

  52. /* int xSrc,int ySrc,int nSrcWidth,int nSrcHeight,DWORD dwRop );

  53. /* 1.参数x、y位图目标矩形左上角x、y的坐标值

  54. /* 2.nWidth、nHeigth位图目标矩形的逻辑宽度和高度

  55. /* 3.pSrcDC表示源设备CDC指针

  56. /* 4.xSrc、ySrc表示位图源矩形的左上角的x、y逻辑坐标值

  57. /* 5.dwRop表示显示位图的光栅操作方式 SRCCOPY用于直接将位图复制到目标环境中

  58. /*******************************************************************************/

  59.  
  60. dcBmp.SelectObject(pbmpOld); //恢复临时DC的位图

  61. DeleteObject(&m_bitmap); //删除内存中的位图

  62. dcBmp.DeleteDC(); //删除CreateCompatibleDC得到的图片DC

  63. }

补充:MFC中DC指device context,设备环境或设备描述表,它其实是GDI内部保存数据的一种数据结构.此结构中属性内容与特定输出设备相关,属性定义了GDI函数的工作细节.总之,使用GDI绘图函数,就需要一个DC句柄,MFC中把和DC相关的封装成类.其中CDC是一个抽象基类,可以访问整个显示器和打印机.其中下面链接中的文章详细描述了CBitmap、HBitmap、Bitmap三者的区别与联系.http://blog.csdn.net/ivan_ljf/article/details/8569130

三.MFC显示BMP图片

下面将详细讲解使用VS2012 MFC创建工程的具体步骤:
第一步:新建项目"MFC应用程序",项目名为ShowBMP,在应用程序类型中选择"单个文档",点击"确定".在右栏的"资源视图"中,点击"Menu->IDR_MAINFRAM"可以查看并修改菜单视图.
第二步:向CShowBMPView类添加成员变量和成员函数.在右栏的"类视图"右键CShowBMPView添加函数或直接在ShowBMPView.h中直接添加public成员变量和成员函数.添加代码如下:

 
  1. public:

  2. //成员变量

  3. CString BmpName; //保存图像文件文件名

  4. CString EntName; //保存图像文件扩展名

  5. CBitmap m_bitmap; //创建位图对象

  6.  
  7. //成员函数

  8. void ShowBitmap(CDC* pDC,CString BmpName); //用来显示指定位图bmp的函数

第三步:设置打开BMP图片函数."项目"->"类向导"->选择"类名"CShowBMPView->在命令对象ID中双击"ID_FILE_OPEN"->自动生成默认成员函数OnFileOpen,消息为COMMAND.双击成员函数(Member Functions)进入函数编辑.(VC++ 6.0中Ctrl+W可以实现建立类向导)

向添加成员函数CShowBMPView::OnFileOpen()添加如下代码,主要是生成打开图片的对话框,并获取图片路径及后缀.自定义四种格式为bmp gif jpg tiff,但目前只能打开bmp格式图片.

 
  1. //**************文件打开****************//

  2. void CShowBMPView::OnFileOpen()

  3. {

  4. //四种格式的文件:bmp gif jpg tiff

  5. CString filter;

  6. filter="所有文件(*.bmp,*.jpg,*.gif,*tiff)|*.bmp;*.jpg;*.gif;*.tiff| BMP(*.bmp)|*.bmp| JPG(*.jpg)|*.jpg| GIF(*.gif)|*.gif| TIFF(*.tiff)|*.tiff||";

  7. CFileDialog dlg(TRUE,NULL,NULL,OFN_HIDEREADONLY,filter,NULL);

  8.  
  9. //按下确定按钮 dlg.DoModal() 函数显示对话框

  10. if( dlg.DoModal() == IDOK )

  11. {

  12. BmpName = dlg.GetPathName(); //获取文件路径名 如D:\pic\abc.bmp

  13. EntName = dlg.GetFileExt(); //获取文件扩展名

  14. EntName.MakeLower(); //将文件扩展名转换为一个小写字符

  15. Invalidate(); //调用该函数就会调用OnDraw重绘画图

  16. }

  17. }

第四步:在ShowBMPView.cpp中编写void CShowBMPView::ShowBitmap(CDC *pDC, CString BmpName)函数,即“二.显示BMP图片基本步骤”.同时通过OnDraw()函数调用ShowBitmap()函数显示图片.代码如下:

 
  1. //在OnDraw函数中调用ShowBitmap()实现图片的显示功能

  2. void CShowBMPView::OnDraw(CDC* pDC)

  3. {

  4. CShowBMPDoc* pDoc = GetDocument();

  5. ASSERT_VALID(pDoc);

  6. if (!pDoc)

  7. return;

  8.  
  9. // TODO: 在此处为本机数据添加绘制代码

  10.  
  11. if( EntName.Compare(_T("bmp")) == 0 ) //bmp格式

  12. {

  13. ShowBitmap(pDC,BmpName); //显示图片

  14. }

  15. }

四.运行结果及总结

运行程序后,显示如下所示:其中可以看到自定义的打开对话框和显示图片.

  

最后,该文章主要是数字图像处理的基础知识,详细介绍了BMP图片格式和使用MFC如何读取BMP图片的相关知识.

 

//

转载:https://blog.csdn.net/eastmount/article/details/18238863


http://chatgpt.dhexx.cn/article/iJnSC4JU.shtml

相关文章

bmp格式说明

bmp24位位图格式 创建bmp24位位图格式的图片 打开Windows系统自带的画图软件,如下: 点击“文件 > 另存为”,在弹出的界面中有4种bmp格式可以选择,如下: 不知道bmp格式是不是只有上面的4种,还是有更多…

如何批量将 bmp 格式图片转换为 png 格式

概要:bmp 格式是纹的操作系统当中非常常见的一种图片格式,这种格式的特点是包含的图像信息较丰富,几乎不进行压缩,所以导致了它存在一个很大的缺点,那就是占用磁盘空间过大,那么我们怎么将 bmp 格式的图片转…

将BMP 格式图片转换为 JPEG 格式【c语言】

源码链接: https://blog.csdn.net/qq_44394952/article/details/122587475?spm1001.2014.3001.5502. 一、任务及目标 利用c语言,通过将 RGB 信息转换为 YCrCb 信息、离散余弦变化、量化和 z 型编码,再进行游程编码和霍夫曼编码,最后进行尾…

如何批量将 bmp 格式图片转换转换为 jpg

概要:png 和 jpg 这两种格式的图片相信大家都非常熟悉,但是 bmp 格式的图片可能大家接触得并没有那么多,bmp 是 Windows 操作系统中的标准图像文件格式,能够被多种 Windows 应用程序所支持,因此格式的图片在 Windows 操…

bmp格式图的解析

文章目录 前言 一、bmp格式图的特点 二、bmp格式图的解析 总结 前言 在图像处理中经常会遇到BMP格式图的解析问题,本文简单介绍了bmp格式图的解析方式,并附上相应的C代码。 一、bmp格式图的特点 bmp图通常由图片的头文件信息和像素数据组成&#xff0c…

R语言与多元线性回归分析计算实例

6.3.7 计算实例 例 6.9 某大型牙膏制造企业为了更好地拓展产品市场,有效地管理库存,公司董事会要求销售部门根据市场调查,找出公司生产的牙膏销售量与销售价格,广告投入等之间的关系,从而预测出在不同价格和广告费用下…

多元线性回归检验

多元线性回归模型通常用来研究一个应变量依赖多个自变量的变化关系,如果二者的以来关系可以用线性形式来刻画,则可以建立多元线性模型来进行分析。 1.t检验 t检验是对单个变量系数的显著性检验,一般看p值; 如果p值小于0.05表示该…

[DataAnalysis]多元线性回归深入浅出-案例+模型假设+参数估计方法+模型评判方法+变量选择+多重共线性问题

一、案例介绍 1、目的:利用上市公司当年的公开财务指标预测来年盈利情况最重要的投资人决策依据。 2、数据来源:随机抽取深市和沪市2002和2003年的500个上市公司样本预测来年的净资产收益率。 3、解释变量包括:资产周转率、当年净资产收益…

基于spss的多元回归分析模型

还是数学建模中的一个小问题,具体概念分析在百度上的大佬说的已经足够详细,在此不再赘述。 链接: 多元回归分析. 我主要根据实例讲解如何通过spss进行建模,并进行模型参数的分析和验证。 打开spss(如果遇到打不开的情况&#x…

多元线性回归分析预测法概述

在市场的经济活动中,经常会遇到某一市场现象的发展和变化取决于几个影响因素的情况,也就是一个因变量和几个自变量有依存关系的情况。而且有时几个影响因素主次难以区分,或者有的因素虽属次要,但也不能略去其作用。例如&#xff0…

用R进行多元线性回归分析建模

概念:多元回归分析预测法,是指通过对两个或两个以上的自变量与一个因变量的相关分析,建立预测模型进行预测的方法。当自变量与因变量之间存在线性关系时,称为多元线性回归分析。 下面我就举几个例子来说明一下 例一:谋…

基于Python的多元线性回归分析

一、多元线性回归分析(Multiple regression) 1.与简单线性回归相比较,具有多个自变量x 2.多元回归模型 其中是误差值,与简单线性回归分析中的要求特点相一致。其余的系数和截距为参数。 3.多元回归方程 4.估计多元回归方程(点估…

多元线性回归--案例分析及python实践

回归分析--多元回归 介绍一下多元回归分析中的统计量 总观测值总自变量自由度:回归自由度 ,残差自由度 SST总平方和 SSR回归平方和 SSE残差平方和 MSR均方回归 MSE均方残差 判定…

回归分析:多元线性回归模型 白话解析与案例实现

文章目录 线性学习多元线性回归模型多元线性回归模型的python实现 线性学习 回归分析是研究自变量x与因变量y的关系的方法。 上一节我们介绍了一元线性回归,经验公式为: $ \hat{y}\hat{\beta}1 x\hat{\beta}0 $ 在实际生活中,我们要研究的…

多元统计分析——多元线性回归

1. 经典的线性回归分析与交叉验证 examDict{ 学习时 :[0.50, 0.75, 1.00, 1.25,1.50,1.75, 1.75,2.00, 2.25,2.50, 2.75,3.00,3.25,3.50,4.00,4.25,4.50,4.75,5.00,5.50], 分:[10,22,13 ,43,20,22,33,50,62 , 48,55,75,62,73,81,76,64,82,90,93]} examDf pd.DataFrame(examDi…

spss进行多元线性回归并分析表格(转载)

1.如何使用spss进行多元线性回归。 2.分析生成结果,并判断回归是否可行。 一、使用spss进行多元线性回归: 1.输入数据 二、表格结果分析: R方是检验回归是否成功的重要要素之一,DW是残差独立性检验,衡量标准如下&…

数据分析方法--回归分析方法((SPSS建模:多元线性回归案例)

文章目录 回归定义最常用回归方法一、线性回归(Linear Regression)二、逻辑回归(Logistic Regression)三、多项式回归(Polynomial Regression)四、逐步回归(Stepwise Regression)五、岭回归(Ridge Regression)六、套索回归(Lasso Regression)七、回归(ElasticNet) 如何正确选择…

线性回归 - 多元线性回归案例 - 分析步骤、输出结果详解、与Python的结果对比 -(SPSS建模)

现在用 Python 写线性回归的博客都快烂大街了,为什么还要用 SPSS 做线性回归呢?这就来说说 SPSS 存在的原因吧。 SPSS 是一个很强大的软件,不用编程,不用调参,点巴两下就出结果了,而且出来的大多是你想要的…

SPSS--回归-多元线性回归模型案例解析!(一)

SPSS--回归-多元线性回归模型案例解析!(一) 多元线性回归,主要是研究一个因变量与多个自变量之间的相关关系,跟一元回归原理差不多,区别在于影响因素(自变量)更多些而已,例如&#x…

多元回归分析(线性回归)

多元线性回归分析 一、回归的基本理解(1)回归的基本任务(2)回归里的关键词(3)回归里的数据类型(4)回归方程中的系数解释(5)扰动项要满足的条件(1&…