Source code for draugr.drawers.terminal.terminal_image_renderer

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

__author__ = "heider"
__doc__ = r"""

           Created on 7/5/22
           """


import argparse
from pathlib import Path
from typing import Any, List, Tuple

import numpy
from PIL import Image

from warg import color, Number

__all__ = ["render_file", "terminalise_image", "terminal_render_image"]


def get_pixel(col: Tuple) -> Any:
    """description"""
    if isinstance(col, (float, int)) or len(col) == 1:
        col = (col, col, col)
    return color("  ", bg=f"rgb({int(col[0])}, {int(col[1])}, {int(col[2])})")


[docs]def terminal_render_image( pixels: numpy.ndarray, scale: Tuple, max_val: Number = None ) -> List[List]: """description""" # first of all scale the image to the scale 'tuple' if len(pixels.shape) < 3: pixels = numpy.array([[pixel] for pixel in pixels]) num_channels = 1 else: num_channels = pixels.shape[2] if max_val is None: max_val = numpy.max(pixels) if max_val <= 1: pixels = pixels * 255 else: pixels = pixels * (255 / max_val) else: pixels = pixels * (255 / max_val) image_size = pixels.shape[:2] block_size = (image_size[0] / scale[0], image_size[1] / scale[1]) blocks = [] y = 0 while y < image_size[0]: x = 0 block_col = [] while x < image_size[1]: # get a block, reshape in into an Nx3 matrix and then get average of each column block_col.append( pixels[int(y) : int(y + block_size[0]), int(x) : int(x + block_size[1])] .reshape(-1, num_channels) .mean(axis=0) ) x += block_size[1] blocks.append(block_col) y += block_size[0] output = [[get_pixel(block) for block in row] for row in blocks] return output
[docs]def terminalise_image(output): """ joins nested str lists with newlines :return:""" return "\n".join(["".join(row) for row in output])
def get_image(path: Path): """description""" img = numpy.asarray(Image.open(path)) if img.shape[2] > 3: return numpy.array([[pixel[:3] for pixel in row] for row in img]) return img
[docs]def render_file(path: Path, scale=(60, 60)): """description""" image = get_image(path) output = terminal_render_image(image, scale) print(terminalise_image(output))
def entry_point() -> None: """ :rtype: None """ parser = argparse.ArgumentParser(description="Render images on the command line") parser.add_argument("path", metavar="path", type=str, help="the image path") parser.add_argument( "--width", dest="width", default=60, type=int, help="width of the rendered image (default 60 pixels)", ) parser.add_argument( "--height", dest="height", default=60, type=int, help="height of the rendered image (default 60 pixels)", ) args = parser.parse_args() render_file(args.path, (args.height, args.width)) if __name__ == "__main__": output = terminal_render_image(numpy.random.random((60, 60, 3)) * 5, (60, 60)) print(terminalise_image(output)) # render_file(Path.home() / "OneDrive" / "Billeder" / "pompey.jpg", scale=(20, 20))