Skip to content

ASCII Art From Image Using Python Image Library

Aaron Luft edited this page Oct 5, 2020 · 4 revisions

Introduction

This page describes one method for converting an image file to ASCII art using the Python Image Library. The original material was derived from the blog post Convert Images to ASCII Art Images Using Python.

Highlights

  • A real example is provided (Swift)
  • You can manipulate the original image size and aspect ratio
  • You can add or remove ASCII characters to improve look
  • You can see the ASCII art rendered image in an image viewer and stdout

Quick

pip install Pillow
wget -O swift.png https://upload.wikimedia.org/wikipedia/commons/thumb/9/9d/Swift_logo.svg/267px-Swift_logo.svg.png
swift.py > swift.ascii
# remove trailing whitespace
gsed -i 's/ *$//g' swift.ascii
# add a color vector to each line 
gsed -i 's/^/{0}/' swift.ascii 

# TESTING
cp swift.ascii resources/swift.ascii
cargo test -- --ignored
make
target/release/onefetch --ascii-language swift

swift.py

Converts image file swift.png to image file swift-ascii.png and outputs the ASCII art to standard output.

#!/usr/local/bin/python3

# Original code from: https://medium.com/towards-artificial-intelligence/convert-images-to-ascii-art-images-using-python-90261de03c53
# See MOD for changes

from PIL import Image,ImageDraw,ImageFont
import math

# MOD: using swift.png as example input
image = Image.open("swift.png")
scaleFac = 1.0
# MOD: resize for onefetch width and height
charWidth = 40
charHeight = 24
w,h = image.size
# MOD: resize without aspect ratio preservation
image = image.resize((charWidth,charHeight),Image.NEAREST)
w,h = image.size
pixels = image.load()

# MOD: not using windows paths
font = ImageFont.truetype('Keyboard.ttf',15)
outputImage = Image.new('RGB',(charWidth*w,charHeight*h),color=(0,0,0))
draw = ImageDraw.Draw(outputImage)

def getSomeChar(h):
    # MOD: using reduced character set (better IMHO)
    chars  = "-_:. "[::-1]
    charArr = list(chars)
    l = len(charArr)
    mul = l/256
    return charArr[math.floor(h*mul)]

for i in range(h):
    for j in range(w):
        # MOD: not all images have RGB pixels so code here is unpacking into a list before unpacking
        # REF: https://stackoverflow.com/questions/52666965/valueerror-too-many-values-to-unpack-expected-3-using-pil/52667876
        p = pixels[j,i]
        r,g,b = p[0], p[1], p[2]
        grey = int((r/3+g/3+b/3))
        pixels[j,i] = (grey,grey,grey)
        draw.text((j*charWidth,i*charHeight),getSomeChar(grey), font=font,fill = (r,g,b))
        # MOD: export ASCII art to stdout too, new column value
        print( getSomeChar(grey), end='' )
    # MOD: export ASCII art to stdout too, new row
    print( "" )

outputImage.save("swift-ascii.png")
Clone this wiki locally