1 # The MIT License (MIT)
3 # Copyright (c) 2020 Melissa LeBlanc-Williams for Adafruit Industries
5 # Permission is hereby granted, free of charge, to any person obtaining a copy
6 # of this software and associated documentation files (the "Software"), to deal
7 # in the Software without restriction, including without limitation the rights
8 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 # copies of the Software, and to permit persons to whom the Software is
10 # furnished to do so, subject to the following conditions:
12 # The above copyright notice and this permission notice shall be included in
13 # all copies or substantial portions of the Software.
15 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 ================================================================================
29 **Software and Dependencies:**
32 https://github.com/adafruit/Adafruit_Blinka/releases
34 * Author(s): Melissa LeBlanc-Williams
38 from recordclass import recordclass
41 __version__ = "0.0.0-auto.0"
42 __repo__ = "https://github.com/adafruit/Adafruit_Blinka_displayio.git"
44 Rectangle = recordclass("Rectangle", "x1 y1 x2 y2")
48 """Stores values of a certain size in a 2D array"""
50 def __init__(self, width, height, value_count):
51 """Create a Bitmap object with the given fixed size. Each pixel stores a value that is
52 used to index into a corresponding palette. This enables differently colored sprites to
53 share the underlying Bitmap. value_count is used to minimize the memory used to store
56 self._bmp_width = width
57 self._bmp_height = height
58 self._read_only = False
61 raise ValueError("value_count must be > 0")
64 while (value_count - 1) >> bits:
70 self._bits_per_value = bits
73 self._bits_per_value > 8
74 and self._bits_per_value != 16
75 and self._bits_per_value != 32
77 raise NotImplementedError("Invalid bits per value")
79 self._image = Image.new("P", (width, height), 0)
80 self._dirty_area = Rectangle(0, 0, width, height)
82 def __getitem__(self, index):
84 Returns the value at the given index. The index can either be
85 an x,y tuple or an int equal to `y * width + x`.
87 if isinstance(index, (tuple, list)):
89 elif isinstance(index, int):
90 x = index % self._bmp_width
91 y = index // self._bmp_width
93 raise TypeError("Index is not an int, list, or tuple")
95 if x > self._image.width or y > self._image.height:
96 raise ValueError("Index {} is out of range".format(index))
97 return self._image.getpixel((x, y))
99 def __setitem__(self, index, value):
101 Sets the value at the given index. The index can either be
102 an x,y tuple or an int equal to `y * width + x`.
105 raise RuntimeError("Read-only object")
106 if isinstance(index, (tuple, list)):
109 index = y * self._bmp_width + x
110 elif isinstance(index, int):
111 x = index % self._bmp_width
112 y = index // self._bmp_width
113 self._image.putpixel((x, y), value)
114 if self._dirty_area.x1 == self._dirty_area.x2:
115 self._dirty_area.x1 = x
116 self._dirty_area.x2 = x + 1
117 self._dirty_area.y1 = y
118 self._dirty_area.y2 = y + 1
120 if x < self._dirty_area.x1:
121 self._dirty_area.x1 = x
122 elif x >= self._dirty_area.x2:
123 self._dirty_area.x2 = x + 1
124 if y < self._dirty_area.y1:
125 self._dirty_area.y1 = y
126 elif y >= self._dirty_area.y2:
127 self._dirty_area.y2 = y + 1
129 def _finish_refresh(self):
130 self._dirty_area.x1 = 0
131 self._dirty_area.x2 = 0
133 def fill(self, value):
134 """Fills the bitmap with the supplied palette index value."""
135 self._image = Image.new("P", (self._bmp_width, self._bmp_height), value)
136 self._dirty_area = Rectangle(0, 0, self._bmp_width, self._bmp_height)
140 """Width of the bitmap. (read only)"""
141 return self._bmp_width
145 """Height of the bitmap. (read only)"""
146 return self._bmp_height