在 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 *)&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 文件才有效