sml - trees - psdraw - python - download

the python script below uses the python image library to render the landscape image seen to the left.  currently, it's completely static. hopefully, this will soon change.  the script can be downloaded here.


11.2002

 

 


import Image, ImageDraw, colorsys, random, math

def btw(rgb1, rgb2, a):
h1, s1, v1 = rgb1[0], rgb1[1], rgb1[2]
h2, s2, v2 = rgb2[0], rgb2[1], rgb2[2]
h3, s3, v3 = h2+a*(h1-h2), s2+a*(s1-s2), v2+a*(v1-v2)
r3, g3, b3 = colorsys.hsv_to_rgb(h3, s3, v3)
return (r3*255, g3*255, b3*255)

def gradRect(xy, color1, color2):
# creates rectangle with gradient fill starting
# args: xy - 4-tuple to position rect
# color 1,2 - start, end fill colors
x1, y1, x2, y2 = xy[0], xy[1], xy[2], xy[3]
dtemp = ImageDraw.Draw(im)
for n in range(y1, y2):
R = color1[0]+(n-y1)*(color2[0]-color1[0])/(y2-y1)
G = color1[1]+(n-y1)*(color2[1]-color1[1])/(y2-y1)
B = color1[2]+(n-y1)*(color2[2]-color1[2])/(y2-y1)
dtemp.line([x1, n, x2, n], fill=(R,G,B))
del dtemp

def trunk(xy,width,color):
#where xy is a 4-tuple giving location of tree
#width dictates branch width, and n = # times branching is done
def itrunkhelper(xy,width,angle,color,n):
print n
dtemp = ImageDraw.Draw(im)
if n<0: print "trunk done!"
else:
a = (xy[2]-xy[0])/2
b = 3*(xy[3]-xy[1])/8
c = (xy[0]+a, xy[1]+b)
dtemp.pieslice(xy,angle-width/2,angle+width/2,fill=color)
xoff=1/6*(xy[3]-xy[1])*math.cos(angle)
yoff=1/6*(xy[3]-xy[1])/math.cos(angle)
xyr=(c[0]-xoff, c[1]-yoff, c[0]+3*xoff, c[1]+yoff)
xyl=(c[0]-3*xoff, c[1]-yoff, c[0]+xoff, c[1]+yoff)
print c, xoff, yoff
print xyr, xyl
itrunkhelper(xyr,width/2,angle*4/3,color,n-1)
itrunkhelper(xyl,width/2,angle*2/3,color,n-1)
del dtemp
itrunkhelper(xy,width,90,color,5)

def tree(xy):
import random
# locate center of leaves
a = (xy[2]-xy[0])/2
b = 3*(xy[3]-xy[1])/8
c = (xy[0]+a, xy[1]+b)
color1 = [.2,.9,.7]
color2 = [.35,.8,.5]
trunkColor = (120,50,0)
leafSize = a/3
dtemp = ImageDraw.Draw(im)
trunk(xy,15,trunkColor)
for i in range(1, max(a,b)*3):
x = random.randrange(xy[0], xy[2])
ymin = round(c[1]-(b**2 - (b*(x-c[0])/a)**2)**0.5)
ymax = round(c[1]+(b**2 - (b*(x-c[0])/a)**2)**0.5)
# print ymin, ymax
if ymin == ymax :
y = random.randrange(ymin-1, ymax+1)
else:
y = random.randrange(ymin, ymax)
alpha = random.random()
rgbNew = btw(color1, color2, alpha)


dtemp.ellipse([x-leafSize/2, y-leafSize/2, x+leafSize/2, y+leafSize/2], fill=rgbNew)
del dtemp

# BACKGROUND
im = Image.new("RGB", (1000, 1000),(255,255,255))
# antialiased later
d = ImageDraw.Draw(im)
# canvas cutoff dimensions
xc = im.size[0]
yc = im.size[1]

# ground
gndColor = (128,210,136)
gndHeight = 3*yc/5
gndDepth = 2*yc/5
gradRect([0, gndHeight, xc, gndHeight+gndDepth], gndColor, (230, 255, 230))

# sky
skyColor = (136, 128, 210)
skyHeight = 0
skyDepth = 3*yc/5
gradRect([0, skyHeight, xc, skyHeight+skyDepth], skyColor, (230, 230, 255))

imtemp = im.copy()
d = ImageDraw.Draw(imtemp)

# cloud front
d.ellipse([5*xc/16, yc/32, 8*xc/16, 5*yc/32], fill=(255,255,255))
d.ellipse([3*xc/16, 3*yc/32, 6*xc/16, 5*yc/32], fill=(255,255,255))
d.ellipse([xc/32, 4.25*yc/32, 17*xc/32, 5*yc/32], fill=(255,255,255))
im = Image.blend(im, imtemp, 0.25)

# cloud back
d.ellipse([12*xc/16, yc/32, 15*xc/16, 2*yc/16], fill=(255,255,255))
d.ellipse([10.5*xc/16, 2*yc/32, 13*xc/16, 2*yc/16], fill=(255,255,255))
d.ellipse([9*xc/16, 3.25*yc/32, 31*xc/32, 2*yc/16], fill=(255,255,255))
im = Image.blend(im, imtemp, 0.25)

# FOREGROUND
d = ImageDraw.Draw(im)
tree([xc/16, 3*yc/8, 5*xc/16, 5*yc/8])
tree([9*xc/16, 5*yc/16, 15*xc/16, 11*yc/16])
treePos = (xc/4, yc/4, 3*xc/4, 3*yc/4)
tree(treePos)
 
del d
im = im.resize((400,400), Image.ANTIALIAS)
im.show()

 
© 2002 sml