]> Repositories - hackapet/Adafruit_Blinka_Displayio.git/commitdiff
Added OnDiskBitmap functionality
authorMelissa LeBlanc-Williams <melissa@adafruit.com>
Fri, 12 Jun 2020 17:38:03 +0000 (10:38 -0700)
committerMelissa LeBlanc-Williams <melissa@adafruit.com>
Fri, 12 Jun 2020 17:38:03 +0000 (10:38 -0700)
displayio/colorconverter.py
displayio/ondiskbitmap.py
displayio/tilegrid.py

index ead3f3407c21e9c38990f719a995d3d83e54ecc6..a93da2dd28fa5a0274225210ac6797e9be5dcc3e 100644 (file)
@@ -51,11 +51,12 @@ class ColorConverter:
         """
         self._dither = dither
         self._depth = 16
+        self._rgba = False
 
     # pylint: disable=no-self-use
     def _compute_rgb565(self, color):
         self._depth = 16
-        return (color >> 19) << 11 | ((color >> 10) & 0x3F) << 5 | (color >> 3) & 0x1F
+        return (color[0] & 0xF8) << 8 | (color[1] & 0xFC) << 3 | color[2] >> 3
 
     def _compute_luma(self, color):
         red = color >> 16
@@ -104,8 +105,20 @@ class ColorConverter:
 
     def convert(self, color):
         "Converts the given rgb888 color to RGB565"
+        if isinstance(color, int):
+            color = ((color >> 16) & 0xFF, (color >> 8) & 0xFF, color & 0xFF, 255)
+        elif isinstance(color, tuple):
+            if len(color) == 3:
+                color = (color[0], color[1], color[2], 255)
+            elif len(color) != 4:
+                raise ValueError("Color must be a 3 or 4 value tuple")
+        else:
+            raise ValueError("Color must be an integer or 3 or 4 value tuple")
+
         if self._dither:
             return color  # To Do: return a dithered color
+        if self._rgba:
+            return color
         return self._compute_rgb565(color)
 
     # pylint: enable=no-self-use
@@ -122,3 +135,16 @@ class ColorConverter:
         if not isinstance(value, bool):
             raise ValueError("Value should be boolean")
         self._dither = value
+
+    @property
+    def rgba(self):
+        """When true the color converter returns a 4-value
+        RGBA tuple rather than an integer
+        """
+        return self._rgba
+
+    @rgba.setter
+    def rgba(self, value):
+        if not isinstance(value, bool):
+            raise ValueError("Value should be boolean")
+        self._rgba = value
index 3a08ab328d7964aa8f4b978bd66f49bc4b47e362..5e1de465ce14f5667b436c830836deb642c7d921 100644 (file)
@@ -50,7 +50,7 @@ class OnDiskBitmap:
     image is visible."""
 
     def __init__(self, file):
-        self._image = Image.open(file)
+        self._image = Image.open(file).convert("RGBA")
 
     @property
     def width(self):
@@ -61,3 +61,19 @@ class OnDiskBitmap:
     def height(self):
         """Height of the bitmap. (read only)"""
         return self._image.height
+
+    def __getitem__(self, index):
+        """
+        Returns the value at the given index. The index can either be
+        an x,y tuple or an int equal to `y * width + x`.
+        """
+        if isinstance(index, (tuple, list)):
+            x = index[0]
+            y = index[1]
+        elif isinstance(index, int):
+            x = index % self._image._width
+            y = index // self._image._width
+        if not 0 <= x < self._image.width or not 0 <= y < self._image.height:
+            return 0
+
+        return self._image.getpixel((x, y))
index 76d3b2c587d9b0baf16e54aeb17d04f281b5dd1e..2536af5d8f9612747b27e563fb629cfcb5eda806 100644 (file)
@@ -82,9 +82,13 @@ class TileGrid:
         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
+        if isinstance(self._pixel_shader, ColorConverter):
+            self._pixel_shader.rgba = True
         self._hidden = False
         self._x = x
         self._y = y
@@ -93,6 +97,8 @@ class TileGrid:
         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:
@@ -184,6 +190,13 @@ class TileGrid:
                     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
+
     # pylint: disable=too-many-locals
     def _fill_area(self, buffer):
         """Draw onto the image"""
@@ -211,11 +224,8 @@ class TileGrid:
                         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["rgba"])
+                        pixel_color = self._shade(self._bitmap[bitmap_x, bitmap_y])
+                        image.putpixel((image_x, image_y), pixel_color)
 
         if self._absolute_transform is not None:
             if self._absolute_transform.scale > 1: