Skip to content

Commit 6ff5ab2

Browse files
committed
Use numpy for rev B
1 parent f277682 commit 6ff5ab2

File tree

1 file changed

+44
-26
lines changed

1 file changed

+44
-26
lines changed

library/lcd/lcd_comm_rev_b.py

Lines changed: 44 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import struct
2121

2222
from serial.tools.list_ports import comports
23+
import numpy as np
2324

2425
from library.lcd.lcd_comm import *
2526
from library.log import logger
@@ -194,6 +195,39 @@ def SetOrientation(self, orientation: Orientation = Orientation.PORTRAIT):
194195
else:
195196
self.SendCommand(Command.SET_ORIENTATION, payload=[OrientationValueRevB.ORIENTATION_LANDSCAPE])
196197

198+
@staticmethod
199+
def imageToRGB565BE(image: Image.Image):
200+
if image.mode not in ["RGB", "RGBA"]:
201+
# we need the first 3 channels to be R, G and B
202+
image = image.convert("RGB")
203+
204+
rgb = np.asarray(image)
205+
206+
# flatten the first 2 dimensions (width and height) into a single stream
207+
# of RGB pixels
208+
rgb = rgb.reshape((image.size[1] * image.size[0], -1))
209+
210+
# extract R, G, B channels and promote them to 16 bits
211+
r = rgb[:, 0].astype(np.uint16)
212+
g = rgb[:, 1].astype(np.uint16)
213+
b = rgb[:, 2].astype(np.uint16)
214+
215+
# construct RGB565
216+
r = (r >> 3)
217+
g = (g >> 2)
218+
b = (b >> 3)
219+
rgb565 = (r << 11) | (g << 5) | b
220+
221+
# serialize to big-endian
222+
return rgb565.astype('>u2').tobytes()
223+
224+
def serialize_image(self, image: Image.Image, height: int, width: int) -> bytes:
225+
if image.width != width or image.height != height:
226+
image = image.crop((0, 0, width, height))
227+
if self.orientation == Orientation.REVERSE_PORTRAIT or self.orientation == Orientation.REVERSE_LANDSCAPE:
228+
image = image.rotate(180)
229+
return self.imageToRGB565BE(image)
230+
197231
def DisplayPILImage(
198232
self,
199233
image: Image.Image,
@@ -231,34 +265,18 @@ def DisplayPILImage(
231265
(y0 >> 8) & 255, y0 & 255,
232266
(x1 >> 8) & 255, x1 & 255,
233267
(y1 >> 8) & 255, y1 & 255])
234-
pix = image.load()
235-
line = bytes()
268+
269+
rgb565be = self.serialize_image(image, image_height, image_width)
236270

237271
# Lock queue mutex then queue all the requests for the image data
238272
with self.update_queue_mutex:
239-
for h in range(image_height):
240-
for w in range(image_width):
241-
if self.orientation == Orientation.PORTRAIT or self.orientation == Orientation.LANDSCAPE:
242-
R = pix[w, h][0] >> 3
243-
G = pix[w, h][1] >> 2
244-
B = pix[w, h][2] >> 3
245-
else:
246-
# Manage reverse orientations from software, because display does not manage it
247-
R = pix[image_width - w - 1, image_height - h - 1][0] >> 3
248-
G = pix[image_width - w - 1, image_height - h - 1][1] >> 2
249-
B = pix[image_width - w - 1, image_height - h - 1][2] >> 3
250-
251-
# Color information is 0bRRRRRGGGGGGBBBBB
252-
# Revision A: Encode in Little-Endian (native x86/ARM encoding)
253-
# Revition B: Encode in Big-Endian
254-
rgb = (R << 11) | (G << 5) | B
255-
line += struct.pack('>H', rgb)
256-
257-
# Send image data by multiple of "display width" bytes
258-
if len(line) >= self.get_width() * 8:
259-
self.SendLine(line)
260-
line = bytes()
273+
# Send image data by multiple of "display width" bytes
274+
start = 0
275+
end = self.get_width() * 8
276+
while end <= len(rgb565be):
277+
self.SendLine(rgb565be[start:end])
278+
start, end = end, end + self.get_width() * 8
261279

262280
# Write last line if needed
263-
if len(line) > 0:
264-
self.SendLine(line)
281+
if start != len(rgb565be):
282+
self.SendLine(rgb565be[start:])

0 commit comments

Comments
 (0)