#!/usr/bin/python from OpenGL.GL import * from OpenGL.GLUT import * from OpenGL.GLU import * from gobject.option import OptionGroup, OptionParser, make_option, OptionError from gobject import GError import math import random import os import string import time import sys import gtk import gc class textureLoader: def __init__(self, filename, idl, buffersize, tilesize, tilequality): print filename self.buffersize = buffersize self.tilesize = tilesize self.tilequality = tilequality self.filename = filename self.closed = False self.resize = False self.loaded = 0 self.f=open(filename,"r") self.pixbuf = gtk.gdk.PixbufLoader() self.pixbuf_new = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB,True,8,self.tilesize,self.tilesize) self.pixbuf_new.fill(0x00000000) def next_chunk(self): if not self.closed: tmpdta = self.f.read(self.buffersize) if tmpdta == "": self.pixbuf.close() self.f.close() self.closed = True self.pixbuf_old = self.pixbuf.get_pixbuf() self.pixbuf_old=self.pixbuf_old.add_alpha(False, "a","a","a") ix = self.pixbuf_old.get_width() iy = self.pixbuf_old.get_height() if ix > iy: self.nix = self.tilesize-4 self.niy = (float(self.nix) / float(ix)) * float(iy) else: self.niy = self.tilesize-4 self.nix = (float(self.niy) / float(iy)) * float(ix) return True else: self.pixbuf.write(tmpdta) return True elif not self.resize: try: self.pixbuf_old = self.pixbuf_old.scale_simple(self.nix,self.niy,self.tilequality) #GPU RESCALING #self.pixbuf_new = gluScaleImage(GL_RGBA, self.pixbuf_old.get_width(), self.pixbuf_old.get_height(), GL_UNSIGNED_BYTE, self.pixbuf_old.get_pixels(),self.tilesize, self.tilesize, GL_UNSIGNED_BYTE) except AttributeError: sys.exit(0) #Disable below line for GPU rescaling self.pixbuf_old.copy_area(0, 0, self.nix, self.niy, self.pixbuf_new, (2+(self.tilesize - 4 - self.nix)/2), (2+(self.tilesize - 4 - self.niy)/2)) self.resize = True return False def transfer(self): pixels = self.pixbuf_new.get_pixels() w = self.pixbuf_new.get_width() h = self.pixbuf_new.get_height() del self.pixbuf del self.pixbuf_old del self.pixbuf_new gc.collect() return pixels, w, h #GPU Rescaling #return self.pixbuf_new, self.tilesize, self.tilesize class phimage: def __init__(self): self.d2 =0 self.init_options() try: self.parser.parse_args() except GError, e: print "Error: " + str(e) sys.exit(0) self.check_options() self.tex = [0,1] self.ESCAPE = '\033' self.state = 0 self.stateCounter = 0 self.stateTime = time.time() self.startTime = self.stateTime self.window = 0 self.texture = range(3) self.alpha = [1,0] self.theta = 0 self.thetar = 0 self.frameCnt = 0 self.counter = 0 self.textureName = '' self.files = os.listdir(self.workingPath) self.files = filter(self.isImage, self.files) self.image2 = [0, 1] self.image = [0, 1] self.lastx = 400 self.lasty = 400 self.main() def init_options(self): self.parser = OptionParser("", description="PHimage", option_list = [ make_option("--tilesize", "-t", type="string", action="store", dest="tilesize", help="Size of tile to use, must be n^2"), make_option("--tilequality", "-q", type="string", action="store", dest="tilequality", help="Quality of resize operation, 0 = bad, 1 = good"), make_option("--dir", "-d", type="string", action="store", dest="dir", help="Directory in which to recurse for images"), make_option("--angle", "-a", type="string", action="store", dest="angle", help="Angle of two images to each other, -90 to 90"), make_option("--buffersize", "-b", type="string", action="store", dest="buffersize", help="Size of progressive buffer"), make_option("--blendtime", "-B", type="string", action="store", dest="blendtime", help="How long to take for blend operation in 100s of second, default = 100"), make_option("--hangtime", "-H", type="string", action="store", dest="hangtime", help="How long an image is displayed for before it is removed in 100s of second, default = 300"), make_option("--constraint", "-c", type="string", action="store", dest="constraint", help="Form xm,ym,xr,yr of the constraints, default = 0.5,0.5,30,30"), make_option("--speed", "-s", type="string", action="store", dest="speed", help="Form c,r of the speed, set to 0 to disable movement or rotation, default = 0.005,0.005"), make_option("--resolution", "-r", type="string", action="store", dest="resolution", help="Form 1024x768:8@75 of the resolution, default = 1024x768:8@75"), make_option("--window", "-w", type="string", action="store", dest="window", help="Use a window 0, 1, default 0"), make_option("--distance", "-D", type="string", action="store", dest="distance", help="Distance from object, default 2.5"), make_option("--perspective", "-p", type="string", action="store", dest="perspective", help="Perspective of view, default 45.0"), # ... ]) def check_options(self): if self.parser.values.blendtime != None: self.blendTime = int(self.parser.values.blendtime) else: self.blendTime = 100 if self.parser.values.hangtime != None: self.displayTime = int(self.parser.values.hangtime) else: self.displayTime = 300 if self.parser.values.dir != None: self.workingPath = self.parser.values.dir else: self.workingPath = os.getcwd() if self.parser.values.angle != None: self.angle = float(self.parser.values.angle) else: self.angle = float(10) if self.parser.values.buffersize != None: self.buffersize = float(self.parser.values.buffersize) else: self.buffersize = 16384 if self.parser.values.tilesize != None: self.tilesize = int(self.parser.values.tilesize) else: self.tilesize = 512 if self.parser.values.tilequality == "0": self.tilequality = gtk.gdk.INTERP_NEAREST else: self.tilequality = gtk.gdk.INTERP_BILINEAR if self.parser.values.resolution != None: self.gamemode = self.parser.values.resolution else: self.gamemode = None if self.parser.values.window != None: self.windowmode = self.parser.values.window else: self.windowmode = 0 if self.parser.values.constraint != None: tmp = self.parser.values.constraint.split(",") if len(tmp) == 4: self.xm = float(tmp[0]) self.ym = float(tmp[1]) self.xr = float(tmp[2]) self.yr = float(tmp[3]) else: sys.exit(0) else: self.xm = 0.5 self.ym = 0.5 self.xr = 30 self.yr = 30 if self.parser.values.speed != None: tmp = self.parser.values.speed.split(",") if len(tmp) == 2: self.movth = float(tmp[0]) self.rotth = float(tmp[1]) else: sys.exit(0) else: self.movth = 0.005 self.rotth = 0.005 if self.parser.values.distance != None: self.distance = float(self.parser.values.distance) else: self.distance = 2.5 if self.parser.values.perspective != None: self.perspective = float(self.parser.values.perspective) else: self.perspective = 45.0 def isImage(self, filename): if os.path.splitext(filename)[-1].lower() in ('.png', '.jpg', '.bmp'): return True else: return False def storeIDLTexture(self, data, idl, w, h): glPixelStorei(GL_UNPACK_ALIGNMENT,1) glBindTexture(GL_TEXTURE_2D,self.textureName[idl]) glTexImage2D(GL_TEXTURE_2D, 0, 3, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, data) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL) def InitGL(self, Width, Height): test = textureLoader(self.nextFile() ,0, self.buffersize, self.tilesize, self.tilequality) while test.next_chunk()==True: True data, w, h = test.transfer() self.storeIDLTexture(data, 0, w, h) test = textureLoader(self.nextFile() ,1, self.buffersize, self.tilesize, self.tilequality) while test.next_chunk()==True: True data, w, h = test.transfer() self.storeIDLTexture(data, 1, w, h) glHint (GL_LINE_SMOOTH_HINT, GL_DONT_CARE); #glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST ) glEnable(GL_TEXTURE_2D) glClearColor(0.0, 0.0, 0.0, 0.0) glClearDepth(1.0) glDepthFunc(GL_LESS) # glEnable(GL_DEPTH_TEST) #This is changed to FLAT to improve speed.....We are not making any curved #surfaces here glShadeModel(GL_FLAT) glMatrixMode(GL_PROJECTION) glLoadIdentity() gluPerspective(self.perspective, float(Width)/float(Height), 0.1, 100.0) glMatrixMode(GL_MODELVIEW) glBlendFunc(GL_SRC_ALPHA,GL_ONE) glEnable(GL_BLEND) # Turn Blending On glDisable(GL_DEPTH_TEST) # Turn Depth Testing Off def stateChecker(self): """This function does the main state checking for the entire process It knows which plane is currently being displayed and which to load next It is run in delta time for everything now""" diffTime = time.time() - self.stateTime self.diffTime = diffTime if self.state == 0: self.alpha[0] = (1.0 / self.blendTime) * self.stateCounter self.alpha[1] = (self.blendTime - self.stateCounter) * (1.0 / self.blendTime) self.stateCounter = self.stateCounter + (diffTime * 100) if self.stateCounter > self.blendTime: self.alpha[0] = 1 self.alpha[1] = 0 self.state = 1 self.stateCounter = 0 elif self.state == 1: self.tex[1] = textureLoader(self.nextFile(), 1, self.buffersize, self.tilesize, self.tilequality) self.state = 2 elif self.state == 2: if self.tex[1].next_chunk() == False: data, w, h = self.tex[1].transfer() self.storeIDLTexture(data, 1, w, h) self.stateCounter = self.stateCounter + (diffTime * 100) if self.stateCounter > self.displayTime: self.state = 3 self.stateCounter = 0 elif self.state == 3: self.alpha[1] = (1.0 / self.blendTime) * self.stateCounter self.alpha[0] = (self.blendTime - self.stateCounter) * (1.0 / self.blendTime) self.stateCounter = self.stateCounter + (diffTime * 100) if self.stateCounter > self.blendTime: self.alpha[1] = 1 self.alpha[0] = 0 self.state = 4 self.stateCounter = 0 elif self.state == 4: self.tex[0] = textureLoader(self.nextFile(), 0, self.buffersize, self.tilesize, self.tilequality) self.state = 5 elif self.state == 5: if self.tex[0].next_chunk() == False: data, w, h = self.tex[0].transfer() self.storeIDLTexture(data, 0, w, h) self.stateCounter = self.stateCounter + (diffTime * 100) if self.stateCounter > self.displayTime: self.state = 0 self.stateCounter = 0 self.stateTime = self.stateTime + diffTime self.frameCnt = self.frameCnt + 1 print self.frameCnt / (self.stateTime - self.startTime) #print self.stateTime def DrawGLScene(self): self.stateChecker() #Trying to imporve performance here glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) #glClear(GL_COLOR_BUFFER_BIT) glLoadIdentity() glTranslatef(0.0,0.0,-self.distance) xmov = math.sin(self.theta) ymov = math.cos(self.theta) xmovr = math.sin(self.thetar) ymovr = math.cos(self.thetar) glTranslate(xmov*self.xm,ymov*self.ym,0) glRotatef (-ymovr*self.yr, 0.0, 1.0, 0.0) glRotatef (xmovr*self.xr, 1.0, 0.0, 0.0) glRotatef(self.angle,0.0,1.0,0.0) # Rotate The Cube On It's Y Axis glColor4f(1.0, 1.0, 1.0, self.alpha[0]) glBindTexture(GL_TEXTURE_2D, self.textureName[0]) glBegin(GL_QUADS) # Start Drawing The Cube glTexCoord2f(0.0, 1.0); glVertex2f(-1.0, -1.0) glTexCoord2f(1.0, 1.0); glVertex2f( 1.0, -1.0) glTexCoord2f(1.0, 0.0); glVertex2f( 1.0, 1.0) glTexCoord2f(0.0, 0.0); glVertex2f(-1.0, 1.0) glEnd() # Done Drawing The Cube glTranslate(-2*xmov*self.xm,-2*ymov*self.ym,0) glRotatef(-2*(self.angle),0.0,1.0,0.0) # Rotate The Cube On It's Y Axis glColor4f(1.0, 1.0, 1.0, self.alpha[1]) glBindTexture(GL_TEXTURE_2D,self.textureName[1]) glBegin(GL_QUADS) # Start Drawing The Cube glTexCoord2f(0.0, 1.0); glVertex2f(-1.0, -1.0) glTexCoord2f(1.0, 1.0); glVertex2f( 1.0, -1.0) glTexCoord2f(1.0, 0.0); glVertex2f( 1.0, 1.0) glTexCoord2f(0.0, 0.0); glVertex2f(-1.0, 1.0) glEnd(); # Done Drawing The Cube if time.time() - self.d2 >= .0001: self.d2 = time.time() self.theta = self.theta + self.movth self.thetar = self.thetar + self.rotth glBlendFunc(GL_SRC_ALPHA,GL_ONE) glFlush() glutSwapBuffers() def ReSizeGLScene(self, Width, Height): if Height == 0: Height = 1 glViewport(0, 0, Width, Height) glMatrixMode(GL_PROJECTION) glLoadIdentity() gluPerspective(self.perspective, float(Width)/float(Height), 0.1, 100.0) glMatrixMode(GL_MODELVIEW) glLoadIdentity() def nextFile(self): self.counter = self.counter + 1 if self.counter >= len(self.files): self.counter = 0 return self.workingPath + "/" + self.files[self.counter] def keyPressed(self, *args): # If escape is pressed, kill everything. if args[0] == self.ESCAPE: glutDestroyWindow(self.window) sys.exit() if args[0] == " ": glutTimerFunc(500, self.skipImage,0) def skipImage(self,void): if self.state==2: self.state = self.state + 1 self.stateCounter=0 if self.state==5: self.state = 0 self.stateCounter=0 def MouseMotion (self, x, y): self.lastx = x/24 self.lasty = y/24 glutPostRedisplay () def MouseClick (self, button, button_state, cursor_x, cursor_y): True def main(self): glutInit(()) glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH) if self.windowmode == "1" or not glutGameModeGet(GLUT_GAME_MODE_POSSIBLE): if self.gamemode == None: glutInitWindowSize(800, 600) else: tmp = self.gamemode.split(":")[0].split("x") glutInitWindowSize(int(tmp[0]), int(tmp[1])) glutInitWindowPosition(0, 0) self.window = glutCreateWindow("Phimage") else: if self.gamemode == None: glutGameModeString(str(glutGet(GLUT_SCREEN_WIDTH))+"x"+str(glutGet(GLUT_SCREEN_HEIGHT))+":8@75"); else: glutGameModeString(self.gamemode) glutEnterGameMode(); glutDisplayFunc(self.DrawGLScene) glutIdleFunc(self.DrawGLScene) glutReshapeFunc(self.ReSizeGLScene) glutKeyboardFunc(self.keyPressed) glutMotionFunc(self.MouseMotion) glutMouseFunc(self.MouseClick) self.textureName = glGenTextures(2) self.InitGL(1024, 768) glutMainLoop() test = phimage()