Daft Adventures in Home-Made Character Sets

Posted by Tom on 2013-04-20 14:36

Silly Python script to create an alphabet of glyphs that look kinda like the I Ching hexagrams? Yeah, I've got one of those.

Pretty pichor!

The below will take a filename as input and then create an image representing the file. It requires the Python Image Library.

import sys
import Image, ImageDraw

chars = 'abcdefghijklmnopqrstuvwxyz0123456789[](){}+-/*=:;.,#@\\\'"_&|^<>!%$'
glyphs = []

PADDING = 0
BORDER = 10

class Glyph:
    def __init__(self, index):
        image = Image.new('L', (8, 12))
        draw = ImageDraw.Draw(image)
        if index < pow(2, 4):
            for x in range(4):
                if (index >> x) & 1 == 0:
                    draw.line((x * 2, 0, x * 2, 10), fill=255)
                else:
                    draw.line((x * 2, 0, x * 2, 3), fill=255)
                    draw.line((x * 2, 7, x * 2, 10), fill=255)
        else:
            index = index - pow(2, 4)
            for x in range(6):
                if (index >> x) & 1 == 0:
                    draw.line((0, x * 2, 6, x * 2), fill=255)
                else:
                    draw.line((0, x * 2, 2, x * 2), fill=255)
                    draw.line((4, x * 2, 6, x * 2), fill=255)
        self.image = image

def create_glyphs():
    # horizontal bars
    for i in range(pow(2, 4)):
        image = Image.new('L', (8, 12))
        glyphs.append(Glyph(i))
    
    # vertical bars
    for i in range(pow(2, 4), len(chars)):
        glyphs.append(Glyph(i))
    
def build_image(f):
    row, col = 0, 0
    maxCol = 0
    while(True):
        c = f.read(1)
        if not c:
            break
        elif c == '\n':
            maxCol = max(col, maxCol)
            col = 0
            row = row + 1
        elif c == '\r':
            pass
        elif c == '\t':
            col = col + 4
        else:
            col = col + 1
    
    dims = (BORDER * 2 + maxCol * (8 + PADDING), 
        BORDER * 2 + row * (12 + PADDING))
    output = Image.new('L', dims)
    row, col = 0, 0
    f.seek(0)
    while(True):
        c = f.read(1)
        if not c:
            break
        elif c == '\n':
            row = row + 1
            col = 0
        elif c == '\r':
            pass
        elif c == '\t':
            col = col + 4 # YES. FOUR SPACES. COME AT ME.
        else:
            index = chars.find(c.lower())
            if index > -1:
                box = (BORDER + col * (8 + PADDING), 
                    BORDER + row * (12 + PADDING))
                output.paste(glyphs[index].image, box)
            col = col + 1
    return output
    
if __name__ == '__main__':
    filename = sys.argv[1] if len(sys.argv) > 1 else sys.argv[0]
    create_glyphs()
    f = open(filename, 'rb')
    build_image(f).save(filename + '.png')
    f.close()

The glyphs don't cover the whole ASCII alphabet, although those could be filled in with a few more combinations of lines. If we mix dimensions we should be able to fill in the blanks since we don't need to worry about control characters. But by that point I'd been distracted by something else.

I do that.