Итерация по вложенным группам GIMP для получения массива слоев - PullRequest
0 голосов
/ 19 апреля 2020

Я новичок в python и пишу плагины GIMP. Я пытаюсь написать простой плагин для выполнения поиска / замены по именам слоев. Мне удалось заставить его работать с «плоским» изображением gimp, но я не могу понять, как заставить его работать итеративно через группы. Вот мой код для «плоской» структуры:

import math
import string
import re
from gimpfu import *
from array import array

def python_search_replace_layer_names(image, layer, searchterm, replaceterm, applyvisible, casesensative) :
    pdb.gimp_image_undo_group_start(image)
    pdb.gimp_context_push() 

    applylayers = []
    for layer in image.layers[::-1]:
        if (applyvisible == 0) or (layer.visible != 0): #user didn't check Only apply visible or if layer is visible.
            applylayers.append([layer,counter])

    for applylayer in applylayers:
        if casesensative == 0:
            searchtermRegEx = re.compile(re.escape(searchterm),re.IGNORECASE)
        else:
            searchtermRegEx = re.compile(re.escape(searchterm))     
        layername = searchtermRegEx.sub(replaceterm, str(applylayer[0].name))
        applylayer[0].name = layername  

    pdb.gimp_context_pop()
    pdb.gimp_image_undo_group_end(image)
    pdb.gimp_displays_flush()

register(
    "python_fu_search_replace_layer_names",
    "Search/Replace in Layer Names",
    "Search/Replace in Layer Names...",
    "stigzler",
    "stigzler",
    "2020",
    "<Image>/Edit/Search and Replace/Replace Layer Names...",
    "RGB*, GRAY*", 
    [
    (PF_STRING, "searchterm", "Search for Term:", "SearchTerm"),
    (PF_STRING, "replaceterm", "Replace With:", "ReplaceWith"),
    (PF_TOGGLE, "applyvisible",   "Only Apply to visible layers:", 0),
    (PF_TOGGLE, "casesensative",   "Case sensative:", 0)
    ],
    [],
    python_search_replace_layer_names)

main()

Я предполагаю, что это будет включать в себя некоторые итеративные, самоссылающиеся функции, но я разбираюсь в трех знаниях:

  1. Соответствующая операция структуры плагина
  2. Не знаю синтаксис / структуру python (обычно. net, хотя я уверен, что есть много общего)
  3. Не зная gimp api для доступа к групповым структурам.

Надеюсь, кто-то может помочь!


ОБНОВЛЕНИЕ:

Благодаря ответу ксеноида, это удалось решить. Если вы ищете переименование слоя, вы можете найти готовый здесь

1 Ответ

1 голос
/ 19 апреля 2020

На самом деле довольно просто. Некоторый код, который я написал для вывода иерархии слоев изображения:

def dump(parent,level,dumpList):
    prefix='     '*level
    for pos,layerOrGroup in enumerate(parent.layers):
        dumpList.append(prefix+layerOrGroup.name)
        if isinstance(layerOrGroup,gimp.GroupLayer):
            dump(layerOrGroup,level+1,dumpList)

def dumpLayerHierarchy(image):
    dumpList=[]
    dump(image,0,dumpList)
    gimp.message('\n'.join(dumpList))

Две вещи, которые нужно знать:

  • Группа слоев является экземпляром gimp.GroupLayer (обычный layer gimp.Layer)
  • duck-typing в своих лучших проявлениях, и у gimp.Image, и у gimp.GroupLayer есть дочерние элементы в атрибуте layers, так что вам даже не нужно специально писать первый случай уровень, на котором вы начинаете с самого изображения.

PS: лучше регистрация:

register(
    "search-replace-layer-names",
    "Search/Replace in Layer Names",
    "Search/Replace in Layer Names...",
    "stigzler",
    "stigzler",
    "2020",
    "Replace Layer Names...",
    "*", 
    [
    (PF_IMAGE,"image", "Image:", None),
    (PF_DRAWABLE, "drawable", "Drawable:", None),
    (PF_STRING, "searchterm", "Search for Term:", "SearchTerm"),
    (PF_STRING, "replaceterm", "Replace With:", "ReplaceWith"),
    (PF_TOGGLE, "applyvisible",   "Only Apply to visible layers:", 0),
    (PF_TOGGLE, "casesensative",   "Case sensative:", 0)
    ],
    [],
    python_search_replace_layer_names
    menu="<Image>/Edit/Search and Replace/"
)

