![](/img/trans.png)
[英]Win32 C++ - Check if the Window PositionX/PositionY and Width/Height changed
[英]Win32 C/C++ Reading BMP width and height from a byte array
我已经将BMP文件读入字节数组。 所以在查看了这个问题的答案之后: 字节数组到int c ++ 。 这种从BMP信息头获取widht和height的安全和正确的方法是什么?
long width, height;
memcpy(&width, &bmp[0x12], sizeof(long));
memcpy(&height, &bmp[0x16], sizeof(long));
这种方法会带来什么问题?
long* width = (long*)(&bmp[0x12]);
long* height= (long*)(&bmp[0x16]);
根据Wikipedia BMP文件格式 , 0x12
是位图宽度的偏移量,以像素为单位, 0x16
是位图高度的偏移量,以像素为单位。
PD。 我已经找到了从内存缓冲区加载位图的解决方案,但我想保持代码简单,因为我只需要位图的宽度,高度和原始数据,我不知道答案是否安全。
谢谢!
这两种方法基本上都是一样的,并且两者都有相同的基本问题:如果主机系统的字节顺序与BMP文件使用的不同,则无法工作。 直接访问大于二进制格式的单个字节的值始终存在问题。
如果主机不能在结果地址处进行long
访问,则后一种方法还具有可能破坏的额外缺点。
简而言之,两种“解决方案”都很糟糕。 最好逐字节提取值并重新构造它:
static uint32_t read_uint32_t(const uint8_t *buffer, size_t offset)
{
buffer += offset;
const uint32_t b0 = *buffer++;
const uint32_t b1 = *buffer++;
const uint32_t b2 = *buffer++;
const uint32_t b3 = *buffer++;
return (b3 << 24) | (b2 << 16) | (b1 << 8) | b0;
}
为简洁起见,上面使用了C99的微型,将它移植回C89是微不足道的。
编辑:以上适用于任何 arcihtecture,因为它不再进行直接访问。 相反,它假设buffer
包含little-endian格式的字节,我相信这是x86发起的BMP格式总是使用的。 因此,它甚至可以在大端机器上运行。 它也不再可能错误对齐大内存访问,因为所有访问都只是字节大小应该工作。
只要long
为32位值, memcpy
可以正常工作(我个人使用uint32_t
代替)。 如果您知道运行代码的体系结构始终是x86,那么转换将会起作用。
[关于字节顺序的其他人的好处]。
如果你关心字节顺序,那么使用类似的东西:
uint32_t width = bmp[0x12] + (bmp[0x13] << 8) + (bmp[0x14] << 16) + (bmp[0x15] << 24);
并且长度相同。 假设您的bmp
值是unsigned char
。
对于Win32,这两种方法都可能是正确的。 但通常两者都不安全。 第一个变体依赖于sizeof(long) == 4
。 第二种也依赖于此,但需要正确对齐数据(这可能是例如ARM上的问题)。 两者都有一个共同点,即他们假设某种结束,并将在x86和mips上显示不同的行为。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.