; random_density_map.scm
; by Rob Antonishen
; http://ffaat.pointclark.net

; Version 2.0 (20080521)

; Description
;
; Script to draw a specified number of random points with the currently 
; selected brush, using a density mask.
; Will appear in Filters->Map Menu
;

; originally  based on random.scm
; by Charles Cave <charlesweb@optusnet.com.au>
; http://members.optusnet.com.au/~charles57/GIMP

; License:
;
; 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 2 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.
;
; The GNU Public License is available at
; http://www.gnu.org/copyleft/gpl.html
(define (script-fu-random-density-map img inLayer inDensityMap inInvertMap inUseAlpha inDensity inMargin inSpacing inJitter inJitterAmt)
  (let* (
        (x1 0)
        (y1 0)
        (ctr 0)
        (x2 (car (gimp-drawable-width inLayer)))
        (y2 (car (gimp-drawable-height inLayer)))
        (xMap (car (gimp-drawable-width inDensityMap)))
        (yMap (car (gimp-drawable-height inDensityMap)))
        (x 0)
        (y 0)
        (map-type 0)
        (get-val 0)
        (test 0)
        (thresh 0)
        (*newpoint* (cons-array 2 'double))
        (drw-width 0)
        (drw-height 0)
		(xcount 0)
		(ycount 0)
		(lc 0)
        )

  ;get map type:  RGB-IMAGE (0), RGBA-IMAGE (1), GRAY-IMAGE (2), GRAYA-IMAGE (3), INDEXED-IMAGE (4), INDEXEDA-IMAGE (5) 
  (set! map-type (car (gimp-drawable-type inDensityMap)))

   
  ; make sure maps isn't indexed
  (if (or (= map-type INDEXED-IMAGE) (= map-type INDEXEDA-IMAGE))
    (gimp-message "Density Map can not be indexed!") ; error
	(if (or (not (= x2 xMap)) (not (= y2 yMap)))
      (gimp-message "Density Map must be the same size as the active layer!") ; error
	    ;it begins here
		(begin 
          ; define drawable area for the algorithm
         (set! x1 (+ x1 inMargin))
         (set! x2 (- x2 inMargin))
         (set! y1 (+ y1 inMargin))
         (set! y2 (- y2 inMargin))  
		 (set! drw-width  (- x2 x1))
         (set! drw-height (- y2 y1))		 
		 (gimp-context-push)
		 (gimp-image-undo-group-start img)
		 
		 ; set up progress bar
		 (gimp-progress-set-text _"Rendering Random Density Map")
		 (while (< ycount drw-height)
		  (begin
		   (while (< xcount drw-width)
		     (begin
			   ;get the pixel value
			   (set! x (+ xcount x1))
			   (set! y (+ ycount y1))
			   (if (and (= inJitter TRUE) (> inJitterAmt 0))
			     (begin
			       (set! x (min (max (- (+ x (random (/ (* inSpacing inJitterAmt 1000) 1000))) (*  inSpacing 0.5 inJitterAmt)) x1) x2))
			       (set! y (min (max (- (+ y (random (/ (* inSpacing inJitterAmt 1000) 1000))) (*  inSpacing 0.5 inJitterAmt)) y1) y2))
			     )
			   )
			   (set! get-val (cadr (gimp-drawable-get-pixel inDensityMap x y)))

			   ; pick a number, any number and scale it by the density function
		       (set! thresh (/ (* (random 255.0) 100.0) inDensity))

    		   (if (and (= inUseAlpha TRUE) (= (car (gimp-drawable-has-alpha inDensityMap)) TRUE))   ; if using alpha
	    		 (begin
		    	   (set! test (aref get-val 3))   ; test threshold against alpha ( index 3)
    			   (gimp-context-set-foreground (list (aref get-val 0) (aref get-val 1) (aref get-val 2)))  ;set brush colour
	    		 )
		    	 (if (or (= map-type GRAY-IMAGE) (= map-type GRAYA-IMAGE))  ;  else if greyscale
    			   (set! test (aref get-val 0))  ; test threshold against colour ( index 0)
	    		   (if (or (= map-type RGB-IMAGE) (= map-type RGBA-IMAGE))  ; else if colour 
		    		 (set! test (/ (+ (aref get-val 0) (aref get-val 1) (aref get-val 2)) 3.0)) ; test threshold against average of r g and b
			    	 (set! test 255) ;  else threshold to full value (always draw)
    			   )
	    		 )
		       )			   
    		   (if (= inInvertMap TRUE)  ; reverse the map if invert option
	    		 (set! test (- 255 test))
		       )
    		   (if (< thresh test)    ; compare threshold against random value
	    		 (begin
    			   (aset *newpoint* 0 x)   ; set the paint array
	    		   (aset *newpoint* 1 y)
    			   (gimp-paintbrush-default inLayer 2 *newpoint*) ; paint point with paintbrush
		   	     )
		       )
			   (set! xcount (+ xcount inSpacing))
			 )
			)
		    (set! ycount (+ ycount inSpacing))
 		    (gimp-progress-update (/ (* xcount ycount) (* drw-height drw-width) ))  ;update progress bar
    	    (gimp-displays-flush)
			(set! xcount 0)
		   )
		 )
		 
		 (gimp-progress-end)
		 (gimp-image-undo-group-end img)
		 (gimp-displays-flush)
		 (gimp-context-pop)
		)
    )
    )
  )  
)

(script-fu-register "script-fu-random-density-map"
                    "<Image>/Filters/Map/Random Density Map..."
                    "Draw a specified number of random points with the currently selected brush, using a density mask."
                    "Rob Antonishen"
                    "Rob Antonishen"
                    "April 2008"
                    "RGB*, GRAY*"
                    SF-IMAGE       "Image"         0
                    SF-DRAWABLE    "Drawable"      0
                    SF-DRAWABLE    "Density Map"   -1
				    SF-TOGGLE      "Invert Map"    FALSE
					SF-TOGGLE      "Use map alpha channel for Density and draw with map colour"  FALSE
                    SF-ADJUSTMENT  "Density"     '(100 1 100 1 10 2 0) 
                    SF-ADJUSTMENT  "Border Margin (pixels)"       '(1 1 100 1 6 0 0)
                    SF-ADJUSTMENT  "Point Spacing"     '(10 1 100 1 10 0 0) 
				    SF-TOGGLE      "Apply Jitter"    TRUE
                    SF-ADJUSTMENT  "Jitter Amount"     '(0.5 0 2 0.01 0.1 2 0) 
                    )
