From be1d21a3345657741fe2d3bf6070768032fb6490 Mon Sep 17 00:00:00 2001 From: 17ms <79069176+17ms@users.noreply.github.com> Date: Thu, 25 Jan 2024 19:10:12 +0200 Subject: [PATCH] move old scripts from dotfiles to separate repo --- ansi-codes.py | 28 ++++++ ascii-wiz.py | 259 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 287 insertions(+) create mode 100755 ansi-codes.py create mode 100755 ascii-wiz.py diff --git a/ansi-codes.py b/ansi-codes.py new file mode 100755 index 0000000..65ab2d0 --- /dev/null +++ b/ansi-codes.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python3 + +# A script to convert RGB to ansi escape codes + + +while (True): + colour = input("R G B (empty to exit): ") + + if colour == "": + print("") + break + + r, g, b = colour.split() + ansi_box = f"\u001b[48;2;{r};{g};{b}m" + ansi_letter = f"\x1b[38;2;{r};{g};{b}m" + end_c = "\u001b[0m" + bold = "\u001b[1m" + + print(f"\nColour: \\x1b[38;2;{r};{g};{b}m") + print(f"Background: \\u001b[48;2;{r};{g};{b}m\n") + + print(f''' + {bold}{ansi_letter}ABCDE {ansi_box}ABCDE{end_c} + {bold}{ansi_letter}FGHIJ {ansi_box}FGHIJ{end_c} + {bold}{ansi_letter}KLMNO {ansi_box}KLMNO{end_c} + + ''') + diff --git a/ascii-wiz.py b/ascii-wiz.py new file mode 100755 index 0000000..268e31b --- /dev/null +++ b/ascii-wiz.py @@ -0,0 +1,259 @@ +#!/usr/bin/env python3 + +import sys +import getopt +from PIL import Image as img + +# ASCII generator with 24-bit colours (requires 'pillow' -> e.g. APT package 'python3-willow') + +DEFAULT_MAX = 100 + + +class Colours: + WELCOME1 = "\x1b[38;2;235;216;52m" + WELCOME2 = "\x1b[38;2;52;183;235m" + WELCOME3 = "\x1b[38;2;235;52;107m" + BOLD = "\u001b[1m" + RESET = "\u001b[0m" + + +def usage(name="ascii-wiz.py"): + print( + f""" +Usage: {name} -i [ optional configuration ] + +Configuration: + + -s --size Set max width/height + -b --background Use background colouring + --colour Disable colours +""" + ) + + +def welcome(colours): + if colours: + print( + f"""{Colours.BOLD} + {Colours.WELCOME2}_ _ {Colours.WELCOME3}_ + {Colours.WELCOME2}(_|_) {Colours.WELCOME3}(_) +{Colours.WELCOME1} __ _ ___ _{Colours.WELCOME2}__ _ _ __ {Colours.WELCOME3} _ _ ____ +{Colours.WELCOME1} / _` / __|/ {Colours.WELCOME2}__| | | ____ \ \{Colours.WELCOME3} /\ / / |_ / +{Colours.WELCOME1}| (_| \__ \ ({Colours.WELCOME2}__| | | |____| \ {Colours.WELCOME3}V V /| |/ / +{Colours.WELCOME1} \__,_|___/\_{Colours.WELCOME2}__|_|_| \{Colours.WELCOME3}_/\_/ |_/___| + + {Colours.RESET}""" + ) + else: + print( + f""" + _ _ _ + __ _ ___ ___(_|_) __ _(_)____ + / _` / __|/ __| | | ____ \ \ /\ / / |_ / +| (_| \__ \ (__| | | |____| \ V V /| |/ / + \__,_|___/\___|_|_| \_/\_/ |_/___| + + """ + ) + + +def handle_arg(argv): + arg_list = [] + inputfile = "" + u_size = -1 + colours = True + background = False + + try: + opts, args = getopt.getopt( + argv, "hi:s:b", ["input=", "size=", "colour", "background"] + ) + except getopt.GetoptError: + usage() + sys.exit(1) + + for opt, arg in opts: + if opt == "-h": + usage() + sys.exit() + elif opt in ("-i", "--input"): + inputfile = arg + elif opt in ("-s", "--size"): + u_size = int(arg) + elif opt in ("-b", "--background"): + background = True + elif opt == "--colour": + colours = False + + welcome(colours) + + arg_list.append(inputfile) + arg_list.append(u_size) + arg_list.append(colours) + arg_list.append(background) + + return arg_list + + +def converter(filename, u_size, colours, background): + chars = [ + "$", + "@", + "B", + "%", + "8", + "&", + "W", + "M", + "#", + "*", + "o", + "a", + "h", + "k", + "b", + "d", + "p", + "q", + "w", + "m", + "Z", + "O", + "0", + "Q", + "L", + "C", + "J", + "U", + "Y", + "X", + "z", + "c", + "v", + "u", + "n", + "x", + "r", + "j", + "f", + "t", + "/", + "\\", + "|", + "(", + ")", + "1", + "{", + "}", + "[", + "]", + "?", + "-", + "_", + "+", + "~", + "<", + ">", + "i", + "!", + "l", + "I", + ";", + ":", + ",", + '"', + "^", + "`", + "'", + ".", + " ", + ] + ascii_string = [] + + with img.open(filename) as image: + size = image.size + # compensate roughly 2 * char_w = char_h (most monospaced fonts) + w, h = size[0], size[1] / 2 + ratio = w / h + + if u_size > 0 and (u_size < w or u_size < h): + if ratio >= 1: + n_size = (u_size, int(u_size / ratio)) + else: + n_size = (int(u_size * ratio), u_size) + elif w > DEFAULT_MAX or h > DEFAULT_MAX: + if ratio >= 1: + n_size = (DEFAULT_MAX, int(DEFAULT_MAX / ratio)) + else: + n_size = (int(DEFAULT_MAX * ratio), DEFAULT_MAX) + else: + n_size = (w, h) + + print(f"Original size: {str(size)}") + print(f"Fixed aspect ratio: {round(ratio, 6)}") + print(f"Fixed ASCII size: {str(n_size)}\n\n") + + image = image.resize(n_size) + + for p in image.getdata(): + # calculate intensity based on rgb value + x = int(p[0]) + int(p[1]) + int(p[2]) + normalized = int(round(x * 69 / 765)) + + if colours: + # convert each rgb value to ansi + if background: + ansi_c = ( + rgb_to_ansi_background(p) + + rgb_to_ansi_letter(p) + + chars[normalized] + ) + else: + ansi_c = rgb_to_ansi_letter(p) + chars[normalized] + + ascii_string.append(ansi_c) + else: + ascii_string.append(chars[normalized]) + + return ascii_string, n_size + + +def rgb_to_ansi_letter(rgb): + r, g, b = rgb[0], rgb[1], rgb[2] + return f"\x1b[38;2;{r};{g};{b}m" + + +def rgb_to_ansi_background(rgb): + r, g, b = rgb[0], rgb[1], rgb[2] + return f"\u001b[48;2;{r};{g};{b}m" + + +def print_ascii(width, ascii_string): + n = 0 + for c in ascii_string: + if n % width == 0: + n += 1 + print(Colours.RESET) + continue + n += 1 + print(c, end="") + + print(Colours.RESET + "\n") + + +def main(argv): + args = handle_arg(argv) + filename = args[0] + u_size = args[1] + colours = args[2] + background = args[3] + + ascii_string, n_size = converter(filename, u_size, colours, background) + print_ascii(n_size[0], ascii_string) + + +if __name__ == "__main__": + if len(sys.argv) < 3: + usage(sys.argv[0]) + sys.exit(1) + main(sys.argv[1:])