Feature/static image manager (#95)

* feat(static-image): Add static image manager with web interface

- Create StaticImageManager class with image scaling and transparency support
- Add configuration options for display duration, zoom scale, and background color
- Integrate with display controller and web interface
- Add image upload functionality to web interface
- Support for various image formats with proper scaling
- Efficient image processing with aspect ratio preservation
- Ready for future scrolling feature implementation

* fix(static-image): Move display duration to main display_durations block

- Remove display_duration from static_image config section
- Update StaticImageManager to read duration from display.display_durations.static_image
- Remove display duration field from web interface form
- Update web interface JavaScript to not include display_duration in payload
- Follows same pattern as all other managers in the project

* feat(static-image): Add fit to display option

- Add fit_to_display checkbox to automatically scale images to fit display
- When enabled, images are scaled to fit display dimensions while preserving aspect ratio
- When disabled, manual zoom_scale control is available
- Update web interface with smart form controls (zoom scale disabled when fit to display is on)
- Prevents stretching or cropping - images are always properly fitted
- Default to fit_to_display=true for better user experience

* refactor(static-image): Remove zoom_scale and simplify to fit_to_display only

- Remove zoom_scale option entirely as it was confusing and redundant
- Simplify image processing to always fit to display dimensions
- Remove zoom_scale field from web interface
- Clean up JavaScript to remove zoom scale logic
- Images are now always properly fitted without stretching or cropping
- Much simpler and more intuitive user experience
This commit is contained in:
Chuck
2025-10-05 10:46:36 -04:00
committed by GitHub
parent a115a1ed6b
commit f3d02e07ea
11 changed files with 600 additions and 15 deletions

100
test_static_image.py Normal file
View File

@@ -0,0 +1,100 @@
#!/usr/bin/env python3
"""
Test script for the static image manager.
This script tests the static image manager functionality without requiring the full LED matrix hardware.
"""
import sys
import os
import logging
from PIL import Image
# Add the src directory to the path
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'src'))
from src.static_image_manager import StaticImageManager
from src.display_manager import DisplayManager
# Configure logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
class MockDisplayManager:
"""Mock display manager for testing without hardware."""
def __init__(self):
self.matrix = type('Matrix', (), {'width': 64, 'height': 32})()
self.image = Image.new("RGB", (self.matrix.width, self.matrix.height))
self.draw = None
def clear(self):
"""Clear the display."""
self.image = Image.new("RGB", (self.matrix.width, self.matrix.height))
logger.info("Display cleared")
def update_display(self):
"""Update the display (mock)."""
logger.info("Display updated")
def test_static_image_manager():
"""Test the static image manager functionality."""
logger.info("Starting static image manager test...")
# Create mock display manager
display_manager = MockDisplayManager()
# Test configuration
config = {
'static_image': {
'enabled': True,
'image_path': 'assets/static_images/default.png',
'display_duration': 10,
'zoom_scale': 1.0,
'preserve_aspect_ratio': True,
'background_color': [0, 0, 0]
}
}
try:
# Initialize the static image manager
logger.info("Initializing static image manager...")
manager = StaticImageManager(display_manager, config)
# Test basic functionality
logger.info(f"Manager enabled: {manager.is_enabled()}")
logger.info(f"Display duration: {manager.get_display_duration()}")
# Test image loading
if manager.image_loaded:
logger.info("Image loaded successfully")
image_info = manager.get_image_info()
logger.info(f"Image info: {image_info}")
else:
logger.warning("Image not loaded")
# Test display
logger.info("Testing display...")
manager.display()
# Test configuration changes
logger.info("Testing configuration changes...")
manager.set_zoom_scale(1.5)
manager.set_display_duration(15)
manager.set_background_color((255, 0, 0))
# Test with a different image path (if it exists)
test_image_path = 'assets/static_images/test.png'
if os.path.exists(test_image_path):
logger.info(f"Testing with image: {test_image_path}")
manager.set_image_path(test_image_path)
logger.info("Static image manager test completed successfully!")
return True
except Exception as e:
logger.error(f"Test failed with error: {e}")
return False
if __name__ == '__main__':
success = test_static_image_manager()
sys.exit(0 if success else 1)