How can I read BMP pixel values into an array?

I'm writing code in C++ (on Windows) and I'm trying to extract the pixel values of a grayscale bmp. I don't care about keeping any of the metadata, and just want to store the pixel values in a char array. I haven't been able to find a standard or "typical" way of doing this manually, so I'm wondering if there's perhaps a simple library that people use to load bitmaps into memory.

Thanks in advance!


Solution 1:

and ready to go code, tested with g++ (not Windows, but may help someone):

#pragma pack(1)

#include <iostream>
#include <fstream>
#include <vector>

using namespace std;

#include "bmp.h"

vector<char> buffer;
PBITMAPFILEHEADER file_header;
PBITMAPINFOHEADER info_header;

void fill() {
    std::ifstream file("data.bmp");

    if (file) {
        file.seekg(0,std::ios::end);
        streampos length = file.tellg();
        file.seekg(0,std::ios::beg);

        buffer.resize(length);
        file.read(&buffer[0],length);

        file_header = (PBITMAPFILEHEADER)(&buffer[0]);
        info_header = (PBITMAPINFOHEADER)(&buffer[0] + sizeof(BITMAPFILEHEADER));
    }
}

int main() {
    fill();

    cout << buffer[0] << buffer[1] << endl;
    cout << file_header->bfSize << endl;
    cout << info_header->biWidth << " " << info_header->biHeight << endl;

    return 0;
}

In bmp.h i have defined structures:

#pragma once

typedef int LONG;
typedef unsigned short WORD;
typedef unsigned int DWORD;

typedef struct tagBITMAPFILEHEADER {
  WORD  bfType;
  DWORD bfSize;
  WORD  bfReserved1;
  WORD  bfReserved2;
  DWORD bfOffBits;
} BITMAPFILEHEADER, *PBITMAPFILEHEADER;

typedef struct tagBITMAPINFOHEADER {
  DWORD biSize;
  LONG  biWidth;
  LONG  biHeight;
  WORD  biPlanes;
  WORD  biBitCount;
  DWORD biCompression;
  DWORD biSizeImage;
  LONG  biXPelsPerMeter;
  LONG  biYPelsPerMeter;
  DWORD biClrUsed;
  DWORD biClrImportant;
} BITMAPINFOHEADER, *PBITMAPINFOHEADER;

Solution 2:

Read the entire file into memory. There will be a small header at the front, and the rest of it will be the pixel values.

The first part will be a BITMAPFILEHEADER structure. The only part you care about is the bfOffBits, which gives the number of bytes from the start of the file to the pixel values.

The next part after the BITMAPFILEHEADER will be a BITMAPINFOHEADER. This will be useful to determine the format of the pixels.

This will be followed by a palette, if the bit depth requires one.

There are a couple of gotchas with the pixel values. First is that the order is (blue,green,red), just opposite of the way everybody else does it. Second is that the rows go from bottom to top of the image, again backwards from everybody else. Finally, the number of bytes in a row will always be padded up to the next multiple of 4.

I almost forgot to mention, it is possible for a JPEG or PNG file to be encoded as a BMP, but this is not common. Have a look at the biCompression field of the BITMAPINFOHEADER, if it's anything but BI_RGB you'll need a little more help.