from textual.widgets import Static from PIL import Image, ImageFilter from rich_pixels import Pixels from rich_pixels._renderer import HalfcellRenderer from pathlib import Path class GameImagePreview(Static): def __init__( self, image_path: str, *, scale_factor: float = 0.098, fallback_text: str = "[red]Failed to load image[/red]", **kwargs ): self.image_path = image_path self.scale_factor = scale_factor self.fallback_text = fallback_text renderable = self.load_and_process_image() # THIS is the key line that makes the image render: super().__init__(renderable, **kwargs) def load_and_process_image(self): path = Path(self.image_path) if not path.exists() or not path.is_file(): return f"{self.fallback_text}\n[dim]Not found: {self.image_path}[/]" try: with Image.open(path) as img: if img.mode != "RGBA": img = img.convert("RGBA") resized = img.resize( ( int(img.width * self.scale_factor), int(img.height * self.scale_factor), ), resample=Image.Resampling.LANCZOS, ) resized = resized.filter(ImageFilter.UnsharpMask(radius=1, percent=150, threshold=3)) return Pixels.from_image( resized, renderer=HalfcellRenderer(default_color="black"), ) except Exception as e: return f"{self.fallback_text}\n[dim]{e}[/]"