Source code for scistag.imagestag.ascii_image

"""
Implements the AsciiImage class which converts an image to ASCII using
different methods
"""
from __future__ import annotations

from enum import IntEnum

import numpy as np

from scistag.imagestag.image import Image

CHARACTERS_GRAY_LEVELS_10 = '@%#*+=-:. '
"ASCII representation with 10 nuances"

CHARACTERS_GRAY_LEVELS_13 = "BS#&@$%*!:. "
"Alternate ASCII representation with 10 nuances"


[docs]class AsciiImageMethod(IntEnum): """ Defines the method which is used to convert an image to gray scale """ GRAY_LEVELS_13 = 0 """ Use grayscale conversions and 13 different levels of gray """ GRAY_LEVELS_10 = 1 """ Use grayscale conversion with 10 different levels of gray """
[docs]class AsciiImage: """ Helper class for converting images from RGB to ASCII, e.g. for being able to add images to text-only logs and to provide at least a coarse "preview" of the real image. """ def __init__(self, image: Image, method: AsciiImageMethod = AsciiImageMethod.GRAY_LEVELS_10, max_width=80, **params): """ :param image: The input image :param max_width: The maximum characters per row :param params: Advanced parameters """ self.image = image "The image to be converted" self.max_width = max_width "The maximum character count per row" self.ascii_image: str = "" "The ASCII representation of the image after it's conversion" self.scaled_image: Image | None = None "The scaled image" self.is_converted = False "Defines if the conversion was executed already" # self.dictionary = GRAY_LEVELS_10_2 self.dictionary = CHARACTERS_GRAY_LEVELS_10 \ if method == CHARACTERS_GRAY_LEVELS_10 \ else CHARACTERS_GRAY_LEVELS_10 "The conversion dictionary to use"
[docs] def convert(self) -> AsciiImage: """ Converts the whole image from pixles to ASCII characters :return: Self """ width_scaling = self.max_width / self.image.width height_scaling = width_scaling / 2 self.scaled_image = \ self.image.resized_ext(factor=(width_scaling, height_scaling)) pixels = self.scaled_image.get_pixels_gray() self.ascii_image = \ "\n".join([ self.convert_row(row) for row in pixels ]) self.is_converted = True return self
[docs] def convert_row(self, pixels: np.ndarray) -> str: """ Converts a single row from pixels to characters :param pixels: The pixel data :return: The characters """ # return ''.join([GRAY_LEVELS_10_2[pixel // 25] for pixel in pixels]) ascd = self.dictionary factor = (len(ascd) - 1) / 255 return ''.join([ascd[int(pixel * factor)] for pixel in pixels])
[docs] def get_ascii(self) -> str: """ Returns the converted image :return: """ if not self.is_converted: self.convert() return self.ascii_image
def __str__(self): return self.get_ascii()