#!/usr/bin/env python3 # coding=utf-8 # # Copyright 2016 Ville Rantanen # # This program is free software: you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published # by the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # """Color by notation.""" __author__ = "Ville Rantanen " __version__ = "0.2" NEWCHAR = "====CHAR" NEWCOLOR = "====COLOR" NEWIMAGE = "====EOI" ENDOFFILE = "====EOF" PAUSE = "====PAUSE" import sys, os, argparse, re, time from argparse import ArgumentParser class bc: K = "\033[1;30m" R = "\033[1;31m" G = "\033[1;32m" Y = "\033[1;33m" B = "\033[1;34m" M = "\033[1;35m" C = "\033[1;36m" W = "\033[1;37m" k = "\033[0;30m" r = "\033[0;31m" g = "\033[0;32m" y = "\033[0;33m" b = "\033[0;34m" m = "\033[0;35m" c = "\033[0;36m" w = "\033[0;37m" nk = "\033[30m" nr = "\033[31m" ng = "\033[32m" ny = "\033[33m" nb = "\033[34m" nm = "\033[35m" nc = "\033[36m" nw = "\033[37m" bk = "\033[40m" br = "\033[41m" bg = "\033[42m" by = "\033[43m" bb = "\033[44m" bm = "\033[45m" bc = "\033[46m" bw = "\033[47m" S = "\033[1m" s = "\033[2m" # strong off U = "\033[4m" # underline u = "\033[24m" # underline off ic = "\033[7m" # inverse colors io = "\033[27m" # inverse off st = "\033[9m" # strike on so = "\033[29m" # strike off Z = "\033[0m" CLR = "\033[2J" CLREND = "\033[K" CLRSCR = CLR + "\033[0;0H" color_keys = "pqwertyu01234567;asdfghjPQWERTYUxXczvVbBnN" color_list = [ K, R, G, Y, B, M, C, W, k, r, g, y, b, m, c, w, bk, br, bg, by, bb, bm, bc, bw, nk, nr, ng, ny, nb, nm, nc, nw, S, s, CLRSCR, Z, U, u, st, so, ic, io, ] def pos(self, y, x): return "\033[" + str(y) + ";" + str(x) + "H" def posprint(self, y, x, s): sys.stdout.write((self.pos(y, x) + str(s))) def clear(self): sys.stdout.write((self.CLR + self.pos(0, 0))) def clear_to_end(self): sys.stdout.write(self.CLREND) def color_char(self, s): for i, c in enumerate(self.color_keys): if c in s: s = s.replace(c, self.color_list[i]) return s return "" def nocolor_string(self, s): return "" def end_drawing(opts): if opts.zero_final: sys.stdout.write(bc.Z) sys.exit(0) def open_data_file(opts): if opts.test_image: return test_data() if opts.filename == "-": return sys.stdin return open(opts.filename, "r") def setup_options(): """ Create command line options """ usage = """ Color image renderer in ANSI codes. Example file: first layer of characters ====CHAR more characters go here ====COLOR color codes go here (letters 1-7,0 and keys below like a piano) 12345670 : red green yellow blue magenta cyan white black (darker tone) qwertyup : red green yellow blue magenta cyan white black (bright tone) QWERTYUP : red green yellow blue magenta cyan white black (without changing brightness) asdfghj; : backround colors zc: reset colors, clearscreen xX: bright color on, bright color off vV: underline on, underline off bB: strikethrough on, strikethrough off nN: inverse on, inverse off ====EOI end of image, start another ====PAUSE1.5 another image starts, pause for 1.5 seconds before drawing the next ====EOF end of file """ parser = ArgumentParser( description=usage, formatter_class=argparse.RawDescriptionHelpFormatter, epilog=__author__, ) parser.add_argument("-v", "--version", action="version", version=__version__) parser.add_argument( "--no-color", "-n", action="store_false", dest="color", default=True, help="Disable color.", ) parser.add_argument( "--test", action="store_true", dest="test_image", default=False, help="Show test image showing features.", ) parser.add_argument( "-z", action="store_true", dest="zero", default=False, help="Reset color codes at the end of each line.", ) parser.add_argument( "-Z", action="store_false", dest="zero_final", default=True, help="Disable reset of colors at the end of file.", ) parser.add_argument( "-c", action="store_true", dest="clear", default=False, help="Clear screen first", ) parser.add_argument( "filename", type=str, nargs="?", default=None, help="File to show, - for stdin" ) opts = parser.parse_args() if not opts.test_image and opts.filename == None: parser.error("Need a file or - as argument") return opts def test_data(): testimage = ''' NOT VISIBLE _ _ _ ____ ___ 1 red 5 magenta / \ | \ | / ___|_ _| 2 green 6 cyan / _ \ | \| \___ \| | 3 yellow 7 white / ___ \| |\ |___) | | 4 blue 0 black /_/ \_\_| \_|____/___| ,ad8888ba, 88 88888888ba d8"' `"8b 88 88 "8b d8' 88 88 ,8P 88 ,adPPYba, 88 ,adPPYba, 88aaaaaa8P' ,adPPYba, 88 a8" "8a 88 a8" "8a 88""""88' I8[ "" Y8, 8b d8 88 8b d8 88 `8b `"Y8ba, Y8a. .a8P "8a, ,a8" 88 "8a, ,a8" 88 `8b aa ]8I `"Y8888Y"' `"YbbdP"' 8888888888 `"YbbdP"' 88 `8b `"YbbdP"' ====CHAR **************************************************** ====COLOR 1 2 3 4 5 6 7 0 q w e r t y u p Q W EXR TxY U P 1 1 5 1 2 6 1 3 7 1 R P Q ~ E f z e f z w f z w f z w f z u f u 7 f ; 7 f ; ====COLOR ~ ~ ~ ~ ~ v V b B bB v V ~ ~ f E ~ f e ~ f w ~ f w ~ f w ; f ; ; f U ; f U ====EOI Outputs:''' return testimage.split("\n") bc = bc() opts = setup_options() f = open_data_file(opts) endoffile = False if opts.clear: bc.clear() if opts.test_image: for row in f: print(row) while True: pause = 0 gray = [] gray.append([]) colors = [] colorFrame = 0 grayFrame = 0 maxRow = 0 for row in f: if not row: end_drawing(opts) row = row.rstrip("\n\r") if row.startswith(NEWIMAGE): break if row.startswith(ENDOFFILE): endoffile = True if endoffile: break if row.startswith(PAUSE): try: new_value = row[len(PAUSE) :].strip() pause = float(new_value) except: pause = 0 continue if row.startswith(NEWCOLOR): colorFrame += 1 colors.append([]) continue if colorFrame == 0: if row.startswith(NEWCHAR): grayFrame += 1 gray.append([]) continue gray[grayFrame].append(row) maxRow = max(maxRow, len(row)) else: colors[colorFrame - 1].append(row) if len(gray[0]) == 0: end_drawing(opts) for i in range(len(gray[0])): while maxRow > len(gray[0][i]): gray[0][i] = gray[0][i] + " " for i in range(len(gray[0])): for frame in colors: if len(frame) < i + 1: frame.append("") while len(gray[0][i]) > len(frame[i]): frame[i] = frame[i] + " " if len(gray) > 1: for layer in gray[1:]: if len(layer) < i + 1: layer.append("") while len(gray[0][i]) > len(layer[i]): layer[i] = layer[i] + " " for i in range(len(gray[0])): for c in range(len(gray[0][i])): if opts.color: for frame in colors: try: if frame[i][c] != " ": sys.stdout.write(bc.color_char(frame[i][c])) except IndexError: pass char = " " for layer in gray: if layer[i][c] == " ": continue char = layer[i][c] sys.stdout.write(char) if opts.color and opts.zero: sys.stdout.write(bc.Z) sys.stdout.write("\n") if pause > 0: time.sleep(pause) if opts.test_image: end_drawing(opts)