(完整word版)BMP文件结构读写操作(图文)c实现_第1页
(完整word版)BMP文件结构读写操作(图文)c实现_第2页
(完整word版)BMP文件结构读写操作(图文)c实现_第3页
(完整word版)BMP文件结构读写操作(图文)c实现_第4页
(完整word版)BMP文件结构读写操作(图文)c实现_第5页
已阅读5页,还剩11页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

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

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

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

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

5、P 文件结构示意图第 2 部分为位图信息头 BITMAPINFOHEADER ,也是一个结构体类型的数据结构,该结构的长度也是固定的,为 40个字节( WORD 为无符号 16位整数, DWORD 为无符号 32位整数, LONG 为 32位整数)。其定义如下:DWORD biClrImportant; BITMAPINFOHEADER, FAR *LPBITMAPINFOHEADER, *PBITMAPINFOHEADER;BITMAPINFOHEADER 结构的各个域的详细说明如下: biSize:本结构的长度,为 40 个字节。biWidth :位图的宽度,以像素为单位。biHeight

6、 :位图的高度,以像素为单位。biPlanes:目标设备的级别,必须是 1。biBitCount :每个像素所占的位数( bit ),其值必须为 1(黑白图像)、 4(16 色图)、 8(256 色)、 24(真彩色图),新的 BMP 格式支持 32 位色。biCompresssion :位图压缩类型, 有效的值为 BI_RGB(未经压缩) 、BI_RLE8 、BI_RLE4 、 BI_BITFILEDS (均为 Windows 定义常量)。这里只讨论未经压缩的情况,即 biCompression=BI_RGB 。biSizeImage :实际的位图数据占用的字节数, 该值的大小在第 4 部分

7、位图数据中有具体 解释。biXPelsPerMeter :指定目标设备的水平分辨率,单位是像素/米。biYPelsPerMeter :指定目标设备的垂直分辨率,单位是像素/米。biClrUsed :位图实际用到的颜色数,如果该值为零,则用到的颜色数为 2的 biBitCount 次幂。biClrImportant :位图显示过程中重要的颜色数, 如果该值为零, 则认为所有的颜色都是 重要的。第 3 部分为颜色表。颜色表实际上是一个 RGBQUAD 结构的数组,数组的长度由 biClrUsed 指定(如果该值为零,则由 biBitCount 指定,即 2 的 biBitCount 次幂个元素)。

8、 RGBQUAD 结构是一个结构体类型,占 4 个字节,其定义如下:typedef struct tagRGBQUADBYTE rgbBlue;BYTE rgbGreen;BYTE rgbRed;BYTE rgbReserved; RGBQUAD;RGBQUAD 结构的各个域的详细说明如下:rgbBlue :该颜色的蓝色分量;rgbGreen:该颜色的绿色分量; rgbRed:该颜色的红色分量; rgbReserved:保留字节,暂不用。有些位图需要颜色表;有些位图(如真彩色图)则不需要颜色表,颜色表的长度由BITMAPINFOHEADER 结构中 biBitCount 分量决定。对于 biB

9、itCount 值为 1 的二值图像,每像素占 1bit ,图像中只有两种(如黑白)颜色,颜色表也就有21=2 个表项,整个颜色表的大小为 个字节;对于 biBitCount 值为 8 的灰度图像,每像素占 8bit ,图像中有颜色,颜色表也就有 256 个表项,且每个表项的 R、 G、B 分量相等,整个颜色表的大小为个字节;而对于biBitCount=24 的真彩色图像,由于每像素 3 个字节中分别代表了 R、G、B 三分量的值,此 时不需要颜色表,因此真彩色图的 BITMAPINFOHEADER 结构后面直接就是位图数据。第 4 部分是位图数据,即图像数据, 其紧跟在位图文件头、位图信息头

