Skip to content

Commit 49154d8

Browse files
committed
Move serialization functions to dedicated module
1 parent 1c88d4d commit 49154d8

File tree

3 files changed

+47
-77
lines changed

3 files changed

+47
-77
lines changed

library/lcd/lcd_comm_rev_a.py

Lines changed: 4 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@
2121
from typing import Optional
2222

2323
from serial.tools.list_ports import comports
24-
import numpy as np
2524

2625
from library.lcd.lcd_comm import *
26+
from library.lcd.serialize import image_to_RGB565, chunked
2727
from library.log import logger
2828

2929

@@ -173,32 +173,6 @@ def SetOrientation(self, orientation: Orientation = Orientation.PORTRAIT):
173173
byteBuffer[10] = (height & 255)
174174
self.serial_write(bytes(byteBuffer))
175175

176-
@staticmethod
177-
def imageToRGB565LE(image: Image.Image):
178-
if image.mode not in ["RGB", "RGBA"]:
179-
# we need the first 3 channels to be R, G and B
180-
image = image.convert("RGB")
181-
182-
rgb = np.asarray(image)
183-
184-
# flatten the first 2 dimensions (width and height) into a single stream
185-
# of RGB pixels
186-
rgb = rgb.reshape((image.size[1] * image.size[0], -1))
187-
188-
# extract R, G, B channels and promote them to 16 bits
189-
r = rgb[:, 0].astype(np.uint16)
190-
g = rgb[:, 1].astype(np.uint16)
191-
b = rgb[:, 2].astype(np.uint16)
192-
193-
# construct RGB565
194-
r = (r >> 3)
195-
g = (g >> 2)
196-
b = (b >> 3)
197-
rgb565 = (r << 11) | (g << 5) | b
198-
199-
# serialize to little-endian
200-
return rgb565.astype('<u2').tobytes()
201-
202176
def DisplayPILImage(
203177
self,
204178
image: Image.Image,
@@ -232,20 +206,12 @@ def DisplayPILImage(
232206
(x0, y0) = (x, y)
233207
(x1, y1) = (x + image_width - 1, y + image_height - 1)
234208

235-
rgb565le = self.imageToRGB565LE(image)
209+
rgb565le = image_to_RGB565(image, "little")
236210

237211
self.SendCommand(Command.DISPLAY_BITMAP, x0, y0, x1, y1)
238212

239213
# Lock queue mutex then queue all the requests for the image data
240214
with self.update_queue_mutex:
241-
242215
# Send image data by multiple of "display width" bytes
243-
start = 0
244-
end = width * 8
245-
while end <= len(rgb565le):
246-
self.SendLine(rgb565le[start:end])
247-
start, end = end, end + width * 8
248-
249-
# Write last line if needed
250-
if start != len(rgb565le):
251-
self.SendLine(rgb565le[start:])
216+
for chunk in chunked(rgb565le, width * 8):
217+
self.SendLine(chunk)

library/lcd/lcd_comm_rev_b.py

Lines changed: 4 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,10 @@
1717
# You should have received a copy of the GNU General Public License
1818
# along with this program. If not, see <https://www.gnu.org/licenses/>.
1919

20-
import struct
21-
2220
from serial.tools.list_ports import comports
23-
import numpy as np
2421

2522
from library.lcd.lcd_comm import *
23+
from library.lcd.serialize import image_to_RGB565, chunked
2624
from library.log import logger
2725

2826

@@ -195,38 +193,12 @@ def SetOrientation(self, orientation: Orientation = Orientation.PORTRAIT):
195193
else:
196194
self.SendCommand(Command.SET_ORIENTATION, payload=[OrientationValueRevB.ORIENTATION_LANDSCAPE])
197195

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-
224196
def serialize_image(self, image: Image.Image, height: int, width: int) -> bytes:
225197
if image.width != width or image.height != height:
226198
image = image.crop((0, 0, width, height))
227199
if self.orientation == Orientation.REVERSE_PORTRAIT or self.orientation == Orientation.REVERSE_LANDSCAPE:
228200
image = image.rotate(180)
229-
return self.imageToRGB565BE(image)
201+
return image_to_RGB565(image, "big")
230202

231203
def DisplayPILImage(
232204
self,
@@ -271,12 +243,5 @@ def DisplayPILImage(
271243
# Lock queue mutex then queue all the requests for the image data
272244
with self.update_queue_mutex:
273245
# 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
279-
280-
# Write last line if needed
281-
if start != len(rgb565be):
282-
self.SendLine(rgb565be[start:])
246+
for chunk in chunked(rgb565be, self.get_width() * 8):
247+
self.SendLine(chunk)

library/lcd/serialize.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
from typing import Iterator, Literal
2+
3+
import numpy as np
4+
from PIL import Image
5+
6+
7+
def chunked(data: bytes, chunk_size: int) -> Iterator[bytes]:
8+
for i in range(0, len(data), chunk_size):
9+
yield data[i : i + chunk_size]
10+
11+
12+
def image_to_RGB565(image: Image.Image, endianness: Literal["big", "little"]) -> bytes:
13+
if image.mode not in ["RGB", "RGBA"]:
14+
# we need the first 3 channels to be R, G and B
15+
image = image.convert("RGB")
16+
17+
rgb = np.asarray(image)
18+
19+
# flatten the first 2 dimensions (width and height) into a single stream
20+
# of RGB pixels
21+
rgb = rgb.reshape((image.size[1] * image.size[0], -1))
22+
23+
# extract R, G, B channels and promote them to 16 bits
24+
r = rgb[:, 0].astype(np.uint16)
25+
g = rgb[:, 1].astype(np.uint16)
26+
b = rgb[:, 2].astype(np.uint16)
27+
28+
# construct RGB565
29+
r = r >> 3
30+
g = g >> 2
31+
b = b >> 3
32+
rgb565 = (r << 11) | (g << 5) | b
33+
34+
# serialize to the correct endianness
35+
if endianness == "big":
36+
typ = ">u2"
37+
else:
38+
typ = "<u2"
39+
return rgb565.astype(typ).tobytes()

0 commit comments

Comments
 (0)