收藏 分享(赏)

VC++数字图像处理.pdf

上传人:HR专家 文档编号:6299152 上传时间:2019-04-05 格式:PDF 页数:72 大小:849.98KB
下载 相关 举报
VC++数字图像处理.pdf_第1页
第1页 / 共72页
VC++数字图像处理.pdf_第2页
第2页 / 共72页
VC++数字图像处理.pdf_第3页
第3页 / 共72页
VC++数字图像处理.pdf_第4页
第4页 / 共72页
VC++数字图像处理.pdf_第5页
第5页 / 共72页
点击查看更多>>
资源描述

1、科研导航 http:/ Visual C+数字图像处理 广义地讲,凡是记录在纸介质上的、拍摄在底片和照片上的、显示在电视、投影仪和计算机屏幕上的所有具有视觉效果的画面都可以称为图像。根据图像记录方式的不同,图像可分为两大类:一类是模拟图像( Analog Image),另一类是数字图像( Digital Image)。模拟图像是通过某种物理量(光、电等)的强弱变化来记录图像上各点的亮度信息的,例如模拟电视图像;而数字图像则完全是用数字(即计算机存储的数据)来记录图像亮度信息的。 所谓数字图像处理( Digital Image Processing),就是指用数字计算机及其他相关的数字技术,对数

2、字图像施加某种或某些运算和处理,从而达到某种预期的处理目的。随着数字技术和数字计算机技术的飞速发展,数字图像处理技术在近 20多年的时间里,迅速发展成为一门独立的有强大生命力 的学科,其应用领域十分广泛。 作为数字图像处理技术的实现环节,本书将在 Visual C+环境下介绍图像各种典型算法的编程实现。而作为一本书的开始,本章我们将介绍图像编程的基础知识,如数字图像的点阵数据、调色板概念、 BMP 文件结构以及设备无关位图( DIB)等,它是后面章节学习的基础。 1.1 图像、颜色表和色彩空间 1.1.1 图像 组成数字图像的基本单位是像素( Pixel),也就是说,数字图像是像素的集合。如图

3、 1-1所示,图中每个格点代表一个像素,该图是一个白色背景下包含灰色矩形的图像。 图 1-1 放大后的矩形图像 数字图像通常存放在计算机的外存储器设备中,例如硬盘、光盘等,在需要进行显示和处理时才被调入内存的数组中。从本质上讲,图像数据在计算机内存或硬盘中是以字符型数据存在的,这与其他整型数据或者浮点型数据没有任何区别,都是一种数字表达符号,当把它在计算机屏幕上显示出来时,才是我们人眼看到的真正有意义的数字图像。普通的显示器屏幕也是由许多点科研导航 http:/ (像素)构成的,显示时,电子枪每次从左到右、从上到下进行扫描,为每个像素着色,利用人眼的视觉暂留效应就可以显示出一屏完整的图像。比如

4、,我们常说的屏幕 分辨率为 1024768,刷新率为 80Hz,意思是说屏幕上每行像素为 1024个,共 768行,而且每秒重复扫描 80次。目前的显示设备的刷新率都在 80Hz以上,一般屏幕刷新频率大于 80Hz时,人眼感受不到屏幕刷新而产生的闪烁,这种显示器被称为位映像设备。所谓位映像,即是指一个二维的像素矩阵,而位图就是采用位映像方法显示和存储的图像。一幅图像的显示就是将图像的像素映射到屏幕的像素上并显示一定的颜色。 图 1-1所示是一个灰度图像的例子,当一幅图像的像素由彩色表示时就是我们通常所说的彩色图像了。对于彩色图像的表达,将在调色板和彩色空间两部分内容中谈到。 1.1.2 图像的

5、矩阵表示 数字图像数据可以用矩阵来表示,因此可以采用矩阵理论和矩阵算法对数字图像进行分析和处理。最典型的例子是灰度图像,如图 1-2所示。灰度图像的像素数据就是一个矩阵,矩阵的行对应图像的高(单位为像素),矩阵的列对应图像的宽(单位为像素),矩阵的元素对应图像的像素,矩阵元素的值就是像素的灰度值。 图 1-2 数字图像与图像矩阵 由于数 字图像可以表示为矩阵的形式,所以在计算机数字图像处理程序中,通常用二维数组来存放图像数据,参见图 1-3。二维数组的行对应图像的高,二维数组的列对应图像的宽,二维数组的元素对应图像的像素,二维数组元素的值就是像素的灰度值。采用二维数组来存储数字图像,符合二维图

