Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.5k views
in Technique[技术] by (71.8m points)

Win32 C/C++ Reading BMP width and height from a byte array

I have read a BMP file into a byte array. So after looking into the answers of this question: byte array to int c++. Is this way of obtaining the widht and height from a BMP information header safe and correct?

long width, height;
memcpy(&width, &bmp[0x12], sizeof(long)); 
memcpy(&height, &bmp[0x16], sizeof(long));

And what problems could this approach bring?

long* width = (long*)(&bmp[0x12]);
long* height= (long*)(&bmp[0x16]);

According to Wikipedia BMP file format, 0x12 is the offset of the bitmap width in pixels, and 0x16 the offset of the bitmap height in pixels.

PD. I have found this solution for loading the bitmap from memory buffer but I want to keep the code simple because I only need the width, the height and the raw data of the bitmap, and I do not know if that answer is safe either.

Thanks!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Both approaches do essentially the same thing, and both have the same fundamental problem: won't work if the host system has a different byte-order than the BMP file uses. This is always the problem with directly accessing values larger than a single byte in binary format.

The latter approach also has the additional disadvantage of possibly breaking if the host cannot do a long access at the resulting addresses.

In short, both "solutions" are bad. It's better to extract the value byte-by-byte and re-consititute it:

static uint32_t read_uint32_t(const uint8_t *buffer, size_t offset)
{
  buffer += offset;
  const uint32_t b0 = *buffer++;
  const uint32_t b1 = *buffer++;
  const uint32_t b2 = *buffer++;
  const uint32_t b3 = *buffer++;
  return (b3 << 24) | (b2 << 16) | (b1 << 8) | b0;
}

The above uses a smidgeon of C99 for brevity, porting it back to C89 is trivial.

Edit: the above works on any arcihtecture, since it's no longer doing direct accesses. Instead it assumes buffer contains bytes in little-endian format, which I believe is what the x86-originated BMP format always uses. So, it will work even on a big-endian machine. It also no longer does possibly mis-aligned large memory accesses, since all accesses are just byte-sized which should work.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...