开发者

Problems with BMP{FileHeader, InfoHeader} structures

I want to load a bmp file into memory in C. I've found many different types of BmpFileHeader and BmpInfoHeader structures. The last one that I've taken it from msdn.microsoft.com but it still does not read properly from binary file. With test file lena Image Size: -1076791624 Memory could not be allocated

What's the point I am missing? Thanks.

#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;

}


The first thing that I would do is to find an authoritative statement on the byte layout of these headers and then, assuming that you want to continue to use the structs that you have defined, add some asserts on the field offsets, for example:

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

Chances are that your use of unsigned int, short, etc plus your compiler options (especially structure packing) might mean that your struct fields do not match the actual BMP file data (in offset, and maybe in length).


Your bitmapInfoHeader is uninitialized!

That is, you read the bitmapFileHeader, and then set the file pointer to where the actual bitmap data should be. But you didn't read the bitmapInfoHeader, which contains all the information about the bitmap (dimensions, bpp and etc.)

P.S. Next time please try do debug your code befure posting the question.


There exist several versions of the BMP file format and most of them differ in the size of the headers. If you want to be able to read all valid BMP files, you'll need to support them all. The lena image seems to be a Windows V3 version.

There's a good description of the different versions in Wikipedia.

Furthermore, I don't see no endianness handling in your code. If you're machine isn't little endian, it will not work.

Finally, the alignment of the struct members is a problem. Your compiler will most likely align the bfSize member at offset 4 but it should be at offset 2. (See the Wikipedia article for a solution.)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