在 GIMP 中使用 python-fu 缩放图像比通过 built-in GUI 更慢
Scaling an image with python-fu in GIMP slower then via built-in GUI
我在 OS X 上使用 GIMP 2.8.14 中的 Python-Fu 来自动化我的游戏资产管道生产。
但我注意到,与 build-in 功能 "Image > Scale Image... ".
相比,当我从我的脚本中执行方法 pdb.gimp_image_scale 时,速度较慢
通过脚本将白色图像从 8000x8000 缩小到 2000x2000 需要 6.8 秒,而通过 GUI 需要 1.7 秒。这并不是那么关键,但通过脚本缩小我的资产需要 3 分 47 秒,而通过 GUI 则需要 40 秒。
我的 Activity Monitor 告诉我,当我执行我的脚本时 CPU 的使用率只达到了大约 30%,而 built-in GUI 缩放使用了 100%,这意味着在 OS X 上,单个 CPU 内核的运行速度尽可能快。
有没有人知道我该如何改变这种行为?
奇怪的是:这个接缝只是因为 gimp_image_scale。 gimp_image_select_contiguous_color、gimp_selection_grow、gimp_selection_feather 和 gimp_edit_bucket_fill_full 等其他操作将 CPU 使用率提高到 100%。
在 Windows 上是一样的,但实际上并没有那么糟糕:通过脚本 1 分 28 秒,通过 build-in GUI 33 秒。
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()
更新 1:
我发现 Activity Monitor 具有 "CPU History" 功能,我发现我的假设是错误的:100% 不在 1 个核心上,而是 25% 分布在 4 个核心上。
那么,为什么在这两种情况下都只有 运行 达到 25%?为什么 gimp_image_scale 不是多线程的?
通过 GUI 进行多线程缩放(左侧)与通过脚本进行单线程缩放(右侧)
更新 2:
当我 运行 我的脚本来自 "Filters>Python-Fu>Console" 时,它实际上是多线程的并且速度很快。
更新 3:
当我 运行 我的脚本没有输入值(例如比例)并对值进行硬编码时,它 运行 也是多线程的并且速度很快。它接缝当从对话框触发缩放时它是单线程的。
我找到了一个 hacky 解决方法 从新线程执行 gimp_image_scale。
现在只需 24 秒,而不是 3 分 37 秒,因此实际上比内置 GUI 解决方案更快,后者需要 40 秒。
如果有人知道或找到合适的解决方案,我会接受它作为答案。
#!/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()
作为提示,这不会影响这个问题,但应该可以帮助其他人解决执行多个(数百个)像素级操作的脚本的性能问题,例如画笔描边或创建选择和填充:UNDO 系统拖动一切都结束了,即使正确分组了 UNDO 步骤。
因此,密集脚本的提示是复制 (pdb.gimp_image_duplicate
) 图像,调用
pdb.gimp_image_undo_disable
在副本上,在那里执行操作,并在完成时,pdb.gimp_edit_copy
和pdb.gimp_edit_paste
将相关drawables转移到原始图像。
我在 OS X 上使用 GIMP 2.8.14 中的 Python-Fu 来自动化我的游戏资产管道生产。
但我注意到,与 build-in 功能 "Image > Scale Image... ".
相比,当我从我的脚本中执行方法 pdb.gimp_image_scale 时,速度较慢通过脚本将白色图像从 8000x8000 缩小到 2000x2000 需要 6.8 秒,而通过 GUI 需要 1.7 秒。这并不是那么关键,但通过脚本缩小我的资产需要 3 分 47 秒,而通过 GUI 则需要 40 秒。
我的 Activity Monitor 告诉我,当我执行我的脚本时 CPU 的使用率只达到了大约 30%,而 built-in GUI 缩放使用了 100%,这意味着在 OS X 上,单个 CPU 内核的运行速度尽可能快。
有没有人知道我该如何改变这种行为?
奇怪的是:这个接缝只是因为 gimp_image_scale。 gimp_image_select_contiguous_color、gimp_selection_grow、gimp_selection_feather 和 gimp_edit_bucket_fill_full 等其他操作将 CPU 使用率提高到 100%。
在 Windows 上是一样的,但实际上并没有那么糟糕:通过脚本 1 分 28 秒,通过 build-in GUI 33 秒。
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()
更新 1: 我发现 Activity Monitor 具有 "CPU History" 功能,我发现我的假设是错误的:100% 不在 1 个核心上,而是 25% 分布在 4 个核心上。
那么,为什么在这两种情况下都只有 运行 达到 25%?为什么 gimp_image_scale 不是多线程的?
通过 GUI 进行多线程缩放(左侧)与通过脚本进行单线程缩放(右侧)
更新 2: 当我 运行 我的脚本来自 "Filters>Python-Fu>Console" 时,它实际上是多线程的并且速度很快。
更新 3: 当我 运行 我的脚本没有输入值(例如比例)并对值进行硬编码时,它 运行 也是多线程的并且速度很快。它接缝当从对话框触发缩放时它是单线程的。
我找到了一个 hacky 解决方法 从新线程执行 gimp_image_scale。 现在只需 24 秒,而不是 3 分 37 秒,因此实际上比内置 GUI 解决方案更快,后者需要 40 秒。
如果有人知道或找到合适的解决方案,我会接受它作为答案。
#!/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()
作为提示,这不会影响这个问题,但应该可以帮助其他人解决执行多个(数百个)像素级操作的脚本的性能问题,例如画笔描边或创建选择和填充:UNDO 系统拖动一切都结束了,即使正确分组了 UNDO 步骤。
因此,密集脚本的提示是复制 (pdb.gimp_image_duplicate
) 图像,调用
pdb.gimp_image_undo_disable
在副本上,在那里执行操作,并在完成时,pdb.gimp_edit_copy
和pdb.gimp_edit_paste
将相关drawables转移到原始图像。