Hlavní navigace

Psaní skriptů pro grafický editor GIMP (2)

13. 5. 2010
Doba čtení: 17 minut

Sdílet

V páté části článku o programovacím jazyce Scheme si na několika demonstračních příkladech ukážeme, jak se specifikují základní vlastností skriptů (nazývaných Script-fu) v grafickém editoru GIMP, jak se tyto skripty přidávají do menu i způsob definice dialogů, v nichž může uživatel nastavovat parametry.

Obsah

1. Definice základních vlastností skriptu a registrace skriptu

2. Registrační funkce „script-fu-register“ a „script-fu-menu-register“

3. První demonstrační příklad – vykreslení spirály

4. Dialog vyvolaný před spuštěním skriptu

5. Druhý demonstrační příklad – zobrazení dialogu se všemi vstupními prvky

6. Třetí demonstrační příklad – nastavení vlastností vykreslované spirály

7. Čtvrtý demonstrační příklad – funkce jako parametr jiných funkcí

8. Obsah následující části seriálu

9. Odkazy na Internetu

1. Definice základních vlastností skriptu a registrace skriptu

V předchozí části článku o programovacím jazyce Scheme jsme si řekli základní informace o podpoře skriptování ve známém rastrovém grafickém editoru GIMP, především o použití skriptů nazývaných Script-Fu. Jedná se o skripty napsané v dialektu programovacího jazyka Scheme, které mohou s využitím zveřejněného API přistupovat k mnoha interním funkcím grafického editoru GIMP a vytvářet i měnit různé typy objektů, se kterými se v GIMPu pracuje. Jedná se například o samotné rastrové obrázky různých typů (plnobarevné obrázky, obrázky ve stupních šedi, obrázky s barvovou paletou…), hladiny (vrstvy), různé kreslicí nástroje (tužky, štětce, rozprašovače), masky, cesty atd. V dnešním článku si nejprve řekneme, jakým způsobem se uživatelské skripty registrují (aby byly volatelné z GIMPu či dalších skriptů) a taktéž to, jak lze definovat dialog, v němž může uživatel zadat parametry potřebné pro běh skriptu.

Obrázek 1: Rozbalené menu Filters, které kromě zaregistrovaných skriptů nabízí i spuštění dalších přídavných modulů, které jsou většinou překládány na danou platformu (tyto moduly mohou být napsané například v céčku či C++, ale i dalších programovacích jazycích).

Nejprve si stručně popíšeme způsob registrace skriptů, protože se jedná o základní věc, kterou je nutné před použitím nějakého skriptu provést. Proces registrace, který se ručně, tj. z grafického uživatelského rozhraní editoru GIMP, spouští příkazem Script-Fu/Obnovit Skripty (Refresh Scripts), slouží mj. i k tomu, aby editor GIMP zajistil správné vygenerování menu zobrazeného nad editovaným obrázkem, umožnil zobrazení základních informací o skriptu (autorovi, datu vytvoření, typu obrázků, se kterými skript dokáže pracovat atd.) a v neposlední řadě též zajistil vytvoření dialogu, který se vyvolá ve chvíli, kdy je skript spuštěný. Zdrojový soubor naprosté většiny skriptů obsahuje minimálně tři části – vlastní funkci, která provádí všechny úkoly, jenž má skript vykonat (jméno této funkce může být téměř libovolné), volání funkce script-fu-menu-register pro vložení skriptu do vybraného menu a nakonec i volání funkce script-fu-register, pomocí níž se skript zaregistruje a která taktéž slouží ke specifikaci parametrů skriptu (tyto parametry jsou nepovinné; pokud nejsou uvedeny, nezobrazí se dialog pro jejich zadání).

Obrázek 2: Spuštění interaktivní konzole jazyka Scheme z grafického editoru GIMP verze 2.4.5. U novějších verzí GIMPu je menu přesunuto přímo do okna s editovaným obrázkem.

2. Registrační funkce „script-fu-register“ a „script-fu-menu-register“

V této kapitole si popíšeme dvojici „registračních“ funkcí nazvaných script-fu-register a script-fu-menu-register. Tyto funkce jsou volané samotným GIMPem po spuštění příkazu Script>Script-Fu/Obnovit Skripty (Refresh Scripts). První z těchto funkcí slouží pro získání základních informací o skriptu. Tyto informace jsou předávány formou řetězců, z nichž mnohé nemají žádný pevně daný formát (což může být někdy problematické, například při zpracovávání data vytvoření skriptu, informace o copyrightu atd.). Jedná se celkem o sedm parametrů, jejichž význam je vypsán v následující tabulce:

Pořadí parametru Význam
1 jméno funkce, v níž je zapsáno tělo skriptu, tato funkce se při spuštění skriptu zavolá
2 jméno skriptu v takové podobě, jak se má zobrazit v menu
3 nápověda, která se zobrazuje například při zastavení kurzoru nad příkazem v menu nebo v browseru konzole jazyka Scheme
4 jméno autora skriptu
5 informace o copyrightu
6 datum vytvoření/poslední úpravy skriptu
7 seznam typů obrázků, na které lze skript použít

Skript, který může být aplikován na plnobarevné obrázky, obrázky ve stupních šedi i obrázky s barvovou paletou, jenž navíc nemá žádné uživatelem měnitelné parametry, by mohl být zaregistrován následujícím příkazem (povšimněte si podtržení před slovem „Spirals“, kterým je možné definovat klávesovou zkratku):

(script-fu-register
    "script-fu-spirals-1"
    "_Spirals-1"
    "Renders spiral with three spins to active layer using current brush"
    "Pavel Tisnovsky"
    "(c) Pavel Tisnovsky"
    "2010-05-11"
    "RGB*, INDEXED*, GRAY*"
)

Funkce script-fu-menu-register je volána s dvojicí parametrů typu řetězec. Prvním parametrem je název funkce, která provádí vlastní skript (jedná se o stejnou funkci, jaká byla uvedena při volání script-fu-register), druhým parametrem cesta ke skriptu v menu. Zastavme se u toho, jakým způsobem se tato cesta zadává. Již v předchozí části tohoto seriálu jsme si řekli, že GIMP rozeznává dva typy skriptů. První typem jsou skripty, které lze volat pouze v případě, že má uživatel otevřený nějaký obrázek, druhým typem skripty, jež naopak nějaký obrázek na základě údajů předaných uživatelem vytváří. U prvního typu skriptů by měla cesta začínat prefixem „<Image>/“, u druhého naopak prefixem „<Toolbox>/“ (ve skutečnosti jsem situaci prozatím poněkud zjednodušil, protože použitelných prefixů a tím i typů skriptů existuje více, například „<Layers>“, „<Channels>“ či „<Patterns>“).

Za prefixem se nachází jméno položky umístěné v hlavním menu, tj. buď se jedná o nějaké již existující jméno (například „File“, „Select“, „Image“, „Filters“ atd.) nebo o položku novou. Pokud se má skript nacházet v nějakém pod-menu (Filters/Render/Clou­ds), je nutné název či názvy jednotlivých úrovní menu od sebe oddělit znakem / (lomítko), takže se výsledná cesta k příkazu podobá běžnému způsobu zadání cesty k souboru. Následuje příklad zařazení skriptu „script-1“ do nového menu nazvaného „Root.cz“, dalšího skriptu „script-2“ do již existujícího menu „Filters“ a třetího skriptu „script-3“ do pod-pod-menu „Filters/Render/Clou­ds“:

(script-fu-menu-register "script-1"
                         "<Image>/Root.cz")
(script-fu-menu-register "script-2"
                         "<Image>/Filters")
(script-fu-menu-register "script-3"
                         "<Image>/Filters/Render/Clouds")

3. První demonstrační příklad – vykreslení spirály

Ukažme si nyní, jakým způsobem můžeme využít informace uvedené v první a ve druhé kapitole při psaní skutečného GIMPovského skriptu, jenž po svém spuštění vykreslí spirálu aktuálně nastaveným štětcem. Při zkoumání zdrojového kódu skriptu, jehož zdrojový kód je vypsán na konci této kapitoly, si můžeme všimnout, že skript je rozdělen na tři části – vlastní kód skriptu představovaný funkcí script-fu-spirals-1, bloku s definicí základních informací o skriptu představovaném funkcí script-fu-register a konečně třetím blokem, který je tvořen funkcí script-fu-menu-register, v níž je provedeno přidání skriptu do menu grafického editoru GIMP. Jak funkci script-fu-register, tak i funkci script-fu-menu-register volá samotný grafický editor a navíc nejsou tyto dvě funkce ze skriptů dostupné (nejsou součástí API GIMPu), na rozdíl od funkce script-fu-spirals-1, kterou lze po zaregistrování našeho skriptu volat prakticky odkudkoli.

