Bátfai Hacker Stream

Bátf41 Haxor Str34m

Bátf41 Haxor Str34m

A GIMP Lisp hackelése - a Scheme programozási nyelv

2019. január 10. - nb

A poszt programjai ugyanúgy használhatók GNU/Linux és Windows rendszereken is!

A GIMP-be épített TinyScheme kipróbálása során villantottuk fel a Lisp programozási nyelvet, mint az eddigiektől merőben más programozói gondolkodásmódot, legalábbis, mint az eddigi BHAX-os C, C++, Java, Python és R példáink szemléletétől távolit. Ha nem tudod, hogy a(z infix, középen a + jel) 2+2 hogy fest fordított lengyel jelölésben, vagy nem tudsz felírni egy rekurzív képletet a faktoriális kiszámításra, akkor Neked is ezzel kell kezdened:

Az eddigi imperatív megközelítésben a faktoriálist úgy csináltuk volna, hogy ciklus a számig és a ciklusváltozóval szorozgatunk egy 1-ről induló változót. A funkcionális gondolkodásban a faktoriális rekurzív definíciója maga a kiszámítás algoritmusa is egyben. (Persze imperatívban is írhatunk rekurzív függvényt, meg funkcionálisban is iteratívat, de utóbbi nem olyan elegáns...)

Ha ezzel a VOD-al megvagy, ráfordulunk egy konkrét példára: mandalát rajzolunk a GIMP-ben! Konkrétan a Tin Tran Pat625_Mandala_With_Your_Name.py Python kódjának eredményét szeretnénk megírni Scheme-ben. A direkt átírás nem látszik jó 5letnek, mert a GIMP változatok 2.4, 2.8 most 2.10 könnyen elveszik a kezdők kedvét, mivel sok példa nem megy pöccintésre... ezért a tutoriál alapján először megcsináljuk a mandalár a GIMP-el, majd ezeket a lépéseket automatizáljuk, hogy egy Scheme program csinálja. Közben persze a Python kód megléte nyilván sokat segít, pédlául abban, hogy a hívandó GIMP függvényeket milyen néven találjuk az API doksiban.

Szóval ilyesmi képeket fogunk rajzolni:

m5.png

Első lépésben a szöveg forgatását valósítsuk meg! A tutoriál számos lépését gépesítsük, sőt tegyük be a GIMP menüjébe, hogy egy kattintásra egyszerűsítsük a használatát, íme ez lesz a végeredmény, mármint nem a mandala, hanem a programozásunké:

gimpm.png

Mandala - első lépés

Mire figyeljünk a következő streamen:

  • valódi API programozásról van szó, hogy használjuk a GIMP Scheme API-ját
  • milyen a program szerkezete, logikája
  • hogyan kell kipróbálni, végül installálni a szkriptet

Második nekifutás

Teljesen befejezzük a tutoriál példáját, itt teljesen eltérünk a Python szkript kódjától és egy sokkal szimplább megoldással keretezzük az elforgatott szövegek rétegét.

A Lisp forráskód olvasása

; bhax_mandala9.scm
;
; BHAX-Mandala creates a mandala from a text box.
; Copyright (C) 2019  Norbert Bátfai, batfai.norbert@inf.unideb.hu
;
;    This program is free software: you can redistribute it and/or modify
;    it under the terms of the GNU General Public License as published by
;    the Free Software Foundation, either version 3 of the License, or
;    (at your option) any later version.
;
;    This program is distributed in the hope that it will be useful,
;    but WITHOUT ANY WARRANTY; without even the implied warranty of
;    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;    GNU General Public License for more details.
;
;    You should have received a copy of the GNU General Public License
;    along with this program.  If not, see <https://www.gnu.org/licenses/>.
;
; Version history
;
;  This Scheme code is partially based on the Python code 
;  Pat625_Mandala_With_Your_Name.py by Tin Tran, which is released under the GNU GPL v3, see 
;  https://gimplearn.net/viewtopic.php/Pat625-Mandala-With-Your-Name-Script-for-GIMP?t=269&p=976
;
;  https://bhaxor.blog.hu/2019/01/10/a_gimp_lisp_hackelese_a_scheme_programozasi_nyelv
; 

