Gimp - Script-fu (skriptování nebo bojové umění?)

6. 3. 2001
Doba čtení: 8 minut

Sdílet

Pracujete s programem GIMP dnes a denně a potřebujete určité postupy nějak zautomatizovat? Dnešní článek vám ukáže jak použít Script-Fu - vnitřní skriptovací jazyk tohoto grafického editoru.

Použití zabudovaného skriptovacího jazyka v programu se dnes stává běžnou záležitostí. Asi vás nepřekvapí, že tuto schopnost můžete najít také v grafickém editoru. Určitě je přínosem mít možnost, jak si relativně snadno postavit vlastní makra například v případech, kdy potřebujeme vyprodukovat větší množství obrázků při zachování stejného stylu (typicky tlačítka nebo jiné grafické prvky webových stránek).

Pro skriptování s Gimpem můžete použít jednak jeho zabudovaný jazyk Script-Fu (tím se dnes budeme zabývat), ale také externí skriptovací jazyky (v současné době vím pouze o modulu pro Perl).

Než začneme

Jak říká Mike Terry ve svém Black Belt School Of Script-Fu: „Před začátkem tréninku bychom se měli přesvědčit, že jsme všichni ve stejné tělocvičně.“ Všechny další informace budou vztahovány k aktuální verzi (1.2) programu Gimp, ať už v jeho unixové nebo windowsové mutaci. Je dost pravděpodobné, že se vám podaří zde popsané chvaty uplatnit i v zápase se staršími verzemi (<= 1.0.4), určitě však přitom narazíte na problém, že některé funkce mají lehce odlišné názvy a parametry.

Script-fu je když ? …

Nebudu vás šetřit, script-fu je scheme – jazyk založený na lispu (už vidím jak se jedni chytají za hlavu, druzí si mnou ruce – protože to není poprvé, co se s ním setkávají). Lisp je opravdu velmi populární jazyk pro zabudované skriptování v programech (Emacs, Siag …) zvláště pro jednoduchost syntaxe (z hlediska počítače). Implementace použitá v programu Gimp se jmenuje SIOD (Scheme In One Defun) a její kompletní referenci naleznete na domovské stránce projektu.

Všechny podrobnosti jazyka se sem nevejdou, ale něco málo vám na něj prozradím. Na první pohled si na lispu všimnete, že každý element kódu je uzavřený do kulatých závorek (  ) , takže je místy dokonale vyzávorkováno. Jazyk je striktně funkcionální s infixovou notací, to znamená, že všechno je funkce (i obyčejné sčítání) a pro každé volání funkce se udává nejprve jméno funkce a pak všechny parametry v pořadí podle použití (pro pamětníky – stejně se počítalo na starých polských kalkulačkách). Takto vypadá sčítání (+ 1 1) . Pokud je tělem funkce vícero výrazů, výsledkem funkce je návratová hodnota posledně vyhodnoceného výrazu (funkce).

Uvedu zde alespoň základní konstrukce v porovnání s jazykem c. Upozorňuji, že důležité jsou i mezery:

Tabulka č. 104
Jazyk C SIOD
3 + ( 5 * 7 ) + 2 (+ 3 (* 5 7) 2)
sin(x) (sin x)
int a=1;
int b=2;

//kod pouzivajici promenne a b
a + b;
a * b;
b = a * a
(let* (
    (a 1)
    (b 2)
    )

    ; Kod pouzivajici lokalni promenne a b
    (+ a b)
    (* a b)
    (set! b (* a a) )

)

int funkce( int arg1; int arg2 ){


    delej_neco( arg2 );

     return delej_neco_ro­zumnyho( arg1 );

}

(define (funkce arg1 arg2)


    (delej-neco arg2)

    (delej-neco-rozumnyho arg1)

)

if ( x = 1 ) {


    // podminka splnena

    return 1;

} else {

    // podminka nesplnena

    return 0;

}

(if (= x 1)


    ;podminka splnena

    1


    ;podminka nesplnena

    0

)

