-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathimg2ascii.py
89 lines (64 loc) · 2.83 KB
/
img2ascii.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
try:
from tqdm import tqdm
except ImportError:
def tqdm(arg):
return arg
from PIL import Image
import json
import argparse
def load_chars(path, pallet_idx=0, invert=False):
with open(path, "rb") as file:
chars = json.loads(file.read().decode("utf8"))[pallet_idx]
chars = [c for c in chars]
if invert:
chars.reverse()
return chars
def load_img(path, max_width=300):
with Image.open(path) as img:
img.load()
# Convert to grayscale
img = img.convert("L")
width, height = img.size
if width > max_width:
ratio = width / height if width < height else height / width
img = img.resize((max_width, int(max_width * ratio)), Image.Resampling.LANCZOS)
return img
def colour_to_char(chars, val, max_val=255):
val_percent = val / max_val
return chars[int(len(chars) * val_percent)-1]
def img_to_str(img, chars, pixel_width=2, silent=False):
out_string = ""
width, height = img.size
x, y = 0, -1
for i, pixel in enumerate(tqdm(img.getdata()) if not silent else img.getdata()):
x = i % width
if x == 0:
y += 1
if y > 0:
out_string += "\n"
out_string += colour_to_char(chars, pixel) * pixel_width
return out_string
def main():
parser = argparse.ArgumentParser(
prog="img_to_ascii.py",
description="Convert an image into ASCII (or unicode) text"
)
parser.add_argument("image_path", help="Path to the image to convert")
parser.add_argument("chars_path", help="Path to the chars file")
parser.add_argument("-o", "--out_path", required=False, default=None, help="File to output to. If left blank, will output to console.")
parser.add_argument("-w", "--width", type=int, required=False, default=300, help="Width to scale the image to. Default is 300px")
parser.add_argument("-c", "--chars_idx", type=int, required=False, default=0, help="Index of the 'pallet' in the given chars json file")
parser.add_argument("-i", "--invert", required=False, action="store_true", help="If included, image will be inverted")
parser.add_argument("-p", "--pixel_width", required=False, default=2, type=int, help="How many characters to place per pixel. Should be adjusted based on font aspect ratio.")
parser.add_argument("-s", "--silent", required=False, action="store_true", help="If included, only the output will be printed to the console")
args = parser.parse_args()
img = load_img(args.image_path, max_width=args.width)
chars = load_chars(args.chars_path, args.chars_idx, invert=args.invert)
out = img_to_str(img, chars, pixel_width=args.pixel_width, silent=args.silent)
if args.out_path:
with open(args.out_path, "wb") as file:
file.write(out.encode("utf8"))
else:
print(out)
if __name__ == '__main__':
main()