0

0

c++如何操作二进制位图文件BMP_c++ 文件头解析与像素数据读写【实战】

裘德小鎮的故事

裘德小鎮的故事

发布时间:2025-12-26 16:49:02

|

446人浏览过

|

来源于php中文网

原创

C++读取BMP需先校验文件头:bfType必须为0x4D42("BM"),bfOffBits≥头大小且不超文件长,biBitCount限1/4/8/16/24/32;像素数据自下而上存储、每行4字节对齐、BGR顺序。

c++如何操作二进制位图文件bmp_c++ 文件头解析与像素数据读写【实战】

如何用 C++ 读取 BMP 文件头并验证有效性

直接读取 BMP 文件前,必须先校验文件头是否合法,否则后续解析会崩溃或读错数据。关键不是“能不能读”,而是“读到的到底是不是真 BMP”。

  • BITMAPFILEHEADER 前两个字节必须是 0x42 0x4D(即 ASCII "BM"),否则直接返回错误
  • bfOffBits 字段决定像素数据起始位置,它必须 ≥ sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER),且不能超过文件大小
  • BITMAPINFOHEADER::biBitCount 必须是 1、4、8、16、24 或 32,其他值(如 15、30)虽在某些 Windows 版本中被容忍,但标准不支持,fread 后可能解码错乱
  • 注意字节序:BMP 是小端(little-endian),Windows 系统上结构体直接 fread 可用,但跨平台时需手动翻转字段(如 biWidthbiHeight
FILE* fp = fopen("test.bmp", "rb");
if (!fp) { /* 错误处理 */ }

BITMAPFILEHEADER bmfh; fread(&bmfh, sizeof(bmfh), 1, fp); if (bmfh.bfType != 0x4D42) { // 'M' 'B',注意小端存储顺序 fclose(fp); return -1; }

为什么读出的像素数据上下颠倒、每行末尾有填充字节

BMP 的像素数据从图像左下角开始存储,逐行向上,且每行字节数必须是 4 的倍数——这是 Windows GDI 的硬性要求,不是可选行为。

  • biHeight 为正数表示“自下而上”存储;为负数表示“自上而下”(Windows NT+ 支持,但多数生成器仍用正值)
  • 每行像素字节数 = ((biWidth * biBitCount + 31) / 32) * 4,即向上对齐到 4 字节边界;原始宽度字节数不足时,末尾补 0x00
  • 如果你按 biWidth * 3 直接读 24 位图,遇到宽度为 101 像素时就会越界(实际每行占 304 字节,而非 303)
  • 图像显示颠倒,是因为你把第 0 行当成了顶部,而它其实是底部;修复方式是按 biHeight 倒序拷贝行,或修改渲染逻辑

如何安全读写 24 位真彩色 BMP 的 RGB 像素

24 位 BMP 最常见,但操作时最容易因对齐和顺序栽跟头。不要假设内存布局和磁盘布局一致。

  • 计算每行真实字节数:rowSize = ((width * 24 + 31) / 32) * 4,别用 width * 3
  • 分配缓冲区时,按 rowSize * abs(height) 分配,而不是 width * height * 3
  • 读取时用 fseek(fp, bmfh.bfOffBits, SEEK_SET) 跳过头,再逐行 fread(lineBuffer, 1, rowSize, fp)
  • 写入时,每行写完后若 rowSize > width * 3,需补 0 到末尾(可用 memset 填充)
  • 注意:BMP 存储顺序是 BGR(不是 RGB),即每个像素三字节为 bluegreenred;直接丢给 OpenGL / SDL 显示前必须交换 R/B
int width = bi.biWidth;
int height = bi.biHeight;
int rowSize = ((width * 24 + 31) / 32) * 4;
std::vector pixelData(rowSize * abs(height));

fseek(fp, bmfh.bfOffBits, SEEK_SET); for (int i = 0; i < abs(height); ++i) { int srcRow = (height > 0) ? (abs(height) - 1 - i) : i; // 自下而上 → 自上而下 fread(pixelData.data() + srcRow * rowSize, 1, rowSize, fp); }

写 BMP 时最容易漏掉的三个字段校验点

手动生成 BMP 文件头时,90% 的失败源于这三个字段没算准,导致系统拒绝打开或显示为黑图。

AITDK
AITDK

免费AI SEO工具,SEO的AI生成器

下载

立即学习C++免费学习笔记(深入)”;

  • bfSize 必须等于整个文件字节数:即 sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + pixelDataSize,少 1 字节都不行
  • biSizeImage 必须等于 rowSize * abs(height);设为 0 在部分旧工具中会被忽略,但新版本(如 Windows 10 Photo App)会直接报“损坏的图像”
  • bfOffBits 必须等于 sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)(无调色板时);若有调色板(如 8 位图),还要加上调色板字节数(256 * sizeof(RGBQUAD)

这些字段之间强耦合,改一个就得重算另外两个。建议封装成函数,传入 width/height/bits,自动填全。

相关文章

c++速学教程(入门到精通)
c++速学教程(入门到精通)

c++怎么学习?c++怎么入门?c++在哪学?c++怎么学才快?不用担心,这里为大家提供了c++速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
golang结构体相关大全
golang结构体相关大全

本专题整合了golang结构体相关大全,想了解更多内容,请阅读专题下面的文章。

193

2025.06.09

golang结构体方法
golang结构体方法

本专题整合了golang结构体相关内容,请阅读专题下面的文章了解更多。

184

2025.07.04

常见的编码方式
常见的编码方式

常见的编码方式有ASCII编码、Unicode编码、UTF-8编码、UTF-16编码、GBK编码等。想了解更多编码方式相关内容,可以阅读本专题下面的文章。

565

2023.10.24

a和A对应的ASCII码数值
a和A对应的ASCII码数值

a的ascii码是65,a的ascii码是97;ascii码表中,一个字母的大小写数值相差32,一般知道大写字母的ascii码数值,其对应的小写字母的ascii码数值就算出来了,是大写字母的ascii码数值“+32”。想了解更多相关的内容,可阅读本专题下面的相关文章。

2010

2024.10.24

windows查看端口占用情况
windows查看端口占用情况

Windows端口可以认为是计算机与外界通讯交流的出入口。逻辑意义上的端口一般是指TCP/IP协议中的端口,端口号的范围从0到65535,比如用于浏览网页服务的80端口,用于FTP服务的21端口等等。怎么查看windows端口占用情况呢?php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

490

2023.07.26

查看端口占用情况windows
查看端口占用情况windows

端口占用是指与端口关联的软件占用端口而使得其他应用程序无法使用这些端口,端口占用问题是计算机系统编程领域的一个常见问题,端口占用的根本原因可能是操作系统的一些错误,服务器也可能会出现端口占用问题。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

1029

2023.07.27

windows照片无法显示
windows照片无法显示

当我们尝试打开一张图片时,可能会出现一个错误提示,提示说"Windows照片查看器无法显示此图片,因为计算机上的可用内存不足",本专题为大家提供windows照片无法显示相关的文章,帮助大家解决该问题。

727

2023.08.01

windows查看端口被占用的情况
windows查看端口被占用的情况

windows查看端口被占用的情况的方法:1、使用Windows自带的资源监视器;2、使用命令提示符查看端口信息;3、使用任务管理器查看占用端口的进程。本专题为大家提供windows查看端口被占用的情况的相关的文章、下载、课程内容,供大家免费下载体验。

400

2023.08.02

虚拟号码教程汇总
虚拟号码教程汇总

本专题整合了虚拟号码接收验证码相关教程,阅读下面的文章了解更多详细操作。

25

2025.12.25

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PostgreSQL 教程
PostgreSQL 教程

共48课时 | 6万人学习

Excel 教程
Excel 教程

共162课时 | 9.6万人学习

PHP基础入门课程
PHP基础入门课程

共33课时 | 1.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号