mirror of
https://github.com/ChuckBuilds/LEDMatrix.git
synced 2026-04-10 13:02:59 +00:00
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:
136
test_static_image_simple.py
Normal file
136
test_static_image_simple.py
Normal file
@@ -0,0 +1,136 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Simple test script for the static image manager.
|
||||
This script tests the image processing functionality without requiring the full LED matrix hardware.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
import logging
|
||||
from PIL import Image
|
||||
|
||||
# Configure logging
|
||||
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
def test_image_processing():
|
||||
"""Test image processing functionality."""
|
||||
logger.info("Testing image processing...")
|
||||
|
||||
# Test image path
|
||||
image_path = 'assets/static_images/default.png'
|
||||
|
||||
if not os.path.exists(image_path):
|
||||
logger.error(f"Test image not found: {image_path}")
|
||||
return False
|
||||
|
||||
try:
|
||||
# Load the image
|
||||
img = Image.open(image_path)
|
||||
logger.info(f"Original image size: {img.size}")
|
||||
|
||||
# Test different zoom scales
|
||||
display_size = (64, 32)
|
||||
|
||||
for zoom_scale in [0.5, 1.0, 1.5, 2.0]:
|
||||
logger.info(f"Testing zoom scale: {zoom_scale}")
|
||||
|
||||
# Calculate target size
|
||||
if zoom_scale == 1.0:
|
||||
# Fit to display while preserving aspect ratio
|
||||
scale_x = display_size[0] / img.size[0]
|
||||
scale_y = display_size[1] / img.size[1]
|
||||
scale = min(scale_x, scale_y)
|
||||
target_size = (int(img.size[0] * scale), int(img.size[1] * scale))
|
||||
else:
|
||||
# Apply zoom scale
|
||||
target_size = (int(img.size[0] * zoom_scale), int(img.size[1] * zoom_scale))
|
||||
|
||||
logger.info(f"Target size: {target_size}")
|
||||
|
||||
# Resize image
|
||||
resized_img = img.resize(target_size, Image.Resampling.LANCZOS)
|
||||
|
||||
# Create display canvas
|
||||
canvas = Image.new('RGB', display_size, (0, 0, 0))
|
||||
|
||||
# Center the image
|
||||
paste_x = max(0, (display_size[0] - resized_img.width) // 2)
|
||||
paste_y = max(0, (display_size[1] - resized_img.height) // 2)
|
||||
|
||||
# Handle transparency
|
||||
if resized_img.mode == 'RGBA':
|
||||
temp_canvas = Image.new('RGB', display_size, (0, 0, 0))
|
||||
temp_canvas.paste(resized_img, (paste_x, paste_y), resized_img)
|
||||
canvas = temp_canvas
|
||||
else:
|
||||
canvas.paste(resized_img, (paste_x, paste_y))
|
||||
|
||||
logger.info(f"Final canvas size: {canvas.size}")
|
||||
logger.info(f"Image position: ({paste_x}, {paste_y})")
|
||||
|
||||
# Save test output
|
||||
output_path = f'test_output_zoom_{zoom_scale}.png'
|
||||
canvas.save(output_path)
|
||||
logger.info(f"Test output saved: {output_path}")
|
||||
|
||||
logger.info("Image processing test completed successfully!")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Test failed with error: {e}")
|
||||
return False
|
||||
|
||||
def test_config_loading():
|
||||
"""Test configuration loading."""
|
||||
logger.info("Testing configuration loading...")
|
||||
|
||||
# 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:
|
||||
# Test configuration parsing
|
||||
static_config = config.get('static_image', {})
|
||||
enabled = static_config.get('enabled', False)
|
||||
image_path = static_config.get('image_path', '')
|
||||
display_duration = static_config.get('display_duration', 10)
|
||||
zoom_scale = static_config.get('zoom_scale', 1.0)
|
||||
preserve_aspect_ratio = static_config.get('preserve_aspect_ratio', True)
|
||||
background_color = tuple(static_config.get('background_color', [0, 0, 0]))
|
||||
|
||||
logger.info(f"Configuration loaded:")
|
||||
logger.info(f" Enabled: {enabled}")
|
||||
logger.info(f" Image path: {image_path}")
|
||||
logger.info(f" Display duration: {display_duration}")
|
||||
logger.info(f" Zoom scale: {zoom_scale}")
|
||||
logger.info(f" Preserve aspect ratio: {preserve_aspect_ratio}")
|
||||
logger.info(f" Background color: {background_color}")
|
||||
|
||||
logger.info("Configuration loading test completed successfully!")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Configuration test failed with error: {e}")
|
||||
return False
|
||||
|
||||
if __name__ == '__main__':
|
||||
logger.info("Starting static image manager simple test...")
|
||||
|
||||
success1 = test_config_loading()
|
||||
success2 = test_image_processing()
|
||||
|
||||
if success1 and success2:
|
||||
logger.info("All tests completed successfully!")
|
||||
sys.exit(0)
|
||||
else:
|
||||
logger.error("Some tests failed!")
|
||||
sys.exit(1)
|
||||
Reference in New Issue
Block a user