Skip to content

Instantly share code, notes, and snippets.

@vanne02135
Created February 16, 2010 22:11
Show Gist options
  • Save vanne02135/305997 to your computer and use it in GitHub Desktop.
Save vanne02135/305997 to your computer and use it in GitHub Desktop.
Playing around with Pyglet and it's OpenGL interface to show some photos. Requires Pyglet and PIL. Displays some public photos from my flickr photostream.
__author__="vanne"
__date__ ="$16.2.2010 22:02:26$"
from pyglet.gl import *
import pyglet
from pyglet.window import *
from pyglet import image
import os
from math import sin
import math
import Image
import tempfile
import glob
import threading
import sys
window = pyglet.window.Window(width=640, height=480, resizable=True)
class Photo:
thumbnailSize = 512
def __init__(self, filename):
self.filename = filename
self.thumbnailtex = ""
self.thumbOk = False
self.createThumbnailTex()
self.location = [0, 0, 0]
self.dims = [5, 5]
def createThumbnailTex(self):
thread = threading.Thread(target=self.resize)
thread.start()
def draw(self):
if self.thumbOk:
glBindTexture(GL_TEXTURE_2D, self.thumbnailtex.id)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
glEnable(GL_TEXTURE_2D)
else:
try:
self.thumbnailtex = self.im.get_texture()
self.thumbOk = True
except: # self.im not loaded apparently
glDisable(GL_TEXTURE_2D)
glColor3f(0.2, 0.2, 0.2)
try:
w = self.width; h = self.height
if w > h:
ww = 1.0
hh = h/float(w)
else:
ww = w/float(h)
hh = 1.0
except AttributeError:
# image not yet loaded
ww = 1.0
hh = 1.0
bl = (self.location[0] - self.dims[0]*0.5*ww, self.location[1] - self.dims[1]*0.5*hh, self.location[2])
br = (self.location[0] + self.dims[0]*0.5*ww, self.location[1] - self.dims[1]*0.5*hh, self.location[2])
tr = (self.location[0] + self.dims[0]*0.5*ww, self.location[1] + self.dims[1]*0.5*hh, self.location[2])
tl = (self.location[0] - self.dims[0]*0.5*ww, self.location[1] + self.dims[1]*0.5*hh, self.location[2])
## remember: with blending the drawing sequence DOES matter. Draw the farthest first
glEnable(GL_BLEND)
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_COLOR)
glBegin(GL_QUADS)
glTexCoord2f(0.0, 0.0); glVertex3f(bl[0], bl[1], bl[2]) # bottom left
glTexCoord2f(ww*1.0, 0.0); glVertex3f(br[0], br[1], br[2]) #bottom right
glTexCoord2f(ww*1.0, hh*1.0); glVertex3f(tr[0], tr[1], tr[2]) #top right
glTexCoord2f(0.0, hh*1.0); glVertex3f(tl[0], tl[1], tl[2]) #top left
glEnd()
#glDisable(GL_BLEND)
if True:
# draw picture frame
glColor3f(1.0, 1.0, 1.0)
epsilon = 1e-2
framewidth = .05;
glBegin(GL_QUADS)
glVertex3f(bl[0]-framewidth, bl[1]-framewidth, bl[2]-epsilon) # bottom left
glVertex3f(br[0]+framewidth, br[1]-framewidth, br[2]-epsilon) #bottom right
glVertex3f(tr[0]+framewidth, tr[1]+framewidth, tr[2]-epsilon) #top right
glVertex3f(tl[0]-framewidth, tl[1]+framewidth, tl[2]-epsilon) #top left
glEnd()
def resize(self):
im = Image.open(self.filename)
(b1, b2, self.width, self.height) = im.getbbox()
im.thumbnail((Photo.thumbnailSize, Photo.thumbnailSize))
tmpfile = tempfile.NamedTemporaryFile()
tmpfilename = tmpfile.name
tmpfile.file.close() # just kikkailua
im.save(tmpfilename, "JPEG")
import time
import random
# just making sure the threaded loading works..
time.sleep(random.random())
self.im = image.load(tmpfilename)
print "loaded %s" % tmpfilename
os.remove(tmpfilename)
class PhotoLayout:
def __init__(self, photos, type = "grid"):
self.type = type
self.photos = photos
def update(self):
N = len(self.photos)
if N == 0:
return
w = int(math.sqrt(N))
h = int(math.ceil(N/float(w)))
if self.type == "grid":
tl = (-w/2.0 * 5.0, h/2.0 * 5.0, 0)
for n in range(N):
col = n % w
row = n / w
self.photos[n].location = add(tl, [col*5.0, -row*5.0, 0])
#print "%d : %s" % (n, self.photos[col*w+row].location)
elif self.type == "queue":
for n in xrange(N):
self.photos[n].location = (0, 0, n)
class Camera:
def __init__(self, x, y, z, xrot=0, yrot=0, zrot=0):
self.x = x
self.y = y
self.z = z
self.xrot = xrot
self.yrot = yrot
self.zrot = zrot
self.xspeed = self.yspeed = self.zspeed = 0.0
self.t = 0.0 # time variable for sin() stuff
def setup(self):
glClear(GL_COLOR_BUFFER_BIT |GL_DEPTH_BUFFER_BIT)
glLoadIdentity()
#glTranslatef(view_x, 0.0, -zoom) # Move left 1.5 units and into the screen 6.0
glTranslatef(self.x, self.y, self.z) # Move left 1.5 units and into the screen 6.0
glRotatef(self.xrot, 1.0, 0.0, 0.0)
glRotatef(self.yrot, 0.0, 1.0, 0.0)
glRotatef(self.zrot, 0.0, 0.0, 1.0)
def update(self, dt):
self.zrot+=self.zspeed
self.yrot+=self.yspeed
self.xrot+=self.xspeed
self.t += 0.08
#self.zoom = sin(zt)-10.0
self.z -= 0.5*sin(self.t)
def setSpeed(self, rv):
if len(rv) != 3:
raise Exception("3d vector assumed")
self.xspeed = rv[0]
self.yspeed = rv[1]
self.zspeed = rv[2]
def reset(self):
self.xspeed = self.yspeed = self.zspeed = 0.0
self.x = self.y = self.z = 0.0
self.xrot = self.yrot = self.zrot = 0.0
def add(a, b):
if len(a)!=len(b):
raise Exception("size mismatch")
return [a[i]+b[i] for i in xrange(len(a))]
def load_photos():
global myphotos
myphotos = list()
if False:
if len(sys.argv) == 1:
files = glob.glob("../data/*.jpg")
else:
files = glob.glob(sys.argv[1] + "/*.jpg")
print files
xloc = -5.0
for file in files:
myphoto = Photo(file)
myphoto.location[0] = xloc
myphotos.append(myphoto)
xloc += 5.0
else:
def flickrload():
import flickrapi
import urllib2
api_key = '12159663e48d19398dfac28562ba8f5e'
flickr = flickrapi.FlickrAPI(api_key)
ajvanne_id = '78714167@N00'
photos = flickr.walk(user_id=ajvanne_id)
for k in xrange(16):
photo = photos.next()
print "%s : %s" %(photo.get("id"), photo.get("title"))
sizes = flickr.photos_getSizes(photo_id=photo.get("id"))
#print "%s : %s" %(sizes[0][k].get("label"), sizes[0][k].get("url"))
url = sizes[0][2].get("source")
print "%s" % url
#tempfid = tempfile.NamedTemporaryFile()
filename = "temppi" + str(k) + ".jpg"
fid = open(filename, "wb")
fid.write(urllib2.urlopen(url).read())
fid.close()
myphotos.append(Photo(filename))
threading.Thread(target=flickrload).start()
@window.event
def on_mouse_drag(x, y, dx, dy, buttons, modifiers):
if buttons & mouse.LEFT:
global mycam
mycam.x += dx/50.0
mycam.y += dy/50.0
@window.event
def on_key_press(symbol, modifiers):
global mycam
if symbol == key.RETURN and not modifiers:
exit()
elif symbol == key.UP and not modifiers:
mycam.y -= 5.0
elif symbol == key.DOWN and not modifiers:
mycam.y += 5.0
elif symbol == key.RIGHT and not modifiers:
mycam.x -= 5.0
elif symbol == key.LEFT and not modifiers:
mycam.x += 5.0
elif symbol == key.LEFT and (modifiers & key.MOD_SHIFT):
mycam.zspeed += 0.1
elif symbol == key.RIGHT and (modifiers & key.MOD_SHIFT):
mycam.zspeed -= 0.1
elif symbol == key.UP and (modifiers & key.MOD_SHIFT):
mycam.xspeed += 0.1
elif symbol == key.DOWN and (modifiers & key.MOD_SHIFT):
mycam.xspeed -= 0.1
elif symbol == key.Z and not modifiers:
mycam.z -= 1.0
elif symbol == key.Z and (modifiers & key.MOD_SHIFT):
mycam.z += 1.0
elif symbol == key.X and not modifiers:
mycam.x += 5.0
elif symbol == key.R and not modifiers:
mycam.reset()
def update(dt):
mycam.update(dt)
# Spin the objects with a constant speed
pyglet.clock.schedule(update)
@window.event
def on_resize(width, height):
if height==0:
height = 1
glViewport(0, 0, width, height)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
# Calculate the aspect ratio of the window
gluPerspective(45.0, 1.0*width/height, 0.1, 100.0)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
return pyglet.event.EVENT_HANDLED
def lay_photos():
global myphotos, mylayout
#mylayout = PhotoLayout(myphotos, "queue")
mylayout = PhotoLayout(myphotos, "grid")
mylayout.update()
def setup():
global window
global mycam
mycam = Camera(0.0, 0.0, -5.0)
glEnable(GL_TEXTURE_2D)
load_photos()
lay_photos()
#glShadeModel(GL_SMOOTH) # Enables smooth shading
glClearColor(0.0, 0.0, 0.0, 0.0) #Black background
glClearDepth(1.0) # Depth buffer setup
glEnable(GL_DEPTH_TEST) # Enables depth testing
glDepthFunc(GL_LESS) # The type of depth test to do
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST) # Really nice perspective calculations
@window.event
def on_draw():
mycam.setup()
global myphotos
global mylayout
mylayout.update()
for myphoto in myphotos:
myphoto.draw()
return pyglet.event.EVENT_HANDLED
if __name__ == "__main__":
setup()
pyglet.app.run()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment