I'm going to struggle to ask this question concisely. My apologies. I
shall try.
I'm grabbing an image of the desktop. For the moment, I use PIL to do
this, which only works on Windows. The following returns a pyglet
ImageData object which looks like the current desktop:
import ImageGrab # PIL
from pyglet.image import ImageData
def grab_desktop():
desktop = ImageGrab.grab()
image = ImageData(
desktop.size[0], desktop.size[1],
'RGB', desktop.tostring(),
pitch=-desktop.size[0]* 3)
return image
Then I open a non-visible fullscreen pyglet window, set projection and
modelview matrices, blit the grabbed desktop image to it, and finally
make the window visible.
def draw(image):
image.blit(0, 0)
image = grab_desktop()
window = Window(visible=False, fullscreen=True)
# set projection and modelview matrices here
window.on_draw = lambda: on_draw(image)
app.run()
This works awesomely! The transition from real desktop to fullscreen
pyglet window that looks like the desktop is totally seamless. I then
mess around with the zoom and rotation to make the desktop image move
around sickeningly. If you look carefully at this screengrab, you can
see the image has started to tilt and zoom slightly. This is exactly
the effect I am after:
http://tartley.com/files/pyglet-users-deskzoom-corruption/normal-small.jpg
My problem occurs when I have two monitors. As it happens PIL grabs
the image from monitor 1, while pyglet opens its fullscreen window on
monitor 2. I thought this could be easily rectified by opening
pyglet's window on monitor 1 instead:
platform = get_platform()
display = platform.get_default_display()
screens = display.get_screens()
self.window = Window(
visible=False, fullscreen=True, screen=screens[1])
screen[0] is the screen returned by display.get_default_screen(), so
here I use screens[1] instead.
However, now the program works as normal, except the blitted image
appears corrupt, or badly formatted in some way:
http://tartley.com/files/pyglet-users-deskzoom-corruption/corrupt-small.jpg
Using screens[0] in the Window constructor above reverts the program
back to its original (non-corrupt, but wrong desktop) behaviour.
Does anyone have any ideas what I'm doing wrong? My two monitors are
both showing the same resolution and color depth.
Full source is below. It requires pyglet, PIL and Windows.
#!/usr/bin/python
from __future__ import division
from math import cos, pi, sin
from random import uniform
import ImageGrab # PIL
from pyglet import app, clock
from pyglet.event import EVENT_HANDLED
from pyglet.image import ImageData
from pyglet.window import get_platform, key, Window
from pyglet.gl import (
glClear, glClearColor, glLoadIdentity, glMatrixMode, gluLookAt,
GL_COLOR_BUFFER_BIT, GL_MODELVIEW, GL_PROJECTION,
)
from pyglet.gl.glu import gluOrtho2D
class Camera(object):
def __init__(self, x, y, scale, angle=0.0):
self.x = x
self.y = y
# scale is distance from screen centre to top or bottom, in
world coords
self.scale = scale
self.angle = angle
def set_modelview(self):
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
gluLookAt(
self.x, self.y, +1.0, # eye
self.x, self.y, -1.0, # look at
sin(self.angle), cos(self.angle), 0.0) # up
def set_projection(self, aspect):
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluOrtho2D(
-self.scale * aspect,
+self.scale * aspect,
-self.scale,
+self.scale)
class View(object):
def __init__(self, model, camera):
self.model = model
self.camera = camera
platform = get_platform()
display = platform.get_default_display()
screens = display.get_screens()
self.window = Window(
visible=False, fullscreen=True, screen=screens[1])
self.window.on_resize = lambda _, __: EVENT_HANDLED
self.window.on_draw = self.on_draw
glClearColor(0, 0, 0, 0)
def on_draw(self):
glClear(GL_COLOR_BUFFER_BIT)
aspect = self.window.width / self.window.height
self.camera.set_projection(aspect)
self.camera.set_modelview()
self.model.draw()
return EVENT_HANDLED
def show(self, _):
self.window.set_visible()
class Model(object):
def __init__(self, image):
self.desktop = image
def draw(self):
self.desktop.blit(0, 0)
class Zoomer(object):
def __init__(self, width, height):
self.width = width
self.height = height
self.zoomx = uniform(0, width)
self.zoomy = uniform(0, height)
def update_camera(self, age, camera):
effect = age / 2 # effect starts at 0.0 and lasts 2 seconds
camera.scale = self.height / 2 - effect ** 2 * 50
# todo, set cam x and y
camera.angle += sin(effect * pi / 2) * effect ** 2 / 1000
class Control(object):
def __init__(self, model, view, zoomer):
self.age = 0.0
self.model = model
self.view = view
self.zoomer = zoomer
def update(self, dt):
self.age += dt
self.zoomer.update_camera(self.age, self.view.camera)
if self.view.camera.scale < 0:
self.view.window.close()
def run(self):
clock.schedule_once(self.view.show, 2/50)
clock.schedule(self.update)
app.run()
def grab_desktop():
desktop = ImageGrab.grab()
image = ImageData(
desktop.size[0], desktop.size[1],
'RGB', desktop.tostring(),
pitch=-desktop.size[0]* 3)
return image
def main():
image = grab_desktop()
model = Model(image)
camera = Camera(image.width / 2, image.height / 2, image.height /
2)
view = View(model, camera)
zoomer = Zoomer(image.width, image.height)
control = Control(model, view, zoomer)
control.run()
if __name__ == '__main__':
main()
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"pyglet-users" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/pyglet-users?hl=en
-~----------~----~----~----~------~----~------~--~---