Archive

Posts Tagged ‘Software’

generating ASCII art from photographs in Python

September 8, 2009 Leave a comment

I’m old school – I have vague recollections of seeing an ASCII art printout of Snoopy printed on mainframe feed paper as a child back in the 70s. I think I drew on top of this with Crayola crayons.

I thought it would be fun to try to recreate this with photos.

ASCII Art works by using bog-standard ASCII characters to build up an image. It’s the creative use of positive and negative space in typography; some characters use more ink (like #) and some use less (like .), and by using the ‘weight’ of characters, you can build up an image.

ascii-art-face

What we need to do is to shrink the image to thumbnail size, then convert the image to monochrome.

With Python, the standard image processing library is PIL. Creating a monochrome thumbnail is trivial:-

im=Image.open(r"c:\test.jpg")
im=im.resize((75, 75), Image.ANTIALIAS)
im=im.convert("L") # convert to mono

Then, it’s a matter of splitting the luminosity values into 7 bands, and assigning each pixel a random character from a group of ascii characters of similar “optical weight”.

Here’s the script…

'''
ASCII Art maker
Creates an ascii art image from an arbitrary image
Created on 7 Sep 2009

@author: Steven Kay
'''

from PIL import Image
import random
from bisect import bisect

# greyscale.. the following strings represent
# 7 tonal ranges, from lighter to darker.
# for a given pixel tonal level, choose a character
# at random from that range.

greyscale = [
            " ",
            " ",
            ".,-",
            "_ivc=!/|\\~",
            "gjez2]/(YL)t[+T7Vf",
            "mdK4ZGbNDXY5P*Q",
            "W8KMA",
            "#%$"
            ]

# using the bisect class to put luminosity values
# in various ranges.
# these are the luminosity cut-off points for each
# of the 7 tonal levels. At the moment, these are 7 bands
# of even width, but they could be changed to boost
# contrast or change gamma, for example.

zonebounds=[36,72,108,144,180,216,252]

# open image and resize
# experiment with aspect ratios according to font

im=Image.open(r"c:\test.jpg")
im=im.resize((160, 75),Image.BILINEAR)
im=im.convert("L") # convert to mono

# now, work our way over the pixels
# build up str

str=""
for y in range(0,im.size[1]):
    for x in range(0,im.size[0]):
        lum=255-im.getpixel((x,y))
        row=bisect(zonebounds,lum)
        possibles=greyscale[row]
        str=str+possibles[random.randint(0,len(possibles)-1)]
    str=str+"\n"

print str

The text can then be pasted into a text editor or web page, but you’ll need to use a monospaced font, where each character takes the same amount of space horizontally. And depending on your editor, you may need to turn off word wrap 🙂

It’s amazing how much difference there is between monospaced fonts; some work better than others. Some fonts are ‘wider’ than others, so it’s worth experimenting with aspect ratios.

Advertisements
Categories: Python Tags: , ,