1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204
|
#!/usr/bin/env python
# Script to render text as a PNG image.
# texttopng
# Example (all ASCII glyphs):
#
# printf $(printf '\\%s' $(seq 40 176 | grep -v '[89]')) |
# fold -w 32 |
# ./texttopng > ascii.png
import itertools
def usage(fil):
fil.write("texttopng [-h|--help] text\n")
font = {
32: '0000000000000000',
33: '0010101010001000',
34: '0028280000000000',
35: '0000287c287c2800',
36: '00103c5038147810',
37: '0000644810244c00',
38: '0020502054483400',
39: '0010100000000000',
40: '0008101010101008',
41: '0020101010101020',
42: '0010543838541000',
43: '000010107c101000',
44: '0000000000301020',
45: '000000007c000000',
46: '0000000000303000',
47: '0000040810204000',
48: '0038445454443800',
49: '0008180808080800',
50: '0038043840407c00',
51: '003c041804043800',
52: '00081828487c0800',
53: '0078407804047800',
54: '0038407844443800',
55: '007c040810101000',
56: '0038443844443800',
57: '0038443c04040400',
58: '0000303000303000',
59: '0000303000301020',
60: '0004081020100804',
61: '0000007c007c0000',
62: '0040201008102040',
63: '0038440810001000',
64: '00384c545c403800',
65: '0038447c44444400',
66: '0078447844447800',
67: '0038444040443800',
68: '0070484444487000',
69: '007c407840407c00',
70: '007c407840404000',
71: '003844405c443c00',
72: '0044447c44444400',
73: '0038101010103800',
74: '003c040404443800',
75: '0044487048444400',
76: '0040404040407c00',
77: '006c545444444400',
78: '004464544c444400',
79: '0038444444443800',
80: '0078447840404000',
81: '0038444444443c02',
82: '0078447844444400',
83: '0038403804047800',
84: '007c101010101000',
85: '0044444444443c00',
86: '0044444444281000',
87: '0044445454543800',
88: '0042241818244200',
89: '0044443810101000',
90: '007c081020407c00',
91: '0038202020202038',
92: '0000402010080400',
93: '0038080808080838',
94: '0010284400000000',
95: '000000000000fe00',
96: '0040200000000000',
97: '000038043c443c00',
98: '0040784444447800',
99: '0000384040403800',
100: '00043c4444443c00',
101: '000038447c403c00',
102: '0018203820202000',
103: '00003c44443c0438',
104: '0040784444444400',
105: '0010003010101000',
106: '0010003010101020',
107: '0040404870484400',
108: '0030101010101000',
109: '0000385454444400',
110: '0000784444444400',
111: '0000384444443800',
112: '0000784444784040',
113: '00003c44443c0406',
114: '00001c2020202000',
115: '00003c4038047800',
116: '0020203820201800',
117: '0000444444443c00',
118: '0000444444281000',
119: '0000444454543800',
120: '0000442810284400',
121: '00004444443c0438',
122: '00007c0810207c00',
123: '0018202060202018',
124: '0010101000101010',
125: '003008080c080830',
126: '0020540800000000',
}
def char(i):
"""Get image data for the character `i` (a one character string).
Returned as a list of rows. Each row is a tuple containing the
packed pixels.
"""
i = ord(i)
if i not in font:
return [(0,)] * 8
return [(ord(row),) for row in font[i].decode('hex')]
def texttoraster(m):
"""Convert the string *m* to a raster image. Any newlines
in *m* will cause more than one line of output. The
resulting raster will be taller. Prior to rendering each
line, it is padded on the right with enough spaces to make
all lines the same length.
"""
lines = m.split('\n')
maxlen = max(len(line) for line in lines)
justified = [line.ljust(maxlen) for line in lines]
rasters = [linetoraster(line) for line in justified]
x, = set(r[0] for r in rasters)
y = sum(r[1] for r in rasters)
raster = itertools.chain(*(r[2] for r in rasters))
return x, y, raster
def linetoraster(m):
"""Convert a single line of text *m* to a raster image,
by rendering it using the font in *font*.
A triple of (*width*, *height*, *pixels*) is returned;
*pixels* is in boxed row packed pixel format.
"""
# Assumes monospaced font.
x = 8 * len(m)
y = 8
return x, y, [itertools.chain(*row) for row in zip(*map(char, m))]
def render(message, out):
import png
x, y, pixels = texttoraster(message)
w = png.Writer(x, y, greyscale=True, bitdepth=1)
w.write_packed(out, pixels)
out.flush()
def main(argv=None):
import sys
if argv is None:
argv = sys.argv
for a in argv:
if a.startswith('-'):
if a in ('-h', '--help'):
usage(sys.stdout)
sys.exit(0)
else:
sys.stderr.write("Unknown option: %s\n" % a)
usage(sys.stderr)
sys.exit(4)
arg = argv[1:]
if len(arg) > 0:
message = arg[0]
out = open("%s.png" % message, 'wb')
else:
message = sys.stdin.read()
out = sys.stdout
# on Windows it is necessary to switch stdout to binary mode
# to avoid \n translation
# http://stackoverflow.com/questions/2374427/python-2-x-write-binary-output-to-stdout
if sys.platform == "win32":
import msvcrt
import os
msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
render(message, out)
if __name__ == '__main__':
main()
|