bmp图像文件格式超详解

这篇具有很好参考价值的文章主要介绍了bmp图像文件格式超详解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

0 BMP简介

BMP(Bitmap-File)图形文件,又叫位图文件,是Windows采用的图形文件格式,在Windows环境下运行的所有图像处理软件都支持BMP图像文件格式。Windows系统内部各图像绘制操作都是以BMP为基础的。一个BMP文件由四部分组成:

BMP文件的数据按照从文件头开始的先后顺序分为四个部分:

  • 文件头(bmp file header):提供文件的格式、大小等信息

  • 信息头(bitmap information):提供图像数据的尺寸、位平面数、压缩方式、颜色索引等信息

  • 调色板(color palette):可选,如使用索引来表示图像,调色板就是索引与其对应的颜色的映射表

  • 位图数据(bitmap data):图像的像素值可以是RGB值,也可以是调色板的索引值。如果使用了调色板,那像素值就是调色板的索引值,可以根据像素值得到调色板索引值,然后根据调色板索引值找到相应的颜色,该颜色即为像素的颜色,如果用RGB值表示位图数据,那位图就没有调色板。通常8位深及8位深以下的图像会用到调色板,8位深以上的就不用调色板了,因为8位深以上的图像再使用调色板内存开销就会很大,直接使用RGB值存储,更节省内存。 以16位深图像为例,共有2^16=65536种颜色,如果使用调色板,调色板的大小就是262144字节,然后每个像素用16位表示,假设是一个100像素 * 100像素的图像,那么图像大小就是(100 * 16 +31)/324100=20000字节,而如果使用RGB值来存储,低5位表示蓝色,中间5位表示绿色,高5位表示红色,最高1位保留位,即每像素用2字节来表示,图像的大小就是(100 * 16 +31)/324100=20000字节,节省了调色板高达262144字节的空间!图像大小计算方式参考bmp图像大小计算方式

一个BMP文件可以用如下代码表示:

typedef struct tagBITMAP_FILE{
 
      BITMAPFILEHEADER bitmapheader;//文件头
      BITMAPINFOHEADER bitmapinfoheader;//信息头
      PALETTEENTRY palette[256];//调色板(可选)
      UCHAR *buffer;   //UCHAR 大小1字节(同C语言的unchar),指向图像数据信息
 
} BITMAP_FILE;

图像文件的底层全都是二进制形式,存储和读取都是以字节位单位的,所以图像数据要么是char* 存储,要么是unchar* 存储,为什么图像数据要用unchar*表示?

如果是char* 存储,那文件的每一个字节都是一个char,最高位是符号位无法表示图像像素信息,这肯定是不行的,比如1bit图像,文件中的某一个字节为00110011,最高位0本应该是表示白色,现在表示符号位就无法表示图像信息了,所以用unchar* 更为合适。且使用unchar* 文件中的每一个字节都是一个unchar,一个unchar的取值对应8位深图像的颜色索引,一个unchar的取值范围在0~255之间刚好对应8位深图像调色板0 ~ 255的颜色索引。

1 文件头

typedef struct tagBITMAPFILEHEADER { // bmfh 
    WORD    bfType; //占2字节
    DWORD   bfSize; //占4字节
    WORD    bfReserved1; //占2字节
    WORD    bfReserved2; //占2字节
    DWORD   bfOffBits; //占4字节
} BITMAPFILEHEADER;

bmp图片 rgb格式,图像处理,c++,图像处理
以1张1bit灰度图像为例来介绍文件头、信息头、调色板和图像数据:
bmp图片 rgb格式,图像处理,c++,图像处理1:0x424D->bfType: BM
2:0x0004a8e2->bfSize: 305378B(278KB)
bmp图片 rgb格式,图像处理,c++,图像处理
打开文件属性,可以看到文件大小计算无误

3:0x00000000->bfReserved1bfReserved2:共4字节的保留字节,全设为0
4:0x0000003e->bfOffBits: 偏移量大小为62字节(14字节的文件头+40字节的信息头+8字节的调色板)

2 信息头

typedef struct tagBITMAPINFOHEADER{ // bmih 
    DWORD  biSize; 
    LONG   biWidth; //4字节
    LONG   biHeight; 
    WORD   biPlanes; 
    WORD   biBitCount 
    DWORD  biCompression; 
    DWORD  biSizeImage; 
    LONG   biXPelsPerMeter; 
    LONG   biYPelsPerMeter; 
    DWORD  biClrUsed; 
    DWORD  biClrImportant; 
} BITMAPINFOHEADER; 

bmp图片 rgb格式,图像处理,c++,图像处理

bmp图片 rgb格式,图像处理,c++,图像处理1:0x00000028->biSize=40字节
2:0x0000040f->biWidth=1039像素
3:0x00000909->biHeight=2313像素
4:0x0001->biPlanes=1
5:0x000a->biBitCount=1

通过图片检测计算无误
bmp图片 rgb格式,图像处理,c++,图像处理
6:0x00000000->biCompression=0(没有压缩)
7:0x0004a8a4->biSizeImage=305316字节
我们可以通过LineBytes = (width * bitCount + 31) / 32 * 4计算来验证biSizeImage的大小是否正确,关于LineBytes = (width * bitCount + 31) / 32 * 4的原理可参考bmp图像大小计算方式
每行字节数为:(1039 * 1+31)/32 * 4=132B
图像大小为132 * 2313 = 305316B
由上述计算方式可知biSizeImage的大小正确
8:0x00000000->biXPelsPerMeter=0
9:0x00000000->biYPelsPerMeter=0
10:0x00000000->biCirUsed = 0
11:0x00000000->biClrImportant=0

注意biSize、bfSize、biSizeImage三者的区别:
biSize是信息头的大小,通常占40字节,bfSize是整个图像文件的大小,包括文件头+信息头+调色板(可选)+图像大小,biSizeImage是整个图像的大小。我们之前算的biSizeImage=305316,bfSize = 305378 = 文件头(14)+信息头(40)+调色板(8)+biSizeImage(305316)。

3 调色板

首先让我们举例说明什么是调色板?为什么需要调色板?

我们前面说过像素值可以是RGB值也可以是调色板索引号,现在有一个长宽各为200个像素,颜色数为16色的彩色图,每一个像素都用R、G、B三个分量表示。因为每个分量有256个级别,要用8位(bit),即一个字节(byte)来表示,所以每个像素需要用3个字节。整个图象要用200×200×3,约120k字节,可不是一个小数目呀!如果我们用调色板就能减少很多空间。

因为是一个16色图,也就是说这幅图中最多只有16种颜色,所以该我们可以用一个表:表中的每一行记录一种颜色的R、G、B值。这样当我们表示一个像素的颜色时,只需要指出该颜色是在第几行,即该颜色在表中的索引值。举个例子,如果表的第0行为255,0,0(红色),那么当某个像素为红色时,只需要用标明0即可,而无需用长达3字节的RGB值。
bmp图片 rgb格式,图像处理,c++,图像处理

让我们再来计算一下:16种状态可以用4位(bit)表示,所以一个像素要用半个字节。整个图像要用200×200×0.5,约20k字节,再加上表占用的字节为3×16=48字节.整个占用的字节数约为前面的1/6,就节省了很多空间!这张记录了R、G、B的表,就是我们常说的调色板(Palette)。

可以使用C++预定义的结构体来定义调色板

typedef struct tagRGBQUAD {
        BYTE    rgbBlue;
        BYTE    rgbGreen;
        BYTE    rgbRed;
        BYTE    rgbReserved;
} RGBQUAD;

具体定义方式如下:

//定义一个1bit图像的调色板
//1bit图像只有2种颜色
RGBQUAD colors1[2];//定义调色板

//实现调色板
//每个分量占8位,所以1个颜色占4字节
colors1[0].rgbBlue = 0;      // 黑色
colors1[0].rgbGreen = 0;
colors1[0].rgbRed = 0;
colors1[0].rgbReserved = 0;

colors1[1].rgbBlue = 255;    // 白色
colors1[1].rgbGreen = 255;
colors1[1].rgbRed = 255;
colors1[1].rgbReserved = 0;

上面测试的图像为1bit图像,其中文件头占14字节,信息头占40字节,而文件头到实际数据之间的偏移量却为62字节,是因为文件头和信息头后面还有8字节的调色板。

注意:当rgb三个值都相等时,对应的颜色是灰色

那么为什么24位真彩色BMP不带调色板呢?

因为我们这张BMP是24位真彩色的BMP,所谓真彩色图(true color),就是它的颜色数高达256×256×256种,也就是说包含我们上述提到的R、G、B颜色表示方法中所有的颜色。真彩色图并不是说一幅图包含了所有的颜色,而是说它具有显示所有颜色的能力,即最多可以包含所有的颜色。表示真彩色图时,每个像素直接用R、G、B三个分量字节表示,而不采用调色板技术。原因很明显:如果用调色板,和直接用RGB值一样,每个像素都是用3字节表示,不但没有任何便宜,还要加上一个256×256×256×4个字节的大调色板。所以真彩色图直接用R、G、B三个分量表示更节省空间,它又叫做24位色图。

这么看来BMP文件不能一概而论了,其是否用调色板或者是RGB掩码,位图数据中的数据的真正含义直接与biBitCount 有关,不同类型的位图,其中的设计原理也不同,下面对此作一个对比:

bmp图片 rgb格式,图像处理,c++,图像处理
上面基本把调色板及相关取色策略梳理清楚了,接着回到我们之前1位深图像的例子。

bmp图片 rgb格式,图像处理,c++,图像处理
该图像是1bit图像,所以肯定是调色板图像,每个像素值占1位,表示调色板索引号,蓝色方框的8字节就是调色板信息,后面的信息就是图像数据信息了,比如0xFF,对应的二进制就是11111111,表示这8个像素每个像素都是调色板中索引号为1的颜色。

由于位图信息头中的图像高度是正数,所以位图数据在文件中的排列顺序是从左下角到右上角,以行为主序排列的。文章来源地址https://www.toymoban.com/news/detail-816462.html

到了这里,关于bmp图像文件格式超详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【图像处理】基于MATLAB的RGB车牌识别

    目录 基于MATLAB的RGB车牌识别 基于MATLAB的RGB车牌识别通常可以分为以下步骤: 读入待处理图像,将RGB图像转换为HSV图像; 提取HSV图像中的Hue和Saturation通道; 利用颜色索引表的方式对提取出的Hue和Saturation进行阈值分割,得到二值化图像; 对二值化图像进行形态学操作,实现

    2023年04月22日
    浏览(46)
  • 【图像处理】音视频色彩:RGB/YUV

    目录 1.RGB  1.1介绍        1.2分类 1.2.1RGB16 1)RGB565 2)RGB555 1.2.2RGB24 1.2.3RGB222 /

    2024年02月20日
    浏览(47)
  • 数字图像处理—— Lab、YCbCr、HSV、RGB之间互转

    “Lab” 图像格式通常指的是 CIELAB 色彩空间,也称为 Lab 色彩空间。它是一种用于描述人类视觉感知的颜色的设备无关色彩空间,与常见的 RGB 和 CMYK 色彩空间不同。CIELAB 由国际照明委员会(CIE)于1976年定义,用于更准确地表示人眼对色彩的感知。 CIELAB 包括三个通道:L(亮

    2024年02月11日
    浏览(44)
  • Python图像处理:使用OpenCV对图像进行HSV和RGB表示法的转换

    Python图像处理:使用OpenCV对图像进行HSV和RGB表示法的转换 在图像处理中,我们经常需要使用不同的颜色表示法来处理图像。在OpenCV中,我们可以使用HSV(色相、饱和度、亮度)表示法来替代标准的RGB(红、绿、蓝)表示法来处理图像。HSV表示法更为直观和易于使用,因为它将

    2024年02月06日
    浏览(71)
  • 智能手机中图像处理的原理解析及 RGB 数值变化规律研究

    图像处理是一种利用计算机算法对数字图像进行处理的技术。数字图像是由像素组成的二维矩阵,每个像素包含了颜色和亮度信息,图像处理就是通过对这些像素进行各种算法操作,改变其颜色、亮度、对比度、清晰度等属性,以及进行滤波、边缘检测、目标识别等操作,使

    2024年02月12日
    浏览(36)
  • 自动驾驶采集多视角图像处理(python实现不同文件夹下同名图片批量拼接并生成视频)

    目录 1.图像拼接 2.合成视频 2.1 cv2.videowriter_fourcc功能介绍 2.2读取图片合成视频 实现目标:将自动驾驶车6个摄像头采集到的图片,按照正确顺序拼接显示,nuScenes数据集测试如下: 图像存放文件夹目录如下: 每个目录下有相同名称,不同视角采集到的图像 。 先显示图片,代

    2024年01月18日
    浏览(63)
  • 图像处理算法大全(基于libyuv或IPP)----RGB32(ARGB)转成yuv420,RGB24,nv12,yuv422集合

    《周星星教你学ffmpeg》技巧 libyuv源码:  ok!打完收工!

    2024年02月07日
    浏览(42)
  • BMP图片读写实践:rgb转bgr

    本实理论上支持24位图和32位图,实际上只测试了24位。原理很简单,就是RGB中的蓝色字节和红色字节交换。 调试信息: 测试结果: 左边是转换之前,右边是转换之后。   由调试信息可知,选取的图片是720X336,也就是行4字节对齐的。换成721X336的图片,测试结果如下:果然出

    2024年02月11日
    浏览(52)
  • 图像处理算法大全(基于libyuv或IPP)----NV12转成I420,RGB24,ARGB集合

    《周星星教你学ffmpeg》技巧 libyuv源码: static void NV12ToI420(BYTE* pNV12_Y, BYTE* pNV12_UV, BYTE* pYV12, int width, int height) {     libyuv::NV12ToI420(pNV12_Y, width, pNV12_UV, width, pYV12, width, pYV12 + height*width, width / 2, pYV12 + height*width * 5 / 4, width / 2, width, height);//去掉注释就是libyuv了 } static void NV12ToBGR

    2024年02月12日
    浏览(42)
  • 2022/7 用python批量将.mat文件转为.jpg/.png/.bmp格式图片

    网上看了一个下午都没找到能用的。。。抄来抄去都没说到点子上 mat文件是Matlab的数据存储的标准格式。 涉及到文件转换肯定要看数据的结构, 事实上别人的代码很难成功就是因为大家的mat文件的数据结构各不相同 照着这个一步一步来你肯定可以学会 1、第一段代码,包括

    2023年04月09日
    浏览(61)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包