在 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 文件的主要内容,如果未能解决你的问题,请参考以下文章