## 4. Ένα σεμινάριο γραφής προσθέτου Python

This tutorial will teach you the basics about writing a Python plug-in for GIMP 3.0. You are expected to already have some basic knowledge about writing Python in general. If not, there are enough Python courses online, we are not going to duplicate them here.

Τα πρόσθετα του GIMP στην Python (και σε άλλες γλώσσες επίσης) καλούνται μέσα από το GIMP για την εκτέλεση ορισμένων ενεργειών. Για να είναι σε θέση να γνωρίζει πώς να επικοινωνεί με το πρόσθετο και να το καλεί, το GIMP πρέπει να γνωρίζει με ποιο όνομα να το καλεί και ποιες συναρτήσεις υποστηρίζει.

Υπάρχουν ορισμένες απαιτήσεις σχετικά με το όνομα αρχείου και το όνομα καταλόγου ενός πρόσθετου, που πρέπει να είναι τα ίδια. Για περισσότερες λεπτομέρειες, ανατρέξτε στην ενότητα Εγκατάσταση νέων προσθέτων.

### 4.1. Τα βασικά στοιχεία ενός προσθέτου για το GIMP

Θα συζητήσουμε τα βασικά μέρη ενός προσθέτου που απαιτούνται, ή τουλάχιστον είναι πολύ συνηθισμένα για την εργασία με το GIMP.

- Απαιτείται σε Linux και macOS, και κοινή πρακτική στα Windows, να ξεκινάτε με ένα λεγόμενο shebang ή hashbang, μια κωδικοποίηση και μια ειδοποίηση πνευματικών δικαιωμάτων. Η πρώτη γραμμή είναι ένα shebang, το οποίο καθορίζει πώς μπορεί να εκτελεστεί αυτό το σενάριο. Η επόμενη γραμμή καθορίζει την κωδικοποίηση του αρχείου Python. Συνιστούμε utf-8. Συνήθως αυτό ακολουθείται από αρκετές γραμμές που καθορίζουν την άδεια χρήσης με την οποία δημοσιεύετε το σενάριο και μια σύντομη περιγραφή του τι κάνει το σενάριο. Δεν θα εμβαθύνουμε σε αυτό, καθώς αυτό είναι κοινό στην Python γενικά.

- Εισαγωγή απαιτούμενων λειτουργικών μονάδων για πρόσβαση σε συναρτήσεις GIMP και προαιρετικά GEGL.

- Δηλώστε μια τάξη με πολλές προκαθορισμένες συναρτήσεις που πρέπει να προσαρμόσετε, ώστε το GIMP να γνωρίζει ποιες συναρτήσεις είναι διαθέσιμες στο πρόσθετό σας και ποιες λειτουργίες υποστηρίζουν. Θα πάμε σε περισσότερες λεπτομέρειες σχετικά με αυτό παρακάτω.

- Μια κλήση που ξεκινά το πρόσθετο σας, ή θέτει ερωτήματα για τις δυνατότητές του, ανάλογα με τα ορίσματα που του αποστέλλονται από το GIMP.

#### 4.1.1. Απαιτούμενες λειτουργικές μονάδες

Για να μπορέσουμε να προσπελάσουμε στις συναρτήσεις GIMP, ξεκινάμε με το `import gi`. Αυτή η ενότητα μπορεί να καταλάβει ποιες συναρτήσεις είναι διαθέσιμες σε κάθε ενότητα που ορίζεται μέσω της «ενδοσκόπησης αντικειμένου (object introspection)». Αυτό σημαίνει για εμάς, είναι ότι εισάγουμε όλες τις ενότητες που σχετίζονται με το GIMP που μπορεί να χρειαστούμε μέσω κλήσεων στο `gi.repository`.

Για βασική λειτουργικότητα, μόνο οι λειτουργικές μονάδες Gimp και GimpUi μπορεί να είναι αρκετές. Εάν θέλετε να τρέξετε το πρόσθετό σας από τη γραμμή εντολών, δεν χρειάζεστε καν το GimpUi. Ας ξεκινήσουμε με ένα παράδειγμα.

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

Ξεκινάμε με την εισαγωγή του sys, το οποίο χρειαζόμαστε στο τέλος για πρόσβαση στο `sys.argv`, και στη συνέχεια το `import gi` λέει στην Python ότι πρέπει να φορτώσει τη λειτουργική μονάδα gi. Αυτή η λειτουργική μονάδα χρησιμοποιείται για να επιτρέψει την πρόσβαση σε συγκεκριμένες συναρτήσεις του GIMP μέσω της «ενδοσκόπησης αντικειμένων».

