Получить данные из OpenGL glReadPixels(используя Pyglet)

Я использую Pyglet(и OpenGL) в Python для приложения, я пытаюсь использовать glReadPixels, чтобы получить значения RGBA для набора пикселей. Насколько я понимаю, OpenGL возвращает данные в виде упакованных целых чисел, поскольку именно так они хранятся на оборудовании. Однако по понятным причинам я хотел бы привести его в нормальный формат для работы с ним. Основываясь на некотором прочтении, я придумал это: http://dpaste.com/99206/, однако это не удается с помощью IndexError. Как бы я поступил так?

5 ответов

Сначала вы должны создать массив правильного типа, а затем передать его glReadPixels:

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

Чтобы проверить это, вставьте в пример "opengl.py" Pyglet следующее:

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

Теперь вы должны видеть цветовой код для пикселя под курсором мыши всякий раз, когда вы щелкаете где-то в окне приложения.

Мне удалось получить весь буфер кадра, используя 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')

Я не интересовался альфой, но я уверен, что вы могли бы легко добавить ее.

Я был вынужден использовать glReadPixels(...)вместо кода Пиглета

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

потому что выход с помощью save(...) не было идентично тому, что я видел в окне. (Буферы мультисэмплинга пропущены?)

Вы можете использовать библиотеку 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)

Я думаю, что включение альфа-канала должно быть довольно простым (вероятно, просто заменить RGB на RGBA, но я не пробовал этого).

Редактировать: я не знал, что API OpenGL Pyglet отличается от PyOpenGL. Я предполагаю, что нужно изменить приведенный выше код, чтобы использовать буфер в качестве седьмого аргумента (в соответствии с менее pythonic pyglet style).

При дальнейшем рассмотрении я полагаю, что мой исходный код был основан на некотором специфическом для Си коде, который работал, потому что массив - это просто указатель, поэтому мое использование арифметики с указателями вы можете получить в определенных байтах, которые, очевидно, не переводятся в Python. Кто-нибудь, как извлечь эти данные, используя другой метод (я предполагаю, что это просто вопрос сдвига данных).

Если вы прочитаете фрагмент, на который вы ссылаетесь, вы поймете, что самый простой и удобный способ получить "нормальные" значения - это просто получить доступ к массиву в правильном порядке.
Этот фрагмент выглядит так, как будто он должен делать эту работу. Если это не так, отладьте его и посмотрите, в чем проблема.

Другие вопросы по тегам