GiMP (Scheme) Script-fu error "illegal function"

1k Views Asked by At

I am busy with a Script-fu and keep getting "Error ( : 1) illegal function". I am not a Scheme/Lisp expert, just trying to automate some photographic tasks. Documentation is rare - either GiMP only writing about their own internal actions but not the syntax of Scheme in Script-fu, or I find "tips" for GiMP v1.0 (i.e. so dated they're useless).

I have looked at a bunch of the scripts supplied with GiMP, trying to learn more and figure this out, but to no avail. I ask here for help to remove the bug, not indentation layout or the fact that Python-fu exists, etc.

And with that, the code (reduced to functional skeleton):

;;
;; license, author, blah blah
;; FOR ILLUSTRATION PURPOSES
;; GiMP 2.8 LinuxMint 18.1
;; does the work, but then blows up saying "Error ( : 1) illegal function"
;;

(define (script-fu-ScriptFails InImage InLayer pickd mrge)
  (let* (
      (CopyLayer (car (gimp-layer-copy InLayer TRUE)) )
    )
    (gimp-image-undo-group-start InImage)
    (gimp-image-add-layer InImage CopyLayer -1)
    (gimp-drawable-set-visible CopyLayer TRUE)
    ;; Perform CHOSEN action on CopyLayer
    (if (equal? pickd 0) (   ;; keep just the RED
      (plug-in-colors-channel-mixer TRUE InImage CopyLayer FALSE  1.0 0 0  0 0 0  0 0 0)
      (gimp-drawable-set-name CopyLayer "RED")
    ))
    (if (equal? pickd 1) (   ;; keep just the GREEN
      (plug-in-colors-channel-mixer TRUE InImage CopyLayer FALSE  0 0 0  0 1.0 0  0 0 0)
      (gimp-drawable-set-name CopyLayer "GRN")
    ))
    (if (equal? pickd 2) (   ;; keep just the BLUE
      (plug-in-colors-channel-mixer TRUE InImage CopyLayer FALSE  0 0 0  0 0 0  0 0 1.0)
      (gimp-drawable-set-name CopyLayer "BLU")
    ))
    (if (equal? mrge #t) (   ;; to merge or not to merge
      (gimp-layers-flatten InImage)
    ))
    (gimp-image-undo-group-end InImage)
    (gimp-display-flush)
  )
)

(script-fu-register "script-fu-ScriptFails"
  _"<Image>/Script-Fu/ScriptFails..."
  "Runs but fails at the end. Why? Please help!"
  "JK"
  "(pop-zip,G-N-U)"
  "2016.12"
  "RGB*"
  SF-IMAGE       "The Image"    0
  SF-DRAWABLE    "The Layer"    0
  ;; other variables:
  SF-OPTION      "Effect"  '("R_ed" "G_rn" "B_lu")
  SF-TOGGLE      "Merge Layers" FALSE
)
1

There are 1 best solutions below

1
On BEST ANSWER

It looks like you use parentheses as blocks. eg:

(if (equal? pickd 2) (   ;; keep just the BLUE
      (plug-in-colors-channel-mixer TRUE InImage CopyLayer FALSE  0 0 0  0 0 0  0 0 1.0)
      (gimp-drawable-set-name CopyLayer "BLU")
    ))

You see the opening paren before the comment about keeping the blue? Well that means that you are doing this:

((plu-in....) (gimp-drawable...))

The first of course need to return a function to be valid Scheme and the return from the second will be the supplied argument. If you wanted to do two expressions because of their side effects then you should use a block. Like the curlies in C dialects blocks are forms starting with begin in Scheme:

(begin
  (plu-in....)
  (gimp-drawable...))

Thus this will evaluate the expressions and the result of the last expression is the result if it's also the tail of the function.

Also for an if with only a consequence and no alternative using when will give you a begin:

(when (equal? pickd 2) ;; keep just the BLUE (and no extra parens)
  (plug-in-colors-channel-mixer TRUE InImage CopyLayer FALSE  0 0 0  0 0 0  0 0 1.0)
  (gimp-drawable-set-name CopyLayer "BLU"))