]> Repositories - hackapet/Adafruit_Blinka_Displayio.git/blobdiff - displayio/_ondiskbitmap.py
Fix indexed bitmaps by correcting argument order at call
[hackapet/Adafruit_Blinka_Displayio.git] / displayio / _ondiskbitmap.py
index f9e9e8b48ba2d994e2b7a6a6efc51a10fd507988..00ea76511b0b3e10907b5513586a17a7fd49d28d 100644 (file)
@@ -19,26 +19,15 @@ displayio for Blinka
 """
 
 from typing import Union, BinaryIO
 """
 
 from typing import Union, BinaryIO
+from ._helpers import read_word
 from ._colorconverter import ColorConverter
 from ._colorconverter import ColorConverter
+from ._colorspace import Colorspace
 from ._palette import Palette
 
 __version__ = "0.0.0+auto.0"
 __repo__ = "https://github.com/adafruit/Adafruit_Blinka_displayio.git"
 
 
 from ._palette import Palette
 
 __version__ = "0.0.0+auto.0"
 __repo__ = "https://github.com/adafruit/Adafruit_Blinka_displayio.git"
 
 
-def _read_uint32(buffer: bytes, idx: int) -> int:
-    return (
-        buffer[idx]
-        | buffer[idx + 1] << 8
-        | buffer[idx + 2] << 16
-        | buffer[idx + 3] << 24
-    )
-
-
-def _read_word(header: bytes, idx: int) -> int:
-    return _read_uint32(header, idx * 2)
-
-
 class OnDiskBitmap:
     # pylint: disable=too-many-instance-attributes
     """
 class OnDiskBitmap:
     # pylint: disable=too-many-instance-attributes
     """
@@ -46,9 +35,6 @@ class OnDiskBitmap:
     load times. These load times may result in frame tearing where only part of the image is
     visible.
 
     load times. These load times may result in frame tearing where only part of the image is
     visible.
 
-    It's easiest to use on a board with a built in display such as the `Hallowing M0 Express
-    <https://www.adafruit.com/product/3900>`_.
-
     .. code-block:: Python
 
         import board
     .. code-block:: Python
 
         import board
@@ -59,7 +45,7 @@ class OnDiskBitmap:
         board.DISPLAY.auto_brightness = False
         board.DISPLAY.brightness = 0
         splash = displayio.Group()
         board.DISPLAY.auto_brightness = False
         board.DISPLAY.brightness = 0
         splash = displayio.Group()
-        board.DISPLAY.show(splash)
+        board.DISPLAY.root_group = splash
 
         odb = displayio.OnDiskBitmap(\'/sample.bmp\')
         face = displayio.TileGrid(odb, pixel_shader=odb.pixel_shader)
 
         odb = displayio.OnDiskBitmap(\'/sample.bmp\')
         face = displayio.TileGrid(odb, pixel_shader=odb.pixel_shader)
@@ -102,31 +88,35 @@ class OnDiskBitmap:
         try:
             self._file = file
             file.seek(0)
         try:
             self._file = file
             file.seek(0)
-            bmp_header = file.read(138)
+            bmp_header = memoryview(file.read(138)).cast(
+                "H"
+            )  # cast as unsigned 16-bit int
 
 
-            if len(bmp_header) != 138 or bmp_header[0:2] != b"BM":
+            if len(bmp_header.tobytes()) != 138 or bmp_header.tobytes()[0:2] != b"BM":
                 raise ValueError("Invalid BMP file")
 
                 raise ValueError("Invalid BMP file")
 
-            self._data_offset = _read_word(bmp_header, 5)
+            self._data_offset = read_word(bmp_header, 5)
 
 
-            header_size = _read_word(bmp_header, 7)
-            bits_per_pixel = bmp_header[14 * 2] | bmp_header[14 * 2 + 1] << 8
-            compression = _read_word(bmp_header, 15)
-            number_of_colors = _read_word(bmp_header, 23)
+            header_size = read_word(bmp_header, 7)
+            bits_per_pixel = bmp_header[14]
+            compression = read_word(bmp_header, 15)
+            number_of_colors = read_word(bmp_header, 23)
 
             indexed = bits_per_pixel <= 8
             self._bitfield_compressed = compression == 3
             self._bits_per_pixel = bits_per_pixel
 
             indexed = bits_per_pixel <= 8
             self._bitfield_compressed = compression == 3
             self._bits_per_pixel = bits_per_pixel
-            self._width = _read_word(bmp_header, 9)
-            self._height = _read_word(bmp_header, 11)
+            self._width = read_word(bmp_header, 9)
+            self._height = read_word(bmp_header, 11)
 
 
-            self._colorconverter = ColorConverter()
+            self._pixel_shader_base = ColorConverter(
+                input_colorspace=Colorspace.RGB888, dither=False
+            )
 
             if bits_per_pixel == 16:
                 if header_size >= 56 or self._bitfield_compressed:
 
             if bits_per_pixel == 16:
                 if header_size >= 56 or 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)
+                    self._r_bitmask = read_word(bmp_header, 27)
+                    self._g_bitmask = read_word(bmp_header, 29)
+                    self._b_bitmask = read_word(bmp_header, 31)
                 else:
                     # No compression or short header mean 5:5:5
                     self._r_bitmask = 0x7C00
                 else:
                     # No compression or short header mean 5:5:5
                     self._r_bitmask = 0x7C00
@@ -136,7 +126,7 @@ class OnDiskBitmap:
                 if number_of_colors == 0:
                     number_of_colors = 1 << bits_per_pixel
 
                 if number_of_colors == 0:
                     number_of_colors = 1 << bits_per_pixel
 
-                palette = Palette(number_of_colors)
+                palette = Palette(number_of_colors, dither=False)
 
                 if number_of_colors > 1:
                     palette_size = number_of_colors * 4
 
                 if number_of_colors > 1:
                     palette_size = number_of_colors * 4
@@ -144,16 +134,20 @@ class OnDiskBitmap:
 
                     file.seek(palette_offset)
 
 
                     file.seek(palette_offset)
 
-                    palette_data = file.read(palette_size)
-                    if len(palette_data) != palette_size:
+                    palette_data = memoryview(file.read(palette_size)).cast(
+                        "I"
+                    )  # cast as unsigned 32-bit int
+                    if len(palette_data.tobytes()) != palette_size:
                         raise ValueError("Unable to read color palette data")
 
                     for i in range(number_of_colors):
                         raise ValueError("Unable to read color palette data")
 
                     for i in range(number_of_colors):
-                        palette[i] = _read_uint32(palette_data, i * 4)
+                        palette._set_color(
+                            i, palette_data[i]
+                        )  # pylint: disable=protected-access
                 else:
                 else:
-                    palette[0] = 0x000000
-                    palette[1] = 0xFFFFFF
-                self._palette = palette
+                    palette._set_color(0x000000, 0)  # pylint: disable=protected-access
+                    palette._set_color(0xFFFFFF, 1)  # pylint: disable=protected-access
+                self._pixel_shader_base = palette
             elif header_size not in (12, 40, 108, 124):
                 raise ValueError(
                     "Only Windows format, uncompressed BMP supported: "
             elif header_size not in (12, 40, 108, 124):
                 raise ValueError(
                     "Only Windows format, uncompressed BMP supported: "
@@ -214,22 +208,6 @@ class OnDiskBitmap:
 
         return self._pixel_shader_base
 
 
         return self._pixel_shader_base
 
-    @property
-    def _colorconverter(self) -> ColorConverter:
-        return self._pixel_shader_base
-
-    @_colorconverter.setter
-    def _colorconverter(self, colorconverter: ColorConverter) -> None:
-        self._pixel_shader_base = colorconverter
-
-    @property
-    def _palette(self) -> Palette:
-        return self._pixel_shader_base
-
-    @_palette.setter
-    def _palette(self, palette: Palette) -> None:
-        self._pixel_shader_base = palette
-
     def _get_pixel(self, x: int, y: int) -> int:
         if not (0 <= x < self.width and 0 <= y < self.height):
             return 0
     def _get_pixel(self, x: int, y: int) -> int:
         if not (0 <= x < self.width and 0 <= y < self.height):
             return 0
@@ -272,7 +250,6 @@ class OnDiskBitmap:
                 return red << 19 | green << 10 | blue << 3
             if bytes_per_pixel == 4 and self._bitfield_compressed:
                 return pixel_data[0] | pixel_data[1] << 8 | pixel_data[2] << 16
                 return red << 19 | green << 10 | blue << 3
             if bytes_per_pixel == 4 and self._bitfield_compressed:
                 return pixel_data[0] | pixel_data[1] << 8 | pixel_data[2] << 16
-
             pixel = pixel_data[0] | pixel_data[1] << 8 | pixel_data[2] << 16
             if bytes_per_pixel == 4:
                 pixel |= pixel_data[3] << 24
             pixel = pixel_data[0] | pixel_data[1] << 8 | pixel_data[2] << 16
             if bytes_per_pixel == 4:
                 pixel |= pixel_data[3] << 24