Στην επόμενη γραμμή λέμε στη gi ότι απαιτούμε η έκδοση API του GIMP να είναι η έκδοση 3.0. (Αυτό το πρόσθετο δεν θα λειτουργεί με παλαιότερες εκδόσεις του GIMP.) Η ακόλουθη γραμμή ζητά την εισαγωγή όλων των συναρτήσεων, των κλάσεων κ.λπ. από τη λειτουργική μονάδα Gimp.

Για τις επόμενες δύο γραμμές, κάντε το ίδιο πράγμα για το GimpUi. Το GimpUi περιέχει όλα τα στοιχεία που σχετίζονται με τη διεπαφή για το GIMP. Εάν σκοπεύετε να δημιουργήσετε ένα πρόσθετο που θα καλείται μόνο από τη γραμμή εντολών, τότε δεν θα το χρειαστείτε. Ολοκληρώνουμε με την εισαγωγή του GLib, το οποίο χρειαζόμαστε αργότερα για πρόσβαση στο GLib.Error.

There are other optional modules that you can use, too, like Gegl and many others, but we won't go into that here.

#### 4.1.2. Καθορίστε την κλάση του πρόσθετου

Το GIMP πρέπει να γνωρίζει ποιες συναρτήσεις είναι διαθέσιμες, ποιες λειτουργίες υποστηρίζει και ποια θέση μενού να χρησιμοποιήσει. Για αυτό ορίζουμε μια κλάση που προέρχεται από την κλάση `Gimp.PlugIn`.

A minimal plug-in needs at least the following functions defined in this class:

- A `do_query_procedure` method, which GIMP calls to find out the names of the procedures that can be called in this plug-in.

- A `do_set_i18n` method, which GIMP calls to find out if your plug-in supports translations.

- A `do_create_procedure` method, which GIMP calls to start one of your plug-ins functions. When this is called you should initialize certain information for GIMP. You start by creating a procedure that tells GIMP the name of the Python function to call to start your plug-in. Then you supply additional information, like what types of images your plug-in supports, where in the menu should your plug-in be found, and other optional settings.

- Η ενεργή συνάρτηση (που ονομάζεται διαδικασία από το GIMP) που καθορίσατε παραπάνω. Συχνά ονομάζουμε αυτό `run`, αλλά μπορεί να έχει οποιοδήποτε όνομα επιτρέπεται από την Python. Αυτή η συνάρτηση είναι όπου θα προσθέσετε τον δικό σας κωδικό για να εφαρμόσετε τα επιθυμητά αποτελέσματα.

Θα μπούμε σε λίγο περισσότερες λεπτομέρειες τώρα. Δεν περιλαμβάνεται παρακάτω το πρώτο μέρος του κώδικα Python που παρουσιάστηκε παραπάνω. Αυτό δείχνει μόνο τη βασική διάταξη της κλάσης σας.

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

Let's take a closer look at `do_query_procedures`. In the line `return [ "jb-plug-in-first-try" ]` we tell GIMP what the name of our procedure is: we call it "jb-plug-in-first-try". This is the name that will be shown in GIMP's Procedure Browser.

Μπορείτε να ορίσετε περισσότερες από μία διαδικασίες σε ένα πρόσθετο. Σε αυτήν την περίπτωση, θα αναφέρετε όλα τα ονόματα, χωρισμένα με κόμμα.

Είναι καλή πρακτική να ξεκινάτε όλες τις διαδικασίες σας με τα αρχικά σας, ή κάποια άλλη αναγνωρίσιμη και μοναδική ετικέτα. Με αυτόν τον τρόπο, είναι λιγότερο πιθανό το όνομά σας να είναι ίδιο με το πρόσθετο κάποιου άλλου, γεγονός που μπορεί να προκαλέσει σύγχυση στο GIMP. Εκτός αυτού, μπορείτε να το ονομάσετε όπως θέλετε.

Στη συνέχεια, λέμε στο GIMP ότι δεν υποστηρίζουμε μεταφράσεις επιστρέφοντας το False στην κλήση στο `do_set_i18n`. Το τι πρέπει να κάνετε όταν θέλετε να μεταφραστεί το πρόσθετό σας δεν εμπίπτει στον σκοπό αυτού του σεμιναρίου.

Η μέθοδος `do_create_procedure` είναι εκεί που γίνεται το μεγαλύτερο μέρος της προετοιμασίας για το GIMP.

Διαδικασία 13.1. Ρύθμιση του do_create_procedure

