https://learn.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-bitmapinfoheader
pub const BITMAPINFOHEADER = extern struct
pub const BITMAPINFOHEADER = extern struct {
bcSize: u32,
biWidth: i32,
biHeight: i32,
biPlanes: u16,
biBitCount: u16,
biCompression: u32,
biSizeImage: u32,
biXPelsPerMeter: i32,
biYPelsPerMeter: i32,
biClrUsed: u32,
biClrImportant: u32,
/// Returns error.TooManyColorsInPalette if the number of colors specified
/// exceeds the number of possible colors referenced in the pixel data (i.e.
/// if 1 bit is used per pixel, then the color table can't have more than 2 colors
/// since any more couldn't possibly be indexed in the pixel data)
///
/// Returns error.InvalidBitsPerPixel if the bit depth is not 1, 4, 8, 16, 24, or 32.
pub fn numColorsInTable(self: BITMAPINFOHEADER) !u32 {
switch (self.biBitCount) {
inline 1, 4, 8 => |bit_count| switch (self.biClrUsed) {
// > If biClrUsed is zero, the array contains the maximum number of
// > colors for the given bitdepth; that is, 2^biBitCount colors
0 => return 1 << bit_count,
// > If biClrUsed is nonzero and the biBitCount member is less than 16,
// > the biClrUsed member specifies the actual number of colors the
// > graphics engine or device driver accesses.
else => {
const max_colors = 1 << bit_count;
if (self.biClrUsed > max_colors) {
return error.TooManyColorsInPalette;
}
return self.biClrUsed;
},
},
// > If biBitCount is 16 or greater, the biClrUsed member specifies
// > the size of the color table used to optimize performance of the
// > system color palettes.
//
// Note: Bit depths >= 16 only use the color table 'for optimizing colors
// used on palette-based devices', but it still makes sense to limit their
// colors since the pixel data is still limited to this number of colors
// (i.e. even though the color table is not indexed by the pixel data,
// the color table having more colors than the pixel data can represent
// would never make sense and indicates a malformed bitmap).
inline 16, 24, 32 => |bit_count| {
const max_colors = 1 << bit_count;
if (self.biClrUsed > max_colors) {
return error.TooManyColorsInPalette;
}
return self.biClrUsed;
},
else => return error.InvalidBitsPerPixel,
}
}
}