Hello again, I am trying to load an image and display it on a texture,
then draw on it. But I can't load the image, I get an error saying:
Traceback (most recent call last):
File "drawerogl.py", line 544, in <module>
if __name__ == '__main__': main()
File "drawerogl.py", line 522, in main
draw()
File "drawerogl.py", line 306, in draw
tex.blit_into(image,0,0,0)
File "C:\Python25\Lib\site-packages\pyglet\image\__init__.py", line
1598, in b
lit_into
source.blit_to_texture(self.target, self.level, x, y, z)
File "C:\Python25\Lib\site-packages\pyglet\image\__init__.py", line
473, in bl
it_to_texture
raise ImageException('Cannot blit %r to a texture.' % self)
pyglet.image.ImageException: Cannot blit <TextureRegion 683x620> to a
texture.
and the code I use to blit it is:
# if there is a loaded picture, blit it into tex
if image:
glBindTexture(GL_TEXTURE_2D,
image.id)
tex.blit_into(image,0,0,0)
the full code, for reference, is as follows:
'''
# Drawer By Noyan Tokgozoglu
#
# For CS 465
#
# Uses Python 2.5
http://www.python.org
# pyglet 1.1 http:/
www.pyglet.org
# psyco
http://psyco.sourceforge.net
#
# Last updated 12 Oct 2008
#
#
#
'''
# psyco is a library that makes the python compiler optimize
# the program as it runs, making it run faster
import psyco
psyco.full()
from
pyglet.gl import *
from pyglet import window
from pyglet.window import mouse
from pyglet.window import key
import pyglet.clock
from Tkinter import *
from tkMessageBox import *
from tkColorChooser import askcolor
from tkFileDialog import askopenfilename
from tkFileDialog import asksaveasfilename
# Initialize Tkinter which enables file dialogs etc
root = Tk()
# make Tkinter's main window invisible
root.withdraw()
# Define global variables
global
win,tex,std,redo,state,begpt,endpt,pressed,ptsize,color,image,drag,win2,polys,mousepos,WIDTH,HEIGHT
# width of main window, make it a power of 2 or saving works weird
WIDTH = 1024
# height of main and secondary window, make it a power of 2 or saving
works weird
HEIGHT = 512
# Create the main display window, make it invisible till we load all
stuff
win = window.Window(width=1024,height=512,visible=False)
# set location of window on screen
win.set_location(40,40)
# give it a caption
win.set_caption('drawer by noyan')
# initialize the main texture to draw to
tex =
pyglet.image.Texture.create(width=1024,height=512,internalformat=GL_RGBA)
# list of objects that have been drawn
std = []
# list of objects "undid", keep this so we can redo
redo = []
# the drawing state
state = 'line'
# the points in the polygon being drawn
polys = []
# current position of the mouse
mousepos = ()
# point where the current shape began
begpt = []
# point where the current shape ends
endpt = []
# is a mouse button currently held down?
pressed = False
# current point size/line width
ptsize = 3
# current color
color = [0,0,0,1.0]
# the loaded image, if any
image = None
# are we dragging the mouse?
drag = False
'''
# WINDOW 2 STUFF
'''
# the toolbar window
win2 = window.Window(width=100,height = HEIGHT)
# set its location
win2.set_location(WIDTH + 60,40)
# set its caption
win2.set_caption('controls')
# the images of the toolbar buttons
global linebut, circbut, brushbut, colorbut,polybut,openbut,savebut
linebut = pyglet.image.load('line.png')
circbut = pyglet.image.load('circ.png')
brushbut = pyglet.image.load('brush.png')
colorbut = pyglet.image.load('choose.png')
polybut = pyglet.image.load('poly.png')
openbut = pyglet.image.load('open.png')
savebut = pyglet.image.load('save.png')
'''
###########################################################################################################################
#
# Event handlers in pyglet are used as follows:
#
# Definition:
#
# @windowname.event
# def predefined_window_function_name(params) <- see pyglet
documentation (
http://www.pyglet.org/doc) for more info
#
###########################################################################################################################
'''
# a button is pressed inside toolbar window
@win2.event
def on_mouse_press(x,y,button,modifiers):
# make the state visible in current scope (will not explain this
kind of syntax again)
global state
# check which button the user clicked on
if x > 10 and x < 40 and y > 10 and y < 40:
state = 'line'
elif x > 10 and x < 40 and y > 60 and y < 90:
state = 'brush'
elif x > 60 and x < 90 and y > 60 and y < 90:
# calls Tkinter's color chooser dialog
asd = askcolor()
global color
# convert from 255,255,255 to 1.0,1.0,1.0 format
color[0] = asd[0][0]*1.0/255
color[1] = asd[0][1]*1.0/255
color[2] = asd[0][2]*1.0/255
elif x > 10 and x < 40 and y > 110 and y < 140:
state = 'poly'
elif x > 60 and x < 90 and y > 110 and y < 140:
global image
# set visible filetypes
filetypes = [('JPEG Image','*.jpg'),('PNG Image','*.png'),
('Bitmap Image','*.bmp'),('TGA Image','*.tga'), ('Any File','*.*')]
# call Tkinter's file chooser dialog
fn = askopenfilename(title='Open Image
File',filetypes=filetypes)
# load the opened image into a texture
image = pyglet.image.load(fn).get_texture()
elif x > 10 and x < 40 and y > 160 and y < 190:
global tex
# set visible filetypes
filetypes = [('JPEG Image','*.jpg'),('PNG Image','*.png'),
('Bitmap Image','*.bmp'),('TGA Image','*.tga'), ('Any File','*.*')]
# call Tkinter's file saver dialog
fn = asksaveasfilename(title='Save
Image',filetypes=filetypes,initialfile='')
# use pyglet.image.Texture 's save function
tex.save(fn)
# Drawing function of the toolbar
def draw2():
global win2
global linebut,circbut, brushbut, colorbut,polybut,openbut,savebut
# make it the active OpenGl context
win2.switch_to()
# Set clear color
glClearColor(1.0, 1.0, 1.0, 1.0)
# clear the buffer
glClear(GL_COLOR_BUFFER_BIT)
# draw the buttons through pyglet.image.blit
linebut.blit(10,10)
circbut.blit(60,10)
brushbut.blit(10,60)
colorbut.blit(60,60)
polybut.blit(10,110)
openbut.blit(60,110)
savebut.blit(10,160)
'''
# WINDOW 1 STUFF
'''
# OpenGl initialization for window 1
def init(w,h):
# self-explanatory
glClearColor(1.0, 1.0, 1.0, 1.0)
glMatrixMode(GL_PROJECTION)
gluOrtho2D (0.,w,0.,h)
glClear(GL_COLOR_BUFFER_BIT)
# mouse moves within window 1
@win.event
def on_mouse_motion(x,y,dx,dy):
global mousepos
# save the mouse position to the global variable
mousepos =(x,y)
# window is resized, also called when window first created
@win.event
def on_resize(width, height):
# make sure height isnt zero
if height==0:
height=1
# self explannatory
glViewport(0, 0, width, height)
# call the init() function which is written right above
init(width,height)
# user left or right clicks within window
@win.event
def on_mouse_press(x,y,button,modifiers):
global begpt,ptsize,polys,color
# mouse clicked here!
begpt = [x,y]
# if we are in brush mode
if state == 'brush':
# just add this point to the stuff we'll draw
std.append(['stroke'])
std.append(['brush',x,y,ptsize,
[color[0],color[1],color[2],color[3]]])
elif state == 'poly':
# if we have no points in our poly list no need to check for
right mouse button yet, else if its left mouse button its simple,
if len(polys) == 0 or button == 1:
# just add the current click point to the poly list
polys.append((x,y))
# if we have 1 pt
elif len(polys) == 1:
# and if it's a right click
if button == 4:
# it means we are done with this poly and we can draw a
line
# so we append a line to 'stuff to draw'
std.append(['line',polys[0][0],polys[0][1],x,y,ptsize,
[color[0],color[1],color[2],color[3]]])
# and empty the poly point list
polys = []
# other cases of right click
elif button == 4:
# we don't add the last click spot if its already the same
as the last point
# (list item number -1 in python means last item in the
list)
if polys[-1][0] != x and polys[-1][0] != y:
polys.append((x,y))
# since we will clear the polys object, we hold variables in
someplace else
items = []
# this loop basically copies polys to items
for item in polys:
items.append(item)
# then delete polys items
polys = []
# ad the poly to 'stuff to draw'
std.append(['poly',items,ptsize,
[color[0],color[1],color[2],color[3]]])
# mouse released in window 1
# (cannot have this event without having mouse pressed within window
first)
@win.event
def on_mouse_release(x,y,button,modifiers):
global std,begpt,ptsize,state,drag
# if we are drawing a line
if state == 'line':
# well then we should draw it!
std.append(['line',begpt[0],begpt[1],x,y,ptsize,
[color[0],color[1],color[2],color[3]]])
# and perhaps stop dragging the mouse
drag = False
elif state == 'square':
# similar to line
std.append(['square',begpt[0],begpt[1],x,y,ptsize,
[color[0],color[1],color[2],color[3]]])
drag = False
# mouse dragged in window 1
# (cannot have this event without having mouse pressed within window
first)
@win.event
def on_mouse_drag(x,y,dx,dy,buttons,modifiers):
global state,drag,ptsize
# brushmode?
if state == 'brush':
# then brush it up!
std.append(['brush',x,y,ptsize,
[color[0],color[1],color[2],color[3]]])
# yes I am really bored of writing comments
elif state == 'line':
# and it's really obvious that this line starts dragging the
mouse
drag = True
global endpt
# and sets the endpoint to current mouse location
endpt = [x,y]
# what's not so immediately obvious is that this is used for
drawing the dynamic line
# as it gets altered as the user drags the mouse
elif state == 'square':
# same as line
drag = True
endpt = [x,y]
# guess what this function does?
# yes! it handles the scrolling of the mouse wheel!
@win.event
def on_mouse_scroll(x,y,scroll_x,scroll_y):
global ptsize
# the scroll factor controls the point size
ptsize += scroll_y
# we don't want our ptsize to grow too small or too big, do we?
if ptsize < 1:
ptsize = 1
if ptsize > 100:
ptsize = 100
# this functions turns iron into gold.
# ...
# ...
# Not really, it just draws the stuff to the screen.
def draw():
# trivial stuff...
global
std,mousepos,win,tex,image,drag,begpt,endpt,color,ptsize
win.switch_to()
glClear(GL_COLOR_BUFFER_BIT)
glEnable(GL_TEXTURE_2D)
glBindTexture(GL_TEXTURE_2D,
tex.id)
####colorBits = GLchar()
####glTexImage2D(GL_TEXTURE_2D,0 ,3 , 1024, 512, 0 , GL_RGB,
GL_UNSIGNED_BYTE, colorBits)
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,
GL_LINEAR)
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,
GL_LINEAR)
glViewport(0,0,1024,512)
# if there is a loaded picture, blit it into tex
if image:
glBindTexture(GL_TEXTURE_2D,
image.id)
tex.blit_into(image,0,0,0)
glBindTexture(GL_TEXTURE_2D,0)
# draw each item in the 'stuff to draw' list, pretty
straightforward
for item in std:
if item[0] == 'brush':
glPointSize( item[3] )
if item[4][3] != 1:
glEnable(GL_BLEND)
glEnable(GL_POINT_SMOOTH)
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
glColor4f(item[4][0],item[4][1],item[4][2],item[4]
[3])
else:
glColor3f(item[4][0],item[4][1],item[4][2])
pyglet.graphics.draw(1, pyglet.gl.GL_POINTS,('v2i',
(item[1], item[2])))
glDisable(GL_POINT_SMOOTH)
if color[3] != 1:
glDisable(GL_BLEND)
elif item[0] == 'line':
glLineWidth(item[5])
if item[6][3] != 1:
glEnable(GL_BLEND)
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
glColor4f(item[6][0],item[6][1],item[6][2],item[6]
[3])
else:
glColor3f(item[6][0],item[6][1],item[6][2])
pyglet.graphics.draw(2, pyglet.gl.GL_LINES,('v2i',
(item[1], item[2], item[3], item[4])))
if item[6][3] != 1:
glDisable(GL_BLEND)
elif item[0] == 'square':
glLineWidth(item[5])
if item[6][3] != 1:
glEnable(GL_BLEND)
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
glColor4f(item[6][0],item[6][1],item[6][2],item[6]
[3])
else:
glColor3f(item[6][0],item[6][1],item[6][2])
pyglet.graphics.draw(4, pyglet.gl.GL_POLYGON,('v2i',
(item[1], item[2],item[1],item[4], item[3], item[4],item[3],item[2])))
if item[6][3] != 1:
glDisable(GL_BLEND)
elif item[0] == 'poly':
glLineWidth(item[2])
if item[3][3] != 1:
glEnable(GL_BLEND)
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
glColor4f(item[3][0],item[3][1],item[3][2],item[3]
[3])
else:
glColor3f(item[3][0],item[3][1],item[3][2])
####pyglet.graphics.draw(len(item[1]),
pyglet.gl.GL_POLYGON,('v2i', item[1]))
glBegin(pyglet.gl.GL_POLYGON)
for itemz in item[1]:
glVertex2i(itemz[0],itemz[1])
glEnd()
if item[3][3] != 1:
glDisable(GL_BLEND)
if color[3] != 1:
glEnable(GL_BLEND)
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
glColor4f(color[0],color[1],color[2],color[3])
else:
glColor3f(color[0],color[1],color[2])
# if something is being dragged, draw it
if drag and state == 'line':
# straightforward again
glLineWidth(ptsize)
glPointSize(ptsize)
pyglet.graphics.draw(2, pyglet.gl.GL_LINES,('v2i',
(begpt[0], begpt[1], endpt[0], endpt[1])))
elif drag and state == 'square':
glLineWidth(ptsize)
glPointSize(ptsize)
print begpt[1]
pyglet.graphics.draw(4, pyglet.gl.GL_POLYGON,('v2i',
(begpt[0],
begpt[1],
begpt[0],
endpt[1],
endpt[0],
endpt[1],
endpt[0],
begpt[1])))
# if a polygon is being drawn
elif len(polys) > 0:
glLineWidth(ptsize)
# if just one point in list,
# draw a line between that point and the mouse location
if len(polys) == 1:
pyglet.graphics.draw(2, pyglet.gl.GL_LINES,('v2i',
(polys[0][0], polys[0][1], mousepos[0], mousepos[1])))
# if 2, draw a triangle with those and the mouse
elif len(polys) == 2:
pyglet.graphics.draw(3, pyglet.gl.GL_TRIANGLES,('v2i',
(polys[0][0], polys[0][1], polys[1][0], polys[1][1], mousepos[0],
mousepos[1])))
# else draw the polygon
else:
glBegin(pyglet.gl.GL_POLYGON)
for itemz in polys:
glVertex2i(itemz[0],itemz[1])
glVertex2i(mousepos[0],mousepos[1])
glEnd()
if color[3] != 1:
glDisable(GL_BLEND)
# this draws all the images onto the texture, so we can save
it easily
glBindTexture(GL_TEXTURE_2D,
tex.id)
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,0,0, 1024, 512, 0)
####glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0,0,0, 1024, 512, 0)
glFinish()
glViewport(0,0,1024,512)
glDisable(GL_TEXTURE_2D)
glFlush()
# function to handle keyboard shortcuts
@win.event
def on_key_press(symbol, modifiers):
global state,std,redo,tex,image,color,win,polys,ptsize
# increase transparency
if symbol == key.W:
color[3]+=0.1
if color[3] > 1: color[3] =1
# decrease transparenct
elif symbol == key.Q:
color[3]-=0.1
if color[3] < 0: color[3] =0
# changing mode when drawing polys is NOT allowed, because it
might lead to weird errors
if len(polys) == 0:
# brush
if symbol == key.B:
state = 'brush'
# line
elif symbol == key.L:
state = 'line'
# polygon
elif symbol == key.P:
state = 'poly'
# color choose
elif symbol == key.C:
asd = askcolor()
# convert 255,255,255 to 1.0,1.0,1.0
color[0] = asd[0][0]*1.0/255
color[1] = asd[0][1]*1.0/255
color[2] = asd[0][2]*1.0/255
# open file
elif symbol == key.O:
filetypes = [('JPEG Image','*.jpg'),('PNG Image','*.png'),
('Bitmap Image','*.bmp'),('TGA Image','*.tga'), ('Any File','*.*')]
fn = askopenfilename(title='Open Image
File',filetypes=filetypes)
image = pyglet.image.load(fn).get_texture()
win.switch_to()
# close file
elif symbol == key.S:
filetypes = [('JPEG Image','*.jpg'),('PNG Image','*.png'),
('Bitmap Image','*.bmp'),('TGA Image','*.tga'), ('Any File','*.*')]
fn = asksaveasfilename(title='Save
Image',filetypes=filetypes,initialfile='')
tex.save(fn)
# undo
elif symbol == key.Z:
if len(std) > 0:
while len(std) > 0 and std[-1] == 'stroke':
std.remove(std[-1])
if std[-1][0] == 'brush':
while len(std) > 0 and std[-1][0] != 'stroke':
redo.append(std[-1])
std.remove(std[-1])
redo.append(std[-1])
std.remove(std[-1])
else:
redo.append(std[-1])
std.remove(std[-1])
# redo
elif symbol == key.X:
if len(redo) > 0:
if redo[-1][0] == 'stroke':
std.append(redo[-1])
redo.remove(redo[-1])
while len(redo) > 0 and redo[-1][0] == 'brush':
std.append(redo[-1])
redo.remove(redo[-1])
else:
std.append(redo[-1])
redo.remove(redo[-1])
# decrease point size
elif symbol == key.E:
ptsize -= 4
# increase point size
elif symbol == key.R:
ptsize += 4
# square drawing mode
elif symbol == key.K:
state = 'square'
# debug
if symbol == key.L:
for item in std:
if item[0] == 'brush' or item[0] == 'stroke':
print item
# debug
if symbol == key.M:
for item in redo:
if item[0] == 'brush' or item[0] == 'stroke':
print item
# main function # useful comment
def main():
global win
global win2
# makes win active
win.switch_to()
# makes it visible since we ar done loading stuff
win.set_visible()
# create clock that keeps track of framerate
clock=pyglet.clock.Clock()
# until user presses the X at the top right hand of the window
while not win.has_exit:
# first check the toolbar for events
win2.dispatch_events()
# draw the toolbar
draw2()
# flip its buffers
win2.flip()
# check the main screen for events
win.dispatch_events()
# draw main screen
draw()
# flip its buffers
win.flip()
# wait until next framerate tick
clock.tick()
"""void brush(shape &s)
{
if(s.brushType==0)
glEnable(GL_POINT_SMOOTH);
else
glDisable(GL_POINT_SMOOTH);
glBegin(GL_POINTS);
for(int i=0;i<s.xycord.size();i+=2)
glVertex2f(s.xycord[i],s.xycord[i+1]);
glEnd();
}"""
# this makes sure that if this file is run directly, the main method
is called after all the global stuff.
# I think this has to be the last line in the file
if __name__ == '__main__': main()