Mercurial > code > home > repos > light9
diff lightsim/lightsim.py @ 0:45b12307c695
Initial revision
author | drewp |
---|---|
date | Wed, 03 Jul 2002 09:37:57 +0000 |
parents | |
children | 62bea321edbf |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lightsim/lightsim.py Wed Jul 03 09:37:57 2002 +0000 @@ -0,0 +1,142 @@ +# lightsim.py by Drew Perttula, 6/28/2002 + +version="1.01" + +from __future__ import division +import Image, ImageTk, ImageChops,ImageEnhance +from Tkinter import Tk,Label,Scale,DoubleVar,Frame +import time, glob + +class Imagemixer(Label): + """tk widget that can load images (based on a glob pattern: each file should + be named like 'scene.light') and displays a weighted mix of the images""" + def __init__(self,parent,*k,**kw): + Label.__init__(self,parent,*k,**kw) + self.im={} + + self.itk = ImageTk.PhotoImage(Image.new('RGB',(100,100))) + self.config(image=self.itk) + self.loadedscale=0 + self.amounts={} + + def loadallimgs(self,basename,scalefactor=1.0): + """load images from disk, scale them immediately, subtract off + the image called 'ambient' (if present) from all other + images. Given basename like path/to/foo, loads images with + names like path/to/foo.light1, path/to/foo.light2, etc. The + filename after the . is considered to be the light name + throughout the program. """ + + if self.loadedscale==scalefactor: # already loaded at this scale + return + + self.im={} + ambientimg=None + sizenotset=1 + for fullname in glob.glob(basename+".*"): + x=fullname[fullname.find('.')+1:] + self.im[x]=Image.open(fullname) + if scalefactor!=1.0: + self.im[x]=self.im[x].resize([a*scalefactor for a in self.im[x].size]) + if x=='ambient': + ambientimg=self.im[x] + if sizenotset: + self.config(width=self.im[x].size[0],height=self.im[x].size[1]) + self.itk=ImageTk.PhotoImage(Image.new('RGB',self.im[x].size)) + self.config(image=self.itk) + sizenotset=0 + + # subtract off an image called 'ambient' from all the rest + if ambientimg is not None: + for k in self.im.keys(): + if k!='ambient': + self.im[k] = ImageChops.subtract(self.im[k],ambientimg) + + self.loadedscale=scalefactor + self._remix() # update the image + + def _remix(self): + """mix all the images in self.im together according to the + weights in self.amounts. Each of those attributes are dicts + with the light names for keys.""" + global fpslabel + i=None + amounts = self.amounts + layers=0 + start=time.time() + for k in self.im.keys(): + scale =amounts.get(k,0) + if scale!=0: + layers+=1 + acc=ImageEnhance.Brightness(self.im[k]).enhance(scale) # scale the image before adding + # acc = ImageChops.add(base,self.im[k],1/scale) ## slower! + if i==None: + i=acc # use first layer directly + else: + i=ImageChops.add(i,acc) # add subsequent layers + dur = time.time()-start + fps=1.0/dur + fpslabel.config(text="%.02f fps, %.02f layers/sec"%(fps,layers/dur)) + if i is not None: + self.itk.paste(i) # put image i in the PhotoImage + + def setamounts(self,amounts): + self.amounts = amounts.copy() + self._remix() + + def lightnames(self): + return self.im.keys() + +basename='room' + +root=Tk() + +# Imagemixer._remix accesses this label, so it needs a name +fpslabel=Label() +fpslabel.pack() + +Label(root,text="Use +/- to change image scale").pack() + +mix=Imagemixer(root,relief='raised',bd=3) + +scalefactor=.5 +mix.loadallimgs(basename,scalefactor) +mix.pack() + +# +# +/- keys should reload the images at new scales +# +def changescale(by=0): + global mix,scalefactor + scalefactor+=by + mix.loadallimgs(basename,scalefactor) +root.bind("<Key-plus>",lambda ev: changescale(.15)) +root.bind("<Key-minus>",lambda ev: changescale(-.15)) + +amountvars={} # each light name maps to a Tkinter.DoubleVar object which the Scale adjusts + +def redraw(*args): + global l,amountvars,update + # read the value out of each Scale + amounts = dict([(k,v.get()) for k,v in amountvars.items()]) + mix.setamounts(amounts) + +for x in mix.lightnames(): + # the Scale sets this; the redraw() callback reads it + amountvars[x]=DoubleVar() + + # a new frame for each slider row + f=Frame(root,bd=1,relief='groove') + f.pack(fill='x',expand=1) + # title + Label(f,text=x,width=10,anchor='e').pack(side='left') + # slider + s=Scale(f,from_=0,to=1,res=.01, + orient='horiz', + variable=amountvars[x],command=redraw) + s.pack(side='left',fill='x',expand=1) + if x=='ambient': # the 'ambient' level (if present) starts at 1 + s.set(1) + +root.mainloop() +