Files @ 72c589cb96d1
Branch filter:

Location: light9/lightsim/lightsim.py - annotation

drewp@bigasterisk.com
looknig for a bug
45b12307c695
62bea321edbf
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
45b12307c695
# lightsim.py by Drew Perttula, 6/28/2002
from __future__ import division

version="1.01"

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()