恰巧作业里有一道要对BMP进行卷积的题,所以干脆就写一篇文章来记录一下
BMP的基本常识
BMP取自位图Bitmap的缩写,也称为DIB(与设备无关的位图),是一种独立于显示器的位图数字图像文件格式。常见于微软视窗和OS/2操作系统,Windows GDI API内部使用的DIB数据结构与 BMP 文件格式几乎相同。
来自于此 BMP - Wikipedia
BMP的主要存储方式
此处主要用C中基本的文件指针操作来读写BMP文件,所以需要先了解BMP的文件构成(此处只列一些需要用的基本信息)。
偏移量 | 大小 | 用途 |
---|---|---|
0x0000 | 2 Byte | 用于标识BMP和DIB文件的前缀,一般为0x42 0x4D,即ASCII的BM(在Windows下) |
0x000E | 4 Byte | BMP Header的大小,Header中存储着此BMP文件的基本信息,此处读取的是Header末尾距离文件头的偏移量 |
0x0012 | 4 Byte | 位图的宽度,单位为像素(有符号整数) |
0x0016 | 4 Byte | 位图高度,单位为像素(有符号整数) |
0x001C | 2 Byte | 每个像素所占位数,即图像的色深。典型值为1、4、8、16、24和32 |
所以接下来先创建文件指针
1 | fpbmp = fopen(inputFileName, "rb"); |
读取Header
读取Header末尾距离文件头的偏移量放置在offset
变量中
1 | //get header size |
读取图片宽高
根据之前的偏移量,可以读取图片的宽高
1 | //get width and height |
读取图片位深
位深可以计算出图片的一行的宽度
1 | //get bit depth |
拷贝Header内容 直接输出
1 | unsigned char *fp_temp = NULL; |
将指针移动到Header末尾 计算rowSize
1 | fseek(fpbmp, offset, SEEK_SET); |
读取一行的pixel
这里需要注意的是,他的存储方式非常神奇
RGB1 RGB2 RGB3
RGB4 RGB5 RGB6
RGB7 RGB8 RGB9
假设这里有一张3x3的点阵BMP
BMP中的存储方式是这样的
像素是从下到上、从左到右保存的 而且为GBR(我也不知道为什么怎么诡异)
读取前一定要移动指针到header的末尾才能进行读取
BGR7 BGR8 BGR9
BGR4 BGR5 BGR6
BGR1 BGR2 BGR3
1 | pix = (unsigned char *)malloc(rowSize); |
然后就可以对R G B 三个数组里面的数据进行处理,然后输出。
输出方式十分类似不再赘述。
完成
这篇文章参考了某位大佬的博客,时间比较久远所以忘记保存来源了,鉴于网上别的博客都比较复杂,不适合刚学文件指针的小朋友们,所以记录下之前自己写的简易版