From edf03d8c3942fb35efacf4012f6dd3f69651b1b0 Mon Sep 17 00:00:00 2001 From: Matthieu Houdebine Date: Thu, 16 Sep 2021 15:18:19 +0200 Subject: [PATCH 1/5] First implementation of progress bar support --- main.py | 45 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/main.py b/main.py index a6418a88..b6a433ee 100644 --- a/main.py +++ b/main.py @@ -122,6 +122,40 @@ def DisplayText(ser, text, x=0, y=0, DisplayPILImage(ser, text_image, x, y) +def DisplayProgressBar(ser, x, y, width, height, min_value=0, max_value=100, value=50, + bar_color=(0, 0, 0), + bar_outline=True, + background_color=(255, 255, 255), + background_image=None): + # Generate a progress bar and display it + # Provide the background image path to display progress bar with transparent background + + assert x + width <= DISPLAY_WIDTH, 'Progress bar width exceeds display width' + assert y + height <= DISPLAY_HEIGHT, 'Progress bar height exceeds display height' + assert min_value <= value <= max_value, 'Progress bar value shall be between min and max' + + if background_image is None: + # A bitmap is created with solid background + bar_image = Image.new('RGB', (width, height), background_color) + else: + # A bitmap is created from provided background image + bar_image = Image.open(background_image) + + # Crop bitmap to keep only the progress bar background + bar_image = bar_image.crop(box=(x, y, x + width, y + height)) + + # Draw progress bar + bar_filled_width = value / (max_value - min_value) * width + draw = ImageDraw.Draw(bar_image) + draw.rectangle([0, 0, bar_filled_width, height], fill=bar_color, outline=bar_color) + + # Draw outline + if bar_outline: + draw.rectangle([0, 0, width, height], fill=None, outline=bar_color) + + DisplayPILImage(ser, bar_image, x, y) + + stop = False if __name__ == "__main__": @@ -173,7 +207,8 @@ def sighandler(signum, frame): font_color=(255, 255, 255), background_image="res/example.png") - # Display the current time as fast as possible + # Display the current time and a progress bar as fast as possible + bar_value = 0 while not stop: DisplayText(lcd_comm, str(datetime.now().time()), 160, 2, font="roboto/Roboto-Bold.ttf", @@ -181,4 +216,12 @@ def sighandler(signum, frame): font_color=(255, 0, 0), background_image="res/example.png") + DisplayProgressBar(lcd_comm, 0, 100, + width=DISPLAY_WIDTH, height=50, + min_value=0, max_value=100, value=bar_value, + bar_color=(255, 255, 0), bar_outline=True, + background_image="res/example.png") + + bar_value = (bar_value + 1) % 100 + lcd_comm.close() From b16f0630552bf74fc0ff2d780ac4768fcb15d192 Mon Sep 17 00:00:00 2001 From: Matthieu Houdebine Date: Thu, 16 Sep 2021 15:20:36 +0200 Subject: [PATCH 2/5] Code format --- main.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/main.py b/main.py index b6a433ee..21e1e154 100644 --- a/main.py +++ b/main.py @@ -78,7 +78,7 @@ def DisplayPILImage(ser, image, x, y): line += struct.pack('H', rgb) # Send image data by multiple of DISPLAY_WIDTH bytes - if len(line) >= DISPLAY_WIDTH*4: + if len(line) >= DISPLAY_WIDTH * 4: ser.write(line) line = bytes() @@ -164,6 +164,7 @@ def sighandler(signum, frame): global stop stop = True + # Set the signal handlers, to send a complete frame to the LCD before exit signal.signal(signal.SIGINT, sighandler) signal.signal(signal.SIGTERM, sighandler) From 055268db436544b2b05341d9e50010ed8034ecab Mon Sep 17 00:00:00 2001 From: Matthieu Houdebine Date: Thu, 16 Sep 2021 15:33:58 +0200 Subject: [PATCH 3/5] Add typing to functions --- main.py | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/main.py b/main.py index 21e1e154..17b748e4 100644 --- a/main.py +++ b/main.py @@ -28,7 +28,7 @@ class Command: DISPLAY_BITMAP = 197 -def SendReg(ser, cmd, x, y, ex, ey): +def SendReg(ser: serial.Serial, cmd: int, x: int, y: int, ex: int, ey: int): byteBuffer = bytearray(6) byteBuffer[0] = (x >> 2) byteBuffer[1] = (((x & 3) << 6) + (y >> 4)) @@ -39,28 +39,28 @@ def SendReg(ser, cmd, x, y, ex, ey): ser.write(bytes(byteBuffer)) -def Reset(ser): +def Reset(ser: serial.Serial): SendReg(ser, Command.RESET, 0, 0, 0, 0) -def Clear(ser): +def Clear(ser: serial.Serial): SendReg(ser, Command.CLEAR, 0, 0, 0, 0) -def ScreenOff(ser): +def ScreenOff(ser: serial.Serial): SendReg(ser, Command.SCREEN_OFF, 0, 0, 0, 0) -def ScreenOn(ser): +def ScreenOn(ser: serial.Serial): SendReg(ser, Command.SCREEN_ON, 0, 0, 0, 0) -def SetBrightness(ser, level): +def SetBrightness(ser: serial.Serial, level: int): # Level : 0 (brightest) - 255 (darkest) SendReg(ser, Command.SET_BRIGHTNESS, level, 0, 0, 0) -def DisplayPILImage(ser, image, x, y): +def DisplayPILImage(ser: serial.Serial, image: Image, x: int, y: int): image_height = image.size[1] image_width = image.size[0] @@ -89,17 +89,17 @@ def DisplayPILImage(ser, image, x, y): sleep(0.01) # Wait 10 ms after picture display -def DisplayBitmap(ser, bitmap_path, x=0, y=0): +def DisplayBitmap(ser: serial.Serial, bitmap_path: str, x=0, y=0): image = Image.open(bitmap_path) DisplayPILImage(ser, image, x, y) -def DisplayText(ser, text, x=0, y=0, +def DisplayText(ser: serial.Serial, text: str, x=0, y=0, font="roboto/Roboto-Regular.ttf", font_size=20, font_color=(0, 0, 0), background_color=(255, 255, 255), - background_image=None): + background_image: str = None): # Convert text to bitmap using PIL and display it # Provide the background image path to display text with transparent background @@ -122,11 +122,12 @@ def DisplayText(ser, text, x=0, y=0, DisplayPILImage(ser, text_image, x, y) -def DisplayProgressBar(ser, x, y, width, height, min_value=0, max_value=100, value=50, +def DisplayProgressBar(ser: serial.Serial, x: int, y: int, width: int, height: int, min_value=0, max_value=100, + value=50, bar_color=(0, 0, 0), bar_outline=True, background_color=(255, 255, 255), - background_image=None): + background_image: str = None): # Generate a progress bar and display it # Provide the background image path to display progress bar with transparent background From 74fde484b6eb417ced7098af4f08bc9e3cbc2bb0 Mon Sep 17 00:00:00 2001 From: Matthieu Houdebine Date: Thu, 16 Sep 2021 23:20:21 +0200 Subject: [PATCH 4/5] Fix progress bar outline, add some assert --- main.py | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/main.py b/main.py index 17b748e4..af05714c 100644 --- a/main.py +++ b/main.py @@ -57,6 +57,7 @@ def ScreenOn(ser: serial.Serial): def SetBrightness(ser: serial.Serial, level: int): # Level : 0 (brightest) - 255 (darkest) + assert 255 >= level >= 0, 'Brightness level must be [0-255]' SendReg(ser, Command.SET_BRIGHTNESS, level, 0, 0, 0) @@ -64,6 +65,9 @@ def DisplayPILImage(ser: serial.Serial, image: Image, x: int, y: int): image_height = image.size[1] image_width = image.size[0] + assert image_height > 0, 'Image width must be > 0' + assert image_width > 0, 'Image height must be > 0' + SendReg(ser, Command.DISPLAY_BITMAP, x, y, x + image_width - 1, y + image_height - 1) pix = image.load() @@ -78,7 +82,7 @@ def DisplayPILImage(ser: serial.Serial, image: Image, x: int, y: int): line += struct.pack('H', rgb) # Send image data by multiple of DISPLAY_WIDTH bytes - if len(line) >= DISPLAY_WIDTH * 4: + if len(line) >= DISPLAY_WIDTH * 8: ser.write(line) line = bytes() @@ -103,6 +107,9 @@ def DisplayText(ser: serial.Serial, text: str, x=0, y=0, # Convert text to bitmap using PIL and display it # Provide the background image path to display text with transparent background + assert len(text) > 0, 'Text must not be empty' + assert font_size > 0, "Font size must be > 0" + if background_image is None: # A text bitmap is created with max width/height by default : text with solid background text_image = Image.new('RGB', (DISPLAY_WIDTH, DISPLAY_HEIGHT), background_color) @@ -148,11 +155,11 @@ def DisplayProgressBar(ser: serial.Serial, x: int, y: int, width: int, height: i # Draw progress bar bar_filled_width = value / (max_value - min_value) * width draw = ImageDraw.Draw(bar_image) - draw.rectangle([0, 0, bar_filled_width, height], fill=bar_color, outline=bar_color) + draw.rectangle([0, 0, bar_filled_width-1, height-1], fill=bar_color, outline=bar_color) - # Draw outline if bar_outline: - draw.rectangle([0, 0, width, height], fill=None, outline=bar_color) + # Draw outline + draw.rectangle([0, 0, width-1, height-1], fill=None, outline=bar_color) DisplayPILImage(ser, bar_image, x, y) @@ -209,7 +216,7 @@ def sighandler(signum, frame): font_color=(255, 255, 255), background_image="res/example.png") - # Display the current time and a progress bar as fast as possible + # Display the current time and some progress bars as fast as possible bar_value = 0 while not stop: DisplayText(lcd_comm, str(datetime.now().time()), 160, 2, @@ -218,12 +225,18 @@ def sighandler(signum, frame): font_color=(255, 0, 0), background_image="res/example.png") - DisplayProgressBar(lcd_comm, 0, 100, - width=DISPLAY_WIDTH, height=50, + DisplayProgressBar(lcd_comm, 10, 40, + width=140, height=30, min_value=0, max_value=100, value=bar_value, bar_color=(255, 255, 0), bar_outline=True, background_image="res/example.png") - bar_value = (bar_value + 1) % 100 + DisplayProgressBar(lcd_comm, 160, 40, + width=140, height=30, + min_value=0, max_value=19, value=bar_value % 20, + bar_color=(0, 255, 0), bar_outline=False, + background_image="res/example.png") + + bar_value = (bar_value + 2) % 101 lcd_comm.close() From 2377d2c6276bb10354ff3bfe136e088cc0c7ef2b Mon Sep 17 00:00:00 2001 From: Matthieu Houdebine Date: Fri, 17 Sep 2021 00:43:28 +0200 Subject: [PATCH 5/5] Update README.md --- README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index a730a94b..789d2629 100644 --- a/README.md +++ b/README.md @@ -11,15 +11,14 @@ Operating systems supported : macOS, Windows, Linux (incl. Raspberry Pi) and all This is a 3.5" USB-C display that shows as a serial port once connected. It cannot be seen by the operating system as a monitor but picture can be displayed on it. -A Windows-only software is [available here](https://translate.google.com/translate?sl=auto&u=https://gitee.com/emperg/usblcd/raw/master/dev0/realse.ini) to manage this display. +A Windows-only software is [available in Chinese](https://lgb123-1253504678.cos.ap-beijing.myqcloud.com/35inch.rar) or [in English](https://lgb123-1253504678.cos.ap-beijing.myqcloud.com/35inchENG.rar) to manage this display. This software allows creating themes to display your computer sensors on the screen, but does not offer a simple way to display custom pictures or text. This Python script has been created to do some simple operations on this display like : - **Display custom picture** - **Display text** +- **Display progress bar** - Clear the screen (blank) - Turn the screen on/off - Display soft reset - Set brightness - -