Pygletで画像データの個々のピクセル値を設定する方法はありますか?
OpenGLレンダリングモードをポイントに設定することでもできると思いますので、誰かがこれについて洞察を持っているなら、それも共有してください。
私に最も適していると思われる解決策は、すべてのサブクラスImageData
に付属するクラスを使用することです。AbstractImage
このImageData
クラスは、イメージをバイトの配列として表現します。より正確には、各文字が目的の色空間の座標を表す文字列として表現します。
特定の のバイト表現を取得するにはimage
、次のように呼び出します。
image_data = image.get_image_data()
width = image_data.width
data = image_data.get_data('RGB', 3*width)
ここで渡す 2 番目のパラメーターはget_data
、画像の各行で取得する予定のバイト数です。すべてのピクセルに R、G、B のすべてのコンポーネントが必要なため、画像の幅を 3 倍にしたいと考えています。たとえば、各ピクセルの強度のみに関心がある場合は、 parameters を渡します('I', image.width)
。ここにいくつかの公式ドキュメントがあります。
関心のあるまさにピクセルの値のみを取得するには、次の(x,y)
ように sth を実行することをお勧めします。
pos = (width*y + x) * 3
rgb = map(ord, data[pos:pos+3])
画像全体の を取得してImageData
後で目的のピクセルの値を選択する代わりにget_image_data()
、特定のregion、つまり目的の位置の 1x1 ピクセルを呼び出すこともできます。
image_data = image.get_region(x,y,1,1).get_image_data()
それがこのGoogleグループの投稿RGBA
である方法です。ここでは、画像データを の代わりにとして取得する方が効率的であると思われる有用な情報を見つけることもできますRGB
。
さて、最後に質問に答えるために、ImageData の画像バイト データのセッター メソッドもありますがset_data
、これは逆に機能します。
image_data.set_data('RGB', image.width*3, data)
これはおそらく地域でも機能しますが、試したことはありません。整数配列に格納したバイト データを設定する場合は、 を渡し''.join(map(chr, data))
ます。数値を設定する方法があるかどうかはわかりません。
これが、この非常に古い質問に出くわした人に役立つことを願っています.
を使用してバッチを設定し、batch = pyglet.graphics.Batch()
を呼び出してバッチに頂点を追加できbatch.add(npts, gl_type, group, pixel_data, color_data)
ます。npts は、pixel_data でタプルとしてリストするポイントの数を指定する整数で、この場合の gl_type は pyglet.gl.GL_POINTS です。batch.draw()
次に、バッチに追加したすべての頂点を描画します。以下の例では、on_draw() を呼び出すたびにバッチに頂点 (つまり GL_POINTS) を追加して線を描画します。
import pyglet
COLOR = (0,255,0)
FRAMERATE = 1.0/60
(x,y) = (50,50)
window = pyglet.window.Window()
batch = pyglet.graphics.Batch()
# the vertex_list will keep a handle on all the vertices we add to the batch
vertex_list = [batch.add(1, pyglet.gl.GL_POINTS, None,('v2i', (x,y)),('c3B', COLOR))]
@window.event
def on_draw():
window.clear()
# the next vertex will use the vertices of the vertex currently at the end of the current vertex_list
(x,y) = vertex_list[-1].vertices
vertex_list.append(batch.add(1, pyglet.gl.GL_POINTS, None,('v2i', (x+1,y+1)),('c3B', COLOR)))
batch.draw()
pyglet.clock.schedule_interval(lambda dt: None, FRAMERATE)
pyglet.app.run()
上記の方法よりも効率的な線の描画方法があるかもしれませんが、この方法を使用すると、バッチがどのように機能するかがよくわかります。詳細については、こちらのドキュメントをご覧ください。
以下は純粋に OpenGL の観点からのものであり、これに関する pyglet のトリックについては知りません。
常にglDrawPixelsが存在するか、ウィンドウと同じ解像度の OpenGL テクスチャを使用して (2 の累乗でないテクスチャ サイズを使用できる場合に最適)、そのテクスチャをウィンドウ全体を占めるクワッドにマップすることができます。
後者は、すべてのデータが既にカードにあるため、更新のたびにピクセルを変更する必要がない場合の最速のソリューションだと思います。
簡単に変更して再アップロードできるように、テクスチャ データの「ローカル」(CPU メモリ内) キャッシュを保持できます。または、おまけとして、テクスチャ データを OpenCL 経由で直接変更できます ;)