【问题标题】:Function to read bmp file header读取bmp文件头的函数
【发布时间】:2015-05-15 15:56:17
【问题描述】:
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 行代码有疑问,我将 char 指针类型转换为无符号整数。我这样做是因为 FileSize 值是unsigned int 类型,我的 baseptr 实际上是一个 char 指针。我做对了吗?代码是否正确?

【问题讨论】:

    标签: pointers types casting header bmp


    【解决方案1】:

    如果您的目标计算机的字节序与 BMP 标头中的字节序相同是正确的。在这种情况下,对于小端机器是正确的,x86 PC 就是这种情况。

    如果您正在为使用大端序的目标计算机进行编译,不幸的是,您别无选择,只能读取组成单词的四个字节,然后将它们重新组合成您愿意使用的 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 标头字段完全匹配的结构中使用 memcpyfread,这比单独复制每个字段要优雅得多:)

    最后一个提示,使用 uint32_t 等类型而不是 unsigned int,这样可以确保您使用的是 32 位 int,因为有些机器使用 16 位整数,而您需要 long 来获取一个 32 位整数。

    【讨论】:

    • 我将在 ARM 上使用它...所以它是 32 位 int
    • 是的,字节序取决于系统。大多数情况下 ARM 是连线的,所以它们使用小端顺序,但并非总是如此,所以你一定要检查一下!
    • 好的。基本上我将从pendrive中读取位图图像并将其保存在我的ARM控制器内存中......然后我会在需要时从内存中读取它......所以数据将如何在内存中...数据“BM”在我看来会像“MB”吗?还是 0x12345678 在我看来会像 0x78563412?
    • 对于“B”和“M”,由于您分别读取两个字节,因此不会因字节顺序而出现错误。至于其余的,ARM 可以是任何一种字节序,所以你应该检查你正在使用的 CPU/芯片/板上的文档。
    【解决方案2】:

    你的怀疑是有道理的。以这种方式投射假定您的输入文件和运行它的机器具有相同的字节序。

    安全的做法是不要假设任何事情,并且首先不要使用演员表。有一些标准函数可以将二进制数据转换为“平台”字节序(ntohlntohshtonlhtons),如果不需要转换,它们什么都不做,否则转换。这是因为他们针对目标操作系统的 library 实现知道系统运行的字节序。

    或者,一次使用一个字节的较大值,并以不知道字节序的顺序连接它们。 (您的程序“不知道”;输入的字节顺序必须是已知的!)

    例如:

    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。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-21
      • 2018-04-10
      • 2014-05-22
      • 1970-01-01
      • 2021-12-05
      相关资源
      最近更新 更多