Obrázek 3: Po zaregistrování prvního demonstračního příkladu vytvoří GIMP novou položku menu, která je na tomto screenshotu zvýrazněna červenou barvou.

Po spuštění obnovy všech skriptů uživatelským příkazem Script-Fu/Obnovit Skripty (Refresh Scripts) začne grafický editor GIMP vyhledávat všechny uživatelské skripty (uložené v adresáři ~/.gimp-verze/script i skripty společné pro všechny uživatele. Pro každý nalezený skript je spuštěna jejich registrace a následně jejich případné zařazení do menu. Náš první demonstrační příklad je pod názvem Spirals-1 přidán do (pravděpodobně ještě neexistujícího) menu pojmenovaného Root.cz. Jedná se o kořenové menu zobrazené přímo na panelu umístěného nad obrázkem, což je ostatně patrné i ze screenshotu. Pokud uživatel skript z tohoto menu vybere, je zahájeno vykreslování spirály se středem v bodě [200, 200] aktuálně nastaveným štětcem. Protože není nadefinován žádný dialog, v němž by uživatel mohl zadat parametry skriptu, je skript ihned spuštěn a proveden jako jeden editační krok (celou spirálu je tudíž možné vymazat pomocí klávesové zkratky CTRL+Z i když byla ve skutečnosti vykreslena v 900 tazích štětcem). Následuje výpis zdrojového kódu prvního demonstračního příkladu:

; Článek "Tvoříme skripty pro grafický editor GIMP (2)"
; Demonstrační příklad číslo 1
; Tato funkce je zavolána příkazem vyvolaným
; uživatelem z grafického uživatelského rozhraní GIMPu.
(define (script-fu-spirals-1
                             selected-image
                             selected-layer)
    ; definice lokálních proměnných
    (let*
        (
            ; konstanta - počet vrcholů křivky
            ; na jednu otočku spirály
            (vertexes-per-spin 300)
            ; počet prvků vektoru = (x1, y1, x2, y2)
            (npoint 4)
            ; vykreslovaná úsečka je představována vektorem
            ; (vektorem je v tomto kontextu myšlena datová
            ; struktura programovacího jazyka Scheme)
            (segment (make-vector 4 ))
            ; úhly zvětšující se pro každý další vykreslený úsek
            (alfa 0)
            (beta 0)
            ; konstanta - 2xPi
            (full-circle (* 3.1415927 2))
            ; počet vykreslených segmentů
            (step (/ full-circle vertexes-per-spin))
            ; počet otoček spirály
            (spins 3)
            ; vzdálenost vykreslovaného úseku od středu spirály
            (radius 20)
            (old-radius 20)
            ; změna vzdálenosti pro každý další úsek
            (radius-delta (/ (- 200 20) (* vertexes-per-spin spins 1)))
        )
        (gimp-undo-push-group-start selected-image)
        ; programová smyčka, v níž se vykreslí úsečkové segmenty
        ; ze kterých se skládá aproximace spirály
        (while (<= alfa (* full-circle spins 1))
            (set! beta (+ alfa step))
            (set! radius (+ radius radius-delta))
            ; vypočet počáteční a koncové souřadice úsečky
            (vector-set! segment 0 (+ 200 (* old-radius (cos alfa ) )))
            (vector-set! segment 1 (+ 200 (* old-radius (sin alfa ) )))
            (vector-set! segment 2 (+ 200 (* radius (cos beta ) )))
            (vector-set! segment 3 (+ 200 (* radius (sin beta ) )))
            ; vykreslení úsečky štětcem
            (gimp-paintbrush selected-layer 100 npoint segment 0 10)
            ; přinutíme GIMP, aby obrázek průběžně vykresloval
            (gimp-displays-flush)
            ; přechod na další úsek
            (set! alfa beta)
            (set! old-radius radius)
        )
        ; uložíme stav obrázku na zásobník
        (gimp-undo-push-group-end selected-image)
    )
    ; naposledy přinutíme GIMP, aby finální obrázek vykreslil
    (gimp-displays-flush)
)
; základní informace o skriptu - v tomto případě se zde nenachází
; žádné měnitelné položky, tudíž není ani zobrazen dialog
(script-fu-register "script-fu-spirals-1"
    "_Spirals-1"
    "Renders spiral with three spins to current layer using current brush"
    "Pavel Tisnovsky"
    "Pavel Tisnovsky"
    "2010-05-11"
    "RGB*, INDEXED*, GRAY*"
    SF-IMAGE       "Image"         0
    SF-DRAWABLE    "Drawable"      0
)
; registrace skriptu do menu
(script-fu-menu-register "script-fu-spirals-1"
                         "<Image>/Root.cz")
; finito

Obrázek 4: První demonstrační příklad po svém spuštění. Nejprve byl vytvořen obrázek s černým pozadím, posléze vybrán štětec nazvaný „Circle Fuzzy 17“, zvolena žlutá barva štětce a nakonec byl spuštěn demonstrační příklad.

4. Dialog vyvolaný před spuštěním skriptu

Funkce script-fu-register akceptuje kromě sedmi povinných parametrů popsaných ve druhé kapitole i libovolné množství dalších parametrů, pomocí nichž je možné specifikovat obsah dialogu zobrazeného před vlastním provedením skriptu. Tento dialog může obsahovat prakticky libovolnou kombinaci ovládacích prvků, mezi něž patří například vstupní textová či číselná pole, tlačítka vyvolávající další specializované dialogy pro výběr fontu, souboru, barvy, vrstvy (hladiny), dále pak posuvníky (slidery) atd. Každý ovládací prvek je popsán trojicí parametrů – typem ovládacího prvku (jedná se o konstantu, například SF-ADJUSTMENT), libovolným řetězcem, který je v dialogu zobrazen vedle prvku (jedná se o jeho popis – label) a třetím parametrem, jehož význam se liší podle toho, o jaký ovládací prvek se jedná – může jít například o implicitní barvu, jméno fontu, jméno štětce, obsah listboxu atd. Hodnoty zadané uživatelem se předávají do funkce představující tělo skriptu jako její parametry – musíme si tedy dát pozor na to, aby počet parametrů odpovídal počtu prvků dialogu a taktéž na jejich správnou posloupnost. Jména (konstanty) všech typů ovládacích prvků, odpovídající datové typy jazyka Scheme i jejich stručný popis, jsou uvedeny v následující tabulce:

Pojmenování typu Datový typ Scheme Popis
SF-IMAGE Integer (id obrázku) nabídne seznam otevřených obrázků
SF-DRAWABLE Integer (id masky, vrstvy…) nabídne seznam hladin v obrázku
SF-VALUE String vstupní pole pro zadání číselné hodnoty
SF-TOGGLE Boolean (TRUE nebo FALSE) většinou checkbox
SF-PATTERN String (jméno vzorku) nabídne výběr vzorků v novém dialogu
SF-ADJUSTMENT (start min max step1 step2 typ) podle specifikace typu zobrazí buď vstupní pole nebo posuvník
SF-FILENAME String (jméno souboru) nový dialog pro výběr souboru
SF-STRING String vstupní pole pro zadání řetězce
SF-FONT String (jméno fontu) zobrazí dialog pro výběr fontu
SF-COLOR List (seznam RGB, rozsah [0–255] zobrazí dialog pro výběr barvy
SF-OPTION List (seznam řetězců) seznam hodnot (lisbox)
SF-GRADIENT String (jméno gradientu) výběr přechodů (gradientů)

5. Druhý demonstrační příklad – zobrazení dialogu se všemi vstupními prvky

Ve druhém demonstračním příkladu je ukázáno použití všech dostupných typů vstupních prvků. Tento demonstrační příklad, jenž je použitelný (spustitelný) i bez nutnosti otevření či vytvoření nového obrázku, po svém vyvolání z menu zobrazí dialog, v němž se nachází všechny ovládací prvky, které je možné použít v grafickém editoru GIMP. Samotný skript sice ve skutečnosti nic neprovádí (zavolaná funkce demo-box pouze vypíše na standardní výstup text „Do nothing“), ovšem vzhledem ke způsobu volání této funkce je nutné, aby akceptovala přesně takový počet parametrů, jaký odpovídá počtu ovládacích prvků zobrazených na dialogu. Po spuštění tohoto demonstračního příkladu a následném zobrazení dialogu si vyzkoušejte, jak se chovají jednotlivé ovládací prvky. Uvidíte, že aktivace některých prvků (například kliknutím na ně) vede ke zobrazení specializovaných dialogů samotného GIMPu, v nichž lze například vybrat barvu, barevný přechod atd.

Obrázek 5: Dialog zobrazený po spuštění druhého demonstračního příkladu.

Následuje výpis zdrojového kódu druhého demonstračního příkladu:

; Článek "Tvoříme skripty pro grafický editor GIMP (2)"
; Demonstrační příklad číslo 2
; Tato funkce musí akceptovat takový počet parametrů,
; aby odpovídal počtu ovládacích prvků zobrazených
; na dialogu.
(define (demo-box
        value
        adj1
        adj2
        image
        drawable
        toggle
        pattern
        string
        font
        color
        option
        gradient)
    (print "Do nothing")
)
; základní informace o skriptu a současně i definice obsahu dialogu
(script-fu-register "demo-box"
                    "Demo Box..."
                    "Do nothing, just show all input widgets available"
                    "Joe User"
                    "Joe User"
                    "August 2000"
                    ""
                    SF-ADJUSTMENT "SF-ADJUSTMENT (slider)" '( 30 1 2000 1 10 1 0)
                    SF-ADJUSTMENT "SF-ADJUSTMENT"         '(400 1 2000 1 10 1 1)
                    SF-COLOR      "SF-COLOR" '(255 0 255)
                    SF-DRAWABLE   "SF-DRAWABLE" 0
                    SF-FONT       "SF-FONT" ""
                    SF-GRADIENT   "SF-GRADIENT"  "Golden"
                    SF-IMAGE      "SF-IMAGE" 0
                    SF-OPTION     "SF-OPTION" '("Option 1" "Option 2" "Option 3")
                    SF-PATTERN    "SF-PATTERN" "Wood"
                    SF-STRING     "SF-STRING" "Test String"
                    SF-TOGGLE     "SF-TOGGLE" TRUE
                    SF-VALUE      "SF-VALUE" "0"
                    SF-FILENAME   "SF-FILENAME" "/"
)
; registrace skriptu do menu
(script-fu-menu-register "demo-box"
                         "<Toolbox>/Root.cz")
; finito

6. Třetí demonstrační příklad – nastavení vlastností vykreslované spirály

Znalost funkce ovládacích prvků, které je možné vložit do dialogu skriptu, můžeme ihned využít pro rozšíření možností prvního demonstračního příkladu, v němž se vykreslovala spirála bez možnosti změny jejích vlastností. Ve třetím demonstračním příkladu je použit dialog, ve kterém může uživatel zadat pozici středu spirály, její minimální a maximální poloměr (přesněji řečeno nejmenší a největší vzdálenost křivky představující spirálu, od jejího středu), počáteční úhel, od kterého se spirála začne vykreslovat a taktéž celkový počet otoček spirály (ten se zadává výběrem hodnoty z listboxu, přičemž první položka má index 0, druhá index 1 atd.). Zajímavá je funkce prvních dvou ovládacích prvků – výběru obrázku a vrstvy, do které se má provést vykreslování. Tyto ovládací prvky se běžně nezobrazují, protože se implicitně používá aktivní obrázek a vybraná vrstva. Pokud tyto ovládací prvky potřebujeme z nějakého důvodu zobrazit, je možné toho docílit nejjednodušeji tak, že se tyto prvky v dialogu přemístí na jiné místo (postačuje před ně vložit jiný typ ovládacího prvku, což si ostatně můžete vyzkoušet editací zdrojového kódu a opětovným načtením všech skriptů).

Obrázek 6: Dialog zobrazený po spuštění třetího demonstračního příkladu.

Zdrojový kód dnešního třetího demonstračního příkladu má tvar:

; Článek "Tvoříme skripty pro grafický editor GIMP (2)"
; Demonstrační příklad číslo 3
; Tato funkce je zavolána z dialogu vyvolaného uživatelem
; z grafického uživatelského rozhraní GIMPu.
(define (script-fu-spirals-2
                             selected-image
                             selected-layer
                             selected-spins
                             center-x center-y
                             start-radius
                             end-radius
                             start-angle)
    ; definice lokálních proměnných
    (let*
        (
            ; konstanta - počet vrcholů křivky
            ; na jednu otočku spirály
            (vertexes-per-spin 300)
            ; počet prvků vektoru = (x1, y1, x2, y2)
            (npoint 4)
            ; vykreslovaná úsečka je představována vektorem
            ; (vektorem je v tomto kontextu myšlena datová
            ; struktura programovacího jazyka Scheme)
            (segment (make-vector 4 ))
            ; úhly zvětšující se pro každý další vykreslený úsek
            (alfa 0)
            (beta 0)
            ; konstanta - 2xPi
            (full-circle (* 3.1415927 2))
            ; počet vykreslených segmentů
            (step (/ full-circle vertexes-per-spin))
            ; úprava hodnoty zadané uživatelem
            (spins (+ selected-spins 1))
            ; vzdálenost vykreslovaného úseku od středu spirály
            (radius start-radius)
            (old-radius radius)
            ; změna vzdálenosti pro každý další úsek
            (radius-delta (/ (- end-radius start-radius) (* vertexes-per-spin spins 1)))
        )
        (gimp-undo-push-group-start selected-image)
        ; programová smyčka, v níž se vykreslí úsečkové segmenty
        ; ze kterých se skládá aproximace spirály
        (while (<= alfa (* full-circle spins 1))
            (set! beta (+ alfa step))
            (set! radius (+ radius radius-delta))
            ; vypočet počáteční a koncové souřadice úsečky
            (vector-set! segment 0 (+ center-x (* old-radius (cos (+ alfa start-angle) ))))
            (vector-set! segment 1 (+ center-y (* old-radius (sin (+ alfa start-angle) ))))
            (vector-set! segment 2 (+ center-x (* radius (cos (+ beta start-angle) ))))
            (vector-set! segment 3 (+ center-y (* radius (sin (+ beta start-angle) ))))
            ; vykreslení úsečky štětcem
            (gimp-paintbrush selected-layer 100 npoint segment 0 10)
            ; přinutíme GIMP, aby obrázek průběžně vykresloval
            (gimp-displays-flush)
            ; přechod na další úsek
            (set! alfa beta)
            (set! old-radius radius)
        )
        ; uložíme stav obrázku na zásobník
        (gimp-undo-push-group-end selected-image)
    )
    ; naposledy přinutíme GIMP, aby finální obrázek vykreslil
    (gimp-displays-flush)
)
; základní informace o skriptu a definice dialogu
; zobrazeného uživateli
(script-fu-register "script-fu-spirals-2"
    _"_Spirals-2"
    _"Renders various spirals to current layer"
    "Pavel Tisnovsky"
    "Pavel Tisnovsky"
    "2010-05-11"
    "RGB*, INDEXED*, GRAY*"
    SF-IMAGE       "Image"         0
    SF-DRAWABLE    "Drawable"      0

    SF-OPTION     _"Spins"        '(_"1"
                                    _"2"
                                    _"3"
                                    _"4")
    SF-ADJUSTMENT _"X center"     '(200 0 999 1 10 0 1)
    SF-ADJUSTMENT _"Y center"     '(200 0 999 1 10 0 1)
    SF-ADJUSTMENT _"Start radius" '(20  0 999 1 10 0 1)
    SF-ADJUSTMENT _"End radius"   '(180 0 999 1 10 0 1)
    SF-ADJUSTMENT _"Start angle"  '(0 0 359 1 10 0 0)
)
; registrace skriptu do menu
(script-fu-menu-register "script-fu-spirals-2"
                         "<Image>/Root.cz")
; finito

Obrázek 7: Spirála vykreslená pomocí třetího demonstračního skriptu.

7. Čtvrtý demonstrační příklad – funkce jako parametr jiných funkcí

Další, dnes již poslední demonstrační příklad, neukazuje žádnou novou vlastnost grafického editoru GIMP, spíše se jedná o demonstraci jednoho rysu programovacího jazyka Scheme. Již v úvodní části seriálu o Scheme jsme si řekli, že se jedná o programovací jazyk s funkcionálními rysy, v němž jsou funkce považovány za objekty prvního řádu – funkce lze předávat jiným funkcím jako parametry, ukládat je do proměnných, vracet jako výsledek jiných funkcí atd. Právě tato vlastnost programovacího jazyka Scheme je využita ve čtvrtém demonstračním příkladu, konkrétně v pomocné funkci coord, která slouží pro výpočet jedné ze souřadnic bodu ležícího na spirále. Této funkci se předávají jak běžné parametry (poloměr, souřadnice středu spirály, úhel), tak i goniometrická funkce, která se má použít pro výpočet souřadnic. Díky tomu bylo možné tělo této pomocné funkce zapsat bez použití podmíněných bloků. Na tomto místě možná stojí za připomenutí, že podobným způsobem, konkrétně s využitím ukazatelů na funkce, lze tento problém řešit i například v céčku, naopak v Javě by se musel předávat objekt implementující nějaké společné rozhraní:

; Článek "Tvoříme skripty pro grafický editor GIMP (2)"
; Demonstrační příklad číslo 4
; Tato funkce je zavolána z dialogu vyvolaného uživatelem
; z grafického uživatelského rozhraní GIMPu.
(define (script-fu-spirals-3
                             selected-image
                             selected-layer
                             selected-spins
                             center-x center-y
                             start-radius
                             end-radius
                             start-angle)
    ; pomocná funkce pro výpočet jedné souřadnice
    ; bodu ležícího na spirále
    ; (povšimněte si především způsobu použití parametru function)
    (define (coord center radius function angle start-angle)
        (+ center (* radius (function (+ angle start-angle))))
    )
    ; definice lokálních proměnných
    (let*
        (
            ; konstanta - počet vrcholů křivky
            ; na jednu otočku spirály
            (vertexes-per-spin 300)
            ; počet prvků vektoru = (x1, y1, x2, y2)
            (npoint 4)
            ; vykreslovaná úsečka je představována vektorem
            ; (vektorem je v tomto kontextu myšlena datová
            ; struktura programovacího jazyka Scheme)
            (segment (make-vector 4 ))
            ; úhly zvětšující se pro každý další vykreslený úsek
            (alfa 0)
            (beta 0)
            ; konstanta - 2xPi
            (full-circle (* 3.1415927 2))
            ; počet vykreslených segmentů
            (step (/ full-circle vertexes-per-spin))
            ; úprava hodnoty zadané uživatelem
            (spins (+ selected-spins 1))
            ; vzdálenost vykreslovaného úseku od středu spirály
            (radius start-radius)
            (old-radius radius)
            ; změna vzdálenosti pro každý další úsek
            (radius-delta (/ (- end-radius start-radius) (* vertexes-per-spin spins 1)))
        )
        (gimp-undo-push-group-start selected-image)
        ; programová smyčka, v níž se vykreslí úsečkové segmenty
        ; ze kterých se skládá aproximace spirály
        (while (<= alfa (* full-circle spins 1))
            (set! beta (+ alfa step))
            (set! radius (+ radius radius-delta))
            ; vypočet počáteční a koncové souřadice úsečky
            (vector-set! segment 0 (coord center-x old-radius cos alfa start-angle) )
            (vector-set! segment 1 (coord center-y old-radius sin alfa start-angle) )
            (vector-set! segment 2 (coord center-x radius cos beta start-angle) )
            (vector-set! segment 3 (coord center-y radius sin beta start-angle) )
            ; vykreslení úsečky štětcem
            (gimp-paintbrush selected-layer 100 npoint segment 0 10)
            ; přinutíme GIMP, aby obrázek průběžně vykresloval
            (gimp-displays-flush)
            ; přechod na další úsek
            (set! alfa beta)
            (set! old-radius radius)
        )
        ; uložíme stav obrázku na zásobník
        (gimp-undo-push-group-end selected-image)
    )
    ; naposledy přinutíme GIMP, aby finální obrázek vykreslil
    (gimp-displays-flush)
)
; základní informace o skriptu a definice dialogu
; zobrazeného uživateli
(script-fu-register "script-fu-spirals-3"
    _"_Spirals-3"
    _"Renders various spirals to current layer"
    "Pavel Tisnovsky"
    "Pavel Tisnovsky"
    "2010-05-11"
    "RGB*, INDEXED*, GRAY*"
    SF-IMAGE       "Image"         0
    SF-DRAWABLE    "Drawable"      0

    SF-OPTION     _"Spins"        '(_"1"
                                    _"2"
                                    _"3"
                                    _"4")
    SF-ADJUSTMENT _"X center"     '(200 0 999 1 10 0 1)
    SF-ADJUSTMENT _"Y center"     '(200 0 999 1 10 0 1)
    SF-ADJUSTMENT _"Start radius" '(20  0 999 1 10 0 1)
    SF-ADJUSTMENT _"End radius"   '(180 0 999 1 10 0 1)
    SF-ADJUSTMENT _"Start angle"  '(0 0 359 1 10 0 0)
)
; registrace skriptu do menu
(script-fu-menu-register "script-fu-spirals-3"
                         "<Image>/Root.cz")
; finito

Obrázek 8: Spirála vykreslená pomocí čtvrtého demonstračního skriptu.

CS24_early

8. Obsah následující části seriálu

V následující části seriálu o programovacím jazyce Scheme se již budeme zabývat poněkud praktičtějšími možnostmi skriptů spouštěných v rámci grafického editoru GIMP. Ukážeme si způsob zadávání a změny parametrů kreslicích nástrojů (včetně manipulace s barevnými přechody), použití vrstev (hladin) a taktéž práci s cestami (paths).

Obrázek 9: Spirály vykreslené pomocí čtvrtého demonstračního skriptu.

9. Odkazy na Internetu

  1. A Script-Fu Tutorial
    http://www.li­nuxtopia.org/on­line_books/grap­hics_tools/gim­p_user_manual/en/gimp-using-script-fu-tutorial.html
  2. A Script-Fu Tutorial
    http://docs.gim­p.org/en/gimp-using-script-fu-tutorial.html
  3. Script-fu Tutorial
    http://www.se­ul.org/~grumbel/gim­p/script-fu/script-fu-tut.html
  4. Lambda calculus
    http://en.wiki­pedia.org/wiki/Lam­bda_calculus
  5. A Short Introduction to the Lambda Calculus
    http://www.cs­.bham.ac.uk/~ax­j/pub/papers/lam­bda-calculus.pdf
  6. A Tutorial Introduction to the Lambda Calculus
    http://www.inf.fu-berlin.de/leh­re/WS03/alpi/lam­bda.pdf
  7. (welcome '(schemers . org))
    http://www.sche­mers.org/
  8. Revised5 Report on the Algorithmic Language Scheme
    http://www.sche­mers.org/Docu­ments/Standar­ds/R5RS/
  9. The Revised6 Report on the Algorithmic Language Scheme
    http://www.r6rs­.org/
  10. Scheme
    http://groups­.csail.mit.edu/mac/pro­jects/scheme/
  11. The Kawa language framework
    http://www.gnu­.org/software/ka­wa/
  12. Scheme 48
    http://s48.org/
  13. Introductory textbooks for Schemers
    http://www.sche­mers.org/Docu­ments/#intro-texts
  14. Scheme (programming language)
    http://en.wiki­pedia.org/wiki/Sche­me_(programmin­g_language)
  15. Scheme
    http://cs.wiki­pedia.org/wiki/Sche­me
  16. Scheme-faq
    http://communi­ty.schemewiki­.org/?scheme-faq
  17. Scheme implementations
    http://communi­ty.schemewiki­.org/?scheme-faq-standards#imple­mentations
  18. Successful Scheme
    http://www.it­world.com/swol-1013-regex
  19. Guy L. Steele, Jr.
    http://en.wiki­pedia.org/wiki/Gu­y_L._Steele
  20. Gerald Jay Sussman
    http://en.wiki­pedia.org/wiki/Ge­rald_Jay_Sussman
  21. PLT Scheme
    http://www.plt-scheme.org/
  22. Quick: An Introduction to PLT Scheme with Pictures
    http://docs.plt-scheme.org/quick/
  23. PLT Scheme
    http://en.wiki­pedia.org/wiki/Plt_sche­me
  24. PLT Scheme Guide
    http://docs.plt-scheme.org/guide/
  25. The DrScheme Project: An Overview
    http://citese­erx.ist.psu.e­du/viewdoc/sum­mary?doi=10.1­.1.22.9543
  26. DrScheme
    http://en.wiki­pedia.org/wiki/DrSche­me
  27. How to Design Programs
    http://www.htdp­.org/
  28. An Introduction to Scheme
    http://www.ac­m.org/crossro­ads/xrds1–2/scheme.html

Byl pro vás článek přínosný?

Autor článku

Vystudoval VUT FIT a v současné době pracuje na projektech vytvářených v jazycích Python a Go.