有没有办法在Pyglet中为图像数据设置单个像素值?
我想也可以通过将OpenGL渲染模式设置为点来完成,所以如果有人对此有所了解,请分享它。
答案 0 :(得分:4)
最适合我的解决方案是使用每个AbstractImage
子类附带的ImageData
类。
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)
。 Here's some official documentation
仅为您感兴趣的像素获取值,例如在(x,y)
的那个,您可能想要这样做:
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()
它的完成方式是this google groups post,您还可以在其中找到有用的信息,将您的图像数据设置为RGBA
而不是RGB
更高效
现在,为了最终回答问题,还有一个用于ImageData的图像字节数据的setter方法,set_data
,它可以反过来工作。
image_data.set_data('RGB', image.width*3, data)
这也适用于地区,但我没有尝试过。如果要设置存储在整数数组中的字节数据,请传递''.join(map(chr, data))
。我不知道是否有办法设定数值。
希望这可以帮助任何人绊倒这个相当古老的问题,而这恰好是某些搜索字词的显着谷歌结果。
答案 1 :(得分:2)
以下纯粹来自OpenGL的观点,我不知道有任何pyglet技巧。
总有glDrawPixels,或者您可以使用与窗口分辨率相同的OpenGL纹理(如果您可以使用两种纹理大小的非幂,则最好)然后将该纹理映射到四边形占据了整个窗口。
后者我认为是最快的解决方案,因为您无需在每次刷新时更改像素,因为所有数据都已在卡上。
您可以保留纹理数据的“本地”(在cpu内存中)缓存,以便于修改和重新上传。或者,对于奖励积分,您可以直接通过OpenCL修改纹理数据;)
答案 2 :(得分:2)
您可以使用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()
绘制线条的方式可能比上面的方式更有效,但这种方式可以让您更好地了解批处理的工作原理。查看文档了解更多here.