1. Εάν ορίζετε περισσότερες από μία διαδικασίες στο πρόσθετό σας, πρέπει πρώτα να ελέγξετε την παράμετρο "name" (όνομα) για να δείτε ποια διαδικασία καλείται από το GIMP. Δεν θα μπούμε σε αυτό εδώ.

   Για να αρχικοποιήσουμε τη διαδικασία του προσθέτου, πρέπει πρώτα να τη δημιουργήσουμε και να συμπληρώσουμε το όνομα της συνάρτησης Python που θα κάνει την πραγματική δουλειά. Αυτό το κάνουμε καλώντας το Gimp.ImageProcedure.new.

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

   Σε αυτήν την περίπτωση ορίζουμε το όνομα του προσθέτου μας ως `self.run`. Όταν χαρακτηρίζουμε τη συνάρτησή μας με το "self.", σημαίνει ότι είναι μια μέθοδος μέσα στην τάξη μας. Εάν προτιμάτε, μπορείτε επίσης να την ορίσετε ως κανονική συνάρτηση εκτός της κλάσης σας, σε αυτήν την περίπτωση θα παραλείψετε το "self". Η ονομασία του "run" δεν απαιτείται, μπορείτε να του δώσετε οποιοδήποτε όνομα αποδέχεται η Python.

2. Στη συνέχεια θα πούμε στο GIMP με ποιους τύπους εικόνων μπορεί να λειτουργήσει αυτό το πρόσθετο καλώντας τη procedure.set_image_types. Σε περίπτωση που ο τύπος της εικόνας δεν έχει σημασία, χρησιμοποιούμε "*", που σημαίνει όλους τους τύπους που υποστηρίζονται από το GIMP. Άλλα παραδείγματα:

   1. "RGB*,GRAY*", όπου το "*" εδώ σημαίνει ότι υποστηρίζουμε και τις δύο εκδόσεις με και χωρίς κανάλι ά(λφα).

   2. "INDEXED", το πρόσθετο λειτουργεί μόνο σε εικόνες με ευρετήριο, χωρίς κανάλι άλφα.

   3. "RGBA", το πρόσθετο λειτουργεί μόνο σε εικόνα RGB με κανάλι άλφα.

3. Το να μπορείτε να ξεκινήσετε το πρόσθετό σας από το μενού του GIMP είναι συνήθως μια καλή ιδέα. Ξεκινάμε ορίζοντας μια περιγραφική ετικέτα για την καταχώρηση μενού: procedure.set_menu_label.

4. Ακολουθεί ο καθορισμός της θέσης στο μενού που πρέπει να φανεί: procedure.add_menu_path. Σε αυτήν την περίπτωση, του λέμε να προσθέσει το πρόσθετό μας στο μενού Φίλτρα, στην κατηγορία Tutorial (υπομενού).

5. Εάν θέλετε, μπορείτε επίσης να προσθέσετε μια επιπλέον συμβουλή βοήθειας, χρησιμοποιώντας procedure.set_documentation και μπορείτε να ορίσετε το όνομά σας ως συντάκτη του προσθέτου χρησιμοποιώντας το procedure.set_attribution .

6. Η τελευταία γραμμή στη διαδικασία δημιουργίας είναι η `return procedure`, η οποία στέλνει τις πληροφορίες που προστέθηκαν παραπάνω πίσω στο GIMP. Μετά από αυτό, το GIMP θα καλέσει τη διαδικασία εκτέλεσης.

#### 4.1.3. Προσθήκη του κύριου σημείου εισόδου στο πρόσθετό σας

Κάθε πρόσθετο ξεκινά με μια κλήση στο `Gimp.main`.

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

Το μόνο πράγμα που πρέπει να αλλάξετε σε αυτήν τη γραμμή για το πρόσθετό σας, είναι το όνομα της κλάσης του προσθέτου σας, που εδώ ονομάζεται «MyFirstPlugin».

#### 4.1.4. Το πλήρες πρόσθετο Python

Παρακάτω παρουσιάζουμε ολόκληρο το σενάριο python, το οποίο θα πρέπει να εκτελείται, με την προϋπόθεση ότι θα του δοθεί το σωστό όνομα σε έναν κατάλογο με το ίδιο όνομα σε μια τοποθεσία που γνωρίζει το GIMP. Θα εμφανίσει το μήνυμα «Hello world!» στην κονσόλα σφαλμάτων, ή σε ένα αναδυόμενο παράθυρο διαλόγου.

    #!/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. Το σενάριο σας και η λειτουργία του |  | Μέρος III. Αναφορά λειτουργιών

Report a bug in GIMP Αναφορά σφάλματος τεκμηρίωσης