summaryrefslogtreecommitdiff
path: root/shared-module/displayio
diff options
context:
space:
mode:
authorBryan Siepert <bsiepert@gmail.com>2019-02-27 21:02:48 -0800
committerBryan Siepert <bsiepert@gmail.com>2019-02-28 23:08:12 -0800
commit398c7060f8a51bb83b0f5e0c2a1611d684603d2b (patch)
tree0c3b13f040917c2a448dfe2ceb29e979d2df847d /shared-module/displayio
parent2c9fbb5d40c457e87a4c0db3906960484f3668c0 (diff)
added monochrome, 8bpp indexed, and 32bpp ARGB BMPs
Diffstat (limited to 'shared-module/displayio')
-rw-r--r--shared-module/displayio/OnDiskBitmap.c104
-rw-r--r--shared-module/displayio/OnDiskBitmap.h4
2 files changed, 73 insertions, 35 deletions
diff --git a/shared-module/displayio/OnDiskBitmap.c b/shared-module/displayio/OnDiskBitmap.c
index bc3064632..76d8fb2d1 100644
--- a/shared-module/displayio/OnDiskBitmap.c
+++ b/shared-module/displayio/OnDiskBitmap.c
@@ -56,42 +56,65 @@ void common_hal_displayio_ondiskbitmap_construct(displayio_ondiskbitmap_t *self,
uint16_t bits_per_pixel = bmp_header[14];
uint32_t compression = read_word(bmp_header, 15);
uint32_t number_of_colors = read_word(bmp_header, 23);
+
+ bool indexed = ((bits_per_pixel <= 8) && (number_of_colors != 0));
self->bitfield_compressed = (compression == 3);
-
- self->grayscale = ((bits_per_pixel == 8) && (number_of_colors == 256));
+ self->bits_per_pixel = bits_per_pixel;
+ self->width = read_word(bmp_header, 9);
+ self->height = read_word(bmp_header, 11);
+
if (bits_per_pixel == 16){
- if (((header_size == 124) || (header_size == 56)) && (self->bitfield_compressed)) {
+ if (((header_size >= 56)) || (self->bitfield_compressed)) {
self->r_bitmask = read_word(bmp_header, 27);
self->g_bitmask = read_word(bmp_header, 29);
self->b_bitmask = read_word(bmp_header, 31);
- if (!((self->r_bitmask == 0xf800) && (self->g_bitmask == 0x07e0) && (self->b_bitmask == 0x001f))){
- mp_raise_ValueError_varg(translate("Only 16bpp RGB 565 supported for bitfield compressed BMPs; R:%x G:%x B:%x"),
- self->r_bitmask, self->g_bitmask, self->b_bitmask);
- }
- } else if (header_size == 40){ // no bitmasks means 5:5:5
+ } else { // no compression or short header means 5:5:5
self->r_bitmask = 0x7c00;
self->g_bitmask = 0x3e0;
self->b_bitmask = 0x1f;
}
+ } else if ((indexed) && (self->bits_per_pixel != 1)) {
+ uint16_t palette_size = number_of_colors * sizeof(uint32_t);
+ uint16_t palette_offset = 0xe + header_size;
+
+ self->palette_data = m_malloc(palette_size, false);
+
+ f_rewind(&self->file->fp);
+ f_lseek(&self->file->fp, palette_offset);
+
+ UINT palette_bytes_read;
+ if (f_read(&self->file->fp, self->palette_data, palette_size, &palette_bytes_read) != FR_OK) {
+ mp_raise_OSError(MP_EIO);
+ }
+ if (palette_bytes_read != palette_size) {
+ mp_raise_ValueError(translate("Unable to read color palette data"));
+ }
+
- } else if (!(header_size == 12 || header_size == 40 || header_size == 108 || header_size == 124) ||
- !(compression == 0)) {
+ } else if (!(header_size == 12 || header_size == 40 || header_size == 108 || header_size == 124)) {
mp_raise_ValueError_varg(translate("Only Windows format, uncompressed BMP supported %d"), header_size);
}
- if (bits_per_pixel < 16 && !(self->grayscale)) {
- mp_raise_ValueError_varg(translate("Only true color (24 bpp or higher), 16bpp 565 and 555, and 8bpp grayscale BMP supported %d"), bits_per_pixel);
+ if ((bits_per_pixel == 4 ) || (( bits_per_pixel == 8) && (number_of_colors == 0))) {
+ mp_raise_ValueError_varg(translate("Only monochrome, indexed 8bpp, and 16bpp or greater BMPs supported: %d"), bits_per_pixel);
}
- self->bytes_per_pixel = bits_per_pixel / 8;
- self->width = read_word(bmp_header, 9);
- self->height = read_word(bmp_header, 11);
- uint32_t byte_width = self->width * self->bytes_per_pixel;
- self->stride = byte_width;
- // Rows are word aligned.
- if (self->stride % 4 != 0) {
- self->stride += 4 - self->stride % 4;
+
+ if (self->bits_per_pixel >=8){
+ self->stride = (self->width * (bits_per_pixel / 8));
+ // Rows are word aligned.
+ if (self->stride % 4 != 0) {
+ self->stride += 4 - self->stride % 4;
+ }
+
+ } else {
+ uint32_t bit_stride = self->width;
+ if (bit_stride % 32 != 0) {
+ bit_stride += 32 - bit_stride % 32;
+ }
+ self->stride = (bit_stride / 8);
}
+
}
@@ -100,39 +123,54 @@ uint32_t common_hal_displayio_ondiskbitmap_get_pixel(displayio_ondiskbitmap_t *s
if (x < 0 || x >= self->width || y < 0 || y >= self->height) {
return 0;
}
- uint32_t location = self->data_offset + (self->height - y) * self->stride + x * self->bytes_per_pixel;
+ uint32_t location;
+ uint8_t bytes_per_pixel = (self->bits_per_pixel / 8) ? (self->bits_per_pixel /8) : 1;
+ if (self->bits_per_pixel >= 8){
+ location = self->data_offset + (self->height - y) * self->stride + x * bytes_per_pixel;
+ } else {
+ location = self->data_offset + (self->height - y) * self->stride + x / 8;
+ }
// We don't cache here because the underlying FS caches sectors.
f_lseek(&self->file->fp, location);
UINT bytes_read;
- uint32_t pixel = 0;
- uint32_t result = f_read(&self->file->fp, &pixel, self->bytes_per_pixel, &bytes_read);
+ uint32_t pixel = 0; // this name is stale
+ uint32_t result = f_read(&self->file->fp, &pixel, bytes_per_pixel, &bytes_read);
if (result == FR_OK) {
uint32_t tmp = 0;
uint8_t red;
uint8_t green;
uint8_t blue;
- if (self->grayscale){
- red = pixel;
- green = pixel;
- blue = pixel;
- tmp = (red << 16 | green << 8 | blue);
+ if (self->bits_per_pixel == 1){
+ uint8_t bit_offset = x%8;
+ tmp = ( pixel & (0x80 >> (bit_offset))) >> (7 - bit_offset);
+ if (tmp == 1) {
+ return 0x00FFFFFF;
+ } else {
+ return 0x00000000;
+ }
+ } else if (bytes_per_pixel == 1){
+ blue = ((self->palette_data[pixel] & 0xFF) >> 0);
+ red = ((self->palette_data[pixel] & 0xFF0000) >> 16);
+ green = ((self->palette_data[pixel] & 0xFF00) >> 8);
+ tmp = (red << 16 | green << 8 | blue );
return tmp;
- } else if (self->bytes_per_pixel == 2) {
- if (self->bitfield_compressed){
+ } else if (bytes_per_pixel == 2) {
+ if (self->g_bitmask == 0x07e0){ // 565
red =((pixel & self->r_bitmask) >>11);
green = ((pixel & self->g_bitmask) >>5);
blue = ((pixel & self->b_bitmask) >> 0);
- } else {
+ } else { // 555
red =((pixel & self->r_bitmask) >>10);
green = ((pixel & self->g_bitmask) >>4);
blue = ((pixel & self->b_bitmask) >> 0);
}
tmp = (red << 19 | green << 10 | blue << 3);
return tmp;
- }else {
+ }else if ((bytes_per_pixel == 4) && (self->bitfield_compressed)){
+ return pixel & 0x00FFFFFF;
+ } else {
return pixel;
}
-
}
return 0;
}
diff --git a/shared-module/displayio/OnDiskBitmap.h b/shared-module/displayio/OnDiskBitmap.h
index 2102863d6..28426f11b 100644
--- a/shared-module/displayio/OnDiskBitmap.h
+++ b/shared-module/displayio/OnDiskBitmap.h
@@ -44,9 +44,9 @@ typedef struct {
uint32_t g_bitmask;
uint32_t b_bitmask;
bool bitfield_compressed;
- bool grayscale;
pyb_file_obj_t* file;
- uint8_t bytes_per_pixel;
+ uint8_t bits_per_pixel;
+ uint32_t* palette_data;
} displayio_ondiskbitmap_t;
#endif // MICROPY_INCLUDED_SHARED_MODULE_DISPLAYIO_ONDISKBITMAP_H