1

有没有办法在 Pyglet 中为图像数据设置单个像素值?

我想也可以通过将OpenGL渲染模式设置为点来完成,所以如果有人对此有见解,也请分享。

4

3 回答 3

5

最终出现的最适合我的解决方案是使用ImageData每个子类附带的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)这是一些官方文档

要仅获取您感兴趣的像素的值,例如 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)). 我不知道是否有办法设置数值。

希望这有助于任何偶然发现这个非常古老的问题的人,但它恰好是某些搜索词的突出谷歌结果。

于 2013-01-07T04:30:24.047 回答
2

以下内容纯粹是从 OpenGL 的角度来看,我不知道任何 pyglet 技巧。

总是有glDrawPixels,或者您可以使用与窗口具有相同分辨率的 OpenGL 纹理(如果您可以使用两个纹理大小的非幂次方则最好),然后将该纹理映射到占据整个窗口的四边形上。

当您不必在每次刷新时更改像素时,我认为后者是最快的解决方案,因为所有数据都已经在卡上。

您可以保留纹理数据的“本地”(在 cpu 内存中)缓存,以便于修改和重新上传。或者,对于加分,您可以直接通过 OpenCL 修改纹理数据;)

于 2010-10-18T20:22:40.360 回答
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()

可能有一种比上述方法更有效的绘制线条的方法,但是这种方法可以让您很好地了解批处理的工作原理。在此处查看文档以获取更多信息。

于 2012-01-31T09:19:10.730 回答