BMP {File Header,Info Header}结构的问题

时间:2010-11-01 17:31:57

标签: c

我想在B中将bmp文件加载到内存中。我发现了许多不同类型的BmpFileHeader和BmpInfoHeader结构。我从msdn.microsoft.com获取的最后一个,但它仍然无法从二进制文件中正确读取。使用测试文件lena 图片大小:-1076791624 无法分配内存

我错过了什么?感谢。

#include <stdio.h>
#include <stdlib.h>

typedef struct tagBITMAPFILEHEADER {
  unsigned short bfType;
  unsigned int bfSize;
  short bfReserved1;
  short bfReserved2;
  unsigned int bfOffBits;
} BITMAPFILEHEADER;

typedef struct tagBITMAPINFOHEADER {
  unsigned int biSize;
  int biWidth;
  int biHeight;
  short biPlanes;
  short biBitCount;
  unsigned int biCompression;
  unsigned int biSizeImage;
  int biXPelsPerMeter;
  int biYPelsPerMeter;
  unsigned int biClrUsed;
  unsigned int biClrImportant;
} BITMAPINFOHEADER;   

int main(int argc, char *argv[])
{
   if(argc != 2)
   {
    printf("Usage: %s input.bmp\n", argv[0]);
    exit(-1);
   }

   FILE *filePtr;
   BITMAPFILEHEADER bitmapFileHeader;
   BITMAPINFOHEADER bitmapInfoHeader;
   unsigned char *bitmapImage;
   int imageIdx=0;
   unsigned char tempRGB;

   filePtr = fopen(argv[1],"rb");
   if (filePtr == NULL)
   {
    printf("File could not opened\n");
    exit(-1);
    }

    //read the bitmap file header
    fread(&bitmapFileHeader, sizeof(bitmapFileHeader), 1, filePtr);

    if (bitmapFileHeader.bfType !=0x4D42)
    {
    fclose(filePtr);
    printf("Not a bmp file\n");
    exit(-1);
    }

    fseek(filePtr, bitmapFileHeader.bfOffBits, SEEK_SET);
    bitmapImage = (unsigned char*)malloc(sizeof(unsigned char)*bitmapInfoHeader.biSizeImage);
    printf("Image Size: %d\n", bitmapInfoHeader.biSizeImage);

    if (!bitmapImage)
    {
    free(bitmapImage);
    fclose(filePtr);
    printf("Memory could not be allocated\n");
    exit(-1);
    }

    //swap the r and b values to get RGB (bitmap is BGR)
    for (imageIdx = 0; imageIdx < bitmapInfoHeader.biSizeImage; imageIdx+=3)
    {
    tempRGB = bitmapImage[imageIdx];
    bitmapImage[imageIdx] = bitmapImage[imageIdx + 2];
    bitmapImage[imageIdx + 2] = tempRGB;
    }

    int i;

    for(i = 0; i < bitmapInfoHeader.biSizeImage; i+=3){
    printf("R: %c G: %c B: %c\n", bitmapImage[i], bitmapImage[i + 1], bitmapImage[i + 2]);
    }

    fclose(filePtr); 

    return 0;

}

3 个答案:

答案 0 :(得分:0)

您的bitmapInfoHeader 未初始化

即,您读取bitmapFileHeader,然后将文件指针设置为实际位图数据的位置。但是您没有阅读bitmapInfoHeader,其中包含有关位图的所有信息(尺寸,bpp等)。

P.S。 下次请尝试调试你的代码发布问题。

答案 1 :(得分:0)

我要做的第一件事是在这些标题的byte layout上找到权威声明,然后假设您要继续使用已定义的结构,在字段上添加一些断言抵消,例如:

assert(offsetof(BITMAPFILEHEADER, bfType) == 0);     // or whatever
assert(offsetof(BITMAPFILEHEADER, bfSize) == 2);     // or whatever
assert(offsetof(BITMAPFILEHEADER, bfOffBits) == 10); // or whatever
etc.

有可能你使用unsigned int,short等加上你的编译器选项(特别是结构打包)可能意味着你的struct字段与实际的BMP文件数据不匹配(偏移量,也许是长度)。

答案 2 :(得分:0)

存在多种版本的BMP文件格式,其中大多数都在标题大小上有所不同。如果您希望能够读取所有有效的BMP文件,则需要全部支持它们。 lena图像似乎是Windows V3版本。

Wikipedia中对不同版本有很好的描述。

此外,我没有看到代码中没有字节序处理。如果你的机器不是小端,那就不行了。

最后,结构成员的对齐是一个问题。您的编译器很可能在偏移量4处对齐 bfSize 成员,但它应该在偏移量2处。(有关解决方案,请参阅Wikipedia文章。)