rich-pixels

repository·master·Indexed 19 days ago

https://github.com/darrenburns/rich-pixels

A Rich-compatible library for rendering pixel images, colorful grids, and ASCII art in the terminal. It supports loading images from file paths or Pillow objects and provides multiple rendering modes via HalfcellRenderer and FullcellRenderer. The library integrates with the Rich framework and Textual applications, allowing developers to create custom pixel grids using character-to-segment mappings.

Tokens
2.7K
Snippets
14
Records
15
Agent score
68%

What's inside rich-pixels

  1. Load a PIL Image object

    master

    Use the Pixels.from_image method to create a Pixels object from an existing Pillow (PIL) Image object. This is useful if you need to perform image processing or modifications using Pillow before rendering to the terminal.

    from rich_pixels import Pixels
    from rich.console import Console
    from PIL import Image
    
    console = Console()
    
    with Image.open("path/to/image.png") as image:
        pixels = Pixels.from_image(image)
    
    console.print(pixels)
  2. Load an image from a file path

    master

    Use the Pixels.from_image_path method to load an image file directly from a filesystem path. The resulting Pixels object is a Rich-compatible renderable that can be printed using a rich.console.Console instance.

    from rich_pixels import Pixels
    from rich.console import Console
    
    console = Console()
    pixels = Pixels.from_image_path("pokemon/bulbasaur.png")
    console.print(pixels)
  3. Create pixel grids from ASCII art with custom mappings

    master

    You can create colorful grids by providing an ASCII string and a mapping dictionary to Pixels.from_ascii.

    • The grid is a multi-line string representing the shape.
    • The mapping dictionary maps specific characters in the grid to rich.segment.Segment objects.
    • This allows you to use characters as 'placeholders' for specific colors or styles (e.g., mapping 'x' to a yellow block).
    from rich_pixels import Pixels
    from rich.console import Console
    from rich.segment import Segment
    from rich.style import Style
    
    console = Console()
    
    # Draw your shapes using any character you want
    grid = """\
         xx   xx
         ox   ox
         Ox   Ox
    xx             xx
    xxxxxxxxxxxxxxxxx
    """
    
    # Map characters to different characters/styles
    mapping = {
        "x": Segment(" ", Style.parse("yellow on yellow")),
        "o": Segment(" ", Style.parse("on white")),
        "O": Segment(" ", Style.parse("on blue")),
    }
    
    pixels = Pixels.from_ascii(grid, mapping)
    console.print(pixels)
  4. Create a Pixels object from an image path

    master

    Use Pixels.from_image_path() to create a Pixels object directly from a file path (string or PurePath). This method handles opening the image file using PIL. You can provide a resize tuple (width, height) and a renderer instance.

    Note: This method requires the image extra dependencies to be installed.

    from pathlib import Path
    from rich_pixels import Pixels, HalfcellRenderer
    
    pixels = Pixels.from_image_path("path/to/image.png", resize=(80, 40), renderer=HalfcellRenderer())
  5. Render Pixels in a Rich Console

    master

    The Pixels class implements the __rich_console__ protocol, meaning you can pass a Pixels object directly to console.print() to render the pixel grid in your terminal.

    from rich.console import Console
    from rich_pixels import Pixels
    
    console = Console()
    pixels = Pixels.from_ascii("X")
    
    console.print(pixels)
  6. Create a Pixels object from a PIL Image

    master

    Use Pixels.from_image() to create a Pixels object from an existing PIL Image instance. You can optionally resize the image to a specific (width, height) tuple and specify a custom Renderer (e.g., FullcellRenderer or HalfcellRenderer). If no renderer is provided, it defaults to HalfcellRenderer.

    Note: This method requires the image extra dependencies to be installed.

    from PIL import Image
    from rich_pixels import Pixels, FullcellRenderer
    
    image = Image.open("path/to/image.png")
    pixels = Pixels.from_image(image, resize=(40, 20), renderer=FullcellRenderer())
  7. Use the Renderer base class

    master

    The Renderer class is the base class for all image-to-terminal rendering logic in rich-pixels. It provides the core render method which converts a PIL Image into a list of rich.segment.Segment objects.

    When initializing a renderer, you can provide an optional default_color (as a string, e.g., 'black'). This color is used when a pixel is transparent or has an alpha value of 0. If default_color is provided, the renderer automatically configures a null_style using the on {default_color} pattern to ensure background consistency.

    from PIL import Image
    from rich_pixels import Renderer
    
    # Note: Renderer is an abstract base class; use HalfcellRenderer or FullcellRenderer instead.
    image = Image.open("example.png")
    renderer = Renderer(default_color="black")
    segments = renderer.render(image, resize=(80, 40))
  8. Render images using FullcellRenderer

    master

    The FullcellRenderer renders an image using full-height cells. Each pixel in the source image is represented by a two-space character ( ) in the terminal, where the background color of the space is set to the pixel's color.

    This is a simpler rendering mode compared to HalfcellRenderer and maps one source pixel to one terminal character cell.

    from PIL import Image
    from rich_pixels import FullcellRenderer
    
    image = Image.open("example.png")
    renderer = FullcellRenderer()
    segments = renderer.render(image, resize=(80, 40))
  9. Render images using HalfcellRenderer

    master

    The HalfcellRenderer renders an image using half-height Unicode blocks (). This technique allows for higher vertical resolution in the terminal by using two vertical pixels to compose a single character row.

    Each rendered row in the terminal actually represents two vertical pixels from the source image:

    1. The lower pixel determines the foreground color and whether the character is used.
    2. The upper pixel determines the background color.

    If the target height is not even, HalfcellRenderer will automatically increment the height to ensure the pixel pairs are complete. The render method accepts an optional resize tuple (width, height).

    from PIL import Image
    from rich_pixels import HalfcellRenderer
    
    image = Image.open("example.png")
    renderer = HalfcellRenderer(default_color="black")
    # Resize to specific dimensions; height will be adjusted to be even if necessary
    segments = renderer.render(image, resize=(100, 50))
  10. Create a Pixels object from Segments

    master

    Use Pixels.from_segments() to create a Pixels object from an iterable of rich.segment.Segment objects. This is the lowest-level way to construct a Pixels object manually.

    from rich.segment import Segment
    from rich_pixels import Pixels
    
    segments = [Segment("X", style="red"), Segment("O", style="blue")]
    pixels = Pixels.from_segments(segments)