6、像的行列特性,同时也便于程序的寻址操作,使得计算机图像编程十分方便。 科研导航 http:/ 图 1-3 数字图像与二维数组 1.1.3 颜色表 图像的位图数据是一个二维数组(矩阵),矩阵的每一个元素对应了图像的一个像素,当保存一幅图像时,不但要保存图像的位图数据矩阵,还要将每个像素的颜色保存下来,颜色的记录是利用颜色表来完成的。 颜色表,也叫颜色查找表,是图像像素数据的颜色索引表。以一个 4色位图为例,则其颜色表有 4个表项,表中每一行记录一种颜色的 R、 G、 B值,这样,当表示一个像素的颜色时,只需要指出该颜色在第几行,即该颜色在表中的索引值即可。假设该 4色位图的颜色表如表 1-1 所

7、示,并假设该 4色位图大小为 8行 8列,其图像数据阵列如图 1-4所示。 表 1-1 4 色位图的颜色表 颜色索引值 蓝色成分 绿色成分 红色成分 0 0 0 0 1 255 0 0 2 0 255 0 3 0 0 255 图 1-4 4 色位图数据矩阵 该位图有 4种颜色(最多也只能有 4种颜色),对于位图矩阵中第 3行第 4列的像素,该像素的值为 2,则其颜色由颜色表第 3行决定(索引值从 0开始),该行的颜色为绿色( 0, 255, 0)。为了简单起见,上面颜色表的例子每一个记录只有 3个分量 R、 G、 B,实际上,真正一幅 BMP图像其颜色表的每一个记录是由 4个分量组成的,这在

8、1.2.1节 “BMP 文件结构 ”中有详细介绍。 科研导航 http:/ 有一个特例,对于真彩色图像,每个像素占存储空间 3 个字节( 24 位),分别对应 R、 G、B 三个分量,每个像素的值已经将该像素的颜色记录下来了,不再需要颜色表,因 此 24位真彩色位图没有颜色表。 1.1.4 彩色空间 自然界中的所有颜色都可以由红、绿、蓝( R、 G、 B)三种颜色合成,数字图像也是如此。针对红(绿 /蓝)分量的多少,人为地划分为 0 255共 256 个等级, 0 表示不含红色(绿 /蓝)成分, 255表示含有 100%红色(绿 /蓝)成分。根据红、绿、蓝各种不同的组合就能表示 2562562

9、56 种颜色,例如一个像素,当它的红、绿、蓝成分分别为 255、 0、 255时显示为紫色。而对于灰度图像的像素,该像素的红、绿、蓝成分是相等的,只不过随着这三个分量数值的增大,像素颜色从黑色变成白色。 从上面介绍可知,彩色数字图像可以由 RGB彩 色空间表示。彩色空间是用来表示彩色的数学模型,又被称为彩色模型。 RGB彩色空间是最常用的一种彩色空间,但在计算机系统中表达颜色信息的空间不止这一种,此处介绍 3种最常用的彩色空间。 1 RGB 彩色空间 几乎所有的彩色成像设备和彩色显示设备都采用 RGB( Red / Green / Blue,红绿蓝)三基色,不仅如此,数字图像文件的常用存储形式

10、,也以 RGB三基色为主,由 RGB三基色为坐标形成的空间称为 RGB彩色空间。 根据色度学原理,自然界的各种颜色光都可由红、绿、蓝三种颜色的光按不同比例混合而成,同样,自然界的 各种颜色光都可分解成红、绿、蓝三种颜色光,所以将红、绿、蓝三种颜色称为三基色。 图 1-5所示是 RGB 三基色合成其他颜色的典型例子和 RGB彩色空间以及基色间的关系。由图 1-5( a)可以看出,青色可以由绿色和蓝色合成,洋红(或品红)可以由红色和蓝色合成,黄色可以由红色和绿色合成,而青色、洋红和黄色恰好是 CMY( Cyan/Magenta/Yellow)三基色。当 RGB三基色以等比例或等量进行混合时,可以得

11、到黑、灰或白色,而采用不同比例进行混合时,就得到千变万化的颜色。 科研导航 http:/ 洋红 红 蓝 ( a) RGB 三基色混色 ( b) RGB 彩色空间 ( c) RGB 三基色二维对称表示 图 1-5 三基色原理图 在 RGB彩色空间中,任意彩色光 L的配色方程参见公式( 1-1)。 ( 1-1) 其中, 、 、 为彩色光 L的三基色分量或百分比。 2 CMY 彩色空间 自然界物体颜色光的形成方式将物体划分为两类 发光物体和不发光物体,发光物体称为有源物体,不发光物体称为无源物体。有源物体是自身发出光波的物体,其颜色由物体发出的光波决定,因此采用 RGB三基色相加模型和 RGB彩色空

12、间描述。有源物体的例子包括彩色电视、彩色显示器等。 无源物体是不发出光波的物体,其颜色由该物体吸收或反射哪些光波来决定,因此采用 CMY 三基色相减模型和 CMY 彩色空间描述。例如,在彩色印刷和彩色打印时,纸张是不能发射光线而只能反射光线的,因此,彩色印刷机和彩色打印机只能通过一些能够吸收特定光波和反射其他光波的油墨和颜料以及它们的不同比例的混合来印出千变万化的颜色。 科研导航 http:/ 油墨和颜料的三基色是 CMY( Cyan / Magenta / Yellow,青 /洋红 /黄)而不是 RGB, CMY三基色的特点是油墨和颜料用得越多,颜色越暗(或越黑),所以将 CMY称为三减色,

13、而 RGB称为三加色。理论上讲,等量的 CMY可以合成黑色,但实际上纯黑色是很难合成出来的,所以彩色印刷机和彩色打印机要提供专门的黑色油墨,被人们称为四色印刷,四色印刷的彩色模型为 CMYK模型。 3 HSI 彩色空间 另一种常见的彩色模型是 HSI( Hue / Saturation / Intensity,色调 /饱和度 /强度)模型。采用色调和饱和度来描述颜色,是从人类的色视觉机理出发提出的。 色调 Hue表示颜色,颜色与彩色光的波长有关,将颜色按红橙黄绿青蓝紫顺序排列定义色调值,并且用角度值( 0 360)来表示。例如红、黄、绿、青、蓝、洋红的角度值分别为 0、60、 120、 180

14、、 240 和 300。 饱和度 Saturation表示色的纯度,也就是彩色光中搀杂白光的程度。白光越多饱和度越低,白光越少饱和度越高且颜色越纯。饱和度的取值采用百分数( 0% 100%), 0%表示灰色光或白光, 100%表示纯色光。 强度 Intensity表示人眼感受到彩色光的颜色的强弱程度,它与彩色光的能量大小(或彩色光的亮度)有关,因此有时也用亮度 Brightness 来表示。 通常把色调和饱和度统称为色度,用来表示颜色的类别与深浅程度。人类的视觉系统对亮度的敏感程度远强于对颜色浓淡的敏感程度,对比 RGB彩色空间,人类的视觉系统的这种特性采用 HSI彩色空间来解释更为适合。 H

15、SI彩色描述对人来说是自然的、直观的,符合人的视觉特性, HSI模型对于开发基于彩色描述的图像处理方法也是一个较为理 想的工具,例如在 HSI彩色空间中,可以通过算法直接对色调、饱和度和亮度独立地进行操作。采用 HSI彩色空间有时可以减少彩色图像处理的复杂性,提高处理的快速性,同时更接近人对彩色的认识和解释。 科研导航 http:/ 图 1-6 HSI 彩色空间示意图 HSI彩色空间是一个圆锥型空间模型,如图 1-6( a)所示。圆锥模型可以将色调、强度以及饱和度的关系变化清楚地表现出来。圆锥型空间的竖直轴表示光强 I,顶部最亮表示白色,底部最暗表示黑色,中间是在最亮和最暗之间过渡的灰度。圆锥

