{ "cells": [ { "cell_type": "code", "execution_count": 27, "metadata": { "collapsed": true }, "outputs": [], "source": [ "import time\n", "import re\n", "from IPython.display import clear_output\n", "from PIL import Image, ImageDraw, ImageColor, ImageFont" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": true }, "outputs": [], "source": [ "WIDTH = 80\n", "HEIGHT = 8" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": true }, "outputs": [], "source": [ "def new_grid(w=WIDTH, h=HEIGHT):\n", " return ['.' * w for r in range(1, h+1)]" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": true }, "outputs": [], "source": [ "def print_grid(grid, md=False, suppress_dots=False):\n", " if md:\n", " print('```')\n", " for row in grid:\n", " if suppress_dots:\n", " print(re.sub(r'\\.', ' ', row))\n", " else:\n", " print(row)\n", " if md:\n", " print('```')" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": true }, "outputs": [], "source": [ "def top(grid, l, r):\n", " new_segment = ''\n", " for i in range(l-1, r):\n", " if grid[0][i] == '.':\n", " new_segment += '*'\n", " else:\n", " new_segment += '.'\n", " grid[0] = grid[0][:l-1] + new_segment + grid[0][r:]\n", " return grid" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": true }, "outputs": [], "source": [ "def left(grid, t, b):\n", " for i in range(t-1, b):\n", " if grid[i][0] == '.':\n", " grid[i] = '*' + grid[i][1:]\n", " else:\n", " grid[i] = '.' + grid[i][1:]\n", " return grid" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "collapsed": true }, "outputs": [], "source": [ "def rotate_column(grid, c, raw_n):\n", " n = raw_n % len(grid)\n", " col = [row[c-1] for row in grid]\n", " new_col = col[-n:] + col[:-n]\n", " for i in range(len(grid)):\n", " grid[i] = grid[i][:c-1] + new_col[i] + grid[i][c:]\n", " return grid" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "collapsed": true }, "outputs": [], "source": [ "def rotate_row(grid, r, raw_n):\n", " n = raw_n % len(grid[0])\n", " grid[r-1] = grid[r-1][-n:] + grid[r-1][:-n]\n", " return grid" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "collapsed": true }, "outputs": [], "source": [ "command_dispatch = {'left': left, 'top': top,\n", " 'rotate row': rotate_row,\n", " 'rotate column': rotate_column}" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "collapsed": true }, "outputs": [], "source": [ "def parse(command):\n", " cmd, a, b = command.rsplit(maxsplit=2)\n", " return cmd, int(a), int(b) " ] }, { "cell_type": "code", "execution_count": 63, "metadata": { "collapsed": true }, "outputs": [], "source": [ "def interpret(commands, grid=None, w=WIDTH, h=HEIGHT, \n", " show_each_step=False, md=False, overprint=False):\n", " if grid is None:\n", " grid = new_grid(w, h)\n", " frames = []\n", " for cn, c in enumerate(commands):\n", " cmd, a, b = parse(c)\n", " if cmd in command_dispatch:\n", " command_dispatch[cmd](grid, a, b)\n", " else:\n", " raise ValueError('Unknown command')\n", " if show_each_step:\n", " frames += [draw_frame(grid, c, cn)]\n", " if show_each_step: \n", " print('Final')\n", " print_grid(grid, md=md)\n", " frames[0].save('frames.gif', save_all=True, append_images=frames[1:], duration=200)\n", " return grid" ] }, { "cell_type": "code", "execution_count": 44, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "...****..............*...................*.....*..............*.................\n", "......*..............*...................***..**..............*.................\n", "......*.*****.*****.****.*****..****.....*.*.***.*****.*****.****.*****..****...\n", "......*.....*.*...*..*.......*..*........*..**.*.....*.*...*..*.......*..*......\n", "......*.*****.*...*..*...*****..*........*..*..*.*****.*...*..*...*****..*......\n", "......*.*...*.*...*..*...*...*..*........*.....*.*...*.*...*..*...*...*..*......\n", "...*..*.*..**.*...*..**..*..**..*........*.....*.*..**.*...*..**..*..**..*......\n", "....**...**.*.*...*...**..**.*..*........*.....*..**.*.*...*...**..**.*..*......\n" ] } ], "source": [ "cmds = [c.strip() for c in open('05-pixels.txt').readlines()]\n", "g = interpret(cmds)\n", "print_grid(g)" ] }, { "cell_type": "code", "execution_count": 60, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(209, 17)\n" ] } ], "source": [ "im = Image.new('RGBA', (WIDTH * 10, HEIGHT * 10 + 21))\n", "\n", "# make a blank image for the text, initialized to transparent text color\n", "# txt = Image.new('RGBA', im.size, (255,255,255,0))\n", "txt = Image.new('RGBA', im.size, (0, 0, 0, 0))\n", "\n", "# get a font\n", "fnt = ImageFont.truetype('Pillow/Tests/fonts/FreeMono.ttf', 18)\n", "# get a drawing context\n", "d = ImageDraw.Draw(txt)\n", "\n", "# draw text, full opacity\n", "d.text((1,1), \"Command description\", font=fnt, fill='black')\n", "\n", "print(d.textsize(\"Command description\", fnt))\n", "\n", "\n", "draw = ImageDraw.Draw(im)\n", "for (r, row) in enumerate(g):\n", " for (c, cell) in enumerate(row):\n", " rx = c * 10\n", " ry = r * 10 + 20\n", " if cell == '*':\n", " fill_colour = 'lime'\n", " else:\n", " fill_colour = 'black'\n", " draw.rectangle([rx, ry, rx + 10, ry + 10], fill=fill_colour, outline='orange')\n", " \n", "# draw.line((0, 0) + im.size, fill=128)\n", "# draw.line((0, im.size[1], im.size[0], 0), fill=128)\n", "\n", "out = Image.alpha_composite(im, txt)\n", "out.save('test.png', 'PNG')\n", "\n", "del draw\n", "\n" ] }, { "cell_type": "code", "execution_count": 76, "metadata": { "collapsed": true }, "outputs": [], "source": [ "def draw_frame(grid, command, frame_number, gif=True):\n", " im = Image.new('RGBA', (WIDTH * 10, HEIGHT * 10 + 21))\n", "\n", " # make a blank image for the text, initialized to transparent text color\n", " if gif:\n", " txt = Image.new('RGBA', im.size, (255,255,255,0))\n", " else:\n", " txt = Image.new('RGBA', im.size, (0, 0, 0, 0)) # use this line rather than line above for animated png\n", "\n", " # get a font\n", " fnt = ImageFont.truetype('Pillow/Tests/fonts/FreeMono.ttf', 18)\n", " # get a drawing context\n", " d = ImageDraw.Draw(txt)\n", "\n", " # draw text, full opacity\n", " if gif:\n", " d.text((1,1), command, font=fnt, fill='white')\n", " else:\n", " d.text((1,1), command, font=fnt, fill='black') # use this line rather than line above for animated png\n", "\n", " draw = ImageDraw.Draw(im)\n", " for (r, row) in enumerate(grid):\n", " for (c, cell) in enumerate(row):\n", " rx = c * 10\n", " ry = r * 10 + 20\n", " if cell == '*':\n", " fill_colour = 'lime'\n", " else:\n", " fill_colour = 'black'\n", " draw.rectangle([rx, ry, rx + 10, ry + 10], fill=fill_colour, outline=128)\n", "\n", " # draw.line((0, 0) + im.size, fill=128)\n", " # draw.line((0, im.size[1], im.size[0], 0), fill=128)\n", "\n", " out = Image.alpha_composite(im, txt)\n", " if not gif:\n", " out.save('frame{:04}.png'.format(frame_number), 'PNG') # uncomment here to save animated png frames\n", "\n", " del draw\n", " \n", " return out" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['...****..............*...................*.....*..............*.................',\n", " '......*..............*...................***..**..............*.................',\n", " '......*.*****.*****.****.*****..****.....*.*.***.*****.*****.****.*****..****...',\n", " '......*.....*.*...*..*.......*..*........*..**.*.....*.*...*..*.......*..*......',\n", " '......*.*****.*...*..*...*****..*........*..*..*.*****.*...*..*...*****..*......',\n", " '......*.*...*.*...*..*...*...*..*........*.....*.*...*.*...*..*...*...*..*......',\n", " '...*..*.*..**.*...*..**..*..**..*........*.....*.*..**.*...*..**..*..**..*......',\n", " '....**...**.*.*...*...**..**.*..*........*.....*..**.*.*...*...**..**.*..*......']" ] }, "execution_count": 24, "metadata": {}, "output_type": "execute_result" } ], "source": [ "g" ] }, { "cell_type": "code", "execution_count": 77, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Final\n", "...****..............*...................*.....*..............*.................\n", "......*..............*...................***..**..............*.................\n", "......*.*****.*****.****.*****..****.....*.*.***.*****.*****.****.*****..****...\n", "......*.....*.*...*..*.......*..*........*..**.*.....*.*...*..*.......*..*......\n", "......*.*****.*...*..*...*****..*........*..*..*.*****.*...*..*...*****..*......\n", "......*.*...*.*...*..*...*...*..*........*.....*.*...*.*...*..*...*...*..*......\n", "...*..*.*..**.*...*..**..*..**..*........*.....*.*..**.*...*..**..*..**..*......\n", "....**...**.*.*...*...**..**.*..*........*.....*..**.*.*...*...**..**.*..*......\n", "...****..............*...................*.....*..............*.................\n", "......*..............*...................***..**..............*.................\n", "......*.*****.*****.****.*****..****.....*.*.***.*****.*****.****.*****..****...\n", "......*.....*.*...*..*.......*..*........*..**.*.....*.*...*..*.......*..*......\n", "......*.*****.*...*..*...*****..*........*..*..*.*****.*...*..*...*****..*......\n", "......*.*...*.*...*..*...*...*..*........*.....*.*...*.*...*..*...*...*..*......\n", "...*..*.*..**.*...*..**..*..**..*........*.....*.*..**.*...*..**..*..**..*......\n", "....**...**.*.*...*...**..**.*..*........*.....*..**.*.*...*...**..**.*..*......\n" ] } ], "source": [ "cmds = [c.strip() for c in open('05-pixels.txt').readlines()]\n", "g = interpret(cmds, show_each_step=True)\n", "print_grid(g)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Create animated png." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "! apngasm frames.png frame0*png 1 5" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.5.2+" } }, "nbformat": 4, "nbformat_minor": 2 }