0

I am trying to get number of bits per pixel in a bmp file. According to Wikipedia, it is supposed to be at 28th byte. So after reading a file:

// Przejscie do bajtu pod ktorym zapisana jest liczba bitow na pixel
        plik.seekg(28, ios::beg);

        // Read number of bytes used per pixel
        int liczbaBitow;
        plik.read((char*)&liczbaBitow, 2);

        cout << "liczba bitow " << liczbaBitow << endl;

But liczbaBitow (variable that is supposed to hold number of bits per pixel value) is -859045864. I don't know where it comes from... I'm pretty lost.

Any ideas?

MindRoller
  • 241
  • 4
  • 15
  • You need to show how the file was opened. Was it opened using the `ios::binary` flag set? – PaulMcKenzie Jun 06 '16 at 21:41
  • You are putting two bytes in an unititialized (probably 4 bytes long) integer. Try to initialize `liczbaBitow` to zero as first step. – VoidStar Jun 06 '16 at 21:42
  • The [bitmap file format](https://msdn.microsoft.com/en-us/library/dd183391.aspx) is **way** too complex, to write your own parser. Use a library, either one that is built into your platform, or a 3rd-party library. – IInspectable Jun 06 '16 at 22:33

2 Answers2

3

To clarify @TheBluefish's answer, this code has the bug

// Read number of bytes used per pixel
int liczbaBitow;
plik.read((char*)&liczbaBitow, 2);

When you use (char*)&libczbaBitow, you're taking the address of a 4 byte integer, and telling the code to put 2 bytes there.

The other two bytes of that integer are unspecified and uninitialized. In this case, they're 0xCC because that's the stack initialization value used by the system.

But if you're calling this from another function or repeatedly, you can expect the stack to contain other bogus values.

If you initialize the variable, you'll get the value you expect.

But there's another bug.. Byte order matters here too. This code is assuming that the machine native byte order exactly matches the byte order from the file specification. There are a number of different bitmap formats, but from your reference, the wikipedia article says:

All of the integer values are stored in little-endian format (i.e. least-significant byte first).

That's the same as yours, which is obviously also x86 little endian. Other fields aren't defined to be little endian, so as you proceed to decode the image, you'll have to watch for it.

Ideally, you'd read into a byte array and put the bytes where they belong. See Convert Little Endian to Big Endian

int libczbaBitow;
unsigned char bpp[2];
plik.read(bpp, 2);
libczbaBitow = bpp[0] | (bpp[1]<<8);
Community
  • 1
  • 1
davenpcj
  • 12,508
  • 5
  • 40
  • 37
2

-859045864 can be represented in hexadecimal as 0xCCCC0018.

Reading the second byte gives us 0x0018 = 24bpp.

What is most likely happening here, is that liczbaBitow is being initialized to 0xCCCCCCCC; while your plik.read is only writing the lower 16 bits and leaving the upper 16 bits unchanged. Changing that line should fix this issue:

int liczbaBitow = 0;

Though, especially with something like this, it's best to use a datatype that exactly matches your data:

int16_t liczbaBitow = 0;

This can be found in <cstdint>.