Изменения:

  • Cosmeti c: сделать «атом» более стандартный. «python -fu» добавлено Gimp в любом случае
  • Измените объявление меню на не устаревший тип с отдельным пунктом меню и расположением меню
  • Сделайте тип изображения "*" для поддержки всех изображений типы (ваш код не будет работать с индексированными изображениями)
  • Сделайте параметры Image и Drawable явными. Это иногда полезно. Так как вы, скорее всего, не используете слой / Drawable в любом случае, вы можете удалить его из списка параметров (и из прототипа вашей функции).

Other:

  • Вы надеваете вам не нужно нажимать / вставлять контекст, так как вы не изменяете контекст
  • Вам не нужно копировать слои изображения (image.layers[::-1]) или даже изменять их, поскольку вы просто обновляете атрибуты (если вы удаление слоев было бы другим делом)
  • Отмена группы - это хорошо, но вы можете заключить в скобки свой код в попытке / за исключением того, что в случае проблем группа отмены будет правильно закрыта, и вы все равно сможете легко отменить частичные изменения:
import traceback # To still get source code location

def the_plugin(image,layer):
    image.undo_group_start()
    try:
       # Your code goes here
    except Exception as e:
        trace(e.args[0])
        gimp.message(e.args[0]+':'+traceback.format_exc())
    image.undo_group_end()

Исправлен ваш код:

import re,traceback
from gimpfu import *

def python_search_replace_layer_names(image,searchterm, replaceterm, applyvisible, casesensitive) :

    image.undo_group_start()

    try:
        searchtermRegEx = re.compile(re.escape(searchterm),0 if casesensitive else re.IGNORECASE)
        renameLayers(image,searchtermRegEx,replaceterm,applyvisible)  

    except Exception as e:
        gimp.message(e.args[0]+':'+traceback.format_exc())  

    image.undo_group_end()

def renameLayers(parent,searchtermRegEx,replaceterm,applyvisible):

    for pos,layerOrGroup in enumerate(parent.layers):
        if not applyvisible or layerOrGroup.visible:
            layerName = searchtermRegEx.sub(replaceterm, layerOrGroup.name)
            layerOrGroup.name = layerName

        if isinstance(layerOrGroup,gimp.GroupLayer):
            renameLayers(layerOrGroup,searchtermRegEx,replaceterm,applyvisible)

register(
    "search-replace-layer-names",
    "Search/Replace in Layer Names",
    "Search/Replace in Layer Names...",
    "stigzler",
    "stigzler",
    "2020",
    "Replace Layer Names...",
    "*", 
    [
        (PF_IMAGE,"image", "Image:", None),
        (PF_STRING, "searchterm", "Search for Term:", "SearchTerm"),
        (PF_STRING, "replaceterm", "Replace With:", "ReplaceWith"),
        (PF_TOGGLE, "applyvisible",   "Only Apply to visible layers:", 0),
        (PF_TOGGLE, "casesensitive",   "Case sensative:", 0)
    ],
    [],
    python_search_replace_layer_names,
    menu="<Image>/Edit/Search and Replace/")

main()

Исправления:

  • добавьте пропущенную запятую в конце python_search_replace_layer_names в регистрация
  • добавлена ​​traceback импорт
  • удален вызов функции trace (только в моем собственном коде)
  • удалено много ненужных импортов
  • удалено layer параметр для функции плагина
  • удален level параметр для рекурсии function
  • некоторый код сделал больше pythoni c

Кроме того, слой в группе может быть невидимым либо потому, что он сам невидим (layer.visible ложно), либо потому, что группа невидима. Ваш текущий код не учитывает невидимость, вызванную группой.

Наконец, некоторые подсказки для отладки скриптов Gimp python (с некоторым акцентом на Windows) можно найти здесь .

...