#!/usr/bin/env python3 """ Test script to render the library view and display it on hardware. Combines library rendering with hardware display testing. """ import sys import asyncio from pathlib import Path # Add parent directory to path sys.path.insert(0, str(Path(__file__).parent.parent)) from dreader.library import LibraryManager from dreader.hal_hardware import HardwareDisplayHAL async def main(args): """Test library rendering on hardware display.""" library_path = args.library_path output_path = "library_render_test.png" vcom = args.vcom print("=" * 60) print("Library Rendering on Hardware Test") print("=" * 60) print(f"Library path: {library_path}") print(f"VCOM: {vcom}V") print(f"Output file: {output_path}") print() # Step 1: Create library manager and scan print("Step 1: Creating library manager...") library = LibraryManager( library_path=library_path, page_size=(1872, 1404) ) print("Scanning library...") library.scan_library() print() print(f"Found {len(library.books)} books:") for i, book in enumerate(library.books[:10], 1): # Show first 10 print(f" {i}. {book['title']} by {book['author']}") if len(library.books) > 10: print(f" ... and {len(library.books) - 10} more") print() # Step 2: Create and render library table print("Step 2: Creating library table (page 1)...") table = library.create_library_table(page=0) print(f"✓ Library table created: {table is not None}") if table: print(f" Table has {len(table.rows)} rows") print() print("Rendering library view...") image = library.render_library() if not image: print("ERROR: No image rendered!") print(f" library.library_table = {library.library_table}") print(f" library.rendered_page = {library.rendered_page}") return 1 print(f"✓ Library rendered: {image.size} {image.mode}") # Check if image is not blank import numpy as np img_array = np.array(image) unique_colors = len(np.unique(img_array.reshape(-1, img_array.shape[-1]), axis=0)) print(f" Image has {unique_colors} unique colors (blank would be ~1)") # Sample some pixels to see what we have print(f" Sample pixels:") print(f" Top-left corner: {image.getpixel((10, 10))}") print(f" Center: {image.getpixel((936, 702))}") print(f" Bottom-right: {image.getpixel((1860, 1390))}") print() # Save for reference print(f"Saving to {output_path}...") image.save(output_path) print(f"✓ Saved to {output_path}") print() # Step 3: Initialize hardware HAL print("Step 3: Initializing hardware HAL...") hal = HardwareDisplayHAL( width=1872, height=1404, vcom=vcom, config_file="hardware_config.json" ) print("Initializing hardware components...") await hal.initialize() print("✓ Hardware initialized") print() # Step 4: Display on e-ink screen print("Step 4: Displaying library on e-ink screen...") print("(This may take a few seconds for the full refresh)") print(f"Converting image from {image.mode} to grayscale for e-ink...") # Convert to grayscale (L mode) for e-ink display if image.mode == 'RGBA': # Convert RGBA to RGB first (flatten alpha) rgb_image = Image.new('RGB', image.size, (255, 255, 255)) rgb_image.paste(image, mask=image.split()[3]) # Use alpha as mask image_gray = rgb_image.convert('L') else: image_gray = image.convert('L') print(f"Image converted to {image_gray.mode} mode") await hal.show_image(image_gray) print("✓ Image displayed!") print() print("=" * 60) print("SUCCESS!") print("=" * 60) print() print("The library view should now be visible on your e-ink screen.") print() print(f"You can also view the saved PNG: {output_path}") print() print("Press Ctrl+C to exit") print() # Keep running so user can see the image try: while True: await asyncio.sleep(1) except KeyboardInterrupt: print("\nCleaning up...") await hal.cleanup() print("Done!") return 0 if __name__ == "__main__": import argparse parser = argparse.ArgumentParser( description='Test library rendering on hardware display' ) parser.add_argument( 'library_path', nargs='?', default='tests/data/library-epub', help='Path to library directory (default: tests/data/library-epub)' ) parser.add_argument( '--vcom', type=float, default=-1.65, help='VCOM voltage (check your display label, default: -1.65)' ) args = parser.parse_args() try: exit_code = asyncio.run(main(args)) sys.exit(exit_code or 0) except KeyboardInterrupt: print("\nTest interrupted") sys.exit(0) except Exception as e: print(f"\nERROR: {e}") import traceback traceback.print_exc() sys.exit(1)