Get data from OpenGL glReadPixels (using Pyglet)
I am using Pyglet (and OpenGL) in Python in an application, I am trying to use glReadPixels to get RGBA values ββfor a set of pixels. I understand that OpenGL returns data as packed integers since it is stored in hardware. However, for obvious reasons, I would like to get it in its normal format to work. Based on some readings I came up with the following: http://dpaste.com/99206/ , however it doesn't work with IndexError. How can i do this?
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, paste the following into 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]
You should now see the color code for the pixel under the mouse cursor when you click anywhere in the application window.
You can use the PIL library, here is the code snippet I am using to capture an image like this:
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 the alpha should be pretty straight forward (maybe just replacing RGB with RGBA, but I haven't tried that).
Edit: I didn't know that the OpenGL API of pyglet is different from PyOpenGL. My guess is that the above code needs to be modified to use a buffer as the seventh argument (to match the less stylish pigment piglet).
I was able to get the entire framebuffer with glReadPixels(...)
, then used PIL to write to a file:
# Capture image from the OpenGL buffer
buffer = ( GLubyte * (3*window.width*window.height) )(0)
glReadPixels(0, 0, window.width, window.height, GL_RGB, GL_UNSIGNED_BYTE, buffer)
# Use PIL to convert raw RGB buffer and flip the right way up
image = Image.fromstring(mode="RGB", size=(window.width, window.height), data=buffer)
image = image.transpose(Image.FLIP_TOP_BOTTOM)
# Save image to disk
image.save('jpap.png')
I wasn't interested in alpha, but I'm sure you can add it easily.
I was forced to use glReadPixels(...)
instead of the Pyglet code
pyglet.image.get_buffer_manager().get_color_buffer().save('jpap.png')
because the output using was save(...)
not identical to what I saw in the window. (Missing multisampling buffers?)
If you are reading the snippet you are referencing, you can understand that the simplest and most efficient way to get "normal" values ββis simply to access the array in the correct order.
This snippet looks like it should do the job. If it doesn't, debug it and see what the problem is.
In a further review, I believe my original code was based on some C code that worked because an array is just a pointer, so I am using pointer arithmetic, which you can get in certain bytes, which obviously doesn't translate to Python. Anyone how to retrieve this data using a different method (I'm guessing it's just a matter of biasing the data).