16、型空间中部的水平面圆周是表示色调 H的角度坐标,如图 1-6( b)所示。 在处理彩色图像时,为了处理方便,经常要把 RGB三基色表示的图像数据转换成 HSI数据。RGB 彩色空间转换到 HSI 彩色空间的转换公式参见( 1-2)式、( 1-3)式、( 1-4)式。 ( 1-2) ( 1-3) 其中, ( 14) 1.1.5 灰度图像和彩色图像 计算机上显示的图像经常有二值图像、灰度图像、伪彩色图像及真彩色图像等不同格式类型。而灰度和彩色格式是数字图像处理中最常用到的类型,本书所涉及的各种图像处理算法都是以这两种类型图像为处理对象的。 1灰度图像 科研导航 http:/ 灰度图像是数字图像的最

17、基本形式,灰度图像可以由黑白照片数字化得到,或从彩色图像进行去色处理得到。灰度图像只表达图像的亮度信息而没有颜色信息,因此,灰度图像的每个像素点上只包含一个量化的灰度级(即灰度值),用来表示该点的亮度水平,并且通常用 1个字节( 8个二进制位)来存储灰度值。 如果灰度值用 1个字节表示,则可以表示的正整数范围是 0 255,也就是说,像素灰度值取值在 0 255之间,灰度级数为 256级。注意到人眼对灰度的分辨能力通常在 20 60级,因此,灰度值存储以字节为单位既保证了人眼的分辨能力,又符合计算机 数据寻址的习惯。在特殊应用中,可能需要采用更高的灰度级数,例如 CT图像的灰度级数高达数千,需

18、要采用 12位或 16位二进制位存储数据,但这类图像通常都采用专用的显示设备和软件来进行显示和处理。 2彩色图像 彩色图像的数据不仅包含亮度信息,还包含颜色信息。彩色的表示方法是多样化的,最常见的是三基色模型,例如 RGB( Red / Green / Blue,红绿蓝)三基色模型,利用 RGB 三基色可以混合成任意颜色。因此, RGB模型在各种彩色成像设备和彩色显示设备中使用,常规的彩色图像也都是用 RGB三基色来表示的,每个像 素包括 RGB三基色数据,每个基色用 1 个字节( 8位二进制位)表示,则每个像素的数据为 3 个字节(即 24位二进制位),这就是人们常说的 24 位真彩色。 1

19、.2 BMP 文件结构及其存取 数字图像在外存储器设备中的存储形式是图像文件,图像必须按照某个已知的、公认的数据存储顺序和结构进行存储,才能使不同的程序对图像文件顺利进行打开或存盘操作,实现数据共享。图像数据在文件中的存储顺序和 结构称为图像文件格式。目前广为流传的图像文件格式有许多种,常见的格式包括 BMP、 GIF、 JPEG、 TIFF、 PSD、 DICOM、 MPEG等。在各种图像文件格式中,一部分是由某个软硬件厂商提出并被广泛接受和采用的格式,例如 BMP、 GIF 和 PSD格式;另一部分是由各种国际标准组织提出的格式,例如 JPEG、 TIFF和 DICOM,其中 JPEG是国

20、际静止图像压缩标准组织提出的格式, TIFF 是由部分厂商组织提出的格式, DICOM 是医学图像国际标准组织提出的医学图像专用格式。 BMP文件是 Windows 操作系统所推荐和支 持的图像文件格式,是一种将内存或显示器的图像数据不经过压缩而直接按位存盘的文件格式,所以称为位图( bitmap)文件,因其文件扩展名科研导航 http:/ 为 BMP,故称为 BMP文件格式,简称 BMP文件。本书对图像的算法编程都是针对 BMP 图像文件的,因此在本章中我们详细介绍 BMP文件结构及其读写操作,以加深对图像数据的理解。 1.2.1 BMP 文件结构 如图 1-7所示, BMP 图像文件被分成

