Last active
February 11, 2026 10:32
-
-
Save zaphodikus/9c2f1e52a86220b9aee27194474ce1f5 to your computer and use it in GitHub Desktop.
Load a 1bpp image
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // 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