Есть ли способ установить отдельные значения пикселей для данных изображения в Pyglet?
Я предполагаю, что это также можно сделать, установив режим рендеринга OpenGL в точки, поэтому, если у кого-то есть понимание этого, пожалуйста, поделитесь им.
Есть ли способ установить отдельные значения пикселей для данных изображения в Pyglet?
Я предполагаю, что это также можно сделать, установив режим рендеринга OpenGL в точки, поэтому, если у кого-то есть понимание этого, пожалуйста, поделитесь им.
Следующее чисто с точки зрения OpenGL, я не знаю никаких трюков с pyglet для этого.
Всегда есть glDrawPixels, или вы можете использовать текстуру OpenGL, которая имеет то же разрешение, что и ваше окно (лучше всего, если вы можете использовать не степень двух размеров текстуры), а затем сопоставьте эту текстуру с четырехугольником, который занимает все окно.
Последнее, на мой взгляд, является самым быстрым решением, когда вам не нужно менять пиксели при каждом обновлении, потому что все данные уже есть на карте.
Вы можете сохранить «локальный» (в памяти процессора) кеш текстурных данных для легкой модификации и повторной загрузки. Или, за бонусные баллы, вы можете изменить данные текстуры напрямую через OpenCL;)
Решение, которое оказалось наиболее подходящим для меня, — использовать класс 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)
. вот официальная документация.
Чтобы получить значения только для интересующего вас пикселя, например. тот, что в (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()
Как это делается, описано в этой записи групп Google, где вы также можете найти полезную информацию о том, что более эффективно получать данные изображения как RGBA
вместо RGB
.
Теперь, чтобы окончательно ответить на вопрос, есть также метод установки для байтовых данных изображения ImageData, set_data
, что работает как раз наоборот.
image_data.set_data('RGB', image.width*3, data)
Вероятно, это работает и для регионов, но я не пробовал. Если вы хотите установить байтовые данные, которые вы сохранили в целочисленном массиве, передайте ''.join(map(chr, data))
. Я не знаю, есть ли способ установить числовые значения.
Надеюсь, это поможет любому, кто наткнется на этот довольно старый вопрос, который до сих пор является заметным результатом Google для определенных условий поиска.
Вы можете настроить пакет, используя 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()
затем рисует все вершины, которые вы добавили в пакет. В приведенном ниже примере линия рисуется путем добавления вершин (т. е. GL_POINTS) в пакет при каждом вызове on_draw():
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()
Вероятно, существует более эффективный способ рисования линий, чем описанный выше, но этот способ дает вам хорошее представление о том, как работает пакетная обработка. Дополнительные сведения см. в документации здесь.