13 "from IPython.display import clear_output\n",
14 "from PIL import Image, ImageDraw, ImageColor, ImageFont"
37 "def new_grid(w=WIDTH, h=HEIGHT):\n",
38 " return ['.' * w for r in range(1, h+1)]"
49 "def print_grid(grid, md=False, suppress_dots=False):\n",
52 " for row in grid:\n",
53 " if suppress_dots:\n",
54 " print(re.sub(r'\\.', ' ', row))\n",
69 "def top(grid, l, r):\n",
70 " new_segment = ''\n",
71 " for i in range(l-1, r):\n",
72 " if grid[0][i] == '.':\n",
73 " new_segment += '*'\n",
75 " new_segment += '.'\n",
76 " grid[0] = grid[0][:l-1] + new_segment + grid[0][r:]\n",
88 "def left(grid, t, b):\n",
89 " for i in range(t-1, b):\n",
90 " if grid[i][0] == '.':\n",
91 " grid[i] = '*' + grid[i][1:]\n",
93 " grid[i] = '.' + grid[i][1:]\n",
105 "def rotate_column(grid, c, raw_n):\n",
106 " n = raw_n % len(grid)\n",
107 " col = [row[c-1] for row in grid]\n",
108 " new_col = col[-n:] + col[:-n]\n",
109 " for i in range(len(grid)):\n",
110 " grid[i] = grid[i][:c-1] + new_col[i] + grid[i][c:]\n",
116 "execution_count": 9,
122 "def rotate_row(grid, r, raw_n):\n",
123 " n = raw_n % len(grid[0])\n",
124 " grid[r-1] = grid[r-1][-n:] + grid[r-1][:-n]\n",
130 "execution_count": 10,
136 "command_dispatch = {'left': left, 'top': top,\n",
137 " 'rotate row': rotate_row,\n",
138 " 'rotate column': rotate_column}"
143 "execution_count": 11,
149 "def parse(command):\n",
150 " cmd, a, b = command.rsplit(maxsplit=2)\n",
151 " return cmd, int(a), int(b) "
156 "execution_count": 63,
162 "def interpret(commands, grid=None, w=WIDTH, h=HEIGHT, \n",
163 " show_each_step=False, md=False, overprint=False):\n",
164 " if grid is None:\n",
165 " grid = new_grid(w, h)\n",
167 " for cn, c in enumerate(commands):\n",
168 " cmd, a, b = parse(c)\n",
169 " if cmd in command_dispatch:\n",
170 " command_dispatch[cmd](grid, a, b)\n",
172 " raise ValueError('Unknown command')\n",
173 " if show_each_step:\n",
174 " frames += [draw_frame(grid, c, cn)]\n",
175 " if show_each_step: \n",
177 " print_grid(grid, md=md)\n",
178 " frames[0].save('frames.gif', save_all=True, append_images=frames[1:], duration=200)\n",
184 "execution_count": 44,
189 "output_type": "stream",
191 "...****..............*...................*.....*..............*.................\n",
192 "......*..............*...................***..**..............*.................\n",
193 "......*.*****.*****.****.*****..****.....*.*.***.*****.*****.****.*****..****...\n",
194 "......*.....*.*...*..*.......*..*........*..**.*.....*.*...*..*.......*..*......\n",
195 "......*.*****.*...*..*...*****..*........*..*..*.*****.*...*..*...*****..*......\n",
196 "......*.*...*.*...*..*...*...*..*........*.....*.*...*.*...*..*...*...*..*......\n",
197 "...*..*.*..**.*...*..**..*..**..*........*.....*.*..**.*...*..**..*..**..*......\n",
198 "....**...**.*.*...*...**..**.*..*........*.....*..**.*.*...*...**..**.*..*......\n"
203 "cmds = [c.strip() for c in open('05-pixels.txt').readlines()]\n",
204 "g = interpret(cmds)\n",
210 "execution_count": 60,
215 "output_type": "stream",
222 "im = Image.new('RGBA', (WIDTH * 10, HEIGHT * 10 + 21))\n",
224 "# make a blank image for the text, initialized to transparent text color\n",
225 "# txt = Image.new('RGBA', im.size, (255,255,255,0))\n",
226 "txt = Image.new('RGBA', im.size, (0, 0, 0, 0))\n",
229 "fnt = ImageFont.truetype('Pillow/Tests/fonts/FreeMono.ttf', 18)\n",
230 "# get a drawing context\n",
231 "d = ImageDraw.Draw(txt)\n",
233 "# draw text, full opacity\n",
234 "d.text((1,1), \"Command description\", font=fnt, fill='black')\n",
236 "print(d.textsize(\"Command description\", fnt))\n",
239 "draw = ImageDraw.Draw(im)\n",
240 "for (r, row) in enumerate(g):\n",
241 " for (c, cell) in enumerate(row):\n",
243 " ry = r * 10 + 20\n",
244 " if cell == '*':\n",
245 " fill_colour = 'lime'\n",
247 " fill_colour = 'black'\n",
248 " draw.rectangle([rx, ry, rx + 10, ry + 10], fill=fill_colour, outline='orange')\n",
250 "# draw.line((0, 0) + im.size, fill=128)\n",
251 "# draw.line((0, im.size[1], im.size[0], 0), fill=128)\n",
253 "out = Image.alpha_composite(im, txt)\n",
254 "out.save('test.png', 'PNG')\n",
262 "execution_count": 76,
268 "def draw_frame(grid, command, frame_number):\n",
269 " im = Image.new('RGBA', (WIDTH * 10, HEIGHT * 10 + 21))\n",
271 " # make a blank image for the text, initialized to transparent text color\n",
272 " txt = Image.new('RGBA', im.size, (255,255,255,0))\n",
273 "# txt = Image.new('RGBA', im.size, (0, 0, 0, 0)) # use this line rather than line above for animated png\n",
276 " fnt = ImageFont.truetype('Pillow/Tests/fonts/FreeMono.ttf', 18)\n",
277 " # get a drawing context\n",
278 " d = ImageDraw.Draw(txt)\n",
280 " # draw text, full opacity\n",
281 " d.text((1,1), command, font=fnt, fill='white')\n",
282 "# d.text((1,1), command, font=fnt, fill='black') # use this line rather than line above for animated png\n",
284 " draw = ImageDraw.Draw(im)\n",
285 " for (r, row) in enumerate(grid):\n",
286 " for (c, cell) in enumerate(row):\n",
288 " ry = r * 10 + 20\n",
289 " if cell == '*':\n",
290 " fill_colour = 'lime'\n",
292 " fill_colour = 'black'\n",
293 " draw.rectangle([rx, ry, rx + 10, ry + 10], fill=fill_colour, outline=128)\n",
295 " # draw.line((0, 0) + im.size, fill=128)\n",
296 " # draw.line((0, im.size[1], im.size[0], 0), fill=128)\n",
298 " out = Image.alpha_composite(im, txt)\n",
299 "# out.save('frame{:04}.png'.format(frame_number), 'PNG') # uncomment here to save animated png frames\n",
308 "execution_count": 24,
314 "['...****..............*...................*.....*..............*.................',\n",
315 " '......*..............*...................***..**..............*.................',\n",
316 " '......*.*****.*****.****.*****..****.....*.*.***.*****.*****.****.*****..****...',\n",
317 " '......*.....*.*...*..*.......*..*........*..**.*.....*.*...*..*.......*..*......',\n",
318 " '......*.*****.*...*..*...*****..*........*..*..*.*****.*...*..*...*****..*......',\n",
319 " '......*.*...*.*...*..*...*...*..*........*.....*.*...*.*...*..*...*...*..*......',\n",
320 " '...*..*.*..**.*...*..**..*..**..*........*.....*.*..**.*...*..**..*..**..*......',\n",
321 " '....**...**.*.*...*...**..**.*..*........*.....*..**.*.*...*...**..**.*..*......']"
324 "execution_count": 24,
326 "output_type": "execute_result"
335 "execution_count": 77,
340 "output_type": "stream",
343 "...****..............*...................*.....*..............*.................\n",
344 "......*..............*...................***..**..............*.................\n",
345 "......*.*****.*****.****.*****..****.....*.*.***.*****.*****.****.*****..****...\n",
346 "......*.....*.*...*..*.......*..*........*..**.*.....*.*...*..*.......*..*......\n",
347 "......*.*****.*...*..*...*****..*........*..*..*.*****.*...*..*...*****..*......\n",
348 "......*.*...*.*...*..*...*...*..*........*.....*.*...*.*...*..*...*...*..*......\n",
349 "...*..*.*..**.*...*..**..*..**..*........*.....*.*..**.*...*..**..*..**..*......\n",
350 "....**...**.*.*...*...**..**.*..*........*.....*..**.*.*...*...**..**.*..*......\n",
351 "...****..............*...................*.....*..............*.................\n",
352 "......*..............*...................***..**..............*.................\n",
353 "......*.*****.*****.****.*****..****.....*.*.***.*****.*****.****.*****..****...\n",
354 "......*.....*.*...*..*.......*..*........*..**.*.....*.*...*..*.......*..*......\n",
355 "......*.*****.*...*..*...*****..*........*..*..*.*****.*...*..*...*****..*......\n",
356 "......*.*...*.*...*..*...*...*..*........*.....*.*...*.*...*..*...*...*..*......\n",
357 "...*..*.*..**.*...*..**..*..**..*........*.....*.*..**.*...*..**..*..**..*......\n",
358 "....**...**.*.*...*...**..**.*..*........*.....*..**.*.*...*...**..**.*..*......\n"
363 "cmds = [c.strip() for c in open('05-pixels.txt').readlines()]\n",
364 "g = interpret(cmds, show_each_step=True)\n",
369 "cell_type": "markdown",
372 "Create animated png."
377 "execution_count": null,
383 "! apngasm frames.png frame0*png 1 5"
389 "display_name": "Python 3",
390 "language": "python",
398 "file_extension": ".py",
399 "mimetype": "text/x-python",
401 "nbconvert_exporter": "python",
402 "pygments_lexer": "ipython3",