Skip to content

Commit 1d74be2

Browse files
authored
Merge pull request #47 from Johennes/feature/numpy
Use numpy for bulk pixel data conversion
2 parents 69569e7 + 4a18be9 commit 1d74be2

File tree

2 files changed

+24
-10
lines changed

2 files changed

+24
-10
lines changed

README.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ Please ensure all dependencies are available on the CircuitPython filesystem.
3030
This is easily achieved by downloading
3131
`the Adafruit library and driver bundle <https://github.com/adafruit/Adafruit_CircuitPython_Bundle>`_.
3232

33+
For improved performance consider installing numpy.
34+
3335
Installing from PyPI
3436
====================
3537

adafruit_rgb_display/rgb.py

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@
2929
"""
3030

3131
import time
32+
try:
33+
import numpy
34+
except ImportError:
35+
numpy = None
3236
try:
3337
import struct
3438
except ImportError:
@@ -59,6 +63,13 @@ def color565(r, g=0, b=0):
5963
pass
6064
return (r & 0xf8) << 8 | (g & 0xfc) << 3 | b >> 3
6165

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()
6273

6374
class DummyPin:
6475
"""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):
179190
if imwidth != self.width or imheight != self.height:
180191
raise ValueError('Image must be same dimensions as display ({0}x{1}).' \
181192
.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)
192204

193205
#pylint: disable-msg=too-many-arguments
194206
def fill_rectangle(self, x, y, width, height, color):

0 commit comments

Comments
 (0)