PyCairo и изменение данных пикселей
Я использую PyCairo для программного рисования векторных изображений из скрипта Python. Работает нормально. Но теперь я хотел бы получить доступ к данным пикселей и выполнить их дальнейшую обработку на уровне пикселей (такие как размытие или другие растровые эффекты), а затем продолжить использовать эту поверхность изображения с PyCairo, чтобы нарисовать еще несколько векторных фигур.
Я нашел get_data()
метод в cairo.ImageSurface
класс, но я не уверен, как его использовать, потому что документация очень загадочно об этом. Он просто говорит, что возвращает то, что называется "буфером Python", но нет примеров кода того, как это может быть использовано в реальном приложении.
Может ли кто-нибудь предоставить пример кода, как получить контроль над этими пикселями в этом "буфере Python"? (желательно без необходимости копировать все изображение туда-сюда с поверхностей PyCairo).
1 ответ
Данные представляют собой необработанные данные пикселей. Это представление , представляющее базовый ImageSurface . Данные имеют различную интерпретацию в зависимости от .памятиформата
Для простоты рассмотрим только формат пикселей RGB24. Каждый пиксель хранится в виде четырех байтов. Красный, зеленый и синий соответственно. Четвертый байт игнорируется и присутствует только из соображений производительности.
Затем пиксели сохраняются строка за строкой, первая строка идет первой, вторая строка следует за ней и так далее и тому подобное.
Также может быть дополнительное дополнение в конце строки, поэтому шаг данных является важным свойством. Чтобы получить индекс байта определенной строки
y
таким образом, нам нужно вычислить
y * stride
. К этому мы добавляем
x
координата, умноженная на ширину байта пикселя 4.
Все это показано в следующей небольшой программе на Python, которая рисует белый прямоугольник на черном фоне.
import cairo
width, height = 100, 100
surface = cairo.ImageSurface(cairo.Format.RGB24, width, height)
data = surface.get_data()
for y in range(50 - 20, 50 + 20):
for x in range(50 - 20, 50 + 20):
index = y * surface.get_stride() + x * 4
data[index] = 255 # red
data[index + 1] = 255 # green
data[index + 2] = 255 # blue
surface.write_to_png("im.png")