Установка отдельных пикселей в Pyglet

Есть ли способ установить отдельные значения пикселей для данных изображения в Pyglet?

Я предполагаю, что это также можно сделать, установив режим рендеринга OpenGL в точки, поэтому, если у кого-то есть понимание этого, пожалуйста, поделитесь им.


person ktdrv    schedule 18.10.2010    source источник


Ответы (3)


Следующее чисто с точки зрения OpenGL, я не знаю никаких трюков с pyglet для этого.

Всегда есть glDrawPixels, или вы можете использовать текстуру OpenGL, которая имеет то же разрешение, что и ваше окно (лучше всего, если вы можете использовать не степень двух размеров текстуры), а затем сопоставьте эту текстуру с четырехугольником, который занимает все окно.

Последнее, на мой взгляд, является самым быстрым решением, когда вам не нужно менять пиксели при каждом обновлении, потому что все данные уже есть на карте.

Вы можете сохранить «локальный» (в памяти процессора) кеш текстурных данных для легкой модификации и повторной загрузки. Или, за бонусные баллы, вы можете изменить данные текстуры напрямую через OpenCL;)

person Toni Ruža    schedule 18.10.2010
comment
Это хороший ответ, спасибо. Только я бы предпочел не лезть в недружественные воды OpenGL, если в этом нет необходимости.. :) - person ktdrv; 19.10.2010
comment
DrawPixels устарел в OpenGL 3.1 - person anatoly techtonik; 22.12.2012

Решение, которое оказалось наиболее подходящим для меня, — использовать класс 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). вот официальная документация.

Чтобы получить значения только для интересующего вас пикселя, например. тот, что в (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 для определенных условий поиска.

person J. Katzwinkel    schedule 07.01.2013
comment
документы: pyglet.readthedocs.io/ ru/latest/programming_guide/ - person Max Reeder; 25.05.2020

Вы можете настроить пакет, используя 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()

Вероятно, существует более эффективный способ рисования линий, чем описанный выше, но этот способ дает вам хорошее представление о том, как работает пакетная обработка. Дополнительные сведения см. в документации здесь.

person Fred P    schedule 31.01.2012