Skip to content

Instantly share code, notes, and snippets.

@zaphodikus
Last active February 11, 2026 10:32
Show Gist options
  • Select an option

  • Save zaphodikus/9c2f1e52a86220b9aee27194474ce1f5 to your computer and use it in GitHub Desktop.

Select an option

Save zaphodikus/9c2f1e52a86220b9aee27194474ce1f5 to your computer and use it in GitHub Desktop.
Load a 1bpp image
// https://en.wikipedia.org/wiki/BMP_file_format#cite_ref-bmp_2-2
//
#ifndef WIN32
// defined in wingdi.h
constexpr uint32_t BI_RGB = 0;
constexpr uint32_t BI_RLE8 = 1;
constexpr uint32_t BI_RLE4 = 2;
constexpr uint32_t BI_BITFIELDS = 3;
constexpr uint32_t BI_JPEG = 4;
constexpr uint32_t BI_PNG = 5;
#endif
constexpr uint32_t BI_ALPHABITFIELDS = 6;
constexpr uint32_t BI_CMYK = 11;
constexpr uint32_t BI_CMYKRLE8 = 12;
constexpr uint32_t BI_CMYKRLE4 = 13;
constexpr std::uintmax_t BMP_PREAMBLE_LENGTH = 14;
constexpr std::uintmax_t BMP_HEADER_LENGTH = 40;
#pragma pack(push, 1)
struct bitmappreamble_t {
uint16_t icon;
uint32_t file_size; // size of entire file
uint16_t reserved1;
uint16_t reserved2;
uint32_t data_offset;
};
struct bitmapheader_t {
uint32_t s_length; // structure length 40
uint32_t width;
uint32_t height;
uint16_t planes; // colors 1
uint16_t bpp; // bits per pixel
uint32_t method; // compression method
uint32_t image_size; // raw
uint32_t horz_res; // horizontal resolution
uint32_t vert_res; // vertical resolution
uint32_t palette_size; // number of colours in palette
uint32_t palette_used; // number important colours
};
#pragma pack(pop)
// an additional bitmapinfoheader2 and pallete may follow in some file formats
template <typename T>static std::uintmax_t read_(std::ifstream& stream, T& value) {
stream.read(reinterpret_cast<char*>(&value), sizeof(value));
return sizeof(value);
}
uint32* load_1bpp_bmp(const char* filename);
////////////////////////////////////////////////////////////////////
// brute force makes many assumptions, but works for large bitmaps
// unlike the ATL library
uint32* load_1bpp_bmp(const char* filename) {
// load the Bitmap headers 1st
//
std::uintmax_t filesize = std::filesystem::file_size(filename);
std::ifstream file(filename, std::ios::binary | std::ios::ate);
file.exceptions(std::ios_base::badbit);
if (! file) {
throw std::ios_base::failure("file does not exist");
}
file.seekg(0, std::ios::beg);
bitmappreamble_t preamble{ 0 };
assert(BMP_PREAMBLE_LENGTH == sizeof(preamble));
read_(file, preamble.icon);
assert(preamble.icon == 0x4D42); // BM
read_(file, preamble.file_size);
assert(preamble.file_size == filesize);
read_(file, preamble.reserved1);
read_(file, preamble.reserved2);
read_(file, preamble.data_offset);
assert((preamble.data_offset > sizeof(preamble)) & (preamble.data_offset < preamble.file_size));
bitmapheader_t header{ 0 };
assert(BMP_HEADER_LENGTH == sizeof(header));
read_(file, header.s_length);
assert(BMP_HEADER_LENGTH == header.s_length);
read_(file, header.width);
read_(file, header.height);
read_(file, header.planes); // expect 1
read_(file, header.bpp); // expect 1
read_(file, header.method);
read_(file, header.image_size);
read_(file, header.horz_res);
read_(file, header.vert_res);
read_(file, header.palette_size);
read_(file, header.palette_used);
// allocate memory
uint32* pBuff = NULL;
size_t row_size = (header.width * header.bpp + 31) >> 4;
size_t isize = ((header.width * header.bpp + 31) >> 5) * header.height;
pBuff = (uint32*)malloc(sizeof(uint32) * (isize + 6)); // Room for image + command-header
if (pBuff) {
// the next few lines are a custom data headder of 6 parameters all DWORDs.
// these are CUSTOM to my application
memset(pBuff, 0, (isize + 6) * sizeof(DWORD)); // Clear out the buffer
pBuff[0] = PCMD_IMAGE; // Command
pBuff[1] = isize + 4; // Dword count
pBuff[2] = 1; // Plane
pBuff[3] = 1; // Xleft
pBuff[4] = 0; // Ytop
pBuff[5] = header.width; // Width
// point to right offset and read raw data
file.seekg(preamble.data_offset, std::ios::beg);
file.read((char*)(&pBuff[6]), isize * sizeof(uint32));
}
else { // handle malloc error
printf("malloc failed!\n");
}
return pBuff;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment