Тестирование python3-расширения для GIMP

от автора

Графический редактор GIMP предоставляет широкие возможности для создания расширений на языках программирования Scheme (функциональный язык, сходный с LISP) или Python. Для доступа к системным операциям и регистрации собственных действий используется общий реестр Procedural Database (PDB), через который можно выполнять любые действия со встроенными механизмами GIMP (например, создание изображения). В этой статье мы рассмотрим основы создания расширений на Python 3 и возможные подходы к тестированию расширений через PDB.

По умолчанию для создания расширений используется Scheme и компонент Script-Fu, который предоставляет методы для регистрации расширений. Список существующих процедур можно посмотреть в меню Help -> Procedure Browser, среди которых есть процедуры для выполнения действий внутри GIMP (например, с префиксом file для загрузки-выгрузке файлов, gimp для обработки изображений), для регистрации дополнительных пунктов меню (gimp-plugin-menu-register), регистрации генераторов миниатюр (gimp-register-thumbnail-loader) и др. Процедуры могут принимать значения (например, название дополнительного пункта меню) и, в некоторых случаях, названия процедур-обработчиков события (например, нажатия на пункт меню). Также процедуры могут возвращать значения (например, gimp-version возвращает версию GIMP). При описании процедуры указывается название, описание, метаданные об авторских правах, перечисление аргументов и результатов функции с уточнением типа данных.

Для использования python с целью создания расширений для GIMP необходимо установить модуль python-fu. GIMP версии 2.99 (и последующий GIMP3) будут поддерживать Python3 и мы будем использовать их в своей статье:

sudo apt update  sudo apt install flatpak flatpak install --user https://flathub.org/beta-repo/appstream/org.gimp.GIMP.flatpakref  flatpak run org.gimp.GIMP//beta

Для более ранних версий GIMP поддержка существовала только для Python 2, но начиная для бета-версии уже доступен Python 3. После запуска GIMP перейдем в Filters -> Development -> Python Fu -> Python Console.

Для доступа к API GIMP будем использовать символ Gimp:

>>> Gimp.version() '2.99.14'

Доступ ко встроенным действиям возможен через реестр Pdb:

>>> Gimp.get_pdb() <Gimp.PDB object at 0x7fcf20523d40 (GimpPDB at 0x557496007ca0)>

Описание интерфейса может быть найдено на этой странице. Для доступа к процедуре можно использовать методы lookup_procedure(возвращает доступ к объекту процедуры для исследования и вызова, а также привязке пункта меню):

Gimp.get_pdb().lookup_procedure('gimp-plug-in-menu-branch-register')

или run_procedure:

>>> Gimp.get_pdb().run_procedure('gimp-version').index(0) <enum GIMP_PDB_SUCCESS of type Gimp.PDBStatusType> >>> Gimp.get_pdb().run_procedure('gimp-version').index(1) '2.99.14'

Также можно передавать значения, например для выбора цвета переднего плана:

>>> Gimp.get_pdb().run_procedure('gimp-context-set-foreground', [Gimp.RGB(255,0,0)])

Для создания плагина будем расширять класс Gimp.Plugin и переопределять методы do_create_procedure и do_query_procedures, также дополнительно проверим корректность версии Gimp:

import gi gi.require_version('Gimp', '3.0') from gi.repository import Gimp gi.require_version('GimpUi', '3.0') from gi.repository import GimpUi from gi.repository import Gio  class SamplePlugin(Gimp.PlugIn):      def do_query_procedures(self):         # получить список процедур         self.set_translation_domain("gimp30-python",                                     Gio.file_new_for_path(Gimp.locale_directory()))          return [ 'python-fu-sample-plugin' ]       def do_create_procedure(self, name):         procedure = Gimp.Procedure.new(self, name,                                             Gimp.PDBProcType.PLUGIN,                                             self.sample_procedure, None, None)         procedure.set_menu_label("Sample Plugin")         procedure.set_attribution("Dmitrii Zolotov",                                   "Dmitrii Zolotov",                                   "2023")         procedure.add_menu_path("<Image>/Filters/SamplePlugin")          return procedure      def sample_procedure(self, procedure, args, data):         return procedure.new_return_values(Gimp.PDBStatusType.SUCCESS, "OK")            Gimp.main(SamplePlugin.__gtype__, sys.argv)

Для тестирования плагина после установки мы можем использовать обнаружение PDB для проверки сигнатуры или результата выполнения функции:

a = Gimp.get_pdb().lookup_procedure('python-fu-sample_plugin') r = a.run([]) assert r.index(0)==Gimp.PDBStatusType.SUCCESS assert r.index(1)=='OK'

В расширениях могут создаваться разных типы процедур:

  • Gimp.Procedure — базовый класс, определяет абстрактное действие с указанными аргументами (может возвращать результат);

  • Gimp.FileProcedure— процедура для модификации возможностей по работе с файлами;

  • Gimp.LoadProcedure — процедура для обработки изображения при загрузке (например, для поддержки других форматов файлов);

  • Gimp.SaveProcedure — обработка изображения при сохранении файла (для экспорта в другие форматы);

  • Gimp.ImageProcedure — обработка изображения (например, этот тип используется при создании фильтров);

  • Gimp.BatchProcedure — пакетная обработка;

  • Gimp.ThumbnailProcedure — подготовка миниатюры.

Для выполнения преобразований можно использовать возможности GEGL, либо подключать другие библиотеки для работы с изображениями (PIL, OpenCV и др.). Для тестирования преобразований изображения (например, фильтров) можно использовать сравнение снимков изображения по степени сходства на основе нескольких преобразований нескольких тестовых изображений (для проверки можно передавать название исходного изображения и путь для сохранения результата как аргументы процедуры), например так:

import cv2 import numpy as np  img1 = cv2.imread('source.jpg') img2 = cv2.imread('target.jpg')  img1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY) img2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)  def mse(img1, img2):    h, w = img1.shape    diff = cv2.subtract(img1, img2)    err = np.sum(diff**2)    mse = err/(float(h*w))    return mse, diff  error, diff = mse(img1, img2) assert mse<5

Также для использования в Python доступны все методы, опубликованные в классе Gimp для получения текущего контекста запущенного редактора и выбранных инструментов, операции с файлами, просмотра списка открытых изображений (list_images). Для манипуляции изображением возможно использовать методы Gimp.Image (в частности, через него можно выполнять изменение размера изображения, управление слоями, выделение и операции с фрагментами) и многое другое.

Пример плагин для GIMP 3 (2.99.14) можно посмотреть в этом проекте.

В завершение хочу пригласить вас на бесплатный урок, где мы познакомимся с системой автоматизации развёртывания и управления приложениями Docker, посмотрим как использовать некоторые базовые команды Docker CLI и попробуем «упаковать» тесты в Docker-контейнер.


ссылка на оригинал статьи https://habr.com/ru/articles/729562/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *