有没有办法在 Pyglet 中为图像数据设置单个像素值?
我想也可以通过将OpenGL渲染模式设置为点来完成,所以如果有人对此有见解,也请分享。
最终出现的最适合我的解决方案是使用ImageData
每个子类附带的AbstractImage
类。
该类ImageData
将图像表示为一个字节数组,或者更准确地说是一个字符串,其中每个字符表示所需颜色空间中的一个坐标。
要获得给定的字节表示image
,您可以调用
image_data = image.get_image_data()
width = image_data.width
data = image_data.get_data('RGB', 3*width)
我们传递给get_data
这里的第二个参数是我们期望为图像的每一行获取的字节数。因为我们希望每个像素都包含所有组件 R、G 和 B,所以我们希望图像的宽度是图像宽度的 3 倍。如果我们只对每个像素的强度感兴趣,我们将传递参数('I', image.width)
。这是一些官方文档。
要仅获取您感兴趣的像素的值,例如 at 的像素(x,y)
,您可能想要这样做:
pos = (width*y + x) * 3
rgb = map(ord, data[pos:pos+3])
除了检索ImageData
整个图像并随后选择所需像素的值之外,您还可以调用get_image_data()
某个区域,即所需位置的 1x1 像素:
image_data = image.get_region(x,y,1,1).get_image_data()
这就是谷歌群组帖子的完成方式,您还可以在其中找到有用的信息,这些信息似乎更有效地获取图像数据RGBA
而不是RGB
.
现在,为了最终回答这个问题,还有一个用于 ImageData 的图像字节数据的 setter 方法set_data
,它正好相反。
image_data.set_data('RGB', image.width*3, data)
这可能也适用于地区,但我没有尝试过。如果要设置已存储在整数数组中的字节数据,请传递''.join(map(chr, data))
. 我不知道是否有办法设置数值。
希望这有助于任何偶然发现这个非常古老的问题的人,但它恰好是某些搜索词的突出谷歌结果。
以下内容纯粹是从 OpenGL 的角度来看,我不知道任何 pyglet 技巧。
总是有glDrawPixels,或者您可以使用与窗口具有相同分辨率的 OpenGL 纹理(如果您可以使用两个纹理大小的非幂次方则最好),然后将该纹理映射到占据整个窗口的四边形上。
当您不必在每次刷新时更改像素时,我认为后者是最快的解决方案,因为所有数据都已经在卡上。
您可以保留纹理数据的“本地”(在 cpu 内存中)缓存,以便于修改和重新上传。或者,对于加分,您可以直接通过 OpenCL 修改纹理数据;)
您可以使用设置批处理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()
可能有一种比上述方法更有效的绘制线条的方法,但是这种方法可以让您很好地了解批处理的工作原理。在此处查看文档以获取更多信息。