Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
script not available
#1
Hi,

Code:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import gi
gi.require_version('Gimp', '3.0')
from gi.repository import Gimp
gi.require_version('GimpUi', '3.0')
from gi.repository import GimpUi
gi.require_version('Gegl', '0.4') # Gegl est utilisé pour les opérations de bas niveau sur les pixels
from gi.repository import Gegl
from gi.repository import GObject
from gi.repository import GLib

import sys
import math # Pour la fonction sqrt (racine carrée) dans le calcul de la différence de couleur

# Fonctions de traduction (standard pour les plugins GIMP)
def N_(message): return message
def _(message): return GLib.dgettext(None, message)

class CleanAndRegularize (Gimp.PlugIn):
   ## GimpPlugIn virtual methods ##

   # Cette méthode est appelée par GIMP au démarrage pour savoir quels plugins sont disponibles
   def do_query_procedures(self):
       # Retourne une liste des noms de procédures que ce plugin fournit
       return [ "plug-in-clean-and-regularize" ]

   # Cette méthode est appelée pour créer une instance de la procédure
   def do_create_procedure(self, name):
       # Crée une nouvelle procédure d'image
       procedure = Gimp.ImageProcedure.new(self, name,
                                           Gimp.PDBProcType.PLUGIN,
                                           self.run, None)

       # Définit les types d'images sur lesquels le plugin peut opérer
       procedure.set_image_types("*") # Peut opérer sur n'importe quel type d'image

       # Définit la sensibilité du plugin (nécessite un calque sélectionné)
       procedure.set_sensitivity_mask(Gimp.ProcedureSensitivityMask.DRAWABLE)

       # Définit le texte qui apparaîtra dans le menu GIMP
       procedure.set_menu_label(_("Nettoyer et Régulariser..."))
       # Définit le chemin dans le menu GIMP
       procedure.add_menu_path('<Image>/Filters/Ma_Regularisation/')

       # Ajoute la documentation (visible dans le navigateur de procédures)
       procedure.set_documentation(_("Nettoie une image en rendant transparents les pixels en dehors d'une couleur sélectionnée, puis régularise la forme restante."),
                                   _("Rend transparents les pixels en dehors d'une couleur sélectionnée et régularise la forme restante."),
                                   name)
       # Attribution de l'auteur
       procedure.set_attribution("Votre Nom", "Votre Nom", "2025")

       # Ajoute les paramètres de la procédure (ceux qui apparaissent dans la boîte de dialogue)
       procedure.add_argument_from_property(GObject.Property(
           "target-color", "Couleur à conserver",
           "La couleur cible à conserver dans l'image.",
           GObject.TYPE_JSUINT64, # Type de propriété pour la couleur (RGBA 64 bits)
           Gimp.RGB(255, 255, 255).to_rgba(), # Valeur par défaut (blanc)
           GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY
       ))
       procedure.add_argument_from_property(GObject.Property(
           "tolerance", "Tolérance de couleur (0-255)",
           "La tolérance pour la comparaison des couleurs (0-255).",
           GObject.TYPE_INT, # Type entier
           30, # Valeur par défaut
           GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
           minimum=0, maximum=255
       ))
       procedure.add_argument_from_property(GObject.Property(
           "operation-type", "Opération de régularisation",
           "Le type d'opération de régularisation à appliquer.",
           GObject.TYPE_INT, # Type entier pour l'option
           0, # Valeur par défaut (0 = Aucune)
           GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
           # Les options sont définies par des paires valeur/label
           blurb_values=["Aucune", "Érosion de la sélection", "Dilatation de la sélection"]
       ))

       return procedure

   # La méthode 'run' est le cœur du plugin, exécutée lorsque l'utilisateur lance le plugin
   def run(self, procedure, run_mode, image, drawables, config, run_data):
       # Vérifie qu'un seul calque est sélectionné
       if len(drawables) != 1:
           msg = _("Procedure '{}' only works with one drawable.").format(procedure.get_name())
           error = GLib.Error.new_literal(Gimp.PlugIn.error_quark(), msg, 0)
           return procedure.new_return_values(Gimp.PDBStatusType.CALLING_ERROR, error)
       else:
           drawable = drawables[0]

       # Récupère les valeurs des paramètres de la configuration
       target_color_rgba = config.get_property("target-color")
       # Convertit la couleur RGBA 64 bits en Gimp.RGB pour un accès facile
       target_color_gimp_rgb = Gimp.RGB()
       target_color_gimp_rgb.parse_rgba(target_color_rgba)
       
       target_r = target_color_gimp_rgb.red_int
       target_g = target_color_gimp_rgb.green_int
       target_b = target_color_gimp_rgb.blue_int

       tolerance = config.get_property("tolerance")
       operation_type = config.get_property("operation-type")

       # Début de l'opération GIMP (pour l'historique d'annulation)
       image.undo_group_start()
       Gimp.progress_init(_("Traitement de l'image..."))

       # Assurez-vous que le calque a un canal alpha pour la transparence
       if not drawable.has_alpha():
           drawable.add_alpha()

       # --- Étape 1 : Rendre transparent les pixels hors couleur cible ---
       width = drawable.get_width()
       height = drawable.get_height()
       
       # Utilisation de Gegl.Buffer pour un accès aux pixels plus performant et moderne
       # Obtient le buffer du calque (le contenu des pixels)
       buffer = drawable.get_buffer()
       # Crée un buffer d'ombre pour les modifications (meilleure pratique pour les plugins)
       shadow_buffer = drawable.get_shadow_buffer()

       # Accès direct aux pixels via Gegl.Buffer.get_pixel() et Gegl.Buffer.set_pixel()
       # C'est plus lent que les opérations GEGL natives, mais plus simple pour ce type de logique
       # Pour des performances extrêmes sur de très grandes images, il faudrait utiliser des opérations GEGL complètes.

       for y in range(height):
           Gimp.progress_update(float(y) / height) # Met à jour la barre de progression
           for x in range(width):
               # Récupère le pixel du buffer original
               pixel_data = buffer.get_pixel(x, y)
               # Les données de pixel sont un tuple (r, g, b, a) où chaque composante est un float de 0.0 à 1.0
               r, g, b, a = pixel_data[0], pixel_data[1], pixel_data[2], pixel_data[3]

               # Convertit les floats (0.0-1.0) en entiers (0-255) pour la comparaison de tolérance
               current_r = int(r * 255)
               current_g = int(g * 255)
               current_b = int(b * 255)
               
               # Calculer la différence de couleur (distance euclidienne)
               diff = math.sqrt((current_r - target_r)**2 + (current_g - target_g)**2 + (current_b - target_b)**2)

               if diff > tolerance:
                   # Rendre le pixel transparent (alpha = 0.0)
                   shadow_buffer.set_pixel(x, y, (r, g, b, 0.0))
               else:
                   # Conserver le pixel tel quel
                   shadow_buffer.set_pixel(x, y, (r, g, b, a))
       
       # Applique les modifications du buffer d'ombre au calque
       drawable.merge_shadow(True)
       # Met à jour la zone modifiée pour l'affichage
       drawable.update(0, 0, width, height)


       # --- Étape 2 : Régulariser la forme restante ---
       # Utilisation des fonctions PDB de GIMP pour les opérations de sélection et de remplissage

       if operation_type == 1: # Érosion de la sélection
           # Crée une sélection à partir du canal alpha du calque
           image.set_selection_mask(drawable.get_alpha_mask())
           # Rétrécit la sélection
           Gimp.selection_shrink(image, 2) # Rétrécir de 2 pixels
           # Inverse la sélection pour remplir l'extérieur
           image.invert_selection()
           # Remplir la sélection inversée avec de la transparence
           drawable.fill(Gimp.FillType.TRANSPARENT)
           # Désélectionne tout
           image.set_selection_mask(None)

       elif operation_type == 2: # Dilatation de la sélection
           image.set_selection_mask(drawable.get_alpha_mask())
           # Agrandit la sélection
           Gimp.selection_grow(image, 2) # Agrandir de 2 pixels
           image.invert_selection()
           drawable.fill(Gimp.FillType.TRANSPARENT)
           image.set_selection_mask(None)
           
       # Rafraîchir l'affichage de toutes les fenêtres GIMP
       Gimp.displays_flush()
       image.undo_group_end() # Fin de l'opération GIMP (pour l'historique d'annulation)
       Gimp.progress_end()

       # Retourne les valeurs de succès
       return procedure.new_return_values(Gimp.PDBStatusType.SUCCESS, GLib.Error())

# Enregistre le plugin dans GIMP
Gimp.main(CleanAndRegularize.__gtype__, sys.argv)

Here's a Python script that's supposed to:
- select a color from an image
- make other colors transparent except for very similar ones
- smooth (delete, add pixels) in the remaining areas so that the angles are sharp in detail

I placed this script in a folder with the same name, but the Gimp3 console returns some errors
Can you fix this script?

thanks
Reply


Forum Jump: