Получить данные из 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. Кто-нибудь, как извлечь эти данные, используя другой метод (я предполагаю, что это просто вопрос сдвига данных).
Если вы прочитаете фрагмент, на который вы ссылаетесь, вы поймете, что самый простой и удобный способ получить "нормальные" значения - это просто получить доступ к массиву в правильном порядке.
Этот фрагмент выглядит так, как будто он должен делать эту работу. Если это не так, отладьте его и посмотрите, в чем проблема.