当前位置: 首页 > news >正文

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;

在这里插入图片描述
以1张1bit灰度图像为例来介绍文件头、信息头、调色板和图像数据:
在这里插入图片描述1:0x424D->bfType: BM
2:0x0004a8e2->bfSize: 305378B(278KB)
在这里插入图片描述
打开文件属性,可以看到文件大小计算无误

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; 

在这里插入图片描述

在这里插入图片描述1:0x00000028->biSize=40字节
2:0x0000040f->biWidth=1039像素
3:0x00000909->biHeight=2313像素
4:0x0001->biPlanes=1
5:0x000a->biBitCount=1

通过图片检测计算无误
在这里插入图片描述
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值。
在这里插入图片描述

让我们再来计算一下: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字节的调色板。

那么为什么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 有关,不同类型的位图,其中的设计原理也不同,下面对此作一个对比:

在这里插入图片描述
上面基本把调色板及相关取色策略梳理清楚了,接着回到我们之前1位深图像的例子。

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

由于位图信息头中的图像高度是正数,所以位图数据在文件中的排列顺序是从左下角到右上角,以行为主序排列的。

相关文章:

bmp图像文件格式超详解

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

Unity Meta Quest 一体机开发(十三):【手势追踪】自定义交互事件 EventWrapper

文章目录 📕教程说明📕交互事件概述📕自定义交互逻辑⭐方法一:Inspector 面板赋值⭐方法二:纯代码处理 此教程相关的详细教案,文档,思维导图和工程文件会放入 Spatial XR 社区。这是一个高质量…...

13、Redis高频面试题

1、项目中为什么用Redis 我们项目中之所以选择Redis,主要是因为Redis有下面这些优点: 操作速度快:Redis的数据都保存在内存中,相比于其它硬盘类的存储,速度要快很多数据类型丰富:Redis支持 string&#x…...

Koa学习笔记

1、npm 初始化 npm init -y生成 package.json 文件,记录项目的依赖2、git 初始化 git init生成 .git 隐藏文件夹,.git 的本地仓库创建 .gitignore 文件,添加不提交文件的名称3、创建 ReadMe.md 文件 记录项目笔记4、搭建项目 安装 Koa 框架npm install koa5、编写最基本的…...

HiDataPlus 3.3.2-005 搭建(个人的一点心得体会 x86 平台)

HDP 集群搭建 前置安装 yum -y install createrepo yum install -y lrzsz yum install -y wget yum install -y vim修改当前集群机器的主机名 hostnamectl set-hostname XXX​ 这里的 XXX 就是要设置的当前机器的主机名称。主机名称是集群唯一的,一定不要重复&am…...

【PHP】PHP实现与硬件串口交互,接收硬件发送的实时数据

一、前言 目的:借助虚拟串口软件(VSPD)模拟硬件串口发送数据,使用PHP语言实现接收硬件发送的数据。 我这里的需求是连接天平,把天平的称量数据实时的传送到PHP使用。 使用工具:vspd串口调试工具 使用语…...

HNU-数据库系统-作业

数据库系统-作业 计科210X 甘晴void 202108010XXX 第一章作业 10.09 1.(名词解释)试述数据、数据库、数据库管理系统、数据库系统的概念。 数据,是描述事物的符号记录。 数据库(DB),是长期存储在计算机内、有组织、可共享的大量…...

Python基础知识:整理10 异常相关知识