21、 4 个部分:位图文件头( Bitmap File Header)、位图信息头( Bitmap Info Header)、颜色表( Color Map) 和位图数据(即图像数据, Data Bits或 Data Body)。 第 1部分为位图文件头 BITMAPFILEHEADER,是一个结构体类型,该结构的长度是固定的,为 14个字节。其定义如下: typedef struct tagBITMAPFILEHEADER WORD bfType; DWORD bfSize; WORD bfReserved1; WORD bfReserved2; DWORD bfOffBits; BITMAPFI

22、LEHEADER, FAR *LPBITMAPFILEHEADER, *PBITMAPFILEHEADER; BITMAPFILEHEADER 结构的各个域详细说明如下: bfType:位图文件类型,必须是 0x424D,即字符串 “BM”,也就是说,所有的 “*.bmp”文件的头两个字节都是 “BM”。 bfSize:位图文件大小,包括这 14 个字节。 bfReserved1, bfReserved2: Windows 保留字,暂不用。 bfOffBits:从文件头到实际的位图数据 的偏移字节数,图 1-7 中前 3 个部分的长度之和。 科研导航 http:/ 图 1-7 BMP 文件结构

23、示意图 第 2部分为位图信息头 BITMAPINFOHEADER,也是一个结构体类型的数据结构,该结构的长度也是固定的,为 40个字节( WORD为无符号 16位整数, DWORD 为无符号 32位整数, LONG为 32位整数)。其定义如下: typedef struct tagBITMAPINFOHEADER DWORD biSize; LONG biWidth; LONG biHeight; WORD biPlanes; WORD biBitCount DWORD biCompression; DWORD biSizeImage; LONG biXPelsPerMeter; LONG b

24、iYPelsPerMeter; DWORD biClrUsed; DWORD biClrImportant; BITMAPINFOHEADER, FAR *LPBITMAPINFOHEADER, *PBITMAPINFOHEADER; BITMAPINFOHEADER 结构的各个域的详细说明如下: biSize:本结构的长度,为 40 个字节。 biWidth:位图的宽度,以像素为单位。 科研导航 http:/ biHeight:位图的高度,以像素为单位。 biPlanes:目标设备的级别,必须是 1。 biBitCount:每个像素所占的位数( bit),其值必须为 1(黑白图像)、 4(

25、16 色图)、 8( 256色)、 24(真彩色图),新的 BMP 格式支持 32 位色。 biCompresssion:位图压缩类型,有效的值为 BI_RGB(未经压缩)、 BI_RLE8、 BI_RLE4、 BI_BITFILEDS(均为 Windows 定义常量)。这里只讨论未经压缩的情况,即 biCompression=BI_RGB。 biSizeImage:实际的位图数据占用的字节数,该值的大小在第 4 部分位图数据中有具体解释。 biXPelsPerMeter:指定目标设备的水平分辨率,单位是像素 /米。 biYPelsPerMeter:指定目标设备的垂直分辨率,单位是像素 /米。

26、 biClrUsed:位图实际用到的颜色数,如果该值为零,则用到的颜色数为 2 的 biBitCount 次幂。 biClrImportant:位图显示过程中重要的颜色数,如果该值为零,则认为所有的颜色都是重要的。 第 3部分为颜色表。颜色表实际上是一个 RGBQUAD结构的数组,数组的长度由 biClrUsed指定(如果该值为零,则由 biBitCount指定,即 2的 biBitCount 次幂个元素)。 RGBQUAD 结构是一个结构体类型, 占 4个字节,其定义如下: typedef struct tagRGBQUAD BYTE rgbBlue; BYTE rgbGreen; BYTE

27、 rgbRed; BYTE rgbReserved; RGBQUAD; RGBQUAD结构的各个域的详细说明如下: rgbBlue:该颜色的蓝色分量; rgbGreen:该颜色的绿色分量; rgbRed:该颜色的红色分量; rgbReserved:保留字节,暂不用。 有些位图需要颜色表;有些位图(如真彩色图)则不需要颜色表,颜色表的长度由 BITMAPINFOHEADER 结构中 biBitCount 分量决定。对于 biBitCount值为 1的二值图像,每像素占 1bi科研导航 http:/ t,图像中只有两种(如黑白)颜色,颜色表也就有 21=2个表项,整个颜色表的大小为个字节;对于 b

