OnDiskBitmap: Correct handling of "0 color palette" images

Microsoft documentation says:

> If biCompression equals BI_RGB and the bitmap uses 8 bpp or less, the bitmap has a color table immediatelly following the BITMAPINFOHEADER structure. The color table consists of an array of RGBQUAD values. The size of the array is given by the biClrUsed member. If biClrUsed is zero, the array contains the maximum number of colors for the given bitdepth; that is, 2^biBitCount colors.

Formerly, we treated 0 colors as "no image palette" during construction,
but then during common_hal_displayio_ondiskbitmap_get_pixel indexed into
the palette anyway.  This could have unpredictable results.  On a pygamer,
it gave an image that was blue and black.  On magtag, it gave a crash.
This commit is contained in:
Jeff Epler 2020-12-17 10:54:37 -06:00
parent 28bd29eb42
commit f224ed1848

View File

@ -57,7 +57,7 @@ void common_hal_displayio_ondiskbitmap_construct(displayio_ondiskbitmap_t *self,
uint32_t compression = read_word(bmp_header, 15); uint32_t compression = read_word(bmp_header, 15);
uint32_t number_of_colors = read_word(bmp_header, 23); uint32_t number_of_colors = read_word(bmp_header, 23);
bool indexed = ((bits_per_pixel <= 8) && (number_of_colors != 0)); bool indexed = bits_per_pixel <= 8;
self->bitfield_compressed = (compression == 3); self->bitfield_compressed = (compression == 3);
self->bits_per_pixel = bits_per_pixel; self->bits_per_pixel = bits_per_pixel;
self->width = read_word(bmp_header, 9); self->width = read_word(bmp_header, 9);
@ -75,6 +75,9 @@ void common_hal_displayio_ondiskbitmap_construct(displayio_ondiskbitmap_t *self,
self->b_bitmask = 0x1f; self->b_bitmask = 0x1f;
} }
} else if (indexed && self->bits_per_pixel != 1) { } else if (indexed && self->bits_per_pixel != 1) {
if (number_of_colors == 0) {
number_of_colors = 1 << bits_per_pixel;
}
uint16_t palette_size = number_of_colors * sizeof(uint32_t); uint16_t palette_size = number_of_colors * sizeof(uint32_t);
uint16_t palette_offset = 0xe + header_size; uint16_t palette_offset = 0xe + header_size;