1 异常的捕获 1.1 基础写法 """基本语法:try:可能发生错误的代码except:如果出现异常,将执行的代码""" try:fr open("D:/abc.txt", "r", encoding"utf-8") except:print("出现异常…...

golang并发安全-select

前面说了golang的channel, 今天我们看看golang select 是怎么实现的。 数据结构 type scase struct {c *hchan // chanelem unsafe.Pointer // 数据 } select 非默认的case 中都是处理channel 的 接受和发送,所有scase 结构体中c是用来存储…...

微软Visual Studio产品之Visual C++编程进阶——一维数组(画画版)

我是荔园微风,作为一名在IT界整整25年的老兵,看到不少初学者在学习编程语言的过程中如此的痛苦,我决定做点什么,我小时候喜欢看小人书(连环画),在那个没有电视、没有手机的年代,这是…...

Moonbeam生态项目分析 — — 下一代DeFi协议HydraDX

作者:David 概览 HydraDX是一个基于Substrate区块链框架构建的DeFi协议,旨在为波卡带来大量流动性。HydraDX的特色服务,HydraDX Omnipool,是一种创新的自动化做市商(AMM),通过将所有资产组合在…...

Spark九:Spark调优之Shuffle调优

Spark shuffle调优方法 map端和reduce端缓存大小设置,reduce端重试次数和等待时间间隔,以及bypass设置 学习资料:https://mp.weixin.qq.com/s/caCk3mM5iXy0FaXCLkDwYQ 一、map和reduce端缓冲区大小 1.1 map端 在Spark任务运行过程中&…...

linux c多线程优先级

在 Linux 系统中,可以使用 pthread_setschedparam 函数来设置线程的优先级。该函数需要传入一个指向 pthread_t 类型的线程 ID,以及一个指向 struct sched_param 类型的结构体对象。struct sched_param 结构体包含了线程的优先级信息。 下面是一个示例代…...

Redis在项目开发中的应用

Spring Boot集成Redis构建博客应用 在这个示例中&#xff0c;我们将展示如何使用Spring Boot和Redis构建一个简单的博客应用&#xff0c;包括文章发布、点赞和评论功能。 1. 添加依赖 首先&#xff0c;我们需要在pom.xml文件中添加Spring Boot和Redis的依赖项。 <!-- Sp…...

mapper向mapper.xml传参中文时的乱码问题

1.起因&#xff1a; 在idea中进行模糊查询传参时&#xff0c;发现在idea中查中文查不出记录&#xff0c;在navicate中可以查出来。 2.猜测&#xff1a; 1.idea中的编码问题导致的乱码。 2.idea和navicate的编码一致性导致的乱码。 3.mapper向mapper.xml传参后出现乱码。 3.解…...

基于Docker官方php:7.1.33-fpm镜像构建支持67个常见模组的php7.1.33镜像

实践说明&#xff1a;基于RHEL7(CentOS7.9)部署docker环境(23.0.1、24.0.2)&#xff0c;所构建的php7.1.33镜像应用于RHEL7-9(如AlmaLinux9.1)&#xff0c;但因为docker的特性&#xff0c;适用场景是不限于此的。 文档形成时期&#xff1a;2017-2023年 因系统或软件版本不同&am…...

Type-C PD充电器受电端sink诱骗取电汇总:小家电应用5V9V12V15V20V28V

小家电产品、美容产品、电动产品等升级采用Type-C接口&#xff0c;在Type-C接口上使用Type-C取电芯片&#xff0c;即可使用快速充电器的5V、9V、12V、15V、20V供电&#xff0c;无需再配充电器&#xff0c;各类品牌的充电器都可以支持。目前充电器常见的USB-PD功率为&#xff1a…...

禁用code server docker容器中的工作区信任提示

VSCode 添加受限模式&#xff0c;主要是防止自动运行代码的&#xff0c;比如在vscode配置的task和launch参数是可以运行自定义代码的。如果用VScode打开未知的工程文件就有可能直接运行恶意代码。 但是当我们的实验基础模板文件可控的情况下&#xff0c;要想禁用code server do…...

JSON格式插件-VUE

JsonEditor 安装&#xff1a; npm i bin-code-editor -S引入&#xff1a; import Vue from vue; import CodeEditor from bin-code-editor; import bin-code-editor/lib/style/index.css; import App from ./App.vue; Vue.use(CodeEditor); new Vue({el: #app,render: h > …...

dubbo的springboot集成

1.什么是dubbo&#xff1f; Apache Dubbo 是一款 RPC 服务开发框架&#xff0c;用于解决微服务架构下的服务治理与通信问题&#xff0c;官方提供了 Java、Golang 等多语言 SDK 实现。使用 Dubbo 开发的微服务原生具备相互之间的远程地址发现与通信能力&#xff0c; 利用 Dubbo …...

Zustand 状态管理库:极简而强大的解决方案

Zustand 是一个轻量级、快速和可扩展的状态管理库&#xff0c;特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...

【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力

引言&#xff1a; 在人工智能快速发展的浪潮中&#xff0c;快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型&#xff08;LLM&#xff09;。该模型代表着该领域的重大突破&#xff0c;通过独特方式融合思考与非思考…...

Spring Boot面试题精选汇总

&#x1f91f;致敬读者 &#x1f7e9;感谢阅读&#x1f7e6;笑口常开&#x1f7ea;生日快乐⬛早点睡觉 &#x1f4d8;博主相关 &#x1f7e7;博主信息&#x1f7e8;博客首页&#x1f7eb;专栏推荐&#x1f7e5;活动信息 文章目录 Spring Boot面试题精选汇总⚙️ **一、核心概…...

成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战

在现代战争中&#xff0c;电磁频谱已成为继陆、海、空、天之后的 “第五维战场”&#xff0c;雷达作为电磁频谱领域的关键装备&#xff0c;其干扰与抗干扰能力的较量&#xff0c;直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器&#xff0c;凭借数字射…...

C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。

1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj&#xff0c;再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...

Rapidio门铃消息FIFO溢出机制

关于RapidIO门铃消息FIFO的溢出机制及其与中断抖动的关系&#xff0c;以下是深入解析&#xff1a; 门铃FIFO溢出的本质 在RapidIO系统中&#xff0c;门铃消息FIFO是硬件控制器内部的缓冲区&#xff0c;用于临时存储接收到的门铃消息&#xff08;Doorbell Message&#xff09;。…...

基于Java Swing的电子通讯录设计与实现:附系统托盘功能代码详解

JAVASQL电子通讯录带系统托盘 一、系统概述 本电子通讯录系统采用Java Swing开发桌面应用&#xff0c;结合SQLite数据库实现联系人管理功能&#xff0c;并集成系统托盘功能提升用户体验。系统支持联系人的增删改查、分组管理、搜索过滤等功能&#xff0c;同时可以最小化到系统…...

Java毕业设计:WML信息查询与后端信息发布系统开发

JAVAWML信息查询与后端信息发布系统实现 一、系统概述 本系统基于Java和WML(无线标记语言)技术开发&#xff0c;实现了移动设备上的信息查询与后端信息发布功能。系统采用B/S架构&#xff0c;服务器端使用Java Servlet处理请求&#xff0c;数据库采用MySQL存储信息&#xff0…...

华为OD机试-最短木板长度-二分法(A卷,100分)

此题是一个最大化最小值的典型例题&#xff0c; 因为搜索范围是有界的&#xff0c;上界最大木板长度补充的全部木料长度&#xff0c;下界最小木板长度&#xff1b; 即left0,right10^6; 我们可以设置一个候选值x(mid)&#xff0c;将木板的长度全部都补充到x&#xff0c;如果成功…...

NineData数据库DevOps功能全面支持百度智能云向量数据库 VectorDB,助力企业 AI 应用高效落地

NineData 的数据库 DevOps 解决方案已完成对百度智能云向量数据库 VectorDB 的全链路适配&#xff0c;成为国内首批提供 VectorDB 原生操作能力的服务商。此次合作聚焦 AI 开发核心场景&#xff0c;通过标准化 SQL 工作台与细粒度权限管控两大能力&#xff0c;助力企业安全高效…...