|
29 | 29 | """
|
30 | 30 |
|
31 | 31 | import time
|
| 32 | +try: |
| 33 | + import numpy |
| 34 | +except ImportError: |
| 35 | + numpy = None |
32 | 36 | try:
|
33 | 37 | import struct
|
34 | 38 | except ImportError:
|
@@ -59,6 +63,13 @@ def color565(r, g=0, b=0):
|
59 | 63 | pass
|
60 | 64 | return (r & 0xf8) << 8 | (g & 0xfc) << 3 | b >> 3
|
61 | 65 |
|
| 66 | +def image_to_data(image): |
| 67 | + """Generator function to convert a PIL image to 16-bit 565 RGB bytes.""" |
| 68 | + #NumPy is much faster at doing this. NumPy code provided by: |
| 69 | + #Keith (https://www.blogger.com/profile/02555547344016007163) |
| 70 | + data = numpy.array(image.convert('RGB')).astype('uint16') |
| 71 | + color = ((data[:, :, 0] & 0xF8) << 8) | ((data[:, :, 1] & 0xFC) << 3) | (data[:, :, 2] >> 3) |
| 72 | + return numpy.dstack(((color >> 8) & 0xFF, color & 0xFF)).flatten().tolist() |
62 | 73 |
|
63 | 74 | class DummyPin:
|
64 | 75 | """Can be used in place of a ``DigitalInOut()`` when you don't want to skip it."""
|
@@ -179,16 +190,17 @@ def image(self, img, rotation=None):
|
179 | 190 | if imwidth != self.width or imheight != self.height:
|
180 | 191 | raise ValueError('Image must be same dimensions as display ({0}x{1}).' \
|
181 | 192 | .format(self.width, self.height))
|
182 |
| - pixels = bytearray(self.width * self.height * 2) |
183 |
| - # Iterate through the pixels |
184 |
| - for x in range(self.width): # yes this double loop is slow, |
185 |
| - for y in range(self.height): # but these displays are small! |
186 |
| - pix = color565(img.getpixel((x, y))) |
187 |
| - pixels[2*(y * self.width + x)] = pix >> 8 |
188 |
| - pixels[2*(y * self.width + x) + 1] = pix & 0xFF |
189 |
| - |
190 |
| - #print([hex(x) for x in pixels]) |
191 |
| - self._block(0, 0, self.width-1, self.height - 1, pixels) |
| 193 | + if numpy: |
| 194 | + pixels = list(image_to_data(img)) |
| 195 | + else: |
| 196 | + # Slower but doesn't require numpy |
| 197 | + pixels = bytearray(self.width * self.height * 2) |
| 198 | + for x in range(self.width): |
| 199 | + for y in range(self.height): |
| 200 | + pix = color565(img.getpixel((x, y))) |
| 201 | + pixels[2*(y * self.width + x)] = pix >> 8 |
| 202 | + pixels[2*(y * self.width + x) + 1] = pix & 0xFF |
| 203 | + self._block(0, 0, self.width - 1, self.height - 1, pixels) |
192 | 204 |
|
193 | 205 | #pylint: disable-msg=too-many-arguments
|
194 | 206 | def fill_rectangle(self, x, y, width, height, color):
|
|
0 commit comments