Win32 C/C++从字节数组读取BMP宽度和高度
Win32 C/C++ Reading BMP width and height from a byte array
我已经将BMP文件读取到字节数组中。因此,在研究了这个问题的答案之后:字节数组到int c++。这种从BMP信息头获取宽度和高度的方法安全正确吗?
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格式一直使用的格式。因此,它甚至可以在大型endian机器上工作。它也不再进行可能不对齐的大型内存访问,因为所有访问都是字节大小的,应该可以工作。
只要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上)。两者都有一个共同点,即它们假设了特定的endianes,并将在例如x86和mips上显示不同的行为。
- 如何读取从UChar缓冲区到CV :: MAT的1位BMP
- C++:读取.BMP文件时出现问题;文件结束时间早于预期
- 读取BMP文件会归还意外数据
- 在C++中读取bmp文件的宽度和高度
- 在C 中读取并编写BMP文件
- 读取 BMP 文件C++(读取 BMP 标头时出现问题)
- BMP读取器无法正常运行
- 用C或C++读取/写入BMP/PNG灰度图像
- 当尝试读取和写入bmp文件c++时中止
- Win32 C/C++从字节数组读取BMP宽度和高度
- 使用fread()读取BMP的文件头
- 从bmp文件读取RGB像素
- 在C++中读取BMP的奇怪行为
- 读取bmp文件中的像素值
- 在c++中读取.bmp文件
- 如何在bmp中读取像素后的像素
- 读取1,8或24位BMP文件与c++
- 读取.bmp(24位)到2D数组中
- 无法正确读取bmp文件
- 读取.bmp文件的c++,错误的值