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")
Другие вопросы по тегам