defmap(r, g, b, al = 256): if al == 0: return' ' gray = int(0.2126 * r + 0.7152 * g + 0.0722 * b) unit = (256.0 + 1) / len(ascii) returnascii[int(gray / unit)]
if __name__ == '__main__': m = Image.open(IMG) m = m.resize((W, H), Image.NEAREST) c = ""
for i inrange(H): for j inrange(W): p = m.getpixel((j, i)) # p[0], p[1], p[2], p[3] c += map(*p) c += '\n' print(c)
if OUTPUT: withopen(OUTPUT, 'w') as f: f.write(c) else: withopen("ascii.txt", 'w') as f: f.write(c)
We use the image below to test our code:
And below is the screenshot of the output ascii.txt:
We noticed that the proportion of the output isn’t quite right. Moreover, it would better if the output is colored, but not just black-and-white. So let us make some improvements.
Colored Output
In the previous case, the output format is in .txt form, and we get a black-and-white output. Now if we want to get a colored output, then the format cannot be .txt anymore, since plain text files do not display colored texts. To achieve this, we need the submodule ImageDraw from the PIL library.
As to the proportion of the output, we’re going to set the width and height of the output, and also adjust the font to get the optimum result. Hence one more submodule from PIL is needed: ImageFont.
Enough for the explanation. The code is shown below:
import argparse from PIL import Image, ImageFont, ImageDraw
r = argparse.ArgumentParser() r.add_argument('file') r.add_argument('-o', '--output')
ag = r.parse_args() Pic = ag.file OUTPUT = ag.output
set = list("$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\|()1{}[]?-_+~<>i!lI;:,\"^`'. ")
defmap(r, g, b, a = 256): if a == 0: return' ' gray = int(0.2126 * r + 0.7152 * g + 0.0722 * b) unit = (256.0 + 1) / len(set) returnset[int(gray / unit)]
if __name__ == '__main__': m = Image.open(Pic) # Don't forget to set the W & H W = int(m.width / 6) H = int(m.height / 15) m_txt = Image.new('RGB', (m.width, m.height), (255, 255, 255)) m = m.resize((W, H)) t = '' color = [] for i inrange(H): for j inrange(W): p = m.getpixel((j, i)) color.append((p[0], p[1], p[2])) t += map(*p) t += '\n' color.append((255, 255, 255))
# Adjust the fonts draw = ImageDraw.Draw(m_txt) font = ImageFont.load_default().font x = y = 0 fw, fh = font.getsize(t[1]) fh *= 1.37
# Coloring the ASCIIs for i inrange(len(t)): if t[i] == '\n': x = x + fh y = -fw # Note: -fw draw.text([y, x], t[i], color[i]) y = y + fw m_txt.save('color.png')
Using the same picture, and this time we got the output like this: