c++如何读取和操作内存中的位图文件头结构

来源:前端技术作者:森沢头衔:网络博主
导读:本期聚焦于小伙伴创作的《c++如何读取和操作内存中的位图文件头结构》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《c++如何读取和操作内存中的位图文件头结构》有用,将其分享出去将是对创作者最好的鼓励。

位图文件(BMP)的结构由文件头、信息头、调色板和像素数据几部分组成,其中文件头和信息头定义了图像的基础属性,直接在内存中操作这些结构可以避免频繁的磁盘IO,提升处理效率。位图文件头的标准长度为14字节,信息头常见的是40字节的BITMAPINFOHEADER结构,两者共同决定了位图的基本参数。

c++如何读取和操作内存中的位图文件头结构

位图文件头结构定义

首先需要明确位图文件头的标准字段,按照Windows BMP格式规范,文件头包含以下字段,注意结构体需要设置按1字节对齐,避免编译器自动添加填充字节导致读取偏移错误:

#include <iostream>
#include <cstring>
#include <cstdint>

// 设置结构体1字节对齐,匹配BMP文件头的实际存储格式
#pragma pack(push, 1)
// 位图文件头结构,共14字节
typedef struct {
    uint16_t bfType;      // 文件类型,必须是0x4D42(即字符BM)
    uint32_t bfSize;      // 整个BMP文件的大小,单位字节
    uint16_t bfReserved1; // 保留字段,必须为0
    uint16_t bfReserved2; // 保留字段,必须为0
    uint32_t bfOffBits;   // 像素数据相对于文件起始位置的偏移量
} BITMAPFILEHEADER;

// 位图信息头结构,共40字节,这里使用最常见的版本
typedef struct {
    uint32_t biSize;          // 信息头结构的大小,固定为40
    int32_t  biWidth;         // 图像宽度,单位像素
    int32_t  biHeight;        // 图像高度,单位像素,正数表示倒向存储,负数表示正向存储
    uint16_t biPlanes;        // 目标设备平面数,必须为1
    uint16_t biBitCount;      // 每个像素的位数,常见值有1、4、8、16、24、32
    uint32_t biCompression;   // 压缩方式,0表示不压缩
    uint32_t biSizeImage;     // 像素数据的大小,单位字节,不压缩时可以为0
    int32_t  biXPelsPerMeter; // 水平分辨率,单位像素/米
    int32_t  biYPelsPerMeter; // 垂直分辨率,单位像素/米
    uint32_t biClrUsed;       // 使用的调色板颜色数,0表示使用所有调色板颜色
    uint32_t biClrImportant;  // 重要颜色数,0表示所有颜色都重要
} BITMAPINFOHEADER;
#pragma pack(pop)

从内存中读取位图文件头

假设我们已经将完整的BMP文件数据加载到了内存缓冲区中,可以通过指针强制转换的方式直接读取文件头结构,这种方式效率最高,不需要逐字段拷贝数据。

// 模拟内存中的BMP数据缓冲区,实际场景中可能是从文件读取或者网络接收的数据
uint8_t bmp_memory_buffer[] = {
    0x42, 0x4D,             // bfType: BM,对应0x4D42,小端存储
    0x36, 0x00, 0x00, 0x00, // bfSize: 54字节(14+40),小端存储
    0x00, 0x00,             // bfReserved1
    0x00, 0x00,             // bfReserved2
    0x36, 0x00, 0x00, 0x00, // bfOffBits: 54字节,小端存储
    // 接下来是40字节的信息头数据
    0x28, 0x00, 0x00, 0x00, // biSize: 40
    0x02, 0x00, 0x00, 0x00, // biWidth: 2像素
    0x02, 0x00, 0x00, 0x00, // biHeight: 2像素
    0x01, 0x00,             // biPlanes: 1
    0x18, 0x00,             // biBitCount: 24位色深
    0x00, 0x00, 0x00, 0x00, // biCompression: 不压缩
    0x00, 0x00, 0x00, 0x00, // biSizeImage: 0
    0x00, 0x00, 0x00, 0x00, // biXPelsPerMeter: 0
    0x00, 0x00, 0x00, 0x00, // biYPelsPerMeter: 0
    0x00, 0x00, 0x00, 0x00, // biClrUsed: 0
    0x00, 0x00, 0x00, 0x00  // biClrImportant: 0
};

int main() {
    // 将内存缓冲区指针转换为文件头结构体指针
    BITMAPFILEHEADER* file_header = (BITMAPFILEHEADER*)bmp_memory_buffer;
    // 信息头起始位置是文件头之后,偏移14字节
    BITMAPINFOHEADER* info_header = (BITMAPINFOHEADER*)(bmp_memory_buffer + sizeof(BITMAPFILEHEADER));

    // 校验文件类型是否正确
    if (file_header->bfType != 0x4D42) {
        std::cout << "不是有效的BMP文件" << std::endl;
        return -1;
    }

    std::cout << "BMP文件大小: " << file_header->bfSize << " 字节" << std::endl;
    std::cout << "像素数据偏移量: " << file_header->bfOffBits << " 字节" << std::endl;
    std::cout << "图像宽度: " << info_header->biWidth << " 像素" << std::endl;
    std::cout << "图像高度: " << info_header->biHeight << " 像素" << std::endl;
    std::cout << "位深: " << info_header->biBitCount << " 位/像素" << std::endl;

    return 0;
}

修改内存中的位图文件头字段

读取到头结构之后,可以直接修改结构体中的字段,修改后的数据会同步到原始内存缓冲区中,适合需要动态修改图像属性的场景,比如调整图像尺寸、修改位深等。

int main() {
    BITMAPFILEHEADER* file_header = (BITMAPFILEHEADER*)bmp_memory_buffer;
    BITMAPINFOHEADER* info_header = (BITMAPINFOHEADER*)(bmp_memory_buffer + sizeof(BITMAPFILEHEADER));

    // 修改图像宽度为4像素
    info_header->biWidth = 4;
    // 重新计算文件大小,假设24位色深,每行像素需要对齐到4字节
    int line_bytes = ((info_header->biWidth * info_header->biBitCount + 31) / 32) * 4;
    int pixel_data_size = line_bytes * info_header->biHeight;
    file_header->bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + pixel_data_size;
    file_header->bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);

    std::cout << "修改后图像宽度: " << info_header->biWidth << " 像素" << std::endl;
    std::cout << "修改后文件大小: " << file_header->bfSize << " 字节" << std::endl;

    return 0;
}

注意事项

  • 结构体必须设置1字节对齐,否则编译器会自动添加填充字节,导致结构大小和BMP文件头实际大小不匹配,读取到错误的数据。
  • BMP文件的所有数值字段都是小端存储,在大小端不一致的平台上需要做字节序转换,上述示例默认运行在小端平台上。
  • 操作内存指针时需要确保缓冲区长度足够,避免越界访问导致程序崩溃。
  • 修改文件头后如果需要保存到文件,需要保证像素数据的大小和头结构中声明的参数匹配,否则图像会显示异常。

C++位图文件头BMP结构内存操作修改时间:2026-06-16 14:48:43

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。