10、和颜色表(如果 有颜色表的话) 之后,记录了图像的每一个像素值。对于有颜色表的位图, 位图数据就是该 像素颜色在调色板中的索引值;对于真彩色图,位图数据就是实际的R、G 、B 值(三个分量的存储顺序是 B、 G、 R)。下面分别就 2色、 16色、 256 色和真彩色位图的位图数据进 行说明:对于2色位图,用1位就可以表示该像素的颜色, 所以 1个字节能存储 8个像素的颜色 值。对于 16色位图,用 4 位可以表示一个像素的颜色。所以一个字节可以存储2个像素的颜色值。对于 256 色位图, 1个字节刚好存储 1 个像素的颜色值。对于真彩色位图, 3个字节才能表示 1 个像素的颜色值。需要注意两

11、点:第一, Windows 规定一个扫描行所占的字节数必须是 4 的倍数,不足 4 的倍数则要对 其进行扩充。假设图像的宽为 biWidth 个像素、每像素 biBitCount 个比特,其一个扫描行所 占的真实字节数的计算公式如下:DataSizePerLine = (biWidth * biBitCount /8+ 3) / 4*4那么,不压缩情况下位图数据的大小( BITMAPINFOHEADER 结构中的 biSizeImage 成员)计算如下:biSizeImage = DataSizePerLine * biHeight第二,一般来说, BMP 文件的数据是从图像的左下角开始逐行扫

12、描图像的,即从下到上、 从左到右,将图像的像素值一一记录下来,因此图像坐标零点在图像左下角。1.2.2 BMP 图像文件的读写1.2.2 BMP 图像文件的读写分析了 BMP 文件结构后,让我们用简单的 C 程序实现一个给定 BMP 位图文件的读写 操作, 来进一步巩固对图像数据的理解, 这也是我们后续图像可视化编程的基础。 此部分的 代码以及后面两节所讲述的代码在工程 chap1-1 中的 bmpReadWrite.cpp 文件中,读者可以查 阅。1 BMP 文件的读入BMP 文件分为 4 个组成部分,那么 BMP 文件的读入也要按照 4 个组成部分依次进行处 理,即先处理 BITMAPFI

13、LEHEADER 结构,然后是 BITMAPINFOHEADER 结构、颜色表, 最后是位图数据。首先,有关 BITMAPFILEHEADER 、BITMAPINFOHEADER 、 RGBQUAD 等结构的定 义包含在头文件 “ Windows.h”中,应把其包含进来。#include Windows.h其次, 为了后面对图像进行修改及存盘方便, 我们定义了几个全局变量, 用来存放读入图像 的位图数据、宽、高、颜色表及每像素位数等信息。所定义的全局变量如下:unsigned char *pBmpBuf;/ 读入图像数据的指针 int bmpWidth;/ 图像的宽 int bmpHeight

14、;/ 图像的高RGBQUAD *pColorTable;/ 颜色表指针 int biBitCount;/ 图像类型,每像素位数根据 BMP 文件结构, BMP 文件读入操作的基本流程如图 1-8 所示。函数名称:readBmp()readBmp() 函数的说明和函数参数:char *bmpName - 文件名字及路径*返回值:* 0 为失败, 1 为成功*说明:给定一个图像文件名及其路径,读图像 的位图数据、宽、高、颜色表及每像素* 位数等数据进内存, 存放在相应的全局变量 中bool readBmp(char *bmpName) readBmp() 函数实现了 BMP 文件的读取操作,下面的

15、代码是对实现。图 1-8 BMP 文件读入操作流程图/ 二进制读方式打开指定的图像文件 FILE *fp=fopen(bmpName,rb); if(fp=0) return 0;/ 跳过位图文件头结构 BITMAPFILEHEADER fseek(fp, sizeof(BITMAPFILEHEADER),0);/ 定义位图信息头结构变量,读取位图信息头进内存, 存放在变量 head 中BITMAPINFOHEADER head; fread(&head, sizeof(BITMAPINFOHEADER), 1,fp);/ 获取图像宽、高、每像素所占位数等信息 bmpWidth = head.

16、biWidth; bmpHeight = head.biHeight; biBitCount = head.biBitCount;/ 定义变量, 计算图像每行像素所占的字节数 (必须是 4 的倍数)int lineByte=(bmpWidth * biBitCount/8+3)/4*4;/ 灰度图像有颜色表,且颜色表表项为 256 if(biBitCount=8)/ 申请颜色表所需要的空间,读颜色表进内存 pColorTable=new RGBQUAD256; fread(pColorTable,sizeof(RGBQUAD),256,fp);/ 申请位图数据所需要的空间,读位图数据进内存 p

