#!/usr/bin/python

# Created 2/15/08 by Daedalus
# http://fublag.wordpress.com
# actaeus@gmail.com

import pygame
import random
import time
pygame.init

def colorshift(color,rate):
color+=random.randint(-1,1)*rate
if color>=256: color=255
if color<=-1: color=0
return color

def main(steps=None, #number of steps to run; see default for None below
width=1280, #width of window
height=1024, #height of window
full=True, #True:fullscreen, False:window
startcolor=[128,128,128], #starting color for turtle [r,g,b]
color2=[1,.5], #[0,[endcolor]] for gradient or [1,increment] for random changes to RGB components
bgcolor=[0,0,0], #background color
watch=True, #True:display process, False:just generate and store the image
seed=None, #RNG seed; see default for None below
pause=0., #amount (ms) to sleep each step; make nonzero to keep the processor happy, or zero for highest speed
save=True): #True:save image to /Images/ directory, False:just draw and discard the image

if not seed: seed=int(time.time()) #RNG seed defaults to the epoch time (as an integer)
random.seed(seed)
if not steps: steps=width*height #this default turns out to cover the image nicely. Not sure why
x,y=width/2,height/2
if full and watch:
surfer=pygame.display.set_mode((width,height),pygame.FULLSCREEN)
elif watch: surfer=pygame.display.set_mode((width,height))
else: surfer=pygame.Surface((width,height))
surfer.fill(bgcolor)
if watch: pygame.display.flip()
red,green,blue=startcolor[0],startcolor[1],startcolor[2]
step=0
while steps==0 or step<=steps:
step+=1
if step%10==0: time.sleep(pause/1000.) #sleep to let the processor breathe a bit
if color2[0]==0:
red=startcolor[0]+((color2[1][0]-startcolor[0])*step/steps)
green=startcolor[1]+((color2[1][1]-startcolor[1])*step/steps)
blue=startcolor[2]+((color2[1][2]-startcolor[2])*step/steps)
if color2[0]==1:
red,green,blue=colorshift(red,color2[1]),colorshift(green,color2[1]),colorshift(blue,color2[1])
tangle=pygame.Rect(x,y,1,1)
surfer.set_at((x,y),(red,green,blue))
if watch: pygame.display.update(tangle)
x,y=random.randint(x-1,x+1),random.randint(y-1,y+1)
if x>=width: x=0 #wraparound if edge is reached
if x<=-1: x=width-1
if y>=height: y=0
if y<=-1: y=height-1
if watch:
event=pygame.event.poll()
if event.type==pygame.KEYDOWN:
break #end script on key press

params="(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)" % (steps, width, height, full, startcolor, color2, bgcolor, True, seed, pause, False)
colorlist=[]
for char in params:
colorlist+=[ord(char)]
colorlist+=[0]*(3-len(colorlist)%3)+[0,0,0]
for dex in range(len(colorlist)/3):
surfer.set_at((0,dex),colorlist[3*dex:3*dex+3]) #encode string of parameters in the leftmost column of the image
#print params
#print colorlist
#for dex in range(len(colorlist)/3): print colorlist[3*dex:3*dex+3]

if save: pygame.image.save(surfer, "Images/gen"+str(int(time.time()))[5:11]+".png") #save with the last five digits of epoch time appended
time.sleep(3) #wait 3 seconds before closing
if watch: pygame.display.quit()

def regen(filename): #takes an image and re-draws it from the encoded parameter string
source=pygame.image.load(filename)
y=0
read=0
params=""
while True:
if source.get_at((0,y))[read]==0: break
params+=chr(source.get_at((0,y))[read])
read+=1
if read==3: read=0; y+=1
eval("main"+params)

if __name__=="__main__":
main()
#regen("Images/gen?????.png") #replace ????? with actual number from filename