28、iBitCount值为 8的灰度图像,每像素占 8bit,图像中有 28=256种颜色,颜色表也就有 256个表项,且每个表项的 R、 G、 B分量相等,整个颜色表的大小为 个字节;而对于 biBitCount=24 的真彩色图像,由于每像素 3个字节中分别代表了 R、 G、 B三分量的值,此时不需要颜色表,因此真彩色图的 BITMAPINFOHEADER 结构后面直接就是位图数据。 第 4部分是位图数据,即图像数据,其紧跟在位图文件头、位图信息头和颜色表(如果有颜色表的话)之后,记录了图像的每一个像素值。对于有颜色表的位图,位图数据就是该像素颜色在调色板中的索引值;对于真彩色图,位图数据就是

29、实际的 R、 G、 B值(三个分量的存储顺序是 B、 G、 R)。下面分别就 2色、 16色、 256色和真彩色位图的位图数据进行说明: 对于 2 色位图,用 1 位就可以表示该像素的 颜色,所以 1 个字节能存储 8 个像素的颜色值。 对于 16 色位图,用 4 位可以表示一个像素的颜色。所以一个字节可以存储 2 个像素的颜色值。 对于 256 色位图, 1 个字节刚好存储 1 个像素的颜色值。 对于真彩色位图, 3 个字节才能表示 1 个像素的颜色值。 需要注意两点: 第一, Windows规定一个扫描行所占的字节数必须是 4的倍数,不足 4的倍数则要对其进行扩充。假设图像的宽为 biWi

30、dth个像素、每像素 biBitCount个比特,其一个扫描行所占的真实字节数的计算公式如下: DataSizePerLine = (biWidth * biBitCount /8+ 3) / 4*4 那么,不压缩情况下位图数据的大小( BITMAPINFOHEADER结构中的 biSizeImage 成员)计算如下: biSizeImage = DataSizePerLine * biHeight 第二,一般来说, BMP文件的数据是从图像的左下角开始逐行扫描图像的,即从下到上、从左到右,将图像的像素值一一记录下来,因此图像坐标零点在图像左下角。 1.2.2 BMP 图像文件的读写 科研导航

31、 http:/ 分析了 BMP文件结构后,让我们用简单的 C程序实现一个给定 BMP位图文件的读写操作,来进一步巩固对图像数据的理解,这也是我们后续图像可视化编程的基础。此部分的代码以及后面两节所讲述的代码在工程 chap1-1中的 bmpReadWrite.cpp 文件中,读者可以查阅。 1 BMP 文件的读入 BMP文件分为 4个组成部分,那么 BMP文件的读入也要按照 4个组成部分依次进行处理,即先处理 BITMAPFILEHEADER 结构,然后是 BITMAPINFOHEADER 结构、颜色表,最后是位图数据。 首先,有关 BITMAPFILEHEADER、 BITMAPINFOHE

32、ADER、 RGBQUAD 等结构的定义包含在头文件“Windows.h” 中,应把其包含进来。 #include “Windows.h“ 其次,为了后面对图像进行修改及存盘方便,我们定义了几个全局变量,用来存放读入图像的位图数据、宽、高、颜色表及每像素位数等信息。所定义的全局变量如下: unsigned char *pBmpBuf;/读入图像数据的指针 int bmpWidth;/图像的宽 int bmpHeight;/图像的高 RGBQUAD *pColorTable;/颜色表指针 int biBitCount;/图像类型,每像素位数 根据 BMP文件结构, BMP文件读入操作的基本流程如

33、图 1-8 所示。 图 1-8 BMP 文件读入操作流程图 科研导航 http:/ readBmp()函数实现了 BMP文件的读取操作,下面的代码是对 readBmp()函数的说明和实现。 /* * 函数名称: * readBmp() * *函数 参数: * char *bmpName -文件名字及路径 * *返回值: * 0 为失败, 1 为成功 * *说明:给定一个图像文件名及其路径,读图像的位图数据、宽、高、颜色表及每像素 * 位数等数据进内存,存放在相应的全局变量中 */ bool readBmp(char *bmpName) /二进制读方式打开指定的图像文件 FILE *fp=fop