A abychom tu neseděli jen tak nasucho, tak si hned ukážeme, jak to vyzkoušet v praxi. Jednou variantou je použít Script-fu konzoli Gimpu kterou vyvoláme z menu palety nástrojů „Rozš. → Script-fu → Konzole“ (pro uživatele s anglickými locales „Xtns → Script-fu → Console“ ). Zde můžeme definovat nebo jen volat funkce, jak se nám zlíbí.

Skript můžeme zadat z konzole, ale mnohem častěji je budeme chtít uchovat nějak trvaleji. Standardně se nahrávají skripty z adresáře „/usr/share/gim­p/1.2/scripts“ a také z $HOME/.gimp-1.2/scripts domovského adresáře aktuálního uživatele (platí pro verzi 1.2). Znovunačtení všech skriptů je možné dosáhnout opět volbou z menu palety nástrojů: „Rozš. → Script-fu → Zaktualizovat“

Při tvorbě Skriptů se vám budou hodit ještě dva nástroje. DB_Browser, který umožňuje prohlížet databázi dostupných funkcí s popisem užití a parametrů. Dostupný je opět z menu „Xtns“ (Rozs.).

Druhým podobným nástrojem je „Plugin Description“ (Popis modulu), dostupný ze stejného menu. Umožňuje listovat pluginy a funkce registrované v systému.

Chcete už konečně nějaký script-fu?

Zatím jsme mluvili pouze o jazyce ve kterém je možné script-fu napsat. Aby se z kódu stal opravdu použitelný script-fu, musí mít dvě části:

  1. Vlastní funkce – provádí samotné operace tak, jak bychom je prováděli v Gimpu ručně
  2. Registrace – způsobí, že se na dané pozici v menu objeví námi definovaná položka. Po jejím vybrání je možné v dialogovém okně scriptu nastavit parametry, se kterými se má naše funkce spustit

Začneme něčím úplně jednoduchým. První skript, neudělá nic jiného, než že otevře nový obrázek požadované velikosti a vybarví ho zadanou barvou. Ukážeme si jak se dá pracovat s grafikou a jak funkci zaregistrovat.

Definujeme funkci script-fu-empty:

