maze_gif.py
'''Maze Image Class.
Coder@Sonnack.com
September 16, 2014
'''
from sys import argv
from PIL import Image, ImageDraw
import colors
from maze_obj import MazeObject
HorzSpace = 20
VertSpace = 20
WallColor = colors.ixColorBlack
GridColor = colors.ixColorLightBlue
ImagePalette = []
for c in colors.ColorPalette:
ImagePalette.extend(c)
class MazeImage (object):
'''|
Maze Image class.
properties:
mz - Maze object
im - Image object
draw - ImageDraw object
pixels - Pixel dimensions of image
pmin,pmax - ULC,LRC of Maze plot area
p0,p1 - ULC,LRC of current cell
methods:
draw_maze ()
show ()
save (fn, mode='GIF')
set_current_cell (row, col) - required first before using paint methods
paint_cell (color) - set cell color
paint_north_wall () - set cell north wall
paint_east_wall () - set cell east wall
paint_south_wall () - set cell south wall
paint_west_wall () - set cell west wall
str(obj) - properties string
repr(obj) - JSON-like string
'''
def __init__ (self, mz):
'''Create new Maze Image instance. NOTE: x=cols, y=rows!'''
self.mz = mz
self.pixels = (HorzSpace * (self.mz.dims[1]+2), VertSpace * (self.mz.dims[0]+2))
self.pmin = (HorzSpace, VertSpace)
self.pmax = (self.pixels[0] - HorzSpace, self.pixels[1] - VertSpace)
self.p0 = (self.pmin[0] , self.pmin[1])
self.p1 = (self.pmin[0]+HorzSpace, self.pmin[1]+VertSpace)
self.im = Image.new('P', self.pixels, colors.ixColorWhite)
self.im.putpalette(ImagePalette)
self.draw = ImageDraw.Draw(self.im)
self.draw.rectangle((0,0)+(self.pixels[0]-1,self.pixels[1]-1), outline=colors.ixColorBlack)
self.draw.rectangle((1,1)+(self.pixels[0]-2,self.pixels[1]-2), outline=colors.ixColorGray100)
self.draw.rectangle((2,2)+(self.pixels[0]-3,self.pixels[1]-3), outline=colors.ixColorGray200)
for ix in range(1, self.mz.dims[1]):
pp = ix * HorzSpace
self.draw.line([(self.pmin[0]+pp, self.pmin[1]), (self.pmin[0]+pp, self.pmax[1])], fill=GridColor)
for ix in range(1, self.mz.dims[0]):
pp = ix * VertSpace
self.draw.line([(self.pmin[0], self.pmin[1]+pp), (self.pmax[0], self.pmin[1]+pp)], fill=GridColor)
for row in range(1, self.mz.dims[0]+2):
py = row * VertSpace
for col in range(1, self.mz.dims[1]+2):
px = col * HorzSpace
self.draw.rectangle((px-1,py-1)+(px+1,py), fill=colors.ixColorBlack, outline=colors.ixColorBlack)
self.draw.line([(self.pmin[0], self.pmin[1]), (self.pmax[0], self.pmin[1])], fill=colors.ixColorDarkBlue, width=2)
self.draw.line([(self.pmin[0], self.pmax[1]), (self.pmax[0], self.pmax[1])], fill=colors.ixColorDarkBlue, width=2)
self.draw.line([(self.pmin[0], self.pmin[1]), (self.pmin[0], self.pmax[1])], fill=colors.ixColorDarkBlue, width=2)
self.draw.line([(self.pmax[0], self.pmin[1]), (self.pmax[0], self.pmax[1])], fill=colors.ixColorDarkBlue, width=2)
def draw_maze (self):
'''Draw a maze.'''
for row in range(self.mz.dims[0]):
for col in range(self.mz.dims[1]):
v = self.mz.cell(row, col)
if 0 < v:
self.set_current_cell(row, col)
self.paint_cell(v)
for row in range(self.mz.dims[0]):
for col in range(self.mz.dims[1]):
self.set_current_cell(row, col)
if self.mz.wall_n(row, col):
self.paint_north_wall()
if self.mz.wall_w(row, col):
self.paint_west_wall()
if self.mz.wall_e(row, col):
self.paint_east_wall()
for col in range(self.mz.dims[1]):
self.set_current_cell(row, col)
if self.mz.wall_s(row, col):
self.paint_south_wall()
def set_current_cell (self, row, col):
'''Set current cell for drawing operations.'''
if (row < 0) or (self.mz.dims[0] <= row):
raise Exception("Row is out of bounds!")
if (col < 0) or (self.mz.dims[1] <= col):
raise Exception("Col is out of bounds!")
cx = self.pmin[0] + (col * HorzSpace)
cy = self.pmin[1] + (row * VertSpace)
self.p0 = (cx,cy)
self.p1 = (cx+HorzSpace, cy+VertSpace)
def paint_cell (self, color):
self.draw.rectangle([self.p0, self.p1], fill=color, outline=colors.ixColorBlack)
def paint_north_wall (self):
'''Draw north wall in current cell.'''
self.draw.line([(self.p0[0], self.p0[1]), (self.p1[0], self.p0[1])], fill=WallColor, width=2)
def paint_south_wall (self):
'''Draw south wall in current cell.'''
self.draw.line([(self.p0[0], self.p1[1]), (self.p1[0], self.p1[1])], fill=WallColor, width=2)
def paint_west_wall (self):
'''Draw west wall in current cell.'''
self.draw.line([(self.p0[0], self.p0[1]), (self.p0[0], self.p1[1])], fill=WallColor, width=2)
def paint_east_wall (self):
'''Draw east wall in current cell.'''
self.draw.line([(self.p1[0], self.p0[1]), (self.p1[0], self.p1[1])], fill=WallColor, width=2)
def show (self):
self.im.show()
return self
def save (self, fn, mode='GIF'):
self.im.save(fn, mode)
return self
def __str__ (self):
s = '%s (%d,%d) %s'
t = (self.im.format, self.im.size[0], self.im.size[1], self.im.mode)
return s % t
def __repr__ (self):
s = '{MazeImage:{format:"%s", size:%s, mode:"%s", addr:%x}}'
t = (self.im.format, str(self.im.size), self.im.mode, self.__hash__())
return s % t
if __name__ == '__main__':
print('autorun: %s' % argv[0])
mz = MazeObject(12, 16)
mi = MazeImage(mz)
mi.set_current_cell(1,0)
mi.paint_north_wall()
mi.paint_west_wall()
mi.set_current_cell(1,1)
mi.paint_cell(colors.ixColorLightRed)
mi.paint_north_wall()
mi.paint_east_wall()
mi.paint_south_wall()
mi.paint_west_wall()
mi.set_current_cell(1,2)
mi.paint_north_wall()
mi.set_current_cell(0,2)
mi.paint_north_wall()
mi.paint_west_wall()
mi.set_current_cell(2,2)
mi.paint_west_wall()
mi.show()
mi.save('maze_gif.gif')
'''eof'''