从OpenGL glReadPixels获取数据(使用Pyglet)

时间:2022-06-30 05:27:59

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?

我在一个应用程序中使用Python中的Pyglet(和OpenGL),我正在尝试使用glReadPixels来获取一组像素的RGBA值。我的理解是OpenGL将数据作为打包整数返回,因为它们是如何存储在硬件上的。然而,出于显而易见的原因,我希望将其变为正常的工作格式。基于一些阅读,我提出了这个问题:http://dpaste.com/99206/,但是它失败并出现了IndexError。我该怎么做呢?

5 个解决方案

#1


4  

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

您必须首先创建一个正确类型的数组,然后将其传递给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:

要测试这一点,请在Pyglet“opengl.py”示例中插入以下内容:

@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.

现在,只要单击应用程序窗口中的某个位置,就会看到鼠标光标下像素的颜色代码。

#2


1  

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

你可以使用PIL库,这是我用来捕获这样一个图像的代码片段:

    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).

我想包括alpha通道应该是非常直接的(可能只是用RGBA替换RGB,但我没有尝试过)。

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).

编辑:我不知道pyglet OpenGL API与PyOpenGL不同。我想必须改变上面的代码,使用缓冲区作为第七个参数(符合pythonic pyglet样式)。

#3


1  

I was able to obtain the entire frame buffer using glReadPixels(...), then used the PIL to write out to a file:

我能够使用glReadPixels(...)获取整个帧缓冲区,然后使用PIL写出文件:

# 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 was not interested in alpha, but I'm sure you could easily add it in.

我对alpha不感兴趣,但我相信你可以轻松添加它。

I was forced to use glReadPixels(...), instead of the Pyglet code

我*使用glReadPixels(...),而不是Pyglet代码

pyglet.image.get_buffer_manager().get_color_buffer().save('jpap.png')

because the output using save(...) was not identical to what I saw in the Window. (Multisampling buffers missed?)

因为使用save(...)的输出与我在Window中看到的输出不同。 (错过多重采样缓冲区?)

#4


0  

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.

如果您阅读链接到的代码段,您可以理解获取“正常”值的最简单方法是以正确的顺序访问数组。该片段看起来应该可以完成这项工作。如果没有,请调试它,看看问题是什么。

#5


0  

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).

在进一步审查时,我相信我的原始代码是基于一些特定的C代码,因为数组只是一个指针,所以我使用指针算法可以得到特定的字节,显然不会转换为Python。有没有人如何使用不同的方法提取数据(我假设它只是一点点移位数据)。

#1


4  

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

您必须首先创建一个正确类型的数组,然后将其传递给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:

要测试这一点,请在Pyglet“opengl.py”示例中插入以下内容:

@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.

现在,只要单击应用程序窗口中的某个位置,就会看到鼠标光标下像素的颜色代码。

#2


1  

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

你可以使用PIL库,这是我用来捕获这样一个图像的代码片段:

    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).

我想包括alpha通道应该是非常直接的(可能只是用RGBA替换RGB,但我没有尝试过)。

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).

编辑:我不知道pyglet OpenGL API与PyOpenGL不同。我想必须改变上面的代码,使用缓冲区作为第七个参数(符合pythonic pyglet样式)。

#3


1  

I was able to obtain the entire frame buffer using glReadPixels(...), then used the PIL to write out to a file:

我能够使用glReadPixels(...)获取整个帧缓冲区,然后使用PIL写出文件:

# 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 was not interested in alpha, but I'm sure you could easily add it in.

我对alpha不感兴趣,但我相信你可以轻松添加它。

I was forced to use glReadPixels(...), instead of the Pyglet code

我*使用glReadPixels(...),而不是Pyglet代码

pyglet.image.get_buffer_manager().get_color_buffer().save('jpap.png')

because the output using save(...) was not identical to what I saw in the Window. (Multisampling buffers missed?)

因为使用save(...)的输出与我在Window中看到的输出不同。 (错过多重采样缓冲区?)

#4


0  

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.

如果您阅读链接到的代码段,您可以理解获取“正常”值的最简单方法是以正确的顺序访问数组。该片段看起来应该可以完成这项工作。如果没有,请调试它,看看问题是什么。

#5


0  

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).

在进一步审查时,我相信我的原始代码是基于一些特定的C代码,因为数组只是一个指针,所以我使用指针算法可以得到特定的字节,显然不会转换为Python。有没有人如何使用不同的方法提取数据(我假设它只是一点点移位数据)。