关于BMP格式图像的理解和读写(c++).docx

144 篇文章 69 订阅
60 篇文章 9 订阅

一、什么是BMP格式?

BMP,(全称Bitmap)是Windows操作系统中的标准图像文件格式,可以分成两类:设备相关位图(DDB)和设备无关位图(DIB),使用非常广。它采用位映射存储格式,除了图像深度可选以外,不采用其他任何压缩,因此,BMP 文件所占用的空间很大。BMP文件的图像深度可选1bit、4bit、8bit及24bit。BMP 文件存储数据时,图像的扫描方式是按从左到右、从下到上的顺序。由于BMP文件格式是Windows环境中交换与图有关的数据的一种标准,因此在Windows环境中运行的图形图像软件都支持BMP图像格式。二、怎么计算BMP的大小BMP是一种不压缩的图像文件,我们怎么计算bmp图像的大小呢?BMP的类别及存储方式1.BMP的常见类型通常我们最常见的就是24位图,所谓的24位图,就是说一个像素的颜色信息用24位来表示,也就是说,对于三原色BRG,每一个颜色都用以字节(8)位来表示。除了24位图,还有1位(单色),2位(4色,CGA),4位(16色,VGA),8位(256色),16位(增强色),24位(真彩色)和32位等。2. BMP的文件头:BMP文件头(bmp file header):共14字节0-1:bfType,表示文件类型,BMP格式的文件这两个字节是0x4D42,10进制就是19778,字符显示就是‘BM’;

2-5:bfSize,表示文件的大小,检查文件信息,验证正确;

6-7:bfReserved1,保留位,必须设置为0;

8-9:bfReserved2,保留位,必须设置为0;

a-d:bfOffBits,4字节的偏移,表示从文件头到位图数据的偏移;位图信息头(bitmap information):共40字节;0e-11:4字节的biSize, 信息头的大小,即40;

12-15:4字节的biWidth,用像素表示图像的宽度,查看文件信息验证正确;

16-19:4字节的biHeight,以像素为单位说明图像的高度,同时如果为正,说明位图倒立(即数据表示从图像的左下角到右上角),如果为负说明正向; (这两个信息在程序要在内存分配的时候使用)

1a-1b:2字节的biPlanes,为目标设备说明颜色平面数,总被设置为1;

1c-1d:2字节的biBitCount,说明比特数/像素数,值有1、2、4、8、16、24、32;

1e-21:4字节的biCompression,说明图像的压缩类型,最常用的就是0(BI_RGB),表示不压缩;

22-25:4字节的biSizeImage,说明位图数据的大小,当用BI_RGB格式时,可以设置为0;

26-29:4字节的biXPelsPerMeter,表示水平分辨率,单位是像素/米,有符号整数;

2a-2d:4字节的biYPelsPerMeter,表示垂直分辨率,单位是像素/米,有符号整数;

2e-31:4字节的biClrUsed,说明位图使用的调色板中的颜色索引数,为0说明使用所有;

32-35:4字节的biClrImportant,说明对图像显示有重要影响的颜色索引数,为0说明都重要;

所以,总的BMP格式从头到尾的顺序应该是:

a. bmp文件头(bmp file header):共14字节;

b. 位图信息头(bitmap information):共40字节;

c. 调色板(color palette):可选;

d. 位图数据;计算大小假设我们获取的是每个像素是24位的bmp图像,即每个像素占用三个字节(按照R、G、B的顺序,每个分量占一个字节),此外,这种格式还需要54个额外的字节来存储“头”信息,可以根据以下公式确定BMP文件大小:

Hbytes=(Hpixels*3+3) & (11.......00)
24b RGB BMP文件大小= 54 + Hbytes*Vpixels

其中Vpixels和Hpixels是图像的高度和宽度,(这里V是指vertical,H是指horizon,与一般width和high表示方式要区别开,如果是640×480的图片,就是对应Vpixels=480, Hpixels=640),则图片大小为:

54+3×640×480=921654 bytes。

