views:

1657

answers:

4

I'm using Pyglet(and OpenGL) in Python on an application, I'm trying to use glReadPixels to get the RGBA values for a set of pixels. It's my understanding that OpenGL returns the data as packed integers, since that's how they are stored on the hardware. However for obvious reasons I'd like to get it into a normal format for working with. Based on some reading I've come up with this: http://dpaste.com/99206/ , however it fails with an IndexError. How would I go about doing this?

A: 

If you read the snippet you link to you can understand that the simplest and way to get the "normal" values is just accessing the array in the right order.
That snippet looks like it's supposed to do the job. If it doesn't, debug it and see what's the problem.

shoosh
Well, the data that glReadPixels returns is just an array with n values where n is the number of pixels in the region. I'm not actually sure the snippet makes any sense, it's more or less an amalgamation of stuff I've read.
Alex Gaynor
A: 

You can use the PIL library, here is a code snippet which I use to capture such an image:

    buffer = gl.glReadPixels(0, 0, width, height, gl.GL_RGB, 
                             gl.GL_UNSIGNED_BYTE)
    image = Image.fromstring(mode="RGB", size=(width, height), 
                             data=buffer)
    image = image.transpose(Image.FLIP_TOP_BOTTOM)

I guess including the alpha channel should be pretty straight forward (probably just replacing RGB with RGBA, but I have not tried that).

Edit: I wasn't aware that the pyglet OpenGL API is different from the PyOpenGL one. I guess one has to change the above code to use the buffer as the seventh argument (conforming to the less pythonic pyglet style).

nikow
When I try this I get a type error that glReadPixels takes 7 arguments, not 6.
Alex Gaynor
Are you sure? I have been using this code on different machines with different PyOpenGL versions.Maybe its something pyglet specific? Maybe pass the buffer variable as the seventh argument.
nikow
A: 

On further review I believe my original code was based on some C specific code that worked because the array is just a pointer, so my using pointer arithmetic you could get at specific bytes, that obviously doesn't translate to Python. Does anyone how to extract that data using a different method(I assume it's just a matter of bit shifting the data).

Alex Gaynor
+1  A: 

You must first create an array of the correct type, then pass it to glReadPixels:

a = (GLuint * 1)(0)
glReadPixels(x, y, 1, 1, GL_RGB, GL_UNSIGNED_INT, a)

To test this, insert the following in the Pyglet "opengl.py" example:

@window.event
def on_mouse_press(x, y, button, modifiers):
    a = (GLuint * 1)(0)
    glReadPixels(x, y, 1, 1, GL_RGB, GL_UNSIGNED_INT, a)
    print a[0]

Now you should see the color code for the pixel under the mouse cursor whenever you click somewhere in the app window.

Deestan