Установка отдельных пикселей в Pyglet - PullRequest
1 голос
/ 18 октября 2010

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

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

Ответы [ 3 ]

4 голосов
/ 07 января 2013

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

2 голосов
/ 31 января 2012

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

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

2 голосов
/ 19 октября 2010

Это чисто с точки зрения OpenGL, я не знаю каких-либо ухищрений для этого.

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

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

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

...