在 C++ 中读取 .bmp 文件

Posted

技术标签:

【中文标题】在 C++ 中读取 .bmp 文件【英文标题】:reading a .bmp file in c++ 【发布时间】:2012-01-12 13:40:02 【问题描述】:

我正在尝试加载一个 bmp 文件以便在 opengl 中重用它。 我通过谷歌找到了一些关于如何加载 bmp 文件的代码。 我拿了这段代码并在我的项目中放入了一个类 Bitmap。 该课程还远未完成,但文件头的读取已经出错。读取 INFOHEADER 和 FILEHEADER 的字节后,我的结构中没有正确的值。 有什么想法吗?

//
//  Bitmap.h
//

#ifndef LaserMaze_Bitmap_h
#define LaserMaze_Bitmap_h

typedef struct                       /**** BMP file header structure ****/

    unsigned short bfType;           /* Magic number for file */
    unsigned int   bfSize;           /* Size of file */
    unsigned short bfReserved1;      /* Reserved */
    unsigned short bfReserved2;      /* ... */
    unsigned int   bfOffBits;        /* Offset to bitmap data */
 BITMAPFILEHEADER;

#  define BF_TYPE 0x4D42             /* "MB" */

typedef struct                       /**** BMP file info structure ****/

    unsigned int   biSize;           /* Size of info header */
    int            biWidth;          /* Width of image */
    int            biHeight;         /* Height of image */
    unsigned short biPlanes;         /* Number of color planes */
    unsigned short biBitCount;       /* Number of bits per pixel */
    unsigned int   biCompression;    /* Type of compression to use */
    unsigned int   biSizeImage;      /* Size of image data */
    int            biXPelsPerMeter;  /* X pixels per meter */
    int            biYPelsPerMeter;  /* Y pixels per meter */
    unsigned int   biClrUsed;        /* Number of colors used */
    unsigned int   biClrImportant;   /* Number of important colors */
 BITMAPINFOHEADER;

/*
 * Constants for the biCompression field...
 */

#  define BI_RGB       0             /* No compression - straight BGR data */
#  define BI_RLE8      1             /* 8-bit run-length compression */
#  define BI_RLE4      2             /* 4-bit run-length compression */
#  define BI_BITFIELDS 3             /* RGB bitmap with RGB masks */

typedef struct                       /**** Colormap entry structure ****/

    unsigned char  rgbBlue;          /* Blue value */
    unsigned char  rgbGreen;         /* Green value */
    unsigned char  rgbRed;           /* Red value */
    unsigned char  rgbReserved;      /* Reserved */
 RGBQUAD;

class Bitmap 
public:
    Bitmap(const char* filename);
    ~Bitmap();
    RGBQUAD* pixels;
    BITMAPFILEHEADER fh;
    BITMAPINFOHEADER ih;

    private:

;

#endif

cpp

//  Bitmap.cpp
//

#include <iostream>
#include <stdio.h>

#include "Bitmap.h"

Bitmap::Bitmap(const char* filename) 
    FILE* file;
    file = fopen(filename, "rb");

    std::cout << sizeof(BITMAPFILEHEADER) << std::endl;

    if(file != NULL)  // file opened
        BITMAPFILEHEADER h;
        size_t x = fread(&h, sizeof(BITMAPFILEHEADER), 1, file); //reading the FILEHEADER

        std::cout << x;
        fread(&this->ih, sizeof(BITMAPINFOHEADER), 1, file);

        fclose(file);
    

【问题讨论】:

【参考方案1】:

标头需要 2 字节对齐。

#pragma pack(2) // Add this

typedef struct

    unsigned short bfType;
    unsigned int   bfSize;
    unsigned short bfReserved1;
    unsigned short bfReserved2;
    unsigned int   bfOffBits;
 BITMAPFILEHEADER;

#pragma pack() // and this

【讨论】:

工作得很好,谢谢 :) 也许你能解释一下为什么这是必要的? 没有编译指示,短字段被填充到 4 个字节。 BITMAPFILEHEADER (w/o pragma) 的大小为 20,但在文件中它按 14 字节顺序写入。所以发生了两件事:(1)你读的结构搞砸了(2)你读的太多了,所以读 BITMAPINFOHEADER 太晚了 6 个字节 我是否也必须更改 BITMAPINFOHEADER 的包?定义中还有一个short 你不要,因为两条short是连续的,内存是对齐的【参考方案2】:

让您的 Windows 操作系统使用 LoadImage 为您加载它怎么样。

HBITMAP hbm = LoadImage( NULL, path, 0, 0, LR_LOADFROMFILE|LR_CREATEDIBSECTION);

使用GetObject() 查找尺寸等更多信息,如果您想了解各个位,请使用GetDIBits()

【讨论】:

是的。你没有指定操作系统,所以我假设是 Windows。如果不是这种情况,请忽略。【参考方案3】:

BITMAPINFOHEADER ::你需要先阅读biSize才能知道信息头有多大,你不能依赖sizeof()

查看wiki article 了解文件格式

【讨论】:

以上是关于在 C++ 中读取 .bmp 文件的主要内容,如果未能解决你的问题,请参考以下文章

C++ - 从 BMP 文件中读取每个像素的位数

读取 BMP 文件 C++(读取 BMP 标头时出现问题)

仅当行填充等于 3 个字节时,C++ 读取 BMP 文件才有效

关于怎么用C++读取bmp图片

读取和写入 BMP 文件

用c ++读取BMP文件的所有字节并旋转图片