eval() in schleifen
Verfasst: Freitag 26. Dezember 2008, 15:23
Hallo
Ich habe ein Programm geschrieben, dass aus trigonometrische Funktionen, mit dem Modul PIL, ein Bild aus Spektralfarben erzeugt. Dazu muss für jeden einzelnen Pixel der Funktionswert errechnen werden, was im Prinzip kein Problem ist. Jedoch will ich gerne, dass man den Funktionsterm im Programm eingeben kann und genau das ist das Problem: die Funktion eval() ist einfach zu langsam. Bei einer Auflösung von 400 * 400 Pixeln muss eval() schon 160.000 mal verwendet werden. Gibt es eine Möglichkeit nur einmal eval() anzuwenden und dann damit weiter zu arbeiten, schließlich verändert sich der Funktionsterm nicht.
hier das Programm:
Ich habe ein Programm geschrieben, dass aus trigonometrische Funktionen, mit dem Modul PIL, ein Bild aus Spektralfarben erzeugt. Dazu muss für jeden einzelnen Pixel der Funktionswert errechnen werden, was im Prinzip kein Problem ist. Jedoch will ich gerne, dass man den Funktionsterm im Programm eingeben kann und genau das ist das Problem: die Funktion eval() ist einfach zu langsam. Bei einer Auflösung von 400 * 400 Pixeln muss eval() schon 160.000 mal verwendet werden. Gibt es eine Möglichkeit nur einmal eval() anzuwenden und dann damit weiter zu arbeiten, schließlich verändert sich der Funktionsterm nicht.
hier das Programm:
Code: Alles auswählen
# -*- coding: cp1252 -*-
from Tkinter import *
import Tix
from math import *
from time import *
from PIL import Image
class Funktionsplotter:
def __init__(self,root):
root.resizable(False,False)
root.title("Funktionsplotter2.0")
self.setTerm("cos(radians(sqrt(x**2+z**2)))")
self.setXStart(-360)
self.setXEnde(360)
self.setZStart(-360)
self.setZEnde(360)
self.setBreite(400)
self.setHoehe(400)
self.__addWIDGETS()
self.funktionsTerm.insert(0,self.getTerm())
self.xStart.insert(0,self.getXStart())
self.xEnde.insert(0,self.getXEnde())
self.zStart.insert(0,self.getZStart())
self.zEnde.insert(0,self.getZEnde())
self.breite.insert(0,self.getBreite())
self.hoehe.insert(0,self.getHoehe())
#SET METHODEN
def setTerm(self,pTerm):
self.__zTerm=pTerm
def setXStart(self,pXStart):
self.__zXStart=int(pXStart)
def setXEnde(self,pXEnde):
if self.getXStart()<int(pXEnde):
self.__zXEnde=int(pXEnde)
def setZStart(self,pZStart):
self.__zZStart=int(pZStart)
def setZEnde(self,pZEnde):
if self.getZStart()<int(pZEnde):
self.__zZEnde=int(pZEnde)
def setBreite(self,pBreite):
self.__zBreite=int(pBreite)
def setHoehe(self,pHoehe):
self.__zHoehe=int(pHoehe)
#GET METHODEN
def getTerm(self):
return self.__zTerm
def getXStart(self):
return self.__zXStart
def getXEnde(self):
return self.__zXEnde
def getZStart(self):
return self.__zZStart
def getZEnde(self):
return self.__zZEnde
def getBreite(self):
return self.__zBreite
def getHoehe(self):
return self.__zHoehe
def getXIntervall(self):
lTemp=float((self.getXEnde()-self.getXStart()))/float(self.getBreite())
return lTemp
def getZIntervall(self):
lTemp=float((self.getZEnde()-self.getZStart()))/float(self.getHoehe())
return lTemp
def __addWIDGETS(self):
distanz =2#padx,pady für frame
distanz2=1#für restliche komponenten
self.frame=Label(root)
self.frame.grid(column=0,row=1,padx=2,sticky=N+E+S+W)
#Labels + Frames
funktionstermFrame=LabelFrame(self.frame,text=" Funktionsterm ")
funktionstermFrame.grid(column=0,row=0,columnspan=2,padx=distanz,pady=distanz,sticky=N+E+S+W)
label=Label(funktionstermFrame,text="f(x,z)=")
label.grid(column=0,row=0,padx=distanz2,pady=distanz2)
wertebereichFrame=LabelFrame(self.frame,text=" Wertebereich in cm ")
wertebereichFrame.grid(column=0,row=1,padx=distanz,pady=distanz,sticky=N+E+S+W)
label=Label(wertebereichFrame,text=" X: von ")
label.grid(column=0,row=0,padx=distanz2,pady=distanz2)
label=Label(wertebereichFrame,text=" Z: von ")
label.grid(column=0,row=1,padx=distanz2,pady=distanz2)
label=Label(wertebereichFrame,text=" bis ")
label.grid(column=2,row=0,padx=distanz2,pady=distanz2)
label=Label(wertebereichFrame,text=" bis ")
label.grid(column=2,row=1,padx=distanz2,pady=distanz2)
aufloesungFrame=LabelFrame(self.frame,text=" Auflösung in Pixeln ")
aufloesungFrame.grid(column=1,row=1,padx=distanz,pady=distanz,sticky=N+E+S+W)
label=Label(aufloesungFrame,text=" Breite: ")
label.grid(column=0,row=0,padx=distanz2,pady=distanz2)
label=Label(aufloesungFrame,text=" Höhe: ")
label.grid(column=0,row=1,padx=distanz2,pady=distanz2)
#Entrys
self.funktionsTerm=Entry(funktionstermFrame,width=41)
self.funktionsTerm.grid(column=1,row=0,padx=distanz2,pady=distanz2)
self.xStart=Entry(wertebereichFrame,width=7)
self.xStart.grid(column=1,row=0,padx=distanz2,pady=distanz2)
self.xEnde =Entry(wertebereichFrame,width=7)
self.xEnde.grid(column=3,row=0,padx=distanz2,pady=distanz2)
self.zStart=Entry(wertebereichFrame,width=7)
self.zStart.grid(column=1,row=1,padx=distanz2,pady=distanz2)
self.zEnde =Entry(wertebereichFrame,width=7)
self.zEnde.grid(column=3,row=1,padx=distanz2,pady=distanz2)
self.breite=Entry(aufloesungFrame,width=7)
self.breite.grid(column=1,row=0,padx=distanz2,pady=distanz2)
self.hoehe=Entry(aufloesungFrame,width=7)
self.hoehe.grid(column=1,row=1,padx=distanz2,pady=distanz2)
#Buttons
self.exportButton=Button(self.frame,text="Exportieren",command=self.export)
self.exportButton.grid(column=0,row=3,columnspan=2,padx=distanz2,pady=distanz2,sticky=N+E+S+W)
def export(self):
self.exportButton.config(state=DISABLED)
self.ladeBalken=Tix.Meter(self.frame,relief=FLAT,width=304,height=5,bd=0,fillcolor="blue")
self.ladeBalken.grid(column=0,row=4,columnspan=2,sticky=N+E+S+W)
start=time()
self.setTerm(self.funktionsTerm.get())
self.setXStart(self.xStart.get())
self.setXEnde(self.xEnde.get())
self.setZStart(self.zStart.get())
self.setZEnde(self.zEnde.get())
self.setBreite(self.breite.get())
self.setHoehe(self.hoehe.get())
self.pic = Image.new("RGB", (self.getBreite(),self.getHoehe()))
self.xz2rgb()
self.pic.save("f(x,z).jpg", "JPEG")
ende=time()
self.ladeBalken.destroy()
self.exportButton.config(state=NORMAL)
print "Exportdauer:",round(ende-start,5),"[sec]\nfür",self.getBreite()*self.getHoehe(),"Pixel"
def xz2rgb(self):
for h in range(self.getBreite()):
x=self.getXStart()+h*self.getXIntervall()
prozent=(float(100)/self.getBreite()*h+1)/100
self.ladeBalken.config(value=prozent)
self.ladeBalken.update()
for v in range(self.getHoehe()):
z=self.getZStart()+v*self.getZIntervall()
y=eval(self.getTerm())
self.pic.putpixel((h,v),(self.getFarbe(y)))
def getFarbe(self,y):
i=0.00196
x=int(y/i)
if 255<x<=510:
r=255
g=510-x
b=0
elif 0<x<=255:
r=x
g=255
b=0
elif -255<x<=0:
r=0
g=255
b=abs(x)
elif -510<=x<=-255:
r=0
g=510+x
b=255
else:
r=0
g=0
b=0
return r,g,b
root=Tix.Tk()
funktionsplotter=Funktionsplotter(root)
root.mainloop()