34、en(bmpName,“rb“); if(fp=0) return 0; /跳过位图文件头结构 BITMAPFILEHEADER fseek(fp, sizeof(BITMAPFILEHEADER),0); /定义位图信息头结构变量,读取位图信息头进内存,存放在变量 head 中 BITMAPINFOHEADER head; fread( /获取图像宽、高、每像素所占位数等信息 科研导航 http:/ bmpWidth = head.biWidth; bmpHeight = head.biHeight; biBitCount = head.biBitCount; /定义变量,计算图像每行像素所

35、占的字节数(必须是 4 的倍数) int lineByte=(bmpWidth * biBitCount/8+3)/4*4; /灰度图像有颜色表,且颜色表表项为 256 if(biBitCount=8) /申请颜色表所需要的空间,读颜色表进内存 pColorTable=new RGBQUAD256; fread(pColorTable,sizeof(RGBQUAD),256,fp); /申请位图数据所需要的空间,读位图数据进内存 pBmpBuf=new unsigned charlineByte * bmpHeight; fread(pBmpBuf,1,lineByte * bmpHeight

36、,fp); /关闭文件 fclose(fp); return 1; 2 BMP 文件的存盘 给定图像路径名以及图像的数据,对图像的写操作也是按照 BMP文件 4个组成部分进行分别处理的。其基本流程如图 1-9所示。 saveBmp()函数实现了 BMP文件的写操作,该函数的说明及代码实现如下。 /* * 函数名称: * saveBmp() * *函数参数: 科研导航 http:/ * char *bmpName-文件名字及路径 * unsigned char *imgBuf-待存盘的位图数据 * int width-以像素为单位待存盘位图的宽 * int height-以像素为单位待存盘位图高

37、 * int biBitCount-每像素所占位数 * RGBQUAD *pColorTable-颜色表指针 *返回值: * 0 为失败, 1 为成功 * *说明:给定一个图像位图数据、宽、高、颜色表指针及每像素所占的位数等信息, * 将其写到指定文件中 */ bool saveBmp(char *bmpName, unsigned char *imgBuf, int width, int height, int biBitCount, RGBQUAD *pColorTable) /如果位图数据指针为 0,则没有数据传入,函数返回 if(!imgBuf) return 0; /颜色表大小,以字

38、节为单位 ,灰度图像颜色表为 1024 字节,彩色图像颜色表大小为 0 int colorTablesize=0; if(biBitCount=8) colorTablesize=1024; /待存储图像数据每行字节数为 4 的倍数 int lineByte=(width * biBitCount/8+3)/4*4; /以二进制写的方式打开文件 FILE *fp=fopen(bmpName,“wb“); if(fp=0) return 0; /申请位图文件头结构变量,填写文件头信息 科研导航 http:/ BITMAPFILEHEADER fileHead; fileHead.bfType =

39、 0x4D42;/bmp 类型 /bfSize 是图像文件 4 个组成部分之和 fileHead.bfSize= sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + colorTablesize + lineByte*height; fileHead.bfReserved1 = 0; fileHead.bfReserved2 = 0; /bfOffBits 是图像文件前 3 个部分所需空间之和 fileHead.bfOffBits=54+colorTablesize; /写文件头进文件 fwrite( /申请位图信息头结构变量,填写信息头

40、信息 BITMAPINFOHEADER head; head.biBitCount=biBitCount; head.biClrImportant=0; head.biClrUsed=0; head.biCompression=0; head.biHeight=height; head.biPlanes=1; head.biSize=40; head.biSizeImage=lineByte*height; head.biWidth=width; head.biXPelsPerMeter=0; head.biYPelsPerMeter=0; /写位图信息头进内存 fwrite( /如果灰度图像

41、,有颜色表,写入文件 if(biBitCount=8) 科研导航 http:/ fwrite(pColorTable, sizeof(RGBQUAD),256, fp); /写位图数据进文件 fwrite(imgBuf, height*lineByte, 1, fp); /关闭文件 fclose(fp); return 1; 对于 readBmp()和 saveBmp()函数的简单调用如下: void main() /读入指定 BMP 文件进内存 char readPath=“dog.BMP“; readBmp(readPath); /输出图像的信息 printf(“width=%d,heig

42、ht=%d, biBitCount=%dn“,bmpWidth,bmpHeight, biBitCount); /将图像数据存盘 char writePath=“dogcpy.BMP“; saveBmp(writePath, pBmpBuf, bmpWidth, bmpHeight, biBitCount, pColorTable); /清除缓冲区, pBmpBuf 和 pColorTable 是全局变量,在文件读入时申请的空间 delete pBmpBuf; if(biBitCount=8) delete pColorTable; 该 main()函数将指定 BMP文件读入内存,将图像信息打

43、印输出,最后又原样存入指定文件中。读者可以打开程序当前目录下的 “dog.bmp” 和 “dogcpy.bmp” 两个文件进行对比。 以上对于 BMP文件的读写函数仅针对灰度图像( biBitCount=8)和彩色图像( biBitCount=24)两种格式,对于其他如 biBitCount=1的图像类型,读者可以根据需要,自己对程序作简单科研导航 http:/ 的修改即可实现。本书中后续的代码实现也都是围绕灰度和彩色两种格式进行的,希望读者予以注意。 1.2.3 BMP 图像位图数据的访问 上面 main()函数将图像文件读入内存,又写到文件里去,那么在读入图像数据后、写入文件前的一段时间里

44、,图像的数据是在内存中存在的,这也是我们可以修改(访问)图像数据的时机所在。 假设内存中位图数据的指针为 pBmpBuf,一行像素所占的字节数为 lineByte( 4的倍数)那么,对于灰度图像,第 i行第 j列的像素指针(所在的存储空间位置)为 pBmpBuf+i*lineByte+j, *( pBmpBuf+i*lineByte+j)是该像素的灰度值,如果想让该像素变成指定颜色,只需要给*( pBmpBuf+i*lineByte+j)赋指定的值即可;对于彩色图像,每像素占 3个字节,那么 pBmpBuf+i*lineByte+j*3+0、 pBmpBuf+i*lineByte+j*3+1、

45、 pBmpBuf+i*lineByte+j*3+2 分别代表了第 i行第 j列像素 B、 G、 R三个分量的指针,若想给该点指定一种颜色,则需要给三个分量分别赋值。 下面的 main()函数中,将读入的图像数据左下角 1/4部分置成黑色并存盘,图 1-10所示是程序运行前后图像的变化情况。 void main() /读入指定 BMP 文件进内存 char readPath=“dog.BMP“; readBmp(readPath); /输出图像的信息 printf(“width=%d,height=%d,biBitCount=%dn“,bmpWidth,bmpHeight,biBitCount)

46、; /循环变量,图像的坐标 int i,j; /每行字节数 int lineByte=(bmpWidth*biBitCount/8+3)/4*4; 科研导航 http:/ /循环变量,针对彩色图像,遍历每像素的三个分量 int k; /将图像左下角 1/4 部分置成黑色 if(biBitCount=8)/对于灰度图像 for(i=0;iBitBlt(0,0,400,300, /释放 bitmap,恢复原 GDI 位图 dcMemory.SelectObject(oldbitmap); 程序中 BitBlt()函数将 building的像素从内存显示环境复制到显示器(或打印机)设备环境中。 bu

47、ilding位图的尺寸是 300400,在显示器上,它占据了逻辑单位为 300400 的一个矩形区域,并且该区域的左上角位于 Windows 客户区域的( 0, 0)点处。下面是 BitBlt()函数的原型。 Bool BitBlt(int x, int y, int nWidth, int nHeight, CDC* pSrcDC, int xSrc, int ySrc, DWORD dwRop); 其中: 科研导航 http:/ x 和 y 表示绘制区域的左上角坐标,跟显示映射模式有关。 nWidth 表示绘制区域的宽度。 nHeight 表示绘制区域的高度。 pSrcDC 表示要复制位图所在的 CDC 对象指针。 xSrc 和 ySrc 表示原位图要绘制区域的左上角坐标(逻辑单位)。 dwRop 表示绘制方式,此处有多个选项,读者可以查阅相关书籍或 MSDN,此处不赘述。 chap1_2的运行结果如图 1

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 企业管理 > 管理学资料

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报