annotate lightsim/lightsim.py @ 2400:9a4bc2ea264e

ui tweaks and link fix
author drewp@bigasterisk.com
date Fri, 17 May 2024 13:25:46 -0700
parents 62bea321edbf
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
45b12307c695 Initial revision
drewp
parents:
diff changeset
1 # lightsim.py by Drew Perttula, 6/28/2002
465
62bea321edbf fix illegal import
drewp@bigasterisk.com
parents: 0
diff changeset
2 from __future__ import division
0
45b12307c695 Initial revision
drewp
parents:
diff changeset
3
45b12307c695 Initial revision
drewp
parents:
diff changeset
4 version="1.01"
45b12307c695 Initial revision
drewp
parents:
diff changeset
5
45b12307c695 Initial revision
drewp
parents:
diff changeset
6 import Image, ImageTk, ImageChops,ImageEnhance
45b12307c695 Initial revision
drewp
parents:
diff changeset
7 from Tkinter import Tk,Label,Scale,DoubleVar,Frame
45b12307c695 Initial revision
drewp
parents:
diff changeset
8 import time, glob
45b12307c695 Initial revision
drewp
parents:
diff changeset
9
45b12307c695 Initial revision
drewp
parents:
diff changeset
10 class Imagemixer(Label):
45b12307c695 Initial revision
drewp
parents:
diff changeset
11 """tk widget that can load images (based on a glob pattern: each file should
45b12307c695 Initial revision
drewp
parents:
diff changeset
12 be named like 'scene.light') and displays a weighted mix of the images"""
45b12307c695 Initial revision
drewp
parents:
diff changeset
13 def __init__(self,parent,*k,**kw):
45b12307c695 Initial revision
drewp
parents:
diff changeset
14 Label.__init__(self,parent,*k,**kw)
45b12307c695 Initial revision
drewp
parents:
diff changeset
15 self.im={}
45b12307c695 Initial revision
drewp
parents:
diff changeset
16
45b12307c695 Initial revision
drewp
parents:
diff changeset
17 self.itk = ImageTk.PhotoImage(Image.new('RGB',(100,100)))
45b12307c695 Initial revision
drewp
parents:
diff changeset
18 self.config(image=self.itk)
45b12307c695 Initial revision
drewp
parents:
diff changeset
19 self.loadedscale=0
45b12307c695 Initial revision
drewp
parents:
diff changeset
20 self.amounts={}
45b12307c695 Initial revision
drewp
parents:
diff changeset
21
45b12307c695 Initial revision
drewp
parents:
diff changeset
22 def loadallimgs(self,basename,scalefactor=1.0):
45b12307c695 Initial revision
drewp
parents:
diff changeset
23 """load images from disk, scale them immediately, subtract off
45b12307c695 Initial revision
drewp
parents:
diff changeset
24 the image called 'ambient' (if present) from all other
45b12307c695 Initial revision
drewp
parents:
diff changeset
25 images. Given basename like path/to/foo, loads images with
45b12307c695 Initial revision
drewp
parents:
diff changeset
26 names like path/to/foo.light1, path/to/foo.light2, etc. The
45b12307c695 Initial revision
drewp
parents:
diff changeset
27 filename after the . is considered to be the light name
45b12307c695 Initial revision
drewp
parents:
diff changeset
28 throughout the program. """
45b12307c695 Initial revision
drewp
parents:
diff changeset
29
45b12307c695 Initial revision
drewp
parents:
diff changeset
30 if self.loadedscale==scalefactor: # already loaded at this scale
45b12307c695 Initial revision
drewp
parents:
diff changeset
31 return
45b12307c695 Initial revision
drewp
parents:
diff changeset
32
45b12307c695 Initial revision
drewp
parents:
diff changeset
33 self.im={}
45b12307c695 Initial revision
drewp
parents:
diff changeset
34 ambientimg=None
45b12307c695 Initial revision
drewp
parents:
diff changeset
35 sizenotset=1
45b12307c695 Initial revision
drewp
parents:
diff changeset
36 for fullname in glob.glob(basename+".*"):
45b12307c695 Initial revision
drewp
parents:
diff changeset
37 x=fullname[fullname.find('.')+1:]
45b12307c695 Initial revision
drewp
parents:
diff changeset
38 self.im[x]=Image.open(fullname)
45b12307c695 Initial revision
drewp
parents:
diff changeset
39 if scalefactor!=1.0:
45b12307c695 Initial revision
drewp
parents:
diff changeset
40 self.im[x]=self.im[x].resize([a*scalefactor for a in self.im[x].size])
45b12307c695 Initial revision
drewp
parents:
diff changeset
41 if x=='ambient':
45b12307c695 Initial revision
drewp
parents:
diff changeset
42 ambientimg=self.im[x]
45b12307c695 Initial revision
drewp
parents:
diff changeset
43 if sizenotset:
45b12307c695 Initial revision
drewp
parents:
diff changeset
44 self.config(width=self.im[x].size[0],height=self.im[x].size[1])
45b12307c695 Initial revision
drewp
parents:
diff changeset
45 self.itk=ImageTk.PhotoImage(Image.new('RGB',self.im[x].size))
45b12307c695 Initial revision
drewp
parents:
diff changeset
46 self.config(image=self.itk)
45b12307c695 Initial revision
drewp
parents:
diff changeset
47 sizenotset=0
45b12307c695 Initial revision
drewp
parents:
diff changeset
48
45b12307c695 Initial revision
drewp
parents:
diff changeset
49 # subtract off an image called 'ambient' from all the rest
45b12307c695 Initial revision
drewp
parents:
diff changeset
50 if ambientimg is not None:
45b12307c695 Initial revision
drewp
parents:
diff changeset
51 for k in self.im.keys():
45b12307c695 Initial revision
drewp
parents:
diff changeset
52 if k!='ambient':
45b12307c695 Initial revision
drewp
parents:
diff changeset
53 self.im[k] = ImageChops.subtract(self.im[k],ambientimg)
45b12307c695 Initial revision
drewp
parents:
diff changeset
54
45b12307c695 Initial revision
drewp
parents:
diff changeset
55 self.loadedscale=scalefactor
45b12307c695 Initial revision
drewp
parents:
diff changeset
56 self._remix() # update the image
45b12307c695 Initial revision
drewp
parents:
diff changeset
57
45b12307c695 Initial revision
drewp
parents:
diff changeset
58 def _remix(self):
45b12307c695 Initial revision
drewp
parents:
diff changeset
59 """mix all the images in self.im together according to the
45b12307c695 Initial revision
drewp
parents:
diff changeset
60 weights in self.amounts. Each of those attributes are dicts
45b12307c695 Initial revision
drewp
parents:
diff changeset
61 with the light names for keys."""
45b12307c695 Initial revision
drewp
parents:
diff changeset
62 global fpslabel
45b12307c695 Initial revision
drewp
parents:
diff changeset
63 i=None
45b12307c695 Initial revision
drewp
parents:
diff changeset
64 amounts = self.amounts
45b12307c695 Initial revision
drewp
parents:
diff changeset
65 layers=0
45b12307c695 Initial revision
drewp
parents:
diff changeset
66 start=time.time()
45b12307c695 Initial revision
drewp
parents:
diff changeset
67 for k in self.im.keys():
45b12307c695 Initial revision
drewp
parents:
diff changeset
68 scale =amounts.get(k,0)
45b12307c695 Initial revision
drewp
parents:
diff changeset
69 if scale!=0:
45b12307c695 Initial revision
drewp
parents:
diff changeset
70 layers+=1
45b12307c695 Initial revision
drewp
parents:
diff changeset
71 acc=ImageEnhance.Brightness(self.im[k]).enhance(scale) # scale the image before adding
45b12307c695 Initial revision
drewp
parents:
diff changeset
72 # acc = ImageChops.add(base,self.im[k],1/scale) ## slower!
45b12307c695 Initial revision
drewp
parents:
diff changeset
73 if i==None:
45b12307c695 Initial revision
drewp
parents:
diff changeset
74 i=acc # use first layer directly
45b12307c695 Initial revision
drewp
parents:
diff changeset
75 else:
45b12307c695 Initial revision
drewp
parents:
diff changeset
76 i=ImageChops.add(i,acc) # add subsequent layers
45b12307c695 Initial revision
drewp
parents:
diff changeset
77 dur = time.time()-start
45b12307c695 Initial revision
drewp
parents:
diff changeset
78 fps=1.0/dur
45b12307c695 Initial revision
drewp
parents:
diff changeset
79 fpslabel.config(text="%.02f fps, %.02f layers/sec"%(fps,layers/dur))
45b12307c695 Initial revision
drewp
parents:
diff changeset
80 if i is not None:
45b12307c695 Initial revision
drewp
parents:
diff changeset
81 self.itk.paste(i) # put image i in the PhotoImage
45b12307c695 Initial revision
drewp
parents:
diff changeset
82
45b12307c695 Initial revision
drewp
parents:
diff changeset
83 def setamounts(self,amounts):
45b12307c695 Initial revision
drewp
parents:
diff changeset
84 self.amounts = amounts.copy()
45b12307c695 Initial revision
drewp
parents:
diff changeset
85 self._remix()
45b12307c695 Initial revision
drewp
parents:
diff changeset
86
45b12307c695 Initial revision
drewp
parents:
diff changeset
87 def lightnames(self):
45b12307c695 Initial revision
drewp
parents:
diff changeset
88 return self.im.keys()
45b12307c695 Initial revision
drewp
parents:
diff changeset
89
45b12307c695 Initial revision
drewp
parents:
diff changeset
90 basename='room'
45b12307c695 Initial revision
drewp
parents:
diff changeset
91
45b12307c695 Initial revision
drewp
parents:
diff changeset
92 root=Tk()
45b12307c695 Initial revision
drewp
parents:
diff changeset
93
45b12307c695 Initial revision
drewp
parents:
diff changeset
94 # Imagemixer._remix accesses this label, so it needs a name
45b12307c695 Initial revision
drewp
parents:
diff changeset
95 fpslabel=Label()
45b12307c695 Initial revision
drewp
parents:
diff changeset
96 fpslabel.pack()
45b12307c695 Initial revision
drewp
parents:
diff changeset
97
45b12307c695 Initial revision
drewp
parents:
diff changeset
98 Label(root,text="Use +/- to change image scale").pack()
45b12307c695 Initial revision
drewp
parents:
diff changeset
99
45b12307c695 Initial revision
drewp
parents:
diff changeset
100 mix=Imagemixer(root,relief='raised',bd=3)
45b12307c695 Initial revision
drewp
parents:
diff changeset
101
45b12307c695 Initial revision
drewp
parents:
diff changeset
102 scalefactor=.5
45b12307c695 Initial revision
drewp
parents:
diff changeset
103 mix.loadallimgs(basename,scalefactor)
45b12307c695 Initial revision
drewp
parents:
diff changeset
104 mix.pack()
45b12307c695 Initial revision
drewp
parents:
diff changeset
105
45b12307c695 Initial revision
drewp
parents:
diff changeset
106 #
45b12307c695 Initial revision
drewp
parents:
diff changeset
107 # +/- keys should reload the images at new scales
45b12307c695 Initial revision
drewp
parents:
diff changeset
108 #
45b12307c695 Initial revision
drewp
parents:
diff changeset
109 def changescale(by=0):
45b12307c695 Initial revision
drewp
parents:
diff changeset
110 global mix,scalefactor
45b12307c695 Initial revision
drewp
parents:
diff changeset
111 scalefactor+=by
45b12307c695 Initial revision
drewp
parents:
diff changeset
112 mix.loadallimgs(basename,scalefactor)
45b12307c695 Initial revision
drewp
parents:
diff changeset
113 root.bind("<Key-plus>",lambda ev: changescale(.15))
45b12307c695 Initial revision
drewp
parents:
diff changeset
114 root.bind("<Key-minus>",lambda ev: changescale(-.15))
45b12307c695 Initial revision
drewp
parents:
diff changeset
115
45b12307c695 Initial revision
drewp
parents:
diff changeset
116 amountvars={} # each light name maps to a Tkinter.DoubleVar object which the Scale adjusts
45b12307c695 Initial revision
drewp
parents:
diff changeset
117
45b12307c695 Initial revision
drewp
parents:
diff changeset
118 def redraw(*args):
45b12307c695 Initial revision
drewp
parents:
diff changeset
119 global l,amountvars,update
45b12307c695 Initial revision
drewp
parents:
diff changeset
120 # read the value out of each Scale
45b12307c695 Initial revision
drewp
parents:
diff changeset
121 amounts = dict([(k,v.get()) for k,v in amountvars.items()])
45b12307c695 Initial revision
drewp
parents:
diff changeset
122 mix.setamounts(amounts)
45b12307c695 Initial revision
drewp
parents:
diff changeset
123
45b12307c695 Initial revision
drewp
parents:
diff changeset
124 for x in mix.lightnames():
45b12307c695 Initial revision
drewp
parents:
diff changeset
125 # the Scale sets this; the redraw() callback reads it
45b12307c695 Initial revision
drewp
parents:
diff changeset
126 amountvars[x]=DoubleVar()
45b12307c695 Initial revision
drewp
parents:
diff changeset
127
45b12307c695 Initial revision
drewp
parents:
diff changeset
128 # a new frame for each slider row
45b12307c695 Initial revision
drewp
parents:
diff changeset
129 f=Frame(root,bd=1,relief='groove')
45b12307c695 Initial revision
drewp
parents:
diff changeset
130 f.pack(fill='x',expand=1)
45b12307c695 Initial revision
drewp
parents:
diff changeset
131 # title
45b12307c695 Initial revision
drewp
parents:
diff changeset
132 Label(f,text=x,width=10,anchor='e').pack(side='left')
45b12307c695 Initial revision
drewp
parents:
diff changeset
133 # slider
45b12307c695 Initial revision
drewp
parents:
diff changeset
134 s=Scale(f,from_=0,to=1,res=.01,
45b12307c695 Initial revision
drewp
parents:
diff changeset
135 orient='horiz',
45b12307c695 Initial revision
drewp
parents:
diff changeset
136 variable=amountvars[x],command=redraw)
45b12307c695 Initial revision
drewp
parents:
diff changeset
137 s.pack(side='left',fill='x',expand=1)
45b12307c695 Initial revision
drewp
parents:
diff changeset
138 if x=='ambient': # the 'ambient' level (if present) starts at 1
45b12307c695 Initial revision
drewp
parents:
diff changeset
139 s.set(1)
45b12307c695 Initial revision
drewp
parents:
diff changeset
140
45b12307c695 Initial revision
drewp
parents:
diff changeset
141 root.mainloop()
45b12307c695 Initial revision
drewp
parents:
diff changeset
142