4. Ei innføring i å skriva programtillegg i Python

Denne innføringa vil læra deg det mest grunnleggjande for å skriva programtillegg i Python for GIMP 3.0. Vi går ut frå at du alt har litt kjennskap til å skriva program i Python frå før. Viss ikkje, er det mange kurs i Python på nettet, så vi tek ikkje dette opp her.

Eit programtillegg for GIMP i Python, og andre programmeringsspråk også, vert kalla opp frå GIMP for å utføra bestemte handlingar. For å vita korleis kommunisera med programtillegget, må GIMP vita kva programmet heiter og kva det gjer.

Det er visse krav til namnet på eit programtillegg og katalognamnet, som må vera det same. Du finn meir om dette i Installera nye programtillegg.

4.1. Dei grunnleggjande elementa i eit programtillegg for GIMP

Vi vil diskutera dei grunnleggjande, nødvendige delane i eit programtillegg, eller som i det minste er svært vanlege for å arbeida med GIMP.

  • Det er ikkje nødvendig, men vanleg praksis å byrja med ein «hashbang», ei koding og ein merknad om opphavsrett. Den første linja er til vanleg ein såkalla «hashbang» (teiknet # blir på engelsk kalla "hash" og vert brukt for å kommentera ut tekst i Python), som spesifiserer korleis skriptet høyrer. Den neste linja spesifiserer kodinga av Python-fila. Vi rår til å bruka teiknkoden utf-8. Til vanleg kjem det nå fleire linjer som spesifiserer kva lisens skriptet vert publisert skriptet under og ein kort omtale av kva det gjer. Vi skal ikkje gå nærare inn på dette, sidan det høyrer til i Python generelt.

  • Importera nødvendige modular for å få tilgang til GIMP og valfrie GEGL-funksjonar.

  • Deklarer ein klasse med fleire førehandsdefinerte funksjonar som du må justera slik at GIMP veit kva funksjonar som er tilgjengelege i programtillegget og kva funksjonar dei støttar. Dette går vi nærare inn på nedanfor.

  • Eit oppkall som opnar programtillegget ditt eller spør etter funksjonane, avhengig av argumenta som vert sende til det av GIMP.

4.1.1. Nødvendige modular

For å få tilgang til GIMP-funksjonane, byrjar vi med import gi. Denne modulen kan finna ut kva funksjonar som er tilgjengelege i kvar modul definert i «object introspection». Dette betyr for oss at vi importerer alle GIMP-relaterte modular som vi kan trengja for å kalla opp gi.repository.

Berre modulane Gimp og GimpUi kan vera nok om du berre skal bruka dei grunnleggjande funksjonane. Viss du vil køyra programtillegget ditt frå kommandolinja, treng du ikkje eingong GimpUi. Lat oss byrja med eit eksempel.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
#   GIMP - The GNU Image Manipulation Program
#   Copyright (C) 1995 Spencer Kimball and Peter Mattis
#
#   gimp-tutorial-plug-in.py
#   sample plug-in to illustrate the Python plug-in writing tutorial
#   Copyright (C) 2023 Jacob Boerema
#
#   This program is free software: you can redistribute it and/or modify
#   it under the terms of the GNU General Public License as published by
#   the Free Software Foundation; either version 3 of the License, or
#   (at your option) any later version.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#   You should have received a copy of the GNU General Public License
#   along with this program.  If not, see <https://www.gnu.org/licenses/>.

import sys

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 GLib
      

Vi byrjar med å importera «sys», som vi treng på slutten for å få tilgang til sys.argv. import gi fortel Python at gi-modulen må lastast inn. Denne modulen vert brukt for å gje GIMP tilgang til spesifikke funksjonar via «object introspection».

I den neste linja fortel vi at GIMP sin API versjon må vera 3.0. (Dette programtillegget kan ikkje brukast på eldre versjonar av GIMP). Den neste linja spør om å importera alle funksjonane, klassane osv. frå GIMP-modulen.

Dei neste to linjene gjer det same for GimpUi. GimpUi inneheld alle grensesnittrelaterte element for GIMP. Viss du planlegg å laga eit programtillegg som berre skal kallast opp frå kommandolinja, treng du ikkje desse. Vi avsluttar med å importera GLib, som vi treng seinare for å få tilgang til GLib.Error.

Det finst også andre valfrie modular som du kan bruka, som Gegl og Glib mellom mange andre, men dette går vi ikkje inn på her.

4.1.2. Definer klassen for programtillegget

GIMP må vita kva funksjonar som er tilgjengelege og kva funksjonalitetar dei støttar og kva menyplassering som skal brukast. For dette definerer vi ein klasse med utgangspunkt i klassen Gimp.PlugIn.

Eit minimalt programtillegg treng i det minste desse funksjonane definert i denne klassen:

  • Ein do_query_procedure-metode som GIMP kallar opp for å finna namna på dei prosedyrane som kan kallas opp i dette programtillegget.

  • Ein do_set_i18n-metode som GIMP kallar opp for å finna ut om dette programtillegget kan omsetjast til andre språk.

  • Ein do_create_procedure-metode som GIMP kallar opp for å opna ein av funksjonane i programtillegget. Når denne er kala opp, må du setja opp ein del informasjon for GIMP. Du byrjar med å laga ein prosedyre som fortel GIMP namnet på Python-funksjonen som skal opna programtillegget. Så legg du til ytterlegare informasjon, som kva bilettype programtillegget støttar, kva meny tillegget skal leggjast inn i og andre innstillingar.

  • Den aktuelle funksjonen (kalla prosedyre i GIMP) som du spesifiserte ovanfor. Ofte kallar vi han run, men du kan bruka kva namn som helst som er tillate i Python. Det er i denne funksjonen du set inn koden som skal føya til den ønskte effekten.

No skal vi gå inn i fleire detaljar. Den første delen av Python-koden som er vist ovanfor er ikkje teke med nedanfor. Berre den grunnleggjande utforminga av klassen er vist.

class MyFirstPlugin (Gimp.PlugIn):
    def do_query_procedures(self):
        return [ "jb-plug-in-first-try" ]

    def do_set_i18n (self, name):
        return False

    def do_create_procedure(self, name):
        procedure = Gimp.ImageProcedure.new(self, name,
                                            Gimp.PDBProcType.PLUGIN,
                                            self.run, None)

        procedure.set_image_types("*")

        procedure.set_menu_label("My first Python plug-in")
        procedure.add_menu_path('<Image>/Filters/Tutorial/')

        procedure.set_documentation("My first Python plug-in tryout",
                                    "My first Python 3 plug-in for GIMP 3",
                                    name)
        procedure.set_attribution("Your name", "Your name", "2023")

        return procedure

    def run(self, procedure, run_mode, image, n_drawables, drawables, config, run_data):
        Gimp.message("Hello world!")
        # do what you want to do, then, in case of success, return:
        return procedure.new_return_values(Gimp.PDBStatusType.SUCCESS, GLib.Error())
      

Lat oss sjå nærare på do_create_procedures. I linja return [ "jb-plug-in-first-try" ] fortel vi GIMP kva prosedyren heiter: vi kalla han "jb-plug-in-first-try". Dette er namnet som vert vist i GIMP sin prosedyrelesar.

Du kan ha fleire prosedyrar definerte i eit programtillegg. I dette tilfellet vil du lista opp alle namna, skilde med komma.

Det er god praksis å byrja alle prosedyrane du lagar med initialane dine eller ein annan unik merkelapp som er lett å kjenna igjen. På denne måten er det mindre sannsynleg at namnet du brukar vil vera det same som andre sine programtillegg har, noko som kan forvirra GIMP. Utanom dette står du sjølvsagt fritt til å gje tillegget kva namn du vil.

No vil vi fortelja GIMP at vi ikkje legg inn støtte for omsetjing ved å returnera False i oppkallet til do_set_i18n. Kva du må gjera for å kunna omsetja programtillegget er utføre føremålet med denne innføringa.

Det meste av det som skal til for å setja opp GIMP ligg i metoden do_create_procedure.

Prosedyre 13.1. Setja opp do_create_procedure

  1. Viss du definerer meir enn ein prosedyre i programtillegget, må du først kontrollera "namn"-parameteren for å sjå kva prosedyrar som vert kalla opp av GIMP. Dett går vi ikkje nærare inn på her.

    For å setja opp programtilleggsprosedyren, må vi først laga han og setja inn namnet på Pythonfunksjonen som skal gjera arbeidet. Dette gjer vi ved å kalla opp Gimp.ImageProcedure.new.

        procedure = Gimp.ImageProcedure.new(self, name,
                                            Gimp.PDBProcType.PLUGIN,
                                            self.run, None)
              

    I dette tilfellet gav vi programtillegget namnet self.run. Når vi kvalifiserer funksjonen med «self.», betyr dette at det er ein metode innføre klassen vår. Om ønskjeleg, kan du også definera han som ein regulær funksjon utføre klassen. Då sløyfer du «self» i namnet. Du kan kalla metoden kva som helst som kan godkjennast av Python.

  2. Det neste er å fortelja GIMP kva bilettypar programtillegget kan arbeida med ved å kalla oppprocedure.set_image_types. Viss bilettypen ikkje betyr noko brukar vi "*" som betyr at alle typar vert støtta av GIMP. Andre eksempel:

    1. "RGB*,GRAY*", der "*" her betyr at vi støttar begge versjonane, både med og utan A(lfa)kanal.

    2. "INDEXED", programtillegget arbeider berre med indekserte bilete utan alfakanal.

    3. "RGBA", programtillegget arbeider berre med RGB-bilete med alfakanal.

  3. Det er som oftast ein god ide å kunna opna programtillegget frå GIMP-menyane. Vi byrjar med å laga ein beskrivande merkelapp for menyoppføringa: procedure.set_menu_label.

  4. Det neste er å spesifisera kvar i menyen det skal vera: procedure.add_menu_path. I dette tilfellet seier vi at programtillegget skal leggjast til i filtermenyen under kategorien innføringar (undermeny).

  5. Om ønskjeleg kan du også leggja til eit ekstra hjelp-tips ved å bruka procedure.set_documentation og du kan setja namnet ditt som utviklar av programtillegget ved å bruka procedure.set_attribution.

  6. Den siste linja i prosedyren er return procedure som sender informasjonen som vart lagt til ovanfor tilbake til GIMP. Dermed vil GIMP kalla opp køyreprosedyren.

4.1.3. Leggja til hovudinngangspunkt til programtillegget

Alle programtillegga vert opna med eit oppkall til Gimp.main.

        Gimp.main(MyFirstPlugin.__gtype__, sys.argv)
      

Det einaste du treng endra i dette programtillegget er namnet på klassen, her kalla «MyFirstPlugin».

4.1.4. Det ferdige programtillegget

Nedanfor finn du heile Pythonskriptet, som skal kunna køyrast viss det har fått rett namn i ei mappe med det same namnet ein stad der GIMP kan finna det. Det vil visa meldinga «Hello world!» i feilkonsollen i eit sprettoppvindauge.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
#   GIMP - The GNU Image Manipulation Program
#   Copyright (C) 1995 Spencer Kimball and Peter Mattis
#
#   gimp-tutorial-plug-in.py
#   sample plug-in to illustrate the Python plug-in writing tutorial
#   Copyright (C) 2023 Jacob Boerema
#
#   This program is free software: you can redistribute it and/or modify
#   it under the terms of the GNU General Public License as published by
#   the Free Software Foundation; either version 3 of the License, or
#   (at your option) any later version.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#   You should have received a copy of the GNU General Public License
#   along with this program.  If not, see <https://www.gnu.org/licenses/>.

import sys

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 GLib

class MyFirstPlugin (Gimp.PlugIn):
    def do_query_procedures(self):
        return [ "jb-plug-in-first-try" ]

    def do_set_i18n (self, name):
        return False

    def do_create_procedure(self, name):
        procedure = Gimp.ImageProcedure.new(self, name,
                                            Gimp.PDBProcType.PLUGIN,
                                            self.run, None)

        procedure.set_image_types("*")

        procedure.set_menu_label("My first Python plug-in")
        procedure.add_menu_path('<Image>/Filters/Tutorial/')

        procedure.set_documentation("My first Python plug-in tryout",
                                    "My first Python 3 plug-in for GIMP 3.0",
                                    name)
        procedure.set_attribution("Your name", "Your name", "2023")

        return procedure

    def run(self, procedure, run_mode, image, n_drawables, drawables, config, run_data):
        Gimp.message("Hello world!")
        # do what you want to do, then, in case of success, return:
        return procedure.new_return_values(Gimp.PDBStatusType.SUCCESS, GLib.Error())

Gimp.main(MyFirstPlugin.__gtype__, sys.argv)