unsigned char* Read_pixels(unsigned char *baseptr)
{
unsigned char pixelinfo[4096];
pFileheader->ID1 = *baseptr++; // save B
pFileheader->ID2 = *baseptr++; // save M
pFileheader->FileSize = *((unsigned int*)baseptr);
baseptr = baseptr + 4;
pFileheader->Reserved = *((unsigned short*)baseptr);
baseptr = baseptr + 2;
pFileheader->Reserved2 = *((unsigned short*)baseptr);
baseptr = baseptr + 2;
pFileheader->PxOffset = *((unsigned int*)baseptr);
}
在这个READ BMP函数中,我收到一个指向内存中bmp文件开头的指针。 我在上面的代码中做的是读取文件头并将数据存储在文件头结构的各个成员中。我在代码的第5行中有一个疑问,我将类型转换为无符号int的char指针。我这样做是因为FileSize值是unsigned int类型和我的baseptr实际上是一个char指针。我做得对吗?代码是否正确?
答案 0 :(得分:0)
如果目标计算机的字节顺序与BMP标题中的字节顺序相同,则正确 。在这种情况下,它适用于小端机器,例如x86 PC。
如果您正在为使用big endian的目标机器进行编译,那么您遗憾的是除了读取生成该字的四个字节之外别无选择,并重新组合它们以形成您愿意的32位整数使用
一种可行的方法是使用预处理器,并在某处:
#ifdef BIG_ENDIAN
length = ((length << 24) & 0xff000000) /* Swap the 4 bytes within the word */
| ((length << 8) & 0x00ff0000)
| ((length >> 8) & 0x0000ff00)
| ((length >> 24) & 0x000000ff);
#endif
另外,如果我是你,我会在一个与BMP标题字段完全匹配的结构中使用memcpy
或fread
,这比单独处理每个字段要优雅得多:)
最后一个提示,使用uint32_t
而不是unsigned int
等类型,这可以确保您使用32位int
,因为有些计算机使用16位整数和你需要long
来获得一个32位整数。
答案 1 :(得分:0)
你的疑惑是合理的。以这种方式进行转换假设您的输入文件和运行它的机器具有相同的字节顺序。
安全的做法是不假设任何而不是首先使用演员表。有一些标准函数可以将二进制数据转换为“平台”字节序(ntohl
,ntohs
和htonl
,htons
),如果不需要转换则不执行任何操作,否则转换。这是有效的,因为目标操作系统的库实现知道系统运行的字节序。
或者,一次消耗一个字节的较大值,并以endianness-unaware顺序连接它们。 (“不知道”为您的程序;必须知道输入字节序!)
例如:
pFileheader->FileSize = (unsigned int)baseptr[0] +
(((unsigned int)baseptr[1])<<8) +
(((unsigned int)baseptr[2])<<16) +
(((unsigned int)baseptr[3])<<24);
baseptr = baseptr + 4;
pFileheader->Reserved =(unsigned int)baseptr[0] +
(((unsigned int)baseptr[1])<<8);
baseptr = baseptr + 2;
等等。如果使用了很多,写一个函数或宏来读取一个字或32位int。