0

I need to get hold of the width and height values from the bmp so that I can pass those as arguments when I later create a gdk pixmap from the raw pixeldata in the bitmap. I did some research on the BMP-format and the file header should look like this:

struct Fileheader
{
    unsigned short Type;          // signature - 'BM'
    unsigned  long Size;          // file size in bytes
    unsigned short Reserved1;     // 0
    unsigned short Reserved2;     // 0
    unsigned long  OffBits;       // offset to bitmap
    unsigned long  StructSize;    // size of this struct (40)
    unsigned long  Width;         // bmap width in pixels
    unsigned long  Height;        // bmap height in pixels
    unsigned short Planes;        // num planes - always 1
    unsigned short BitCount;      // bits per pixel
    unsigned long  Compression;   // compression flag
    unsigned long  SizeImage;     // image size in bytes
    long           XPelsPerMeter; // horz resolution
    long           YPelsPerMeter; // vert resolution
    unsigned long  ClrUsed;       // 0 -> color table size
    unsigned long  ClrImportant;  // important color count
    Fileheader()
    {
        Size=Width=Height=Planes=BitCount=Compression=SizeImage=XPelsPerMeter= YPelsPerMeter=ClrUsed=ClrImportant=Type=StructSize=Reserved1=Reserved2=OffBits=0;}
    };
}

after fetching the blob the standard way into row[0]

Fileheader fh;
memcpy(&fh, row[0], sizeof(Fileheader));

will give just gibberish values when

cout << "width: " << fh.Width << ", height: " << fh.Height << endl;

namely: width: 65536, height: 5626121834492592128

Anyone see what's wrong here? I'm on a 64-bit linux box BTW.

3 Answers 3

2

If you are going to parse the data that way, which is discouraged, at least:

  • Use correct, platform-independed types. uint16_t instead of unsigned short, uint32_t instead unsigned long
  • Make your structures packed.

It won't work everywhere, but should work at least on x86 and x86_64.

It's discouraged mainly because it's platform and compiler dependent:

  • __attribute__ ((packed)) is gcc extension. Other compilers may handle it differently.
  • On some platforms it's impossible to tightly pack a structure. On others, they will work a little slower.
  • It will work only on little-endian machines.
Sign up to request clarification or add additional context in comments.

Comments

0

The unsigned long values in this structure should be only 32 bits. Given the value you're displaying for height you're reading much more than that.

Comments

0

The type long on gcc 64 bit is 64 bits long, but the original structure uses LONG, defined as 32 bit integers on Windows:

#pragma pack(push,1)
typedef struct tagBITMAPINFOHEADER {
  DWORD biSize; // use uint32_t instead
  LONG  biWidth;  // use int32_t instead
  LONG  biHeight; // use int32_t instead
  WORD  biPlanes;  // use uint16_t instead
  WORD  biBitCount;  // use uint16_t instead
  DWORD biCompression;  // use uint32_t instead
  DWORD biSizeImage;  // use uint32_t instead
  LONG  biXPelsPerMeter;  // use int32_t instead
  LONG  biYPelsPerMeter;  // use int32_t instead
  DWORD biClrUsed;  // use uint32_t instead
  DWORD biClrImportant;  // use uint32_t instead
} BITMAPINFOHEADER, *PBITMAPINFOHEADER;
#pragma pack(pop)

Also, be aware of negative height values: this identify an image where the first scan row is at the top of the image (you have to get a labs() of the height) Positive height values identify an image where the first scan row is at the bottom of the image.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.