Background: the shellout.py (7 years old script) is an approach for calling NikCollection Filters and using the result in GIMP. It still worked with win10 & win11 until GIMP 3.x.
I’m having trouble converting the Python plug-in script from GIMP 2.x to 3.x.
Thank @Ofnuts for pointing out the helloworld plugin example, that helped me understand the basics a little bit.
TLDR:
1. What are the correct replacements for PF_RATIO & PF_OPTION? Can you provide corresponding code with GIMP 3.x procedure?
2. What is the appropriate way to debug python plugins?
------------------------------
1. I tried using add_enum_argument() and add_choice_argument(), but it seems I don’t fully understand the documentation.
2. I cannot properly debug the code:
- Running "C:\Program Files\gimp3\bin\gimp-console.exe" does not print any useful information when the plugin code is incorrect; it simply does not appear in the menu.
- Running the shellout.py script in VSCode using its interpreter "C:\Program Files\gimp3\bin\python.exe" is also not helpful. It executes but only outputs: "shellout.py is a GIMP plug-in and must be run by GIMP to be used."
(03-24-2025, 04:35 PM)iiey Wrote: TLDR:
1. What are the correct replacements for PF_RATIO & PF_OPTION? Can you provide corresponding code with GIMP 3.x procedure?
2. What is the appropriate way to debug python plugins?
#!/usr/bin/env python3
#
# 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 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')
from gi.repository import Gegl
from gi.repository import GObject
from gi.repository import GLib
from gi.repository import Gio
import time
import sys
Temporarily, just testing widgets for subclasses of GimpResource.
Temporarily, just testing Brush subclass of Resource.
FUTURE: For all the parameter types.
Formerly PF_ constants, now all parameters for which GimpParamSpecs exist.
Not localized, no i18n
'''
def process_args(brush, font, gradient, palette, pattern, choice_val):
'''
Test the args are sane.
'''
assert brush is not None
assert isinstance(brush, Gimp.Brush)
id = brush.get_id()
name = brush.get_name()
assert id is not None
msg = "Brush: {} (ID: {})".format(name, id)
print(msg)
Gimp.message(msg)
assert font is not None
assert isinstance(font, Gimp.Font)
id = font.get_id()
name = font.get_name()
assert id is not None
msg = "Font: {} (ID: {})".format(name, id)
print(msg)
Gimp.message(msg)
assert gradient is not None
assert isinstance(gradient, Gimp.Gradient)
id = gradient.get_id()
name = gradient.get_name()
assert id is not None
msg = "Gradient: {} (ID: {})".format(name, id)
print(msg)
Gimp.message(msg)
assert palette is not None
assert isinstance(palette, Gimp.Palette)
id = palette.get_id()
name = palette.get_name()
assert id is not None
msg = "Palette: {} (ID: {})".format(name, id)
print(msg)
Gimp.message(msg)
assert pattern is not None
assert isinstance(pattern, Gimp.Pattern)
id = pattern.get_id()
name = pattern.get_name()
assert id is not None
msg = "Pattern: {} (ID: {})".format(name, id)
print(msg)
Gimp.message(msg)
assert choice_val is not None
assert isinstance(choice_val, str)
msg = "Choice : {}".format(choice_val)
print(msg)
Gimp.message(msg)
return
def test_dialog(procedure, run_mode, image, drawables, config, data):
'''
Just a standard shell for a plugin.
'''
if run_mode == Gimp.RunMode.INTERACTIVE:
GimpUi.init('python-fu-test-dialog')
Gegl.init(None)
dialog = GimpUi.ProcedureDialog(procedure=procedure, config=config)
dialog.fill(None)
if not dialog.run():
dialog.destroy()
return procedure.new_return_values(Gimp.PDBStatusType.CANCEL, GLib.Error())
else:
dialog.destroy()
03-24-2025, 08:06 PM (This post was last modified: 03-24-2025, 08:06 PM by nchen.)
(03-24-2025, 04:50 PM)iiey Wrote: Hi nchen,
Thank you for your reply, I will take your example with choice as reference and test it out.
Hello iiey,
You're welcome! Hope that helps.
Were you trying to get Radio options working?
You can theoretically use any GTK 3 widgets with the GimpUI dialog.
I just learned GTK recently because I didn't know how to use GimpUI...
Here is an example I just created with Radio option:
Code:
#!/usr/bin/env python3
#
# 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 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')
from gi.repository import Gegl
from gi.repository import GObject
from gi.repository import GLib
from gi.repository import Gio
from gi.repository import Gtk
from gi.repository import Gdk
import time
import sys
Temporarily, just testing widgets for subclasses of GimpResource.
Temporarily, just testing Brush subclass of Resource.
FUTURE: For all the parameter types.
Formerly PF_ constants, now all parameters for which GimpParamSpecs exist.
Not localized, no i18n
'''
def process_args(brush, font, gradient, palette, pattern, choice_val):
'''
Test the args are sane.
'''
assert brush is not None
assert isinstance(brush, Gimp.Brush)
id = brush.get_id()
name = brush.get_name()
assert id is not None
msg = "Brush: {} (ID: {})".format(name, id)
print(msg)
Gimp.message(msg)
assert font is not None
assert isinstance(font, Gimp.Font)
id = font.get_id()
name = font.get_name()
assert id is not None
msg = "Font: {} (ID: {})".format(name, id)
print(msg)
Gimp.message(msg)
assert gradient is not None
assert isinstance(gradient, Gimp.Gradient)
id = gradient.get_id()
name = gradient.get_name()
assert id is not None
msg = "Gradient: {} (ID: {})".format(name, id)
print(msg)
Gimp.message(msg)
assert palette is not None
assert isinstance(palette, Gimp.Palette)
id = palette.get_id()
name = palette.get_name()
assert id is not None
msg = "Palette: {} (ID: {})".format(name, id)
print(msg)
Gimp.message(msg)
assert pattern is not None
assert isinstance(pattern, Gimp.Pattern)
id = pattern.get_id()
name = pattern.get_name()
assert id is not None
msg = "Pattern: {} (ID: {})".format(name, id)
print(msg)
Gimp.message(msg)
assert choice_val is not None
assert isinstance(choice_val, str)
msg = "Choice : {}".format(choice_val)
print(msg)
Gimp.message(msg)
return
class CustomProcedureDialog(GimpUi.ProcedureDialog):
def __init__(self, procedure, config):
super().__init__(procedure=procedure, config=config)
self.set_default_size(600, 100)
# Apply CSS
self.apply_css()
# Get the main content area of the ProcedureDialog
content_area = self.get_content_area()
# Create a scrolled window for the entire dialog
scrolled_window = Gtk.ScrolledWindow()
scrolled_window.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
scrolled_window.set_size_request(400, 300) # Adjust scrolled window size request dims
# Create a container to hold all the UI elements inside the scroll area
content_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=10)
content_box.set_border_width(10)
content_box.get_style_context().add_class("content_box")
# Populate GIMP's default argument UI elements,
# This adds the GIMP argument widgets to the content area
self.fill(None)
# Retrieve all GIMP UI elements that were just added
for child in content_area.get_children():
# Skip the GtkBox and GtkButtonBox elements (ok buttons at the bottom to add them later)
if child.get_name() == "GtkBox" or child.get_name() == "GtkButtonBox":
continue
content_area.remove(child) # Remove them temporarily
content_box.pack_start(child, False, False, 5) # Repack them inside the scrollable box
def get_radio_result(self):
"""Store the radio button selection before closing."""
if self.png_radio.get_active():
self.selected_format = "png"
elif self.jpg_radio.get_active():
self.selected_format = "jpg"
def test_dialog(procedure, run_mode, image, drawables, config, data):
'''
Just a standard shell for a plugin.
'''
I didn't think much about Radio Option because your advice with add_choice_argument() fits for that case too.
The Gimp.message() together with try/except and inspection the Error Console (Add Tab > Error Console) help a lot by debugging, thank you very much again! ?
Now the plugin is working again, at least it works for me locally with win11 and gimp3 ?
I put it in a repository here for archive: https://github.com/iiey/nikGimp
03-26-2025, 05:17 PM (This post was last modified: 03-26-2025, 05:18 PM by Ofnuts.)
(03-26-2025, 04:03 PM)Neptunus Wrote: Hi iiey,
I followed your instructions to install nikplugin :
I created a folder named nikplugin\ under C:\Program Files\GIMP 3\lib\gimp\3.0\plug-ins\
I copied nikplugin.py in this folder.
The Nik collection is in C:\Program Files\Google\Nik Collection\ so, I didn’t change anything in the nikplugin.py file.
I re-started GIMP 3, opened a picture and tried to find NikCollection among the filters without any success.
Please, could you help me ?
Note that ShellOut plugin worked well with Gimp 2.
Thanks.
Neptunus
Is the python support working in your Gimp? Some packages for Windows are missing it. Check if you have Filter > Development > Python-fu > Python console. If it's not there, upgrade your Gimp.
03-26-2025, 07:30 PM (This post was last modified: 03-26-2025, 07:55 PM by denzjos.)
(03-26-2025, 05:17 PM)Ofnuts Wrote:
(03-26-2025, 04:03 PM)Neptunus Wrote: Hi iiey,
I followed your instructions to install nikplugin :
I created a folder named nikplugin\ under C:\Program Files\GIMP 3\lib\gimp\3.0\plug-ins\
I copied nikplugin.py in this folder.
The Nik collection is in C:\Program Files\Google\Nik Collection\ so, I didn’t change anything in the nikplugin.py file.
I re-started GIMP 3, opened a picture and tried to find NikCollection among the filters without any success.
Please, could you help me ?
Note that ShellOut plugin worked well with Gimp 2.
Thanks.
Neptunus
Is the python support working in your Gimp? Some packages for Windows are missing it. Check if you have Filter > Development > Python-fu > Python console. If it's not there, upgrade your Gimp.
Same problem here. I checked the python support and it is like you mentioned.
03-26-2025, 08:01 PM (This post was last modified: 03-26-2025, 08:04 PM by Zbyma72age.)
(03-25-2025, 11:20 PM)iiii Wrote: Cześć nchen,
nie myślałem wiele o Radio Option, ponieważ Twoja rada z add_choice_argument() pasuje również do tego przypadku.
Gimp.message () razem z try/except i inspekcją Error Console ( Dodaj kartę > Error Console ) bardzo pomagają w debugowaniu, dziękuję bardzo jeszcze raz! ?
Teraz wtyczka działa ponownie, przynajmniej u mnie działa lokalnie z win11 i gimp3 ?
Umieściłem ją w repozytorium tutaj do archiwizacji: https://github.com/iiey/nikGimp
Wszelkie porady i/lub PR są mile widziane!
Zainstalowałem i przetestowałem GIMP 3.0.2, działa, ale na razie są dwa problemy
NDE i HDR nie działają.
Współpracy z innymi programami na razie nie sprawdzałem.
Pozdrowienia i dziękuję
(03-26-2025, 08:01 PM)Zbyma72wiek Wrote:
(03-25-2025, 11:20 PM)iiii Wrote: Cześć nchen,
nie odpowiadając na wiele o Radio Option, ponieważ Twoja rada z add_choice_argument() pasuje również do tego przypadku.
Gimp.message () razem z próbą/z wyjątkiem inspekcji Konsola błędów ( Dodaj kartę > Konsola błędów ) bardzo dostępna w debugowaniu, dziękuję bardzo jeszcze raz! ?
Teraz ponownie działa, regularnie u mnie działa lokalnie z win11 i gimp3?
Umieściłem ją w repozytorium tutaj do archiwizacji: https://github.com/iiey/nikGimp
Wszelkie porady i/lub PR są mile dostępne!
Zainstalowałem i przetestowałem GIMP 3.0.2, działa, ale w razie problemów są dwa problemy
NDE i HDR, które nie zostały opisane.
Współpracy z innymi programami w razie nie sprawdzałem.
Pozdrowienia, dziękuję