C++读取bmp文件的宽高

Read width and height of bmp file in C++

我正在尝试用 C++ 读取 bmp 文件的宽度和高度。我的 bmp 文件的宽度和高度是 512。 18. byte是bmp文件的宽度值。

我的代码如下所示:

int main() {

char header[54];    
ifstream bmp;
bmp.open("image.bmp", ios::in | ios::binary);   

if (!bmp) {
    cout << "Error" << endl;
    system("PAUSE");
    exit(1);
}

bmp.read(header, 54);

char a = header[18];

int b = *(int *)&header[18];

system("PAUSE");
}

a变成'[=15=]'时,b怎么变成512?抱歉我的英语不好。

因为char是一个字节而int是(可能)4个字节。 512 作为 four-byte int 看起来像 0x00 0x00 0x02 0x00。请注意,这四个字节中只有一个是 non-zero.

char a = header[18]; 仅读取位置 18 处的单个字节,而 int b = *(int *)&header[18]; 将位置 18 到 21 解释为单个 int 值。

根据BMP file format,宽度是一个带符号的整数,包括4个字节,而不是一个字节。 所以如果宽度是512,那么 - 当表示为4字节整数时,字节是0x00 - 0x00 - 0x02 - 0x00,分别存储在18到21的位置。所以位置 18 是 0x00(你的值 a),而 width 当被解释为从位置 18 到 21 的 4 字节有符号整数时是 512.

我不确定的重要说明可以在评论中展开。

int b = *(int *)&header[18];

header[18] 视为 int。这不是 int。欢迎使用严格别名。您转换了不相同的类型您在这里所做的是进入未定义的行为。这是一种通常 "works" 未定义的行为,但考虑一下:

header[18] 不是 32 位或 64 位字节对齐的。读取 32 位或 64 位整数时,程序将在处理器玩游戏以读取未对齐的数据时受到性能影响,或者在处理器举起其数字中指并彻底崩溃时痛苦地死去。

几乎正确的方法是

int width;
memcpy(&width, &header[18], sizeof(width));

但这忽略了一个事实,即 header 和程序可能不同意 int 的大小和字节顺序。

查看 BMP 规范,图像宽度是小端无符号 16 位整数。将其读入典型的 32 位 int 将导致完全垃圾。至少使用 uint16_t 代替并祈祷小端处理器(对 PC 硬件的合理假设)。

uint16_t width;
memcpy(&width, &header[18], sizeof(width));

更好

uint16_t width = (uint8_t)header[19];
width <<= 8;
width += (uint8_t)header[18]; 

或类似的方法以确保字节以正确的顺序排列,而不管本机字节序如何。