Yesterday, 04:33 PM
Hi,
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
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