但是看公式,可以知道Hbytes必须舍入为下一个可以被4整除的整数,以确保BMP图像大小是4的倍数。为什么要确保BMP图像大小是4的倍数?1.首先普及一个概念,什么是32位系统、64位系统?32位和64位操作系统是指:CPU一次处理数据的能力是32位还是64位。现在市场上的CPU一般都是64位的,但是这些CPU并不是真正意义上的64 位CPU,里面依然保留了大部分32位的技术,只是进行了部分64位的改进。32位和64位的区别还涉及了内存的寻址方面,32位系统的最大寻址空间是2 的32次方= 4294967296(bit)= 4(GB)左右,而64位系统的最大寻址空间的寻址空间则达到了2的64次方= 4294967296(bit)的32次方=数值大于1亿GB。换而言之,就是说32位系统的处理器最大只支持到4G内存,而64位系统最大支持的内存高达亿位数。2.网上最多的解释位图数据记录了位图的每一个像素值,记录顺序是在扫描行内是左到右,扫描行之间是从下到上。位图的一个像素值所占的字节数:

当biBitCount(每个像素所需的位数)=1时,8个像素占1个字节;

当biBitCount=4时,2个像素占1个字节;

当biBitCount=8时,1个像素占1个字节;

当biBitCount=24时,1个像素占3个字节;

Windows规定一个扫描行所占的字节数必须是4的倍数(即以long为单位),不足的以0填充。

3.举个例子如果是24位1024×1024的BMP文件需要的存储空间为:

54+1024*1024*3 = 3145782字节

如果是24位321×1024的BMP文件需要的存储空间为:

54+321*3+1*127 = 122482字节

相当于需要每行要浪费一个字节,总共需要浪费127个字节。

三、怎么读取bmp格式的图片

#include "ImageStuff.h"

unsigned char **ReadBMP(char *filename) {
    int i;
    FILE *f = fopen(filename, "rb");
    if (f == NULL) {
        printf("\n\n%s NOT FOUND\n\n", filename);
        exit(1);
    }

    unsigned char HeaderInfo[54];
    fread(HeaderInfo, sizeof(unsigned char), 54, f); // read the 54-byte header

    // extract image height and width from header
    int width = *(int *) &HeaderInfo[18];
    int height = *(int *) &HeaderInfo[22];

    //copy header for re-use
        for (i = 0; i < 54; i++) { ip.HeaderInfo[i] = HeaderInfo[i]; } ip.Vpixels = height; ip.Hpixels = width; int RowBytes = (width * 3 + 3) & (~3);//Be careful with this! ip.Hbytes = RowBytes; printf("\n Input BMP File name: %20s (%u x %u)", filename, ip.Hpixels, ip.Vpixels); unsigned char tmp; unsigned char **TheImage = (unsigned char **) malloc(height * sizeof(unsigned char *)); for (i = 0; i < height; i++) { TheImage[i] = (unsigned char *) malloc(RowBytes * sizeof(unsigned char)); } for (i = 0; i < height; i++) { fread(TheImage[i], sizeof(unsigned char), RowBytes, f); } fclose(f); return TheImage; // remember to free() it in caller! 

四、怎么写入bmp格式的图片

void WriteBMP(unsigned char **img, char *filename) {
    FILE *f = fopen(filename, "wb");
    if (f == NULL) {
        printf("\n\nFILE CREATION ERROR: %s\n\n", filename);
        exit(1);
    }
    unsigned long int x, y;
    char temp;
    //write header
        for (x = 0; x < 54; x++) { fputc(ip.HeaderInfo[x], f); } //write data for (x = 0; x < ip.Vpixels; x++) { for (y = 0; y < ip.Hbytes; y++) { temp = img[x][y]; fputc(temp, f); } } printf("\n Output BMP File name: %20s (%u x %u)", filename, ip.Hpixels, ip.Vpixels); fclose(f); }

对应的头文件 ImageStuff.h:

#include 
#include 
#include 
struct ImgProp {
    int Hpixels;
    int Vpixels;
    unsigned char HeaderInfo[54];
    unsigned long int Hbytes;
};
struct Pixel {
    unsigned char R;
    unsigned char G;
    unsigned char B;
};
unsigned char **ReadBMP(char *);
void WriteBMP(unsigned char **, char *);
extern struct ImgProp ip;

备注:

点击下面链接,进入奥比中光开发者社区,了解更多3D视觉技术信息:
https://developer.orbbec.com.cn/

或扫描下方二维码,进入奥比中光开发者社区:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值