繁体   English   中英

Win32 C / C ++从字节数组中读取BMP宽度和高度

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM