## 4. Een handleiding voor het schrijven van een plug-in met Python

Deze handleiding zal u de basisbeginselen leren van het schrijven van een plug-in in Python voor GIMP 3.0. U wordt verwacht al enige basiskennis van het schrijven in Python in het algemeen te hebben. Als dat niet zo is, er zijn voldoende online cursussen voor Python, we gaan ze hier niet herhalen.

Plug-ins voor GIMP in Python (en ook in andere talen) worden aangeroepen vanuit GIMP om bepaalde acties uit te voeren. Om in staat te zijn te begrijpen hoe ermee te communiceren en de plug-in aan te roepen, moet GIMP weten met welke naam het aan te roepen en welke functies het ondersteunt.

Er zijn bepaalde vereisten met betrekking tot de bestandsnaam en de naam van de map van een plug-in, die hetzelfde moeten zijn. Bekijk voor meer Nieuwe plug-ins installeren.

### 4.1. De basiselementen van een plug-in voor GIMP

We zullen de basisdelen bespreken van een plug-in die vereist zijn, of ten minste heel veel voorkomen bij het werken met GIMP.

- Vereist op Linux en macOS, en algemene praktijk op Windows, is om te beginnen met een zogenaamde shebang of hashbang, een codering en een opmerking over auteursrecht. De eerste regel is een shebang, die specificeert hoe dit script kan worden uitgevoerd. De volgende regel specificeert de codering van het bestand van Python. Wij bevelen utf-8 aan. Gewoonlijk wordt dat gevolgd door verschillende regels die specificeren onder welke licentie u het script publiceert en een korte beschrijving van wat het script doet. We zullen hier niet dieper op ingaan, omdat het heel gewoon is voor Python in het algemeen.

- Importeren van vereiste modules om toegang te krijgen tot GIMP en optioneel de functies van GEGL.

- Declareer een klasse met verscheidene vooraf gedefinieerde functies die u moet aanpassen, zodat GIMP weet welke functies beschikbaar zijn in uw plug-in en welke functionaliteiten ze ondersteunen. We zullen hieronder meer in detail hierop ingaan.

- Een aanroep die uw plug-in opstart, of de mogelijkheden ervan bevraagt, afhankelijk van de argumenten die er naartoe zijn gestuurd door GIMP.

#### 4.1.1. Vereiste modules

Om toegang te krijgen tot functies van GIMP, beginnen we met `import gi`. Deze module kan uitzoeken welke functies beschikbaar zijn in elke module die wordt gedefinieerd met “object introspectie”. Wat dat voor ons betekent is dat we alle GIMP gerelateerde modules importeren, die we nodig zouden kunnen hebben, met het aanroepen van `gi.repository`.

Voor basis functionaliteit zouden alleen de modules Gimp en GimpUi voldoende kunnen zijn. Als u uw plug-in vanaf de opdrachtregel wilt uitvoeren, heeft u zelfs GimpUi niet nodig. Laten we beginnen met een voorbeeld.

    #!/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

We beginnen met het importeren van sys, dat we aan het einde nodig hebben voor toegang tot `sys.argv`, gevolgd door `import gi` die Python vertelt dat het de module gi moet laden. Deze module wordt gebruikt voor toegang tot specifieke functies van GIMP via “object introspectie”.

In de volgende regel vertellen we gi dat we eisen dat de API-versie van GIMP versie 3.0 moet zijn. (Deze plug-in zal niet werken met oudere versies van GIMP.) De volgende regel verzoekt om alle functies, klassen etc te importeren uit de module Gimp.

De volgende twee regels doen hetzelfde voor GimpUi. GimpUi bevat alle aan de interface gerelateerde elementen voor GIMP. Als u van plan bent een plug-in te maken die alleen vanaf de opdrachtregel gaat worden aangeroepen, dan heeft u dit niet nodig. We besluiten met het importeren van GLib, dat we later nodig hebben voor toegang tot GLib.Error.

Er zijn andere optionele modules die u ook kunt gebruiken, zoals Gegl en nog vele andere, maar we gaan daar hier verder niet op in.

#### 4.1.2. Uw klasse voor de plug-in definiëren

GIMP moet weten welke functies beschikbaar zijn, welke functionaliteit ze ondersteunen en welke locatie van het menu te gebruiken. Daarvoor definiëren we een klasse die is afgeleid van de klasse `Gimp.PlugIn`.

Een minimale plug-in moet ten minste de volgende functies hebben gedefinieerd in deze klasse:

- Een methode `do_query_procedure`, die GIMP aanroept om de namen van de procedures, die in this plug-in kunnen worden aangeroepen, te zoeken.

- Een methode `do_set_i18n`, die GIMP aanroept om uit te zoeken of uw plug-in vertalingen ondersteunt.

- Een methode `do_create_procedure`, die GIMP aanroept om een van de functies in uw plug-in te starten. Wanneer dit wordt aangeroepen zou u bepaalde informatie moeten initialiseren voor GIMP. U begint met het maken van een procedure die GIMP de naam vertelt van de aan te roepen functie van Python om uw plug-in te starten. Daarna geeft u aanvullende informatie, zoals welke typen afbeeldingen uw plug-in ondersteunt, waar in het menu uw plug-in te vinden is en andere optionele instellingen.

- De feitelijke functie (procedure genoemd door GIMP) die u hierboven specificeerde. We noemen dit vaak `run`, maar het mag elke naam hebben die is toegestaan door Python. Deze functie is waar u uw eigen code zult toevoegen om de door u gewenste effecten toe te passen.

We zullen nu iets meer in detail treden. Hieronder is niet het eerste gedeelte opgenomen van de code voor Python, dat hierboven werd weergegeven. Dit geeft alleen de basis lay-out voor uw klasse weer.

    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, 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())

Laten we eens wat beter kijken naar `do_query_procedures`. In de regel `return [ "jb-plug-in-first-try" ]` vertellen we GIMP wat de naam is van onze procedure: we noemen het "jb-plug-in-first-try". Dat is de naam die zal worden weergegeven in de Procedureverkenner van GIMP.

U mag meer dan een procedure hebben gedefinieerd in een plug-in. In dat geval zou u alle namen vermelden, gescheiden door een komma.

Het is een goede werkwijze om al uw procedures te beginnen met uw initialen of een andere herkenbare en unieke tag. Op deze manier is het minder waarschijnlijk dat uw naam hetzelfde zal zijn als de plug-in van iemand anders, wat GIMP in verwarring zou kunnen brengen. Daarnaast bent u vrij om het te noemen zoals u dat wilt.

Vervolgens vertellen we GIMP dat we geen vertalingen ondersteunen door False terug te geven in de aanroep naar `do_set_i18n`. Wat te doen als u wilt dat uw plug-in wordt vertaald, ligt buiten het bereik van deze handleiding.

De methode `do_create_procedure` is waar het meeste initialiseren van GIMP wordt uitgevoerd.

Procedure 13.1. Instellen van do_create_procedure

1. Als u meer dan een procedure definieert in uw plug-in, moet u eerst de parameter "name" controleren om te zien welke procedure door GIMP wordt aangeroepen. We zullen daar hier niet op ingaan.

   Initialiseren van uw plug-in procedure, we moeten het eerst maken en vullen met de naam van onze functie voor Python die het feitelijke werk zal gaan doen. We doen dat door Gimp.ImageProcedure.new aan te roepen.

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

   In dit geval definiëren we de naam van onze plug-in als `self.run`. Wanneer we onze functie kwalificeren met "self.", betekent het dat het een methode binnen onze klasse is. Als u dat liever hebt, mag u het ook definiëren als een normale functie buiten uw klasse, in dat geval zou u "self." weg moeten laten. Het "run" noemen is niet vereist, u mag het elke naam geven die Python accepteert.

2. Vervolgens zullen we GIMP vertellen met welke typen afbeeldingen deze plug-in kan werken door procedure.set_image_types aan te roepen. In het geval dat het type afbeelding niet van belang is, gebruiken we "*", wat alle door GIMP ondersteunde typen betekent. Andere voorbeelden:

   1. "RGB*,GRAY*", waar de "*" hier betekent dat we zowel de versies met als zonder A(lfa)kanaal ondersteunen.

   2. "INDEXED", plug-in werkt alleen op geïndexeerde afbeeldingen, zonder alfakanaal.

   3. "RGBA", plug-in werkt alleen op afbeelding RGB met alfakanaal.

3. In staat zijn om uw plug-in te kunnen starten vanuit het menu van GIMP is gewoonlijk een goed idee. We beginnen met het definiëren van een beschrijvend label voor het menu-item: procedure.set_menu_label.

4. Gevolgd door het specificeren van waar in het menu het zou moeten verschijnen: procedure.add_menu_path. In dit geval vertellen we het onze plug-in toe te voegen aan het menu Filters, onder de categorie Tutorial (submenu).

5. Als u wilt mag u ook een extra Helptip toevoegen, met procedure.set_documentation, en u kunt uw naam als auteur voor de plug-in instellen met procedure.set_attribution.

6. De laatste regel in create procedure is `return procedure`, wat de hierboven toegevoegde informatie terugstuurt naar GIMP. Hierop volgend zal GIMP uw procedure run aanroepen.

#### 4.1.3. Het hoofd invoerpunt aan uw plug-in toevoegen

Elke plug-in wordt gestart met een aanroep naar `Gimp.main`.

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

Het enige dat u in deze regel moet veranderen voor uw plug-in, is de naam van de klasse van uw plug-in, hier “MyFirstPlugin” genoemd.

#### 4.1.4. De volledige plug-in voor Python

Hieronder presenteren we het gehele script voor Python, wat uitgevoerd zou moeten kunnen worden, vooropgesteld dat het de juiste naam heeft gekregen in een map met dezelfde naam op een locatie die bekend is bij GIMP. Het zal de boodschap “Hello world!” weergeven in de foutconsole of in een pop-updialoogvenster.

    #!/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, 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)

3.7. Uw script en het werkt |  | Deel III. Functielijst

Report a bug in GIMP Rapporteer een fout in de documentatie