在 C++ 中读取 bmp 文件的宽度和高度

Posted

技术标签:

【中文标题】在 C++ 中读取 bmp 文件的宽度和高度【英文标题】:Read width and height of bmp file in C++ 【发布时间】:2017-02-11 20:21:12 【问题描述】:

我正在尝试。宽度和高度是我的 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'\0' 时,b 如何变成 512?对不起我的英语不好。

【问题讨论】:

不太清楚你在问什么... 需要注意的两件事 1) 文件和平台上 int 的大小相同,2) 文件中值的字节序与平台的字节序匹配. 【参考方案1】:

因为char 是一个字节,而int 是(可能)4 个字节。 512 作为一个四字节的int 看起来像0x00 0x00 0x02 0x00。请注意,这四个字节中只有一个非零。

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

【讨论】:

我现在完全明白了。非常感谢!【参考方案2】:

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

【讨论】:

我现在完全明白了。非常感谢!【参考方案3】:

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

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

header[18] 视为int。这不是int。欢迎使用严格别名。您已经转换了不同的类型您在这里所做的是进入未定义的行为。这是通常“有效”的未定义行为之一,但请考虑一下:

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

几乎正确的方法是

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

但这忽略了标头和程序可能在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]; 

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

【讨论】:

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

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

用C语言编写程序处理图片bmp文件 1.读取图片的宽度,高度,每个像素所需的位数,水平分辨率,垂直

读取 BMP 标头,打包。读取不正确的值

用标准c读取bmp文件的长宽?

C++实现红外Fir谱图文件转BMP图片文件

在 C++ 中读取 .dat 二进制文件(深度图)