Make ASCII art GIF animation in Python

サンプル

I wrote Python to make ASCII art GIF animation from multiple images without any particular meaning, so I will write it here because there is no particular use.

The sample image above was generated using the letters "polikej #", using eight photos to make your head turn. The number of images to be arranged in tiles, font color, size, etc. are specified by the uppercase variable at the beginning of the script. (The sample image is made by slightly tweaking the code below.)

The font path can be found in the Finder display by checking the monospaced font with Font Book on OS X and right-clicking.

Pillow for ASCII art and ImageMagick For GIF animation generation. php) is required. I'm using a Mac and have pip and brew installed respectively.

from PIL import Image, ImageDraw, ImageFont
import os.path
import os
import commands


FONT_SIZE = 12
GRID_SIZE = (3, 2)
FONT_COLOR_SET = ("#ffffff", "#000000")
FONT_PATH = 'Font (monospaced) path'
IMAGE_NAMES = [
    'f0.png',
    'f1.png',
    'f2.png',
    'f3.png',
    'f4.png',
    'f5.png',
    'f6.png',
    'f7.png',
]

FONT_COLOR, FONT_BACKGROUND_COLOR = FONT_COLOR_SET
COLUMNS, ROWS = GRID_SIZE


def image2ascii(input_image):

    original_width, original_height = input_image.size

    width = original_width * COLUMNS
    height = original_height * ROWS

    character, line = "", []
    font = ImageFont.truetype(FONT_PATH, FONT_SIZE, encoding="utf-8")
    input_pix = input_image.load()
    output_image = Image.new("RGBA", (width, height), FONT_BACKGROUND_COLOR)
    draw = ImageDraw.Draw(output_image)

    font_width, font_height = font.getsize("#")

    margin_width = width % font_width
    margin_height = height % font_height

    offset_x = int(round(margin_width / 2))
    offset_y = int(round(margin_height / 2))

    for row in range(ROWS):
        for y in range(offset_y, original_height - offset_y, font_height):
            line = []
            for column in range(COLUMNS):
                for x in range(offset_x, original_width - offset_x, font_width):
                    r, g, b, _ = input_pix[x - offset_x, y - offset_y]
                    gray = r * 0.2126 + g * 0.7152 + b * 0.0722
                    "polikeiji"
                    if gray > 130:
                        character = " "
                    elif gray > 100:
                        character = "i"
                    elif gray > 90:
                        character = "l"
                    elif gray > 80:
                        character = "j"
                    elif gray > 60:
                        character = "o"
                    elif gray > 50:
                        character = "e"
                    elif gray > 40:
                        character = "p"
                    elif gray > 30:
                        character = "k"
                    else:
                        character = "#"
                    line.append(character)
            draw.text((offset_x, y + row * original_height), "".join(line), font = font, fill = FONT_COLOR)
    return output_image

if __name__ == "__main__":
    directory_name = os.path.dirname(IMAGE_NAMES[0])
    if directory_name != '':
        directory_name = directory_name + "/"
    ascii_image_directory = "{0}ascii_{1}_{2}x{3}_{4}_{5}".format(
        directory_name, FONT_SIZE, ROWS, COLUMNS, FONT_COLOR, FONT_BACKGROUND_COLOR)

    for image_name in IMAGE_NAMES:
        print "Input image: {0}".format(image_name)

        with Image.open(image_name) as input_image:
            output_image = image2ascii(input_image)
         
            file_name, extension = os.path.splitext(os.path.basename(image_name))
    
            ascii_image_name = "{0}/ascii_{1}_{2}x{3}_{4}{5}".format(
                ascii_image_directory,
                FONT_SIZE, ROWS, COLUMNS, file_name, extension)

            ascii_image_directory = os.path.dirname(ascii_image_name)
            if not os.path.exists(ascii_image_directory):
                os.makedirs(ascii_image_directory)
    
            output_image.save(ascii_image_name)

            print "Output image: {0}".format(ascii_image_name)

    make_gif_animation_command = "convert -delay 10 -loop 0 {0}/*.png {0}/{1}.gif".format(
        ascii_image_directory, os.path.basename(ascii_image_directory))

    print commands.getoutput(make_gif_animation_command)

Generate ASCII art with Pillow

Please refer to here including the code. It feels like examining an image pixel by pixel and assigning characters according to the brightness.

The size of one character differs depending on the font, so I checked the size of one character in advance and adjusted it so that ASCII art is centered.

Later, I specified an image with a wild card and made a GIF animation with ImageMagick, so the ASCII art images are saved together in one folder.

Gif Ani generation with ImageMagick

Generated simply with the convert command.

convert -delay 10 -loop 0 {folder}/*.png {folder}/output.gif

The speed changes somehow with the delay option, but it seems that the speed differs depending on the viewer, and it seems that you can not specify exactly FPS.

I wondered if I could make a GIF animation with Python, but there was no library or it seemed to be annoying. stackoverflow

Recommended Posts

Make ASCII art GIF animation in Python
Create gif video in Python
Don't make test.py in Python!
Make a bookmarklet in Python
Make Opencv available in Python
Make python segfault in 2 lines
Convert images passed to Jason Statham-like in Python to ASCII art
Make python segfault in one line
Make ASCII art with deep learning
Make standard output non-blocking in Python
Make python segfault in three lines
Try drawing a simple animation in Python
Make a GIF animation with folder monitoring
Let's make a combination calculation in Python
Make cron-like jobs run regularly in Python
Quadtree in Python --2
Python in optimization
CURL in python
Metaprogramming in Python
Python 3.3 in Anaconda
Geocoding in python
SendKeys in Python
Convert FBX files to ASCII <-> BINARY in Python
Meta-analysis in Python
Unittest in python
Epoch in Python
Discord in Python
Make a copy of the list in Python
Sudoku in Python
DCI in Python
quicksort in python
nCr in python
N-Gram in Python
Programming in python
Make a rock-paper-scissors game in one line (python)
Plink in Python
Constant in python
Let's make some notification processing samples in Python
Lifegame in Python.
FizzBuzz in Python
[Blender x Python] How to make an animation
Sqlite in python
Make a joyplot-like plot of R in python
StepAIC in Python
N-gram in python
LINE-Bot [0] in Python
Csv in python
Disassemble in Python
Reflection in Python
[Blender x Python] How to make vertex animation
Constant in python
nCr in Python.
format in python
Scons in Python3
Puyo Puyo in python
python in virtualenv
PPAP in Python
Quad-tree in Python
How to make Python Interpreter changes in Pycharm
Reflection in Python
Chemistry in Python