49 lines
1.6 KiB
Python
49 lines
1.6 KiB
Python
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}[/]"
|