3

我在 OS X 上的 GIMP 2.8.14 中使用 Python-Fu 来自动化我的游戏资产管道生产。

但是我注意到,与内置功能“Image > Scale Image...”相比,当我从脚本执行pdb.gimp_image_scale方法时,它的速度较慢。

通过脚本将白色图像从 8000x8000 缩小到 2000x2000 需要 6.8 秒,而 GUI 需要 1.7 秒。这不是那么关键,但是通过脚本缩小我的资产需要 3 分 47 秒,而 GUI 需要 40 秒。

我的活动监视器显示,当我执行脚本时 CPU 使用率仅高达 30% 左右,而内置 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 秒,通过内置 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()

UPDATE1: 我发现活动监视器具有“CPU 历史记录”功能,我发现我的假设是错误的:100% 不在 1 个核心上,25% 分布在 4 个核心上。

那么为什么在这两种情况下都只运行 25% 呢?为什么 gimp_image_scale 不是多线程的?

通过 GUI 进行多线程缩放(左侧)与通过脚本进行单线程缩放(右侧)

更新 2: 当我从“Filters>Python-Fu>Console”运行我的脚本时,它实际上是多线程的并且速度很快。

更新 3: 当我在没有输入值(例如比例)的情况下运行我的脚本并对值进行硬编码时,它也可以多线程快速运行。当从对话框触发缩放时,它看起来是单线程的。

4

2 回答 2

2

作为一个提示,这不会影响这个问题,但应该可以帮助其他人解决执行几个(数百个)像素级操作的脚本的性能问题,比如画笔描边,或创建选择和填充:UNDO 系统将所有内容拖下,即使当正确分组 UNDO 步骤。

因此,密集脚本的提示是复制 ( pdb.gimp_image_duplicate) 图像,调用 pdb.gimp_image_undo_disable副本,在那里执行操作,然后完成,pdb.gimp_edit_copy并将pdb.gimp_edit_paste相关的可绘制对象转移到原始图像。

于 2015-01-22T10:53:21.740 回答
1

我找到了一个从新线程执行 gimp_image_scale 的 hacky 解决方法。现在只需要 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()
于 2015-01-22T09:13:42.140 回答