From bf54a1402ad8b787ec3308e85b39c9f5fbd9fd00 Mon Sep 17 00:00:00 2001 From: Vladimir Smitka Date: Sun, 18 Oct 2026 17:12:06 +0000 Subject: [PATCH] bitmaptools: readinto() reads whole rows from streams like sockets readinto() read each row with one call and took a short read as the end of the file. A socket returns what has arrived, so a row split across TCP segments raised EOFError. It now reads until the row is complete, with mp_stream_read_exactly(), as jpegio and audiocore do. On a PicoPad (RP2040), a 312x276 4-bit BMP streamed from a socket into a Bitmap now takes about 0.63 s instead of 2.2 s for the same decode in Python, with the same pixels. Reading from a file is unchanged. +16 bytes. --- shared-module/bitmaptools/__init__.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/shared-module/bitmaptools/__init__.c b/shared-module/bitmaptools/__init__.c index bcfbac3cf71..295b0429b41 100644 --- a/shared-module/bitmaptools/__init__.c +++ b/shared-module/bitmaptools/__init__.c @@ -576,7 +576,7 @@ void common_hal_bitmaptools_arrayblit(displayio_bitmap_t *self, void *data, int void common_hal_bitmaptools_readinto(displayio_bitmap_t *self, mp_obj_t *file, int element_size, int bits_per_pixel, bool reverse_pixels_in_element, bool swap_bytes, bool reverse_rows) { uint32_t mask = (1 << common_hal_displayio_bitmap_get_bits_per_value(self)) - 1; - const mp_stream_p_t *file_proto = mp_get_stream_raise(file, MP_STREAM_OP_READ); + mp_get_stream_raise(file, MP_STREAM_OP_READ); displayio_area_t a = {0, 0, self->width, self->height, NULL}; displayio_bitmap_set_dirty_area(self, &a); @@ -593,8 +593,9 @@ void common_hal_bitmaptools_readinto(displayio_bitmap_t *self, mp_obj_t *file, i const int y_draw = reverse_rows ? (self->height) - 1 - y : y; + // A stream such as a socket can return part of a row, so read until the row is complete. int error = 0; - mp_uint_t bytes_read = file_proto->read(file, rowdata32, rowsize, &error); + mp_uint_t bytes_read = mp_stream_read_exactly(file, rowdata32, rowsize, &error); if (error) { mp_raise_OSError(error); }