(define (script-fu-empty sizex sizey color)
(let* ((img (car (gimp-image-new sizex sizey RGB)))
    (drawable (car (gimp-layer-new img sizex sizey RGB_IMAGE "Empty Layer" 100 NORMAL)))
    (old-fg (car (gimp-palette-get-foreground)))
    (old-bg (car (gimp-palette-get-background))))

    ;vse provedeme v jednom kroku (pujde vratit jednim klikem na undo
    (gimp-image-undo-disable img)

    ;pridame novy layer do naseho noveho obrazku do urovne 0 (background)
    (gimp-image-add-layer img drawable 0)

    ;nastavime barvu pozadi
    (gimp-palette-set-background color)

    ;layer vyplnime barvou
    (gimp-edit-fill drawable BG-IMAGE-FILL)

    ;zrusime selekci
    (gimp-selection-none img)

    ;vratime nastaveni palety na puvodni hodnoty
    (gimp-palette-set-background old-bg)
    (gimp-palette-set-foreground old-fg)

    ;opet zapneme undo logovani
    (gimp-image-undo-enable img)

    ;zobrazime novy obrazek
    (gimp-display-new img))
)

Všimněte si zejména:

  1. jmenné konvence: slova se oddělují pomlčkou „-“. Prefixem „gimp-“ začínají api funkce gimpu, „script-fu-“ všechny script-fu a (nečekaně) i funkce pluginu začínají na „plug-in-“
  2. layer nestačí jen vytvořit funkcí gimp-layer-new, ale je potřeba jej i přidat do nějakého obrázku do určité hladiny funkcí gimp-image-add-layer. Čím vyšší číslo vrstvy tím níž by se zobrazil v dialogu vrstev.
  3. vše co je mezi gimp-image-undo-disable a enablegimp-image-undo-enable se provede vzhledem k undo jako jediná akce

Nyní můžeme funkci zaregistrovat. Položka by se měla objevit v menu palety nástrojů „/Xtns/Script-Fu/Tutor/Empty“.

(script-fu-register
    "script-fu-empty"
    "<Toolbox>/Xtns/Script-Fu/Tutor/Empty"

    "Creates empty new image with given size and color."
    "(c) 2001 Michal Ambroz (O_O)"
    "Licence GPL"
    "January 10, 2001"
    ""
    SF-VALUE "Image sizex"  "100"
    SF-VALUE "Image sizey"  "100"
    SF-COLOR "Background:"  '(255 255 255)
)

Výsledkem je jednoduchý skript-fu, kde v dialogu vyberete barvu a velikost nového obrázku a takový obrázek se vytvoří. Proměnné budou funkcí předány v pořadí, ve kterém byly registrovány. Obecně registrace proměnné vypadá takto:
TYP_PARAMETRU „Výzva pro zadání“ „defaultní hodnota“
například:

Tabulka č. 105
SF-VALUE „Text“ „\“standardni text\""
SF-VALUE „Cislo“ „42“
SF-COLOR „Barva“ '(100 200 0)
SF-TOGGLE „Pravda?“ TRUE
SF-IMAGE „Obrazek“ 0 (nastaví se defaultně aktuální image)
SF-DRAWABLE „Layer“ 0 (defaultně aktuální layer)

Na závěr jsem si pro vás nechal bonbónek. Doslova. Druhý a poslední skriptík bude totiž lentilka. Sice už trošku nakousnutá, ale zato prima bliká, když přes ni přejedete myší.

bitcoin školení listopad 24


(define (script-fu-lentilka sizex sizey uradius lradius bg ucolor lcolor
pressed effect)
(let* ((midx (/ sizex 2))
    (midy (/ sizey 2))
    ;    Vytvor novy obrazek
    (img (car (gimp-image-new sizex sizey RGB)))
    ;    A v nem tri nove vrstvy
    (background (car (gimp-layer-new img sizex sizey RGB_IMAGE "Background" 100 NORMAL)))
    (lower (car (gimp-layer-new img sizex sizey RGB_IMAGE "Lower" 100 NORMAL)))
    (upper (car (gimp-layer-new img sizex sizey RGB_IMAGE "Upper" 100 NORMAL)))
    (offset (* lradius 0.1))
    ;    Uloz si aktualni paletu
    (old-fg (car (gimp-palette-get-foreground)))
    (old-bg (car (gimp-palette-get-background))))

    ;    Vse proved v jednom undo kroku
    (gimp-image-undo-disable img)

    ;    Nastav novou paletu
    (gimp-palette-set-background bg)
    (gimp-palette-set-foreground lcolor)

    ;    Pridej nejvyssi vrstvu
    (gimp-layer-add-alpha upper)            ;horni vrstva bude zcasti prusvitna
    (gimp-selection-all img)                ;vypln barvou pozadi
    (gimp-edit-fill upper BG-IMAGE-FILL)    ;aby po oriznuti nebyly zubate okraje
    (gimp-image-add-layer img upper 0)      ;pridej vrstvu


    ;   Pridej nizsi vrstvu
    (gimp-layer-add-alpha lower)
    (gimp-selection-all img)
    (gimp-edit-fill lower BG-IMAGE-FILL)
    (gimp-image-add-layer img lower 2)

    ;   Pridej vrstvu pozadi (pro orezavani pruhledneho gifu je potreba mit
spravne barevne pozadi
    (gimp-image-add-layer img background 20)
    (gimp-edit-fill background BG-IMAGE-FILL)


    ;    Namaluj vnitrek lentilky
    (gimp-ellipse-select img (- midx lradius) (- midy lradius) (* 2 lradius)
    (* 2 lradius) REPLACE TRUE FALSE 0)
    (gimp-palette-set-foreground lcolor)

    ;    Vypln normalne a pak gradientem
    (gimp-bucket-fill lower FG-BUCKET-FILL MULTIPLY 100 0 FALSE 0 0)
    (gimp-selection-invert img)
    (gimp-edit-cut lower)
    (gimp-layer-set-preserve-trans lower TRUE)
    (gimp-blend lower 2 SCREEN 7 100 0 0 FALSE 0 0 midx midy (+ midx lradius) midy)


    ;    Duplikuj stred lentilky a podle priznaku zapni viditelnost nove vrstvy
    (let ((pressed-layer (car (gimp-layer-copy lower 0))))
        (gimp-layer-set-mode pressed-layer SCREEN)
        (gimp-image-add-layer img pressed-layer 1)
        (if (= pressed TRUE)
            (gimp-layer-set-visible pressed-layer 1)
        )
    (if (= pressed FALSE)
            (gimp-layer-set-visible pressed-layer 0)
        )
    )


    ;    Nakresli horni vrstvu lentilky
    (gimp-ellipse-select img (- midx uradius) (- midy uradius) (* 2 uradius)
    (* 2 uradius) REPLACE TRUE FALSE 0)
    (gimp-palette-set-foreground ucolor)
    (gimp-bucket-fill upper FG-BUCKET-FILL MULTIPLY 100 0 FALSE 0 0)
    (gimp-selection-invert img)
    (gimp-edit-cut upper)
    (gimp-layer-set-preserve-trans upper TRUE)
    (gimp-blend upper 2 SCREEN 7 100 0 0 FALSE 0 0 midx midy (+ midx lradius) midy)



    ;    Vykousni do horni vrstvy diru
    (gimp-ellipse-select img (- midx (* uradius 2)) (- midy (* uradius 2))
    (* 2 uradius) (* 2 uradius) REPLACE TRUE FALSE 0)
    (gimp-edit-cut upper)


    ;    Nahodny efekt spise jako nucena ukazka pouziti pluginu
    (if (= effect TRUE)
        (let (())
        (plug-in-noisify 1 img upper 0 23.0 23.0 23.0 0)
            (plug-in-gauss-rle 1 img upper 2.0 1 1)
            (plug-in-colorify 1 img upper ucolor)
    )
    )


    (gimp-selection-none img)

    ; Vrat puvodni paletu
    (gimp-palette-set-background old-bg)
    (gimp-palette-set-foreground old-fg)

    (gimp-image-undo-enable img)
    (gimp-display-new img))
)


(script-fu-register
   "script-fu-lentilka"
   "<Toolbox>/Xtns/Script-Fu/Tutor/Lentilka"

   "Creates a simple buttone in shape of lenticel."
   "(c) 2001 Michal Ambroz (O_O)"
   "Licence GPL"
   "January 10, 2001"
   ""
   SF-VALUE "Image sizex"  "100"
   SF-VALUE "Image sizey"  "100"
   SF-VALUE "Upper Radius:"  "45"
   SF-VALUE "Lower Radius:"  "40"
   SF-COLOR "Background:"      '(255 255 255)
   SF-COLOR "Upper Color:"      '(0 0 150)
   SF-COLOR "Lower Color:"      '(0 150 180)
   SF-TOGGLE "Pressed:"  FALSE
   SF-TOGGLE "Effect:"  FALSE

)

A to je vše přátelé

Přeji vám veselé gimpování. Budete asi potřebovat spoustu štěstí a trpělivosti. Díky databázi funkcí sice není až takový problém najít to, co chcete použít, ale debugování je opravdu příšerné. Někde jsem četl výstižnou větu, že: „hledání chyby v script-fu je jenom o něco málo méně bolestivé, než kdybyste se většinu času šťouchali tupou vidličkou do oka.“. Přesto si myslím, že přidat k nějaké fungující kostře pár řádek tak, aby to fungovalo, není zase až takový problém a často se taková investice může vyplatit.

Skripty

Odkazy

Použité materiály: