Search code examples
gimpscript-fu

Auto threshold functionality in a gimp script-fu


In the GIMP UI, there is an Apply Threshold functionality (GIMP 2.6) which has an option called Auto. This automatically calculates an appropriate lower threshold value for the image. Is this function/option available to use in a plugin? The gimp-threshold and gimp-histogram functions don't seem to have this option.


Solution

  • Here's the solution I finally used. Works only for grayscale images. Its the same algorithm as in the gimp_histogram_get_threshold function in gimphistogram.c

    http://git.gnome.org/browse/gimp/tree/app/base/gimphistogram.c

    (define (auto-threshold imagePath)
        (let*
            (
                (theImage (car (gimp-file-load
                                        RUN-NONINTERACTIVE
                                        imagePath
                                        imagePath
                                )
                        )
                )
    
                (theDrawable (car  (gimp-image-get-active-drawable theImage)))
                (hist (get-hist theDrawable 0))
            )
            (get-auto-threshold hist)
        )
    )
    
    ;returns the threshold 
    (define (get-auto-threshold hist)
        (let*
            (
                (hist_max (vector-ref hist 0))
                (chist (make-vector 256))
                (cmom (make-vector 256))
                (maxval 255) ;end - start
                (i 1)
                (tmp )
                (chist_max)
                (cmom_max)
                (bvar_max 0)
                (threshold 127)
            )
    
            (vector-set! chist 0 (vector-ref hist 0))
            (vector-set! cmom 0 0)
    
            (set! i 1)
            (while (<= i maxval)
                (if (> (vector-ref hist i) hist_max)
                    (set! hist_max (vector-ref hist i))
                )
                (vector-set! chist i (+ (vector-ref chist (- i 1)) (vector-ref hist i)) )
                (vector-set! cmom i (+ (vector-ref cmom (- i 1)) (* i (vector-ref hist i))) )
                (set! i (+ i 1))
            )
    
            (set! chist_max (vector-ref chist maxval))
            (set! cmom_max (vector-ref cmom maxval))
    
            (set! i 0)      
            (while (< i maxval)
            (if (and (> (vector-ref chist i) 0) (< (vector-ref chist i) chist_max) ) 
                (let* 
                   ((bvar (/ (vector-ref cmom i) (vector-ref chist i))))
    
                   (set! bvar (- bvar (/ (- cmom_max (vector-ref cmom i)) (- chist_max (vector-ref chist i)) ) ))
                   (set! bvar (* bvar bvar))
                   (set! bvar (* bvar (vector-ref chist i)) )
                   (set! bvar (* bvar (- chist_max (vector-ref chist i)) ))
    
                   (if (> bvar bvar_max) 
                      (begin
                        (set! threshold i)
                        (set! bvar_max bvar)
                      )
                    )
    
                )   
            )
            (set! i (+ i 1))
        )
    
        threshold
    )   
    
    
    )
    
    ;returns the raw histogram  with values 0-1 as an array
    (define (get-hist drawable chan)
    (let* (
    (i 0)
    (hist (make-vector 256))
    )
    (set! i 0)
    (while (< i 256)
    (vector-set! hist i (car (cddddr (gimp-histogram drawable chan i i))))
    (set! i (+ i 1))
    )
    hist
    )
    )