BMP文件结构读写操作
2016-04-11 09:27
405 查看
之前一直都准备写blog来记录自己的学习,但是无奈拖延症!现在总算有时间有精力了,希望大家能共同学习,互相讨论,如果文中有什么不妥之处,还请您指出,谢谢。
今天写的是一篇有关位图操作的文章,主要是实现了bmp的读写操作,为什么要做这个呢? 因为这是基础啊,c语言做图像处理都能搞定,还有什么语言搞不定的呢!当然核心的还是算法,这些在后面会慢慢扩充。
说到BMP文件结构读写操作,我们就不得不先了解bmp文件的结构,什么这头啊,那头啊,巴拉巴拉一大堆,下面给两个参考网站,极力推荐:
1. 你所能用到的BMP格式介绍
2.bmp图像大小biSizeImage算法公式由来
下面我也简单介绍一下bmp文件的结构,加深加深印象啦!
BMP文件的结构
BMP图像文件被分成4个部分:位图文件头(Bitmap File Header)、位图信息头(Bitmap Info Header)、颜色表(Color Map)和位图数据(即图像数据,Data Bits或Data Body)。
第1部分为位图文件头BITMAPFILEHEADER,是一个结构体类型,该结构的长度是固定的,为14个字节。其定义如下:
第3部分为颜色表。颜色表实际上是一个RGBQUAD结构的数组,数组的长度由biClrUsed指定(如果该值为零,则由biBitCount指定,即2的biBitCount次幂个元素)。RGBQUAD结构是一个结构体类型,占4个字节,其定义如下:
第4部分是位图数据,即图像数据,其紧跟在位图文件头、位图信息头和颜色表(如果有颜色表的话)之后,记录了图像的每一个像素值。对于有颜色表的位图,位图数据就是该像素颜色在调色板中的索引值;对于真彩色图,位图数据就是实际的R、G、B值(三个分量的存储顺序是B、G、R)。下面分别就2色、16色、256色和真彩色位图的位图数据进行说明:
对于2色位图,用1位就可以表示该像素的颜色,所以1个字节能存储8个像素的颜色值。
对于16色位图,用4位可以表示一个像素的颜色。所以一个字节可以存储2个像素的颜色值。
对于256色位图,1个字节刚好存储1个像素的颜色值。
对于真彩色位图,3个字节才能表示1个像素的颜色值。
相信经过上面的洗礼,我们对bmp已经有了充分的了解,下面我们就可以开始读写bmp图像了!
对于以上的四个部分在Windows.h中都有定义,因此我们需要在程序中include这个头文件。
下面给出本次程序的源代码:
下图是在VS2015中运行的结果:
![](https://img-blog.csdn.net/20160411094128034)
我们打开该图片的信息,可以右键图片,在属性中查看详细信息:
![](https://img-blog.csdn.net/20160411094133402)
bingo!
大伙儿有任何问题,都可以直接评论,谢谢!
用MFC实现bmp图像的显示与处理,请看下一篇文章!
今天写的是一篇有关位图操作的文章,主要是实现了bmp的读写操作,为什么要做这个呢? 因为这是基础啊,c语言做图像处理都能搞定,还有什么语言搞不定的呢!当然核心的还是算法,这些在后面会慢慢扩充。
说到BMP文件结构读写操作,我们就不得不先了解bmp文件的结构,什么这头啊,那头啊,巴拉巴拉一大堆,下面给两个参考网站,极力推荐:
1. 你所能用到的BMP格式介绍
2.bmp图像大小biSizeImage算法公式由来
下面我也简单介绍一下bmp文件的结构,加深加深印象啦!
BMP文件的结构
BMP图像文件被分成4个部分:位图文件头(Bitmap File Header)、位图信息头(Bitmap Info Header)、颜色表(Color Map)和位图数据(即图像数据,Data Bits或Data Body)。
第1部分为位图文件头BITMAPFILEHEADER,是一个结构体类型,该结构的长度是固定的,为14个字节。其定义如下:
typedef struct tagBITMAPFILEHEADER { WORD bfType; //位图文件类型,必须是0x424D,即字符串“BM”. DWORD bfSize; //位图文件大小,包括这14个字节。 WORD bfReserved1; //Windows保留字,暂不用 WORD bfReserved2; DWORD bfOffBits; //从文件头到实际的位图数据的偏移字节数 } BITMAPFILEHEADER, FAR *LPBITMAPFILEHEADER, *PBITMAPFILEHEADER;第2部分为位图信息头BITMAPINFOHEADER,也是一个结构体类型的数据结构,该结构的长度也是固定的,为40个字节(WORD为无符号16位整数,DWORD为无符号32位整数,LONG为32位整数)。其定义如下:
typedef struct tagBITMAPINFOHEADER { DWORD biSize; //本结构的长度,为40个字节 LONG biWidth; //位图的宽度,以像素为单位 LONG biHeight; //位图的高度,以像素为单位 WORD biPlanes; //目标设备的级别,必须是1 WORD biBitCount //每个像素所占的位数(bit) DWORD biCompression; //位图压缩类型,一般都是未压缩的,取0 DWORD biSizeImage; //实际的位图数据占用的字节数 LONG biXPelsPerMeter; LONG biYPelsPerMeter; DWORD biClrUsed; //位图实际用到的颜色数,取0,颜色数为2的biBitCount次幂 DWORD biClrImportant; //位图显示过程中重要的颜色数 } BITMAPINFOHEADER, FAR *LPBITMAPINFOHEADER, *PBITMAPINFOHEADER;
第3部分为颜色表。颜色表实际上是一个RGBQUAD结构的数组,数组的长度由biClrUsed指定(如果该值为零,则由biBitCount指定,即2的biBitCount次幂个元素)。RGBQUAD结构是一个结构体类型,占4个字节,其定义如下:
typedef struct tagRGBQUAD { BYTE rgbBlue; //该颜色的蓝色分量 BYTE rgbGreen; //该颜色的绿色分量 BYTE rgbRed; //该颜色的红色分量 BYTE rgbReserved; //保留 }RGBQUAD;有些位图需要颜色表;有些位图(如真彩色图)则不需要颜色表,颜色表的长度由BITMAPINFOHEADER结构中biBitCount分量决定。
第4部分是位图数据,即图像数据,其紧跟在位图文件头、位图信息头和颜色表(如果有颜色表的话)之后,记录了图像的每一个像素值。对于有颜色表的位图,位图数据就是该像素颜色在调色板中的索引值;对于真彩色图,位图数据就是实际的R、G、B值(三个分量的存储顺序是B、G、R)。下面分别就2色、16色、256色和真彩色位图的位图数据进行说明:
对于2色位图,用1位就可以表示该像素的颜色,所以1个字节能存储8个像素的颜色值。
对于16色位图,用4位可以表示一个像素的颜色。所以一个字节可以存储2个像素的颜色值。
对于256色位图,1个字节刚好存储1个像素的颜色值。
对于真彩色位图,3个字节才能表示1个像素的颜色值。
相信经过上面的洗礼,我们对bmp已经有了充分的了解,下面我们就可以开始读写bmp图像了!
对于以上的四个部分在Windows.h中都有定义,因此我们需要在程序中include这个头文件。
下面给出本次程序的源代码:
#include<stdio.h> #include<Windows.h> //包含位图文件结构定义 //函数声明 bool readBmp(char *bmpName); bool saveBmp(char * bmpName, unsigned char *imgBuf, int width, int height, int biBitCount, RGBQUAD * pcolortable); //定义需要的全局变量 unsigned char *pBmpBuf; //指向bmp数据区的指针 int bmpWidth; //bmp图片的宽度 int bmpHeight; //bmp图片的高度 RGBQUAD *pcolortable; //指向颜色表的指针,注意:若是24位bmp图片则没有颜色表 int biBitCount; //每一个像素需要的位数,若为8则一个像素需要8位来表示,即一个字节 int main() //主函数入口 { char readPath[] = "lena.bmp"; //bmp图片路径名,注意要把lena.bmp放在了工程目录下,否则就要加上绝对路径。 readBmp(readPath); printf(" weight:%d\n",bmpWidth); printf(" height:%d\n",bmpHeight); printf(" bitCount:%d\n",biBitCount); //char writePath[] = "lena0.bmp"; //saveBmp(writePath, pBmpBuf, bmpWidth, bmpHeight, biBitCount, pcolortable); delete[]pBmpBuf; if (biBitCount == 8) delete[]pcolortable; system("pause"); return 0; } bool readBmp(char *bmpName) //读bmp图片 { FILE * fp = fopen(bmpName, "rb"); if (fp == 0) return 0; fseek(fp, sizeof(BITMAPFILEHEADER), 0); //跳过文件头,因为我们默认读取的就是bmp图片 BITMAPINFOHEADER head; fread(&head, sizeof(BITMAPINFOHEADER), 1, fp); //读取信息头 bmpWidth = head.biWidth; bmpHeight = head.biHeight; biBitCount = head.biBitCount; int lineBytes = (bmpWidth*biBitCount / 8 + 3) / 4 * 4; //为了保证每行的大小都是4的整数倍,可以直接带个数算算,多体会体会 if (biBitCount == 8) //如果biBitCount等于8,则说明不是真彩色图像,需要颜色表 { pcolortable = new RGBQUAD[256]; fread(pcolortable, sizeof(RGBQUAD), 256, fp); } pBmpBuf = new unsigned char[lineBytes*bmpHeight]; fread(pBmpBuf,lineBytes*bmpHeight,1, fp); // printf("Bmpsize:%d\n", lineBytes*bmpHeight); fclose(fp); return 1; } bool saveBmp(char * bmpName, unsigned char *imgBuf, //存bmp图片 int width, int height, int biBitCount, RGBQUAD * pcolortable) { if (!imgBuf) return 0; int colortablesize = 0; if (biBitCount == 8) colortablesize = 1024; int lineByte = (width*biBitCount / 8 + 3) / 4 * 4; FILE * fp = fopen(bmpName,"wb"); if (fp == 0) return 0; BITMAPFILEHEA 4000 DER fileHead; fileHead.bfType = 0x4D42; //bmp类型 fileHead.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + colortablesize + height*lineByte; fileHead.bfReserved1 = 0; fileHead.bfReserved2 = 0; fileHead.bfOffBits = 54 + colortablesize; fwrite(&fileHead, sizeof(BITMAPFILEHEADER), 1, fp); BITMAPINFOHEADER Head; Head.biBitCount = biBitCount; Head.biClrImportant = 0; Head.biClrUsed = 0; Head.biCompression = BI_RGB; Head.biHeight = height; Head.biPlanes = 1; Head.biSize = 40; Head.biSizeImage = height*lineByte ; Head.biWidth = width; Head.biXPelsPerMeter = 0x270E; Head.biYPelsPerMeter = 0x270E; fwrite(&Head, sizeof(BITMAPINFOHEADER), 1, fp); if (biBitCount == 8) fwrite(pcolortable, sizeof(RGBQUAD), 256, fp); fwrite(imgBuf, height*lineByte+2, 1, fp); printf("datasize:%d\n", height*lineByte); fclose(fp); return 1; }
下图是在VS2015中运行的结果:
我们打开该图片的信息,可以右键图片,在属性中查看详细信息:
bingo!
大伙儿有任何问题,都可以直接评论,谢谢!
用MFC实现bmp图像的显示与处理,请看下一篇文章!
相关文章推荐
- 如何组织构建多文件 C 语言程序(二)
- 如何写好 C main 函数
- Lua和C语言的交互详解
- 获取图片宽度和高度的类,支持JPG,GIF,PNG,BMP
- 关于C语言中参数的传值问题
- 简要对比C语言中三个用于退出进程的函数
- 深入C++中API的问题详解
- 基于C语言string函数的详解
- C语言中fchdir()函数和rewinddir()函数的使用详解
- C语言内存对齐实例详解
- C语言编程中统计输入的行数以及单词个数的方法
- C语言自动生成enum值和名字映射代码
- 使用C语言判断英文字符大小写的方法
- c语言实现的带通配符匹配算法
- C语言实现顺序表基本操作汇总
- C语言中计算正弦的相关函数总结
- 使用C语言详解霍夫曼树数据结构
- C语言实现选择排序、冒泡排序和快速排序的代码示例
- 探讨C语言的那些小秘密之断言
- C语言实现BMP转换JPG的方法