Skip to content
This repository has been archived by the owner on Feb 26, 2022. It is now read-only.

Latest commit

 

History

History
229 lines (198 loc) · 7.25 KB

aa.md

File metadata and controls

229 lines (198 loc) · 7.25 KB

5. Create Ascii Art Applicaion

5.1 What is Ascii Art? {#what-is-ascii-art}

Ascii art is a graphic style composed of alphabets and symboles.

Beethoven

TheGirlWithThePearlEarring

godfatherII

Mona_Lisa

matrix

matrix

matrix

5.2 Load Image {#load-image}

You use Python Image Library. If you installed Python with Anaconda, it alredy installed the library, otherwise execute pip install Pillow. We use the sample input image Lenna.png . Locate the image in the same folder as .py file.

First, You write very simple code. you load an image, print its size and show the image.

from PIL import Image
img = Image.open('Lenna.png')
print(img.size)
img.show()

(512, 512)

Lenna

5.3 Convert into Grayscale {#convert-into-grayscale}

Each pixel is defined by the value of red, green and blue, (r, g, b), 0 <= r <= 255, 0<= g <= 255, 0 <= b <= 255. (r, g, b) is converted into the intensity (or Brightness) by

gray = red * 0.2126 + green * 0.7152 + b * 0.0722

You can see pixel data by load(). Also, convert image type by .convert('RGB') for when an input image's mode is not RGB.

from PIL import Image
img = Image.open('Lenna.png').convert('RGB')
pixels = img.load()
print(pixels)

Bunch of (r, g, b) is shown now. Each pixel is accessed by pixels[x,y], 0 <= x < width, 0 <= y < height. xy Coordination in a image is below.

O ---------> x
|
|
| Image
|
|/
y

convert them into grayscale because we are making grayscale ascii art.

from PIL import Image
img = Image.open('Lenna.png').convert('RGB')
w, h = img.size
pixels = img.load()
for y in range(h):
    row = []
    for x in range(w):
        r, g, b = pixels[x, y]
        gray = r * 0.2326 + g * 0.7152 + b * 0.0722
        print(gray)

5.4 Prepare for a white canvas, font and drawing {#prepare-canvas}

You create a white canvas to output. import other libraries.

from PIL import Image, ImageFont, ImageDraw
img = Image.open('Lenna.png').convert('RGB')
w, h = img.size
pixels = img.load()
fontsize = 24
font = ImageFont.truetype("path/to/font.ttc", fontsize, encoding='utf-8')
# On windows, fontpath = 'C://Windows/Fonts/msgothic.ttc'
# On Mac, fontpath = '/System/Library/Fonts/Menlo.ttc'
# On Linux, fontpath = '/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf'
output_img = Image.new(mode='RGBA', size=(w,h), color=(255,255,255)) # white canvas. Its size is the same as the input image's size.
draw = ImageDraw.Draw(output_img)
for y in range(h):
    for x in range(w):
        r, g, b = pixels[x, y]
        gray = r * 0.2326 + g * 0.7152 + b * 0.0722
output_img.show()

5.5 Draw Ascii Art {#draw-ascii-art}

Put a character corresponding to the grayscale in the same pixel of the input image. x and y should step by fontsize. Monospaced font is recommended. We divide 0-255 grayscale into ten levels. Edit for-loops.

from PIL import Image, ImageFont, ImageDraw
img = Image.open('Lenna.png').convert('RGB')
w, h = img.size
pixels = img.load()
fontsize = 24
fontpath = 'path/to/your/font'
font = ImageFont.truetype(fontpath, fontsize, encoding='utf-8')
output_img = Image.new(mode='RGBA', size=(w,h), color=(255,255,255))
draw = ImageDraw.Draw(output_img)
for y in range(0, h, fontsize): # The third parameter in range is a step 
    for x in range(0, w, fontsize):
        r, g, b = pixels[x, y]
        gray = r * 0.2326 + g * 0.7152 + b * 0.0722
        r, g, b = pixels[x, y]
        gray = r * 0.2326 + g * 0.7152 + b * 0.0722
        if gray  > 225:
            character = ' '
        elif gray > 200:
            character = '.'
        elif gray > 175:
            character = ','
        elif gray > 150:
            character = ':'
        elif gray > 125:
            character = ';'
        elif gray > 100:
            character = '+'
        elif gray > 75:
            character = '*'
        elif gray > 50:
            character = '%'
        elif gray > 25:
            character = '#'
        else:
            character = 'W'
        draw.text((x, y), character, font=font, fill = '#000000') # #000000 corresponds black
output_img.show()

Lenna-fontsize24

It is too low image quality. Change fontsize to 12 by fontsize = 12 and re-run.

from PIL import Image, ImageFont, ImageDraw
img = Image.open('Lenna.png').convert('RGB')
w, h = img.size
pixels = img.load()
fontsize = 12
fontpath = 'path/to/your/font'
# On windows, fontpath = 'C://Windows/Fonts/msgothic.ttc'
# On Mac, fontpath ='/System/Library/Fonts/Menlo.ttc'
font = ImageFont.truetype(fontpath, fontsize, encoding='utf-8')
output_img = Image.new(mode='RGBA', size=(w,h), color=(255,255,255))
draw = ImageDraw.Draw(output_img)
for y in range(0, h, fontsize): # The third parameter in range is a step 
    for x in range(0, w, fontsize):
        r, g, b = pixels[x, y]
        gray = r * 0.2326 + g * 0.7152 + b * 0.0722
        if gray  > 225:
            character = ' '
        elif gray > 200:
            character = '.'
        elif gray > 175:
            character = ','
        elif gray > 150:
            character = ':'
        elif gray > 125:
            character = ';'
        elif gray > 100:
            character = '+'
        elif gray > 75:
            character = '*'
        elif gray > 50:
            character = '%'
        elif gray > 25:
            character = '#'
        else:
            character = 'W'
        draw.text((x, y), character, font=font, fill = '#000000') # #000000 corresponds black
output_img.show()

Lenna-fontsize12

It lookes better. The input image size is 512 x 512. When fontsize = 24, as 512 / 24 = 21.3... so 22 characters are written in each row, and when fontsize = 12, as 512 / 12 = 42.6..., so 43 characters are done likewise.

5.6 Save Image {#save-image}

Add the last line to save an image.

from PIL import Image, ImageFont, ImageDraw
img = Image.open('Lenna.png').convert('RGB')
w, h = img.size
pixels = img.load()
fontsize = 12
fontpath = 'path/to/your/font'
font = ImageFont.truetype(fontpath, fontsize, encoding='utf-8')
output_img = Image.new(mode='RGBA', size=(w,h), color=(255,255,255))
draw = ImageDraw.Draw(output_img)
for y in range(0, h, fontsize):
    for x in range(0, w, fontsize):
        r, g, b = pixels[x, y]
        gray = r * 0.2326 + g * 0.7152 + b * 0.0722
        if gray  > 225:
            character = ' '
        elif gray > 200:
            character = '.'
        elif gray > 175:
            character = ','
        elif gray > 150:
            character = ':'
        elif gray > 125:
            character = ';'
        elif gray > 100:
            character = '+'
        elif gray > 75:
            character = '*'
        elif gray > 50:
            character = '%'
        elif gray > 25:
            character = '#'
        else:
            character = 'W'
        draw.text((x, y), character, font=font, fill = '#000000') # #000000 means black
output_img.save('Lenna_AA.png')