I use Python-Fu inside GIMP 2.8.14 on OS X to automate my asset pipeline production for a game.
But I noticed that the method pdb.gimp_image_scale is slower when I execute it from my script, compared to the build-in feature "Image > Scale Image... ".
Scaling down a white image from 8000x8000 to 2000x2000 takes 6.8 seconds by script compared to 1.7 seconds by GUI. That's not that critical, but scaling down my assets with a lot of layers takes 3 minutes and 47 seconds by script, compared to 40 seconds by GUI.
My Activity Monitor showed my that the CPU usage when I executed my script goes only up to about 30%, where the built-in GUI scaling uses up to 100%, which means on OS X a single CPU core is going as fast it can.
Does anybody have an idea, how I can change that behavior?
The odd thing: This seams only to be cause with gimp_image_scale. Other operations like gimp_image_select_contiguous_color, gimp_selection_grow, gimp_selection_feather and gimp_edit_bucket_fill_full drives the CPU usage up to 100%.
On Windows it's the same, but not that bad actually: 1min 28s via script and 33 seconds via build-in GUI.
from gimpfu import *
def scale_image(scale):
image = gimp.image_list()[0]
w = image.width
h = image.height
pdb.gimp_progress_init("Scaling Image...",None)
pdb.gimp_context_set_interpolation(INTERPOLATION_LANCZOS)
pdb.gimp_image_scale(image, w/scale, h/scale)
pass
register(
"jeanluc_scale_image",
"Scale Image",
"Scale Image",
"JeanLuc",
"JeanLuc",
"2015",
"Scale Image...",
"*",
[
(PF_INT, "scale", "Scale of Image", 1)
],
[],
scale_image,
menu="<Image>/JeanLuc"
)
main()
UPDATE1: I found out that Activity Monitor has "CPU History"-feature, where I saw that my assumption was wrong: the 100% is not on 1 core it's distributed 25% over 4 Cores.
So why does it in both cases only run at 25% percent? and why is gimp_image_scale not multithreaded?
Multithreaded Scaling via GUI (on the left) vs Single Threaded via Script (on the right)
UPDATE 2: When I run my script from the "Filters>Python-Fu>Console", it is actually multithreaded and fast.
UPDATE 3: When I run my script without an input value (e.g. scale) and hardcode the value, it runs also multithreaded and fast. It seams that when the scaling is triggered from the dialog it is single threaded.
I found a hacky workaround to execute gimp_image_scale from a new thread. And now instead of 3 minutes and 37 seconds it just takes 24 seconds, so actually faster then build-in GUI solution, that takes 40 seconds.
If somebody knows or finds a proper solution, I will accept that as an answer.
#!/usr/bin/env python
from threading import Thread
import time
from gimpfu import *
def scale_image(scale):
pdb.gimp_progress_init("Scaling Image...",None)
time.sleep(0.5)
thread = Thread(target = thread_scale_image, args = (scale, ))
thread.start()
thread.join()
pass
def thread_scale_image(scale):
image = gimp.image_list()[0]
w = image.width
h = image.height
pdb.gimp_context_set_interpolation(INTERPOLATION_LANCZOS)
pdb.gimp_image_scale(image, w/scale, h/scale)
pass
register(
"jeanluc_scale_image",
"Scale Image",
"Scale Image",
"JeanLuc",
"JeanLuc",
"2015",
"Scale Image...",
"RGB*",
[
(PF_INT, "scale", "Scale of Image", 4)
],
[],
scale_image,
menu="<Image>/JeanLuc"
)
main()