diff --git a/textual_image/_pixeldata.py b/textual_image/_pixeldata.py index fa0bb97..4101c18 100644 --- a/textual_image/_pixeldata.py +++ b/textual_image/_pixeldata.py @@ -53,7 +53,9 @@ class PixelData: """Provides access to pixel data from a path or `PIL.Image.Image` instance.""" def __init__( - self, image: StrOrBytesPath | IO[bytes] | PILImage.Image, mode: Literal["grayscale", "rgb"] | None = None + self, + image: StrOrBytesPath | IO[bytes] | PILImage.Image, + mode: Literal["grayscale", "rgb", "rgba"] | None = None, ) -> None: """Initializes a PixelData. @@ -68,6 +70,8 @@ def __init__( self._image = self._image.convert("L") elif mode == "rgb": self._image = self._image.convert("RGB") + elif mode == "rgba": + self._image = self._image.convert("RGBA") @property def pil_image(self) -> PILImage.Image: diff --git a/textual_image/renderable/halfcell.py b/textual_image/renderable/halfcell.py index e60e1e5..cc4fd1d 100644 --- a/textual_image/renderable/halfcell.py +++ b/textual_image/renderable/halfcell.py @@ -16,7 +16,7 @@ from textual_image._utils import StrOrBytesPath, grouped -def _map_pixel(pixel_value: Tuple[int, int, int]) -> Color: +def _map_pixel(pixel_value: Tuple[int, int, int, int]) -> Color: """Maps a pixel value to a colored halfcells. Args: @@ -25,7 +25,7 @@ def _map_pixel(pixel_value: Tuple[int, int, int]) -> Color: Returns: Color resembling the pixel value. """ - return Color.from_triplet(ColorTriplet(*pixel_value)) + return Color.from_triplet(ColorTriplet(*(pixel_value[:3]))) class Image: @@ -47,7 +47,7 @@ def __init__( height: height specification to render the image. See `textual_image.geometry.ImageSize` for details about possible values. """ - self._image_data = PixelData(image, mode="rgb") + self._image_data = PixelData(image, mode="rgba") self._render_size = ImageSize(self._image_data.width, self._image_data.height, width, height) def cleanup(self) -> None: @@ -73,7 +73,16 @@ def __rich_console__(self, console: Console, options: ConsoleOptions) -> RenderR for upper_row, lower_row in grouped(self._image_data.scaled(width, height), 2): for upper_pixel, lower_pixel in zip(upper_row, lower_row, strict=True): - yield Segment("▀", style=Style(color=_map_pixel(upper_pixel), bgcolor=_map_pixel(lower_pixel))) # type: ignore + if upper_pixel[3] == lower_pixel[3] == 0: + yield Segment(" ") + elif upper_pixel[3] == 0: + yield Segment("▄", style=Style(color=_map_pixel(lower_pixel[:3]))) + elif lower_pixel[3] == 0: + yield Segment("▀", style=Style(color=_map_pixel(upper_pixel[:3]))) + else: + yield Segment( + "▀", style=Style(color=_map_pixel(upper_pixel[:3]), bgcolor=_map_pixel(lower_pixel[:3])) + ) yield Segment("\n") def __rich_measure__(self, console: Console, options: ConsoleOptions) -> Measurement: