Das bißchen Script-Fu macht sich von allein … (Part 3) | von Clara Fall

Antworten
Benutzeravatar
Gimplyworxs
Beiträge: 2762
Registriert: Sa 22. Aug 2020, 09:11
Wohnort: Crailsheim, BaWü
Deine Galerie: https://gimp-werkstatt.de/werkstatt-galerie/gimplyworxs
Betriebssystem: Linux Mint 20.1 MATE

Das bißchen Script-Fu macht sich von allein … (Part 3) | von Clara Fall

Beitrag von Gimplyworxs »

ClaraFall
aktiv 05.07.2011 - 29.03.2014

Leider ist ClaraFall nicht mehr aktiv in der GIMP-Werkstatt. Wir halten ihre /seine Arbeiten aber in Ehren.

Dieses Tutorial entstand am: 10. Mär 2012

Hallo Ihr Lieben

Dann wollen wir mal weitermachen.

Wir kennen bereits die drei Teile eines GIMP - Skript – Fu - Programmes.
Das Skript, die Registrierung und die Menüstruktureinstellung.
Wir haben auch schon die ersten Skriptbefehle und GIMP-Prozeduren
kennengelernt.

Nachdem wir jetzt die ersten Schritte in Skript – Fu gemeistert haben und uns
Im letzten Part mit der ersten Version des Hilfslinien-Tools beschäftigt hatten.
wollen wir heute der Nummer 2 etwas Leben einhauchen.
Hier noch einmal das Gerippchen:

Bild

An der Maske erkennen wir, wie unser Tutorial (Grobprogramm) aussehen sollte:
  • Soll gelöscht werden
    • Wenn ja
    • Sollen die horizontalen Hilfslinien gelöscht werden
      • Wenn ja; alle horizontalen Hilfslinien löschen
    • Sollen die vertikalen Hilfslinien gelöscht werden
      • Wenn ja; alle vertikalen Hilfslinien löschen
    • Sollen alle Hilfslinien gelöscht werden.
      • Wenn ja; alle Hilfslinien löschen
  • Sollen horizontale Hilfslinien gesetzt werden
    • Wenn ja
    • Ist die Bemaßung Prozent
      • Wenn ja; Berechne den Pixelabstand
    • Ist die Bemaßung Pixel
      • Wenn ja; wir haben bereits den Pixelabstand
    • Soll nur eine Hilfslinie an einer bestimmten Position gesetzt werden
      • Wenn ja; Schleifen-Ende-Zähler auf 1 setzen
    • Sollen mehrere Hilfslinien in bestimmten Abständen gesetzt werden
      • Wenn ja; Schleifen-Ende-Zähler aus Pixelabstand berechnen
    • Schleife "Horizontale Hilfslinie setzen" ausführen
  • Sollen vertikale Hilfslinien gesetzt werden
    • Wenn ja
    • Ist die Bemaßung Prozent
      • Wenn ja; Berechne den Pixelabstand
    • Ist die Bemaßung Pixel
      • Wenn ja; wir haben bereits den Pixelabstand
    • Soll nur eine Hilfslinie an einer bestimmten Position gesetzt werden
      • Wenn ja; Schleifen-Ende-Zähler auf 1 setzen
    • Sollen mehrere Hilfslinien in bestimmten Abständen gesetzt werden
      • Wenn ja; Schleifen-Ende-Zähler aus Pixelabstand berechnen
    • Schleife "Vertikale Hilfslinie setzen" ausführen

Hilfslinien Löschen

Beginnen wir wieder mit dem Löschen.
Dieses Mal soll allerdings nicht nur entweder gelöscht oder nicht gelöscht werden,
es kann sich auch ausgesucht werden, ob nur die horizontalen oder nur die vertikalen Hilfslinien entfernt werden sollen.
Dazu benutzen wir nicht das Kontrollkästchen SF-TOGGLE sondern ein Auswahlfeld SF-OPTION.
Bei der Parameterübergabe wird also dieses Mal nicht TRUE oder FALSE übergeben,
sondern das Ergebnis der Auswahl.
Das ist aber nicht der Text wie ALLE oder KEINE
sondern die Positionsnummer in der Liste,
wobei GIMP (Sheme) beim Zählen mit 0 beginnt.

Unserer Zeile:

Code: Alles auswählen

SF-OPTION "Hilfslinien löschen"     '("Alle" 
                                      "Alle Horizontalen"
                                      "Alle Vertikalen" 
                                      "Keine")
bedeutet also, daß einer der folgenden Werte übergeben wird:

0 bei "Alle"
1 bei "Alle Horizontalen"
2 bei "Alle Vertikalen" und
3 bei "Keine"

Ob wir also überhaupt löschen, prüfen wir mit der if – Abfrage:

Code: Alles auswählen

(if ( < p-Loesch 3)  ; wenn der übergebene Wert kleiner 3 ist 
  (begin             ; dann kann gelöscht werden 

  )
)
Wie das Löschen ALLER Hilfslinien vor sich geht, wissen wir bereits,
Wir holen die erste Hilfslinien ID und löschen sie.
Wir holen die nächste Hilfslinien ID und löschen sie.
Das passiert so lange, bis die zu holende ID Null ist.

Es wird also zuerst mal wieder eine Variable angelegt.
Diese wird auch gleich im (let* Variablendefinitionsbereich vorbelegt.

Code: Alles auswählen

(hilfslinien-ID (car (gimp-image-find-next-guide p-Bild 0)))
Was aber ist zu tun, wenn nur die horizontalen Hilfslinien gelöscht werden sollen?
Wir holen die HilfslinienID
Prüfen deren Ausrichtung
Ist sie Horizontal wird gelöscht.

Hier ergibt sich jetzt ein Problem:
Wenn die nächste Hilfslinie nicht horizontal sondern vertikal ist,
wir aber immer mit 0 anfangen, nach der nächsten Hilfslinie zu suchen,
dann bekommen wir immer wieder diese vertikale Hilfslinie
und unser Skript läuft bis in alle Ewigkeit.
Das kann umgangen werden, indem nur einmal bei 0 begonnen wird,
anschließend wird der gefundene Wert als neuer Startwert genommen.

Wenn jetzt aber die gefundene Hilfslinie wirklich horizontal angelegt ist,
soll sie ja gelöscht werden.
Wenn wir dann diese Hilfslinie löschen und ihre ID als Ausgangs-ID benutzen,
wird es aber eine Fehlermeldung geben, da sie ja nicht mehr existiert.

Ein Teufelskreis

Dieses Problem zu lösen gibt es verschiedene Möglichkeiten:
  • Es werden zuerst alle IDs gesammelt (natürlich in einer Variablen),
    die gelöscht werden sollen.
    Danach werden die IDs aus der Variablen wieder ausgelesen
    und nacheinander gelöscht.
    Wir müssen also im Extremfall zweimal durch die Hilfslinien-ID-Liste.
    Keine tolle Idee.
  • Wenn wir löschen, dann nehmen wir nicht die aktuelle ID als Ausgangswert,
    sondern wieder 0.
    Das kann allerdings dazu führen,
    daß die Liste mit den IDs einige Dutzend male durchforstet wird.
    Noch schlechtere Idee
  • Wir merken uns einfach die letzte funktionierende (nicht gelöschte) ID.
    Das machen wir!
Wie wir uns was merken wissen wir, klar in einer Variablen:

Code: Alles auswählen

(last-ID 0)    ; Variable wird gleich bei der Definition mit 0 vorbelegt
Sollte nämlich bereits die allererste ID gelöscht werden,
war die zuletzt funktionierende ID die Null.

Code: Alles auswählen

( if ( = SollGeloeschtWerden TRUE)
  (begin
    (gimp-image-delete-guide p-Bild hilfslinien-ID)  ; dann lösche
    (set! hilfslinien-ID last-ID)	; und setze  hl-ID zurück auf last-ID
  )
  (begin					; wird nicht gelöscht
    (set! Last-ID hilfslinien-ID) 	; merke diese ID als letze-ID
  )
)

; hole die nächste ID
(set! hilfslinien-ID (car (gimp-image-find-next-guide p-Bild hilfslinien-ID)))
Zwei Dinge fallen hier auf.
  • Die beiden (beginn … ) Blöcke in der if – Abfrage.
    Der erste Block ist klar, der soll erledigt werden,
    wenn die Abfrage wahr ist.
    Der zweite hingegen ist der sogenannte ELSE (Ansonsten) Block
    Der wird genau nur dann ausgeführt,
    wenn die if – Abfrage nicht wahr ist.
    In unserem Fall wird sich die Hilfslinien-ID gemerkt, wenn sie nicht gelöscht wird.
  • Wo kommt das SollGeloeschtWerden her?
    hier müßte ja drinnen stehen, ob die aktuelle Hilfslinie gelöscht werden soll.
    Genau, das wird eine Variable, der wir mitteilen, ob oder ob nicht gelöscht wird.
Zuerst wird die Variable natürlich wieder definiert und
mit auf keinen Fall Löschen (FALSE) vorbelegt.

Code: Alles auswählen

(SollGeloeschtWerden FALSE)
Da wir jetzt 3 verschiedene Löschmöglichkeiten haben,
müßten wir drei if – Abfragen konstruieren.
Und selbst wenn die erste schon wahr wäre
würden die anderen Beiden trotzdem immer mit abgearbeitet werden.
Das wäre zu viel verschwendete Rechnerarbeitszeit.
Hierfür gibt es das (cond ) Konstrukt.

Das sieht in etwa so aus:

Code: Alles auswählen

(cond ((Abfrage 1)
	(begin
			; Block der abgearbeitet wird,
			; wenn Abfrage 1 wahr ist 
	)
      )
      ((Abfrage 2)
	(begin
			; Block der abgearbeitet wird,
			; wenn Abfrage 2 wahr ist 
	)
      )
      ((Abfrage 3)
	(begin
			; Block der abgearbeitet wird,
			; wenn Abfrage 3 wahr ist 
	)
      )

 ; und so weiter

)
Für uns würde es dann so aussehen:

Code: Alles auswählen

(set! SollGeloeschtWerden FALSE)
 
(cond ((= p-Loesch 0) ; Alles Löschen wurde gewählt
	(begin
	  (set! SollGeloeschtWerden TRUE) 
	)
      )
      ((= p-Loesch 1) ; Alle Horizontalen Hilfslinien Löschen wurde gewählt
	(begin
	  (set! SollGeloeschtWerden TRUE) 
	)
      )
      ((= p-Loesch 2) ; Alle Vertikalen Hilfslinien Löschen wurde gewählt
	 (begin
	    (set! SollGeloeschtWerden TRUE) 
	)
      )
Wir prüfen zwar, welche Auswahl getroffen wurde, aber es werden dennoch immer ALLE Hilfslinien gelöscht, da wir ja noch nicht testen, ob sie auch wirklich horizontal oder vertikal ausgerichtet sind.

Das kann schnell korrigiert werden mit gimp-image-get-guide-orientation.

Code: Alles auswählen

(if (= (car(gimp-image-get-guide-orientation p-Bild hilfslinien-ID)) ORIENTATION-HORIZONTAL)
 	(begin
		(set! SollGeloeschtWerden TRUE) 
	)
)
Es wird also geprüft, ob die Richtung der Hilfslinie Horizontal ist.
Dann wird die Variable SollGeloeschtWerden auf TRUE gesetzt.

Der komplette Löschabschnitt sieht jetzt bereits schon so aus.

Code: Alles auswählen

; Löschen vorhandener Hilfslinien
; ===============================

  (if ( < p-Loeschen 3)          ; wenn der übergebene Löschwert kleiner 3 ist 
    (begin                       ; dann kann gelöscht werden 
      (while (<> hilfslinien-ID 0)
        (begin
   	   (set! SollGeloeschtWerden FALSE) ;Setzt die Variable auf FALSE
           (cond ((= p-Loeschen 0)    ; Alles Löschen wurde gewählt
             (begin
               (set! SollGeloeschtWerden TRUE) 
              )
            )
                ((= p-Loeschen 1) ; Alle Horizontale Hilfslinien Löschen wurde gewählt
                  (begin
                    (if (= (car(gimp-image-get-guide-orientation p-Bild hilfslinien-ID)) ORIENTATION-HORIZONTAL)
                      (begin
                        (set! SollGeloeschtWerden TRUE) 
                      )
                    )
                  )
                )
                ((= p-Loeschen 2) ; Alle Vertikalen Hilfslinien Löschen wurde gewählt
                  (begin
                    (if (= (car(gimp-image-get-guide-orientation p-Bild hilfslinien-ID)) ORIENTATION-VERTICAL)
                      (begin
                        (set! SollGeloeschtWerden TRUE) 
                      )
                    )
                  )
                )
              )

        ( if ( = SollGeloeschtWerden TRUE)
          (begin
            (gimp-image-delete-guide p-Bild hilfslinien-ID) ; dann lösche
            (set! hilfslinien-ID last-ID)	; und setze  hl-ID zurück auf last-ID
          )
          (begin					                  ; wird nicht gelöscht
            (set! last-ID hilfslinien-ID) 	; merke diese ID als letze-ID
          )
          )

            (set! hilfslinien-ID (car (gimp-image-find-next-guide p-Bild last-ID)))

          )
        )
      )
    )
Ihr seht, daß auch Verschachtelungen von (if), (while) und(cond) möglich sind.
Wichtig ist nur, daß alle Klammern richtig gesetzt werden.


Horizontale Hilfslinien setzen

Zuerst benötigen wir den Abstand der Hilfslinien
Dazu testen wir, ob die Einheit Prozent ist.
Wenn das der Fall ist, berechnen wir die Prozent mittels ((Bildbreite / 100) * Prozentwert)

Code: Alles auswählen

(if  (= p-Einheit 0)   ; Sind die Angaben in Prozent
  ( begin
    (set! TeilBreite (* (/ BildBreite 100) p-Wert))    
    (set! TeilHoehe (* (/ BildHoehe 100) p-Wert))    
  )
)


; Sollen horizontale Hilfslinien gesetzt werden?
    (if (= p-Hor TRUE)

; Wenn Ja, dann beginne
      (begin

; Sollen sie mehrfach gesetzt werden
        (cond  ((= p-Wie 0)

; Wenn ja, dann beginne
          (begin

; setze den Zähler auf 1
            (set! zaehler 1)

; prüfe ob Zähler mal Horizontaler Abstand noch im Bild sind?
            (while (< (* zaehler TeilHoehe) BildHoehe)

; Wenn ja durchlaufe den Schleifenzyklus
              (begin

; Setze eine horizontale Hilfslinie bei (Zähler * horizontaler Abstand) 
                (gimp-image-add-hguide p-Bild (* zaehler TeilHoehe))

; erhöhe den Zähler um 1
                (set! zaehler (+ zaehler 1))								
              )
            )
          )		
        )

; Soll nur eine horizontale Hilfslinie gesetzt werden
          ( (= p-Wie 1)
            (begin

; dann setze sie bei Abstand
              (gimp-image-add-hguide p-Bild TeilHoehe)

            )		
          )
        )
      )
    )
Sicher ist Euch aufgefallen, daß hier einige Variablen benutzt wurden, die überhaupt noch nicht definiert sind. Das wollen wir gleich mal nachholen.

Code: Alles auswählen

(AbstandHor in-Wert)	
(zaehler 0)
(BildBreite (car (gimp-image-width in-Bild)))
(BildHoehe (car (gimp-image-height in-Bild)))
(TeilBreite p-Wert)
(TeilHoehe p-Wert)	
Die Programmierung des Setzens der vertikalen Hilfslinien sollte jetzt kein Problem mehr sein.
Hier noch einmal das komplette Skript.
Kopiert es in eine SCM-Datei und Ihr spart Euch die Arbeit es abzuschreiben.

Code: Alles auswählen

;**************************************************************
;* Version B  etwas Flexibler
;**************************************************************
; Teil 1 Das Script
;======================================================
(define (script-fu-cf-tools-hilfslinien-b 
            p-Bild 
            p-Ebene 
            p-Loeschen 
            p-Hor 
            p-Ver 
            p-Wie 
            p-Wert 
            p-Einheit)   
            
  (let* (		              ;beginn der Variablendefinition
    (hilfslinien-ID (car (gimp-image-find-next-guide p-Bild 0)))
    (last-ID 0)           ; Variable wird gleich bei der Definition mit 0 vorbelegt
    (SollGeloeschtWerden FALSE)
    (zaehler 0)
    (BildBreite (car (gimp-image-width p-Bild)))
    (BildHoehe (car (gimp-image-height p-Bild)))
    (TeilBreite p-Wert)
    (TeilHoehe p-Wert)	
  )		                    ; ende der Variablendefinition


; Löschen vorhandener Hilfslinien
; ===============================

  (if ( < p-Loeschen 3)          ; wenn der übergebene Löschwert kleiner 3 ist 
    (begin                       ; dann kann gelöscht werden 
      (while (<> hilfslinien-ID 0)
        (begin
   				(set! SollGeloeschtWerden FALSE) ;Setzt die Variable auf FALSE
          (cond ((= p-Loeschen 0)    ; Alles Löschen wurde gewählt
                  (begin
                    (set! SollGeloeschtWerden TRUE) 
                  )
                )
                ((= p-Loeschen 1) ; Alle Horizontale Hilfslinien Löschen wurde gewählt
                  (begin
                    (if (= (car(gimp-image-get-guide-orientation p-Bild hilfslinien-ID)) ORIENTATION-HORIZONTAL)
                      (begin
                        (set! SollGeloeschtWerden TRUE) 
                      )
                    )
                  )
                )
                ((= p-Loeschen 2) ; Alle Vertikalen Hilfslinien Löschen wurde gewählt
                  (begin
                    (if (= (car(gimp-image-get-guide-orientation p-Bild hilfslinien-ID)) ORIENTATION-VERTICAL)
                      (begin
                        (set! SollGeloeschtWerden TRUE) 
                      )
                    )
                  )
                )
              )

        ( if ( = SollGeloeschtWerden TRUE)
          (begin
            (gimp-image-delete-guide p-Bild hilfslinien-ID) ; dann lösche
            (set! hilfslinien-ID last-ID)	; und setze  hl-ID zurück auf last-ID
          )
          (begin					                  ; wird nicht gelöscht
            (set! last-ID hilfslinien-ID) 	; merke diese ID als letze-ID
          )
          )

            (set! hilfslinien-ID (car (gimp-image-find-next-guide p-Bild last-ID)))

          )
        )
      )
    )

    (if  (= p-Einheit 0)   ; Sind die Angaben in Prozent
      ( begin
        (set! TeilBreite (* (/ BildBreite 100) p-Wert))    
        (set! TeilHoehe (* (/ BildHoehe 100) p-Wert))    
      )
    )


; Sollen horizontale Hilfslinien gesetzt werden?
    (if (= p-Hor TRUE)

; Wenn Ja, dann beginne
      (begin

; Sollen sie mehrfach gesetzt werden
        (cond  ((= p-Wie 0)

; Wenn ja, dann beginne
          (begin

; setze den Zähler auf 1
            (set! zaehler 1)

; prüfe ob Zähler mal Horizontaler Abstand noch im Bild sind?
            (while (< (* zaehler TeilHoehe) BildHoehe)

; Wenn ja durchlaufe den Schleifenzyklus
              (begin

; Setze eine horizontale Hilfslinie bei (Zähler * horizontaler Abstand) 
                (gimp-image-add-hguide p-Bild (* zaehler TeilHoehe))

; erhöhe den Zähler um 1
                (set! zaehler (+ zaehler 1))								
              )
            )
          )		
          )

; Soll nur eine horizontale Hilfslinie gesetzt werden
          ( (= p-Wie 1)
            (begin

; dann setze sie bei Abstand
              (gimp-image-add-hguide p-Bild TeilHoehe)
            )		
          )
        )
      )
    )
    
; Setze vertikale Hilfslinien 
    (if (= p-Ver TRUE)
      (begin
        (cond  ((= p-Wie 0)
          (begin
            (set! zaehler 1)
            (while (< (* zaehler TeilBreite) BildBreite)
              (begin
                (gimp-image-add-vguide p-Bild (* zaehler TeilBreite))
                (set! zaehler (+ zaehler 1))								
              )
            )
          )		
          )
          ( (= p-Wie 1)
            (begin
              (gimp-image-add-vguide p-Bild TeilBreite)
            )		
          )
        )
      )
    )    
   
  )
)
  

; Teil 2 Registrierung des Skriptes
;======================================================
	(script-fu-register
		"script-fu-cf-tools-hilfslinien-b"        ;Name der Funktion, die aufgerufen werden soll
		"CFU Hilfslinien Test B"                         ;Name des Skripts
		"Löscht und setzt Hilfslinien" 						;Beschreibung des Skripts
		"CF"                                     	;Name des Autors
		"Copyleft by CF"                         	;Copyright-Infos
		"25.02.2012"                             	;Datum
		"RGB* GRAY* INDEXED*"                     ;
		SF-IMAGE "Das Bild" 0
		SF-DRAWABLE "Die Ebene" 0
 		SF-OPTION "Hilfslinien löschen"     '("Alle" "Alle Horizontalen" "Alle Vertikalen" "Keine")
		SF-TOGGLE "Horizontale Hilfslinien setzen:" TRUE
		SF-TOGGLE "Vertikale Hilfslinien setzen:" TRUE
 		SF-OPTION "Hilfslinien setzen"     	'("Alle" "Bei")
 		SF-ADJUSTMENT "Wert"     						'(25 1 9999 1 10 0 0)
 		SF-OPTION "Einheit"     						'("Prozent" "Pixel")
	)
  
; Teil 3 Festlegen der Menüstruktur
;======================================================
	(script-fu-menu-register "script-fu-cf-tools-hilfslinien-b" "<Image>/CFU/Tests")		



Zusammenfassung

Heute haben wir die zweite Version des Hilfslinienskriptes erarbeitet.
Dieses Skript ist schon etwas Flexibler im Einsatz.
Dadurch benötigt es aber auch ein wenig mehr Programmieraufwand.

Dabei haben wir das (cond ) – Konstrukt kennengelernt.
Es kann mehrere Fälle/Zustände unterscheiden.

(cond ), (if ) und (while ) Abfragen können ineinander verschachtelt sein.

Ansonsten haben wir nur Befehle und Kommandos benutzt,
die wir bereits kannten.

Es ist also möglich, mit wenigen unterschiedlichen Anweisungen
ein oder mehrere Skripte zu erstellen.

Wer bis hierher durchgehalten und vielleicht sogar etwas verstanden hat,
von dem Kauderwelsch, den ich hier fabrizierte,
der sollte sich ruhig trauen und eine eigene Idee angehen und umsetzen.
Nicht gleich zu hohe Ziele stecken, damit es überschaubar bleibt,
aber es darf ruhig etwas Sinnvolles sein.
Und sollte es mal wirklich nicht weitergehen, haben wir ja noch das Forum.
Auf jeden Fall werde ich versuchen zu helfen.


Dann wünsche ich Euch noch viel Erfolg beim Nacharbeiten und Lernen.

Liebe Grüße
Clara
Antworten