]> Repositories - hackapet/Adafruit_Blinka_Displayio.git/blobdiff - displayio/tilegrid.py
Divide by zero and speed up bug fixes
[hackapet/Adafruit_Blinka_Displayio.git] / displayio / tilegrid.py
index 2a2222a5e9395edcb271f0453cc8723e4218577d..c88498da33e94d2e11755c06ba0c51771b350169 100644 (file)
@@ -21,7 +21,7 @@
 # THE SOFTWARE.
 
 """
 # THE SOFTWARE.
 
 """
-`displayio`
+`displayio.tilegrid`
 ================================================================================
 
 displayio for Blinka
 ================================================================================
 
 displayio for Blinka
@@ -35,18 +35,20 @@ displayio for Blinka
 
 """
 
 
 """
 
+from recordclass import recordclass
 from PIL import Image
 from displayio.bitmap import Bitmap
 from displayio.colorconverter import ColorConverter
 from displayio.ondiskbitmap import OnDiskBitmap
 from displayio.shape import Shape
 from displayio.palette import Palette
 from PIL import Image
 from displayio.bitmap import Bitmap
 from displayio.colorconverter import ColorConverter
 from displayio.ondiskbitmap import OnDiskBitmap
 from displayio.shape import Shape
 from displayio.palette import Palette
-from displayio import Rectangle
-from displayio import Transform
 
 __version__ = "0.0.0-auto.0"
 __repo__ = "https://github.com/adafruit/Adafruit_Blinka_displayio.git"
 
 
 __version__ = "0.0.0-auto.0"
 __repo__ = "https://github.com/adafruit/Adafruit_Blinka_displayio.git"
 
+Rectangle = recordclass("Rectangle", "x1 y1 x2 y2")
+Transform = recordclass("Transform", "x y dx dy scale transpose_xy mirror_x mirror_y")
+
 # pylint: disable=too-many-instance-attributes
 class TileGrid:
     """Position a grid of tiles sourced from a bitmap and pixel_shader combination. Multiple
 # pylint: disable=too-many-instance-attributes
 class TileGrid:
     """Position a grid of tiles sourced from a bitmap and pixel_shader combination. Multiple
@@ -80,9 +82,13 @@ class TileGrid:
         bitmap_width = bitmap.width
         bitmap_height = bitmap.height
 
         bitmap_width = bitmap.width
         bitmap_height = bitmap.height
 
-        if not isinstance(pixel_shader, (ColorConverter, Palette)):
+        if pixel_shader is not None and not isinstance(
+            pixel_shader, (ColorConverter, Palette)
+        ):
             raise ValueError("Unsupported Pixel Shader type")
         self._pixel_shader = pixel_shader
             raise ValueError("Unsupported Pixel Shader type")
         self._pixel_shader = pixel_shader
+        if isinstance(self._pixel_shader, ColorConverter):
+            self._pixel_shader._rgba = True  # pylint: disable=protected-access
         self._hidden = False
         self._x = x
         self._y = y
         self._hidden = False
         self._x = x
         self._y = y
@@ -91,14 +97,16 @@ class TileGrid:
         self._transpose_xy = False
         self._flip_x = False
         self._flip_y = False
         self._transpose_xy = False
         self._flip_x = False
         self._flip_y = False
+        self._top_left_x = 0
+        self._top_left_y = 0
         if tile_width is None:
             tile_width = bitmap_width
         if tile_height is None:
             tile_height = bitmap_height
         if tile_width is None:
             tile_width = bitmap_width
         if tile_height is None:
             tile_height = bitmap_height
-        if bitmap_width % tile_width != 0:
+        if tile_width > 0 and bitmap_width % tile_width != 0:
             raise ValueError("Tile width must exactly divide bitmap width")
         self._tile_width = tile_width
             raise ValueError("Tile width must exactly divide bitmap width")
         self._tile_width = tile_width
-        if bitmap_height % tile_height != 0:
+        if tile_height > 0 and bitmap_height % tile_height != 0:
             raise ValueError("Tile height must exactly divide bitmap height")
         self._tile_height = tile_height
         if not 0 <= default_tile <= 255:
             raise ValueError("Tile height must exactly divide bitmap height")
         self._tile_height = tile_height
         if not 0 <= default_tile <= 255:
@@ -182,6 +190,27 @@ class TileGrid:
                     self._current_area.y1,
                 )
 
                     self._current_area.y1,
                 )
 
+    def _shade(self, pixel_value):
+        if isinstance(self._pixel_shader, Palette):
+            return self._pixel_shader[pixel_value]["rgba"]
+        if isinstance(self._pixel_shader, ColorConverter):
+            return self._pixel_shader.convert(pixel_value)
+        return pixel_value
+
+    def _apply_palette(self, image):
+        image.putpalette(
+            self._pixel_shader._get_palette()  # pylint: disable=protected-access
+        )
+
+    def _add_alpha(self, image):
+        alpha = self._bitmap._image.copy().convert(  # pylint: disable=protected-access
+            "P"
+        )
+        alpha.putpalette(
+            self._pixel_shader._get_alpha_palette()  # pylint: disable=protected-access
+        )
+        image.putalpha(alpha.convert("L"))
+
     # pylint: disable=too-many-locals
     def _fill_area(self, buffer):
         """Draw onto the image"""
     # pylint: disable=too-many-locals
     def _fill_area(self, buffer):
         """Draw onto the image"""
@@ -198,22 +227,29 @@ class TileGrid:
         x = self._x
         y = self._y
 
         x = self._x
         y = self._y
 
-        for tile_x in range(0, self._width):
-            for tile_y in range(0, self._height):
+        for tile_x in range(self._width):
+            for tile_y in range(self._height):
                 tile_index = self._tiles[tile_y * self._width + tile_x]
                 tile_index_x = tile_index % tile_count_x
                 tile_index_y = tile_index // tile_count_x
                 tile_index = self._tiles[tile_y * self._width + tile_x]
                 tile_index_x = tile_index % tile_count_x
                 tile_index_y = tile_index // tile_count_x
-                for pixel_x in range(self._tile_width):
-                    for pixel_y in range(self._tile_height):
-                        image_x = tile_x * self._tile_width + pixel_x
-                        image_y = tile_y * self._tile_height + pixel_y
-                        bitmap_x = tile_index_x * self._tile_width + pixel_x
-                        bitmap_y = tile_index_y * self._tile_height + pixel_y
-                        pixel_color = self._pixel_shader[
-                            self._bitmap[bitmap_x, bitmap_y]
-                        ]
-                        if not pixel_color["transparent"]:
-                            image.putpixel((image_x, image_y), pixel_color["rgb888"])
+                tile_image = self._bitmap._image  # pylint: disable=protected-access
+                if isinstance(self._pixel_shader, Palette):
+                    tile_image = tile_image.copy().convert("P")
+                    self._apply_palette(tile_image)
+                    tile_image = tile_image.convert("RGBA")
+                    self._add_alpha(tile_image)
+                elif isinstance(self._pixel_shader, ColorConverter):
+                    # This will be needed for eInks, grayscale, and monochrome displays
+                    pass
+                image.alpha_composite(
+                    tile_image,
+                    dest=(tile_x * self._tile_width, tile_y * self._tile_height),
+                    source=(
+                        tile_index_x * self._tile_width,
+                        tile_index_y * self._tile_height,
+                    ),
+                )
+
         if self._absolute_transform is not None:
             if self._absolute_transform.scale > 1:
                 image = image.resize(
         if self._absolute_transform is not None:
             if self._absolute_transform.scale > 1:
                 image = image.resize(