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];
或类似的方法以确保字节以正确的顺序排列,而不管本机字节序如何。
我正在尝试用 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];
或类似的方法以确保字节以正确的顺序排列,而不管本机字节序如何。