17、BmpBuf=new unsigned charlineByte * bmpHeight; fread(pBmpBuf,1,lineByte * bmpHeight,fp);/ 关闭文件 fclose(fp);return 1;2 BMP 文件的存盘给定图像路径名以及图像的数据,对图像的写操作也是按照BMP 文件 4 个组成部分进行分别处理的。其基本流程如图 1-9 所示。saveBmp()函数实现了 BMP 文件的写操作,该函数的说明及代码实现如下。/* 函数名称:* saveBmp()*函数参数:*char *bmpName- 文件名字及路径*unsigned char *imgBuf-

18、待存盘的位图数据*int width- 以像素为单位待存盘位图的宽*int height- 以像素为单位待存盘位图高*int biBitCount- 每像素所占位数*RGBQUAD *pColorTable- 颜色表指针*返回值:*0 为失败, 1 为成功*说明:给定一个图像位图数据、宽、高、颜色表 指针及每像素所占的位数等信息,* 将其写到指定文件中*/bool saveBmp(char *bmpName, unsigned char*imgBuf, int width, int height,int biBitCount, RGBQUAD *pColorTable)/ 如果位图数据指针为

19、0,则没有数据传入,函数返回 if(!imgBuf) return 0;/ 颜色表大小,以字节为单位,灰度图像颜色表 为 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;/ 申请位图文件头结构变量,填写文件头信息 BITMAPFILEHE

20、ADER fileHead; fileHead.bfType = 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;/ 写文件头

21、进文件fwrite(&fileHead, sizeof(BITMAPFILEHEADER),1, fp); / 申请位图信息头结构变量,填写信息头信息 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;hea

22、d.biXPelsPerMeter=0; head.biYPelsPerMeter=0; / 写位图信息头进内存 fwrite(&head, sizeof(BITMAPINFOHEADER),1, fp);/ 如果灰度图像,有颜色表,写入文件if(biBitCount=8)fwrite(pColorTable, sizeof(RGBQUAD),256, fp);/ 写位图数据进文件fwrite(imgBuf, height*lineByte, 1, fp);/ 关闭文件fclose(fp);return 1;对于 readBmp() 和 saveBmp()函数的简单调用如下:void main

23、()/ 读入指定 BMP文件进内存char readPath=dog.BMP; readBmp(readPath);/ 输出图像的信息 printf(width=%d,height=%d, biBitCount =%dn,bmpWidth,bmpHeight, biBitCount);/ 将图像数据存盘char writePath=dogcpy.BMP; saveBmp(writePath, pBmpBuf, bmpWidth, bmpHeight, biBitCount, pColorTable);/ 清除缓冲区, pBmpBuf和 pColorTable 是 全局变量,在文件读入时申请的空

24、间 delete pBmpBuf;if(biBitCount=8)delete pColorTable;该 main() 函数将指定 BMP 文件读入内存,将图像信息打印输出,最后又原样存入指定文件 中。读者可以打开程序当前目录下的“dog.bmp”和 “dogcpy.bmp”两个文件进行对比。以上对于 BMP 文件的读写函数仅针对灰度图像( biBitCount=8 )和彩色图像( biBitCount=24 )两种格式, 对于其他如 biBitCount=1 的图像类型, 读者可以根据需要,自 己对程序作简单的修改即可实现。 本书中后续的代码实现也都是围绕灰度和彩色两种格式进 行的,希望读

25、者予以注意。1.2.3 BMP 图像位图数据的访问1.2.3 BMP 图像位图数据的访问上面 main() 函数将图像文件读入内存, 又写到文件里去, 那么在读入图像数据后、 写入 文件前的一段时间里,图像的数据是在内存中存在的,这也是我们可以修改 (访问)图像数 据的时机所在。假设内存中位图数据的指针为 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 、 pBmpBuf+i*lineByte+j*3+2 分别代表了第 i 行第 j 列像素 B、G、

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论