アプリケーションで Python で Pyglet(および OpenGL) を使用しています。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)
これをテストするには、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]
これで、アプリ ウィンドウ内のどこかをクリックするたびに、マウス カーソルの下にあるピクセルのカラー コードが表示されるはずです。
を使用してフレーム バッファ全体を取得し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 コードの代わりにを使用することを余儀なくされました
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に置き換えるだけですが、私はそれを試していません)。
編集:私はピグレットOpenGLAPIがPyOpenGLのものと異なることに気づいていませんでした。バッファを7番目の引数として使用するには、上記のコードを変更する必要があると思います(Pythonicの少ないpygletスタイルに準拠しています)。
さらに調べてみると、元のコードは、配列が単なるポインターであるため機能する C 固有のコードに基づいていたと思います。そのため、特定のバイトで取得できるポインター演算を使用すると、明らかに Python に変換されません。別の方法を使用してそのデータを抽出する方法はありますか(データをビットシフトするだけの問題だと思います)。
リンク先のスニペットを読むと、「通常の」値を取得する最も簡単な方法は、正しい順序で配列にアクセスすることであることがわかります。
そのスニペットは、仕事をすることになっているように見えます。そうでない場合は、デバッグして何が問題なのかを確認してください。