(define (elem x lista)

    (if (= x 1) (car lista) (elem (- x 1) ( cdr lista ) ) )

)

(define (text-width text font fontsize)
(let*
    (
        (text-width 1)
    )
    (set! text-width (car (gimp-text-get-extents-fontname text fontsize PIXELS font)))    

    text-width
    )
)

(define (text-wh text font fontsize)
(let*
    (
        (text-width 1)
        (text-height 1)
    )
    ;;;
    (set! text-width (car (gimp-text-get-extents-fontname text fontsize PIXELS font)))    
    ;;; ved ki a lista 2. elemét
    (set! text-height (elem 2  (gimp-text-get-extents-fontname text fontsize PIXELS font)))    
    ;;;    
    
    (list text-width text-height)
    )
)


;(text-width "alma" "Sans" 100)

(define (script-fu-bhax-mandala text text2 font fontsize width height color gradient)
(let*
    (
        (image (car (gimp-image-new width height 0)))
        (layer (car (gimp-layer-new image width height RGB-IMAGE "bg" 100 LAYER-MODE-NORMAL-LEGACY)))
        (textfs)
        (text-layer)
        (text-width (text-width text font fontsize))
        ;;;
        (text2-width (car (text-wh text2 font fontsize)))
        (text2-height (elem 2 (text-wh text2 font fontsize)))
        ;;;
        (textfs-width)
        (textfs-height)
        (gradient-layer)
    )

    (gimp-image-insert-layer image layer 0 0)

    (gimp-context-set-foreground '(0 255 0))
    (gimp-drawable-fill layer FILL-FOREGROUND)
    (gimp-image-undo-disable image) 

    (gimp-context-set-foreground color)

    (set! textfs (car (gimp-text-layer-new image text font fontsize PIXELS)))
    (gimp-image-insert-layer image textfs 0 -1)
    (gimp-layer-set-offsets textfs (- (/ width 2) (/ text-width 2))  (/ height 2))
    (gimp-layer-resize-to-image-size textfs)

    (set! text-layer (car (gimp-layer-new-from-drawable textfs image)))
    (gimp-image-insert-layer image text-layer 0 -1)
    (gimp-item-transform-rotate-simple text-layer ROTATE-180 TRUE 0 0)
    (set! textfs (car(gimp-image-merge-down image text-layer CLIP-TO-BOTTOM-LAYER)))

    (set! text-layer (car (gimp-layer-new-from-drawable textfs image)))
    (gimp-image-insert-layer image text-layer 0 -1)
    (gimp-item-transform-rotate text-layer (/ *pi* 2) TRUE 0 0)
    (set! textfs (car(gimp-image-merge-down image text-layer CLIP-TO-BOTTOM-LAYER)))

    (set! text-layer (car (gimp-layer-new-from-drawable textfs image)))
    (gimp-image-insert-layer image text-layer 0 -1)
    (gimp-item-transform-rotate text-layer (/ *pi* 4) TRUE 0 0)
    (set! textfs (car(gimp-image-merge-down image text-layer CLIP-TO-BOTTOM-LAYER)))
    
    (set! text-layer (car (gimp-layer-new-from-drawable textfs image)))
    (gimp-image-insert-layer image text-layer 0 -1)
    (gimp-item-transform-rotate text-layer (/ *pi* 6) TRUE 0 0)
    (set! textfs (car(gimp-image-merge-down image text-layer CLIP-TO-BOTTOM-LAYER)))    
    
    (plug-in-autocrop-layer RUN-NONINTERACTIVE image textfs)
    (set! textfs-width (+ (car(gimp-drawable-width textfs)) 100))
    (set! textfs-height (+ (car(gimp-drawable-height textfs)) 100))
        
	(gimp-layer-resize-to-image-size textfs)
    
    (gimp-image-select-ellipse image CHANNEL-OP-REPLACE (- (- (/ width 2) (/ textfs-width 2)) 18) 
        (- (- (/ height 2) (/ textfs-height 2)) 18) (+ textfs-width 36) (+ textfs-height 36))
	(plug-in-sel2path RUN-NONINTERACTIVE image textfs)
        
    (gimp-context-set-brush-size 22)
    (gimp-edit-stroke textfs)
    
    (set! textfs-width (- textfs-width 70))
    (set! textfs-height (- textfs-height 70))
    
    (gimp-image-select-ellipse image CHANNEL-OP-REPLACE (- (- (/ width 2) (/ textfs-width 2)) 18) 
        (- (- (/ height 2) (/ textfs-height 2)) 18) (+ textfs-width 36) (+ textfs-height 36))
	(plug-in-sel2path RUN-NONINTERACTIVE image textfs)
        
    (gimp-context-set-brush-size 8)
    (gimp-edit-stroke textfs)
        
    (set! gradient-layer (car (gimp-layer-new image width height RGB-IMAGE "gradient" 100 LAYER-MODE-NORMAL-LEGACY)))
    
    (gimp-image-insert-layer image gradient-layer 0 -1)
	(gimp-image-select-item image CHANNEL-OP-REPLACE textfs)
	(gimp-context-set-gradient gradient) 
	(gimp-edit-blend gradient-layer BLEND-CUSTOM LAYER-MODE-NORMAL-LEGACY GRADIENT-RADIAL 100 0 REPEAT-NONE FALSE TRUE 5 .1 TRUE 500 500 (+ (+ 500 (/ textfs-width 2)) 8) 500)
	
	(plug-in-sel2path RUN-NONINTERACTIVE image textfs)

    (set! textfs (car (gimp-text-layer-new image text2 font fontsize PIXELS)))
    (gimp-image-insert-layer image textfs 0 -1)
    (gimp-message (number->string text2-height))
    (gimp-layer-set-offsets textfs (- (/ width 2) (/ text2-width 2)) (- (/ height 2) (/ text2-height 2)))
		
    ;(gimp-selection-none image)
    ;(gimp-image-flatten image)
    
    (gimp-display-new image)
    (gimp-image-clean-all image)
    )
)

;(script-fu-bhax-mandala "Bátfai Norbert" "BHAX" "Sans" 100 1000 1000 '(255 0 0) "Deep Sea")

(script-fu-register "script-fu-bhax-mandala"
    "Mandala9"
    "Creates a mandala from a text box."
    "Norbert Bátfai"
    "Copyright 2019, Norbert Bátfai"
    "January 9, 2019"
    ""
    SF-STRING       "Text"      "Bátf41 Haxor"
    SF-STRING       "Text2"     "BHAX"
    SF-FONT         "Font"      "Sans"
    SF-ADJUSTMENT   "Font size" '(100 1 1000 1 10 0 1)
    SF-VALUE        "Width"     "1000"
    SF-VALUE        "Height"    "1000"
    SF-COLOR        "Color"     '(255 0 0)
    SF-GRADIENT     "Gradient"  "Deep Sea"
)
(script-fu-menu-register "script-fu-bhax-mandala" 
    "<Image>/File/Create/BHAX"
)

 

A program végső változata

Eltávolítjuk a kódból azokat a behuzalozott részeket, melyek próbálkozásainkból maradtak meg, vagy kérdések alapjául szolgáltak, de a program logikájába nem illenek, illetve pár behuzalozott (melyek előbújhatnak már akkor is, ha a szkript indító paramétereit variálod) hibát javítunk.

A különböző változatokat lásd a repóban: https://gitlab.com/nbatfai/bhax/tree/master/attention_raising/GIMP_Lisp/Mandala

A bejegyzés trackback címe:

https://bhaxor.blog.hu/api/trackback/id/tr9014553360

Kommentek:

A hozzászólások a vonatkozó jogszabályok  értelmében felhasználói tartalomnak minősülnek, értük a szolgáltatás technikai  üzemeltetője semmilyen felelősséget nem vállal, azokat nem ellenőrzi. Kifogás esetén forduljon a blog szerkesztőjéhez. Részletek a  Felhasználási feltételekben és az adatvédelmi tájékoztatóban.

Nincsenek hozzászólások.
süti beállítások módosítása