From f3975e1ac0272666a3a00be7f00dad81afe740a3 Mon Sep 17 00:00:00 2001 From: ChuckBuilds <33324927+ChuckBuilds@users.noreply.github.com> Date: Fri, 11 Apr 2025 10:40:02 -0500 Subject: [PATCH] Optimize stock news display performance: - Cache text image to reduce rendering overhead - Improve frame creation and update logic - Optimize text wrapping for smoother scrolling - Remove unnecessary display clears --- src/stock_news_manager.py | 55 +++++++++++++++++++++++++++----------- test_stock_news_manager.py | 9 ++----- 2 files changed, 41 insertions(+), 23 deletions(-) diff --git a/src/stock_news_manager.py b/src/stock_news_manager.py index 38f97eff..61effd8d 100644 --- a/src/stock_news_manager.py +++ b/src/stock_news_manager.py @@ -26,6 +26,8 @@ class StockNewsManager: self.news_data = {} self.current_news_group = 0 # Track which group of headlines we're showing self.scroll_position = 0 + self.cached_text_image = None # Cache for the text image + self.cached_text = None # Cache for the text string # Get scroll settings from config with faster defaults self.scroll_speed = self.stock_news_config.get('scroll_speed', 1) @@ -205,33 +207,54 @@ class StockNewsManager: separator = " - " # Visual separator between news items news_text = separator.join(news_texts) - # Create a text image for efficient scrolling - text_image = self._create_text_image(news_text) - text_width = text_image.width - text_height = text_image.height + # Only create new text image if the text has changed + if news_text != self.cached_text: + self.cached_text = news_text + self.cached_text_image = self._create_text_image(news_text) + self.scroll_position = 0 # Reset scroll position for new text - # Calculate display position + if not self.cached_text_image: + return + + text_width = self.cached_text_image.width + text_height = self.cached_text_image.height display_width = self.display_manager.matrix.width total_width = text_width + display_width # Update scroll position self.scroll_position = (self.scroll_position + self.scroll_speed) % total_width - # Clear the display - self.display_manager.clear() - # Calculate the visible portion of the text visible_width = min(display_width, text_width - self.scroll_position) if visible_width > 0: - # Crop the text image to show only the visible portion - visible_portion = text_image.crop((self.scroll_position, 0, - self.scroll_position + visible_width, text_height)) + # Create a new blank image for this frame + frame_image = Image.new('RGB', (display_width, text_height), (0, 0, 0)) - # Paste the visible portion onto the display - self.display_manager.image.paste(visible_portion, (0, 0)) - - # Update the display - self.display_manager.update_display() + # Crop and paste in one operation + if self.scroll_position + visible_width <= text_width: + # Normal case - text is still scrolling in + visible_portion = self.cached_text_image.crop(( + self.scroll_position, 0, + self.scroll_position + visible_width, text_height + )) + frame_image.paste(visible_portion, (0, 0)) + else: + # Wrapping case - text is wrapping around + first_part_width = text_width - self.scroll_position + first_part = self.cached_text_image.crop(( + self.scroll_position, 0, + text_width, text_height + )) + second_part = self.cached_text_image.crop(( + 0, 0, + visible_width - first_part_width, text_height + )) + frame_image.paste(first_part, (0, 0)) + frame_image.paste(second_part, (first_part_width, 0)) + + # Update the display with the new frame + self.display_manager.image = frame_image + self.display_manager.update_display() # If we've completed a full scroll, move to the next group if self.scroll_position == 0: diff --git a/test_stock_news_manager.py b/test_stock_news_manager.py index e7928b1e..bd98f8e6 100644 --- a/test_stock_news_manager.py +++ b/test_stock_news_manager.py @@ -38,14 +38,9 @@ def main(): print("Testing news display. Press Ctrl+C to exit.") - # Run the news display in a loop with proper timing - last_update = time.time() + # Run the news display in a loop while True: - current_time = time.time() - # Ensure we're not updating too frequently - if current_time - last_update >= 0.001: # 1ms minimum between updates - news_manager.display_news() - last_update = current_time + news_manager.display_news() except KeyboardInterrupt: print("\nTest interrupted by user")