; Blending (layer) operations for channels
; 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.
; GIMP 2.6 compatibility procedures
;
(unless (defined? 'gimp-item-is-group)
(define gimp-item-is-layer gimp-drawable-is-layer)
(define gimp-item-get-name gimp-drawable-get-name)
(define gimp-item-set-name gimp-drawable-set-name)
(define gimp-item-get-visible gimp-drawable-get-visible)
(define gimp-item-set-visible gimp-drawable-set-visible)
(define gimp-item-is-layer-mask gimp-drawable-is-layer-mask)
(define gimp-item-is-channel gimp-drawable-is-channel)
(define (gimp-item-is-group item) '(0))
(define (gimp-item-get-parent item) '(-1))
(define (gimp-item-get-children item) (list 0 #(0)))
)
(define (script-fu-sg-channel-blend-down image channel mode opacity use-hidden?)
(set! use-hidden? (not (zero? use-hidden?)))
(let* ((channels (vector->list (cadr (gimp-image-get-channels image))))
(base-channel #f)
(mode-lut '#( 0 1 10 4 16 7 9 3 17 5 19 18 6 8 20 21 15))
(channel-name (car (gimp-drawable-get-name channel))) )
(gimp-image-undo-group-start image)
(unless (or (= (car (gimp-item-is-layer channel)) TRUE)
(= (car (gimp-item-is-layer-mask channel)) TRUE)
(not (member channel channels))
(and (not use-hidden?)
(zero? (car (gimp-item-get-visible channel))) ))
(set! base-channel
(let loop ((channels (cdr (member channel channels)))
(base-channel #f) )
(if (null? channels)
base-channel
(if (or use-hidden? (not (zero? (car (gimp-item-get-visible (car channels))))))
(loop '() (car channels))
(loop (cdr channels) base-channel) ))))
(when base-channel
(let ((orig-sel (car (gimp-selection-save image))))
(gimp-selection-none image)
(let* ((buffer (car (gimp-edit-named-copy base-channel "Temp")))
(tmp-image (car (gimp-edit-named-paste-as-new buffer)))
(bot-layer (car (gimp-image-get-active-layer tmp-image)))
(top-layer (car (gimp-layer-new-from-drawable channel tmp-image))) )
(gimp-image-undo-disable tmp-image)
(gimp-item-set-visible bot-layer TRUE)
(gimp-item-set-visible bot-layer TRUE)
(gimp-image-add-layer tmp-image top-layer 0)
(gimp-item-set-visible top-layer TRUE)
(gimp-layer-set-opacity top-layer opacity)
(gimp-layer-set-mode top-layer (vector-ref mode-lut mode))
(set! bot-layer (car (gimp-image-merge-down tmp-image top-layer CLIP-TO-IMAGE)))
(gimp-buffer-delete buffer)
(set! buffer (car (gimp-edit-named-copy bot-layer "Temp")))
(gimp-image-remove-channel image channel)
(gimp-floating-sel-anchor (car (gimp-edit-named-paste base-channel buffer TRUE)))
(gimp-buffer-delete buffer)
(when (string=? "Qmask" channel-name)
(gimp-item-set-name base-channel "Qmask")
(gimp-item-set-visible base-channel TRUE) )
(gimp-image-delete tmp-image) )
(gimp-selection-load orig-sel)
(gimp-image-remove-channel image orig-sel) )))
(gimp-image-undo-group-end image)
(gimp-displays-flush)
)
)
(script-fu-register "script-fu-sg-channel-blend-down"
"Blend Down..."
"Blend channel with the channel beneath it."
"Saul Goode"
"Saul Goode"
"November"
"GRAY"
SF-IMAGE "Image" 0
SF-CHANNEL "Channel" 0
SF-OPTION "Blend Mode" '( "Normal" ; 0
"Dissolve" ; 1
"Lighten only (Union)" ; 10
"Screen" ; 4
"Dodge" ; 16
"Addition" ; 7
"Darken only (Intersect)" ; 9
"Multiply" ; 3
"Burn" ; 17
"Overlay" ; 5
"Soft light" ; 19
"Hard light" ; 18
"Difference" ; 6
"Subtract" ; 8
"Grain extract" ; 20
"Grain merge" ; 21
"Divide" ; 15
)
SF-ADJUSTMENT "Opacity" '( 100 0 100 1 10 0 0)
SF-TOGGLE "Use hidden channels" TRUE
)
(script-fu-menu-register "script-fu-sg-channel-blend-down"
"<Channels>/"
)
(define (script-fu-sg-drawable-show-only image drawable)
(gimp-image-undo-group-start image)
(map (lambda (x) (gimp-item-set-visible x FALSE))
(vector->list (cadr (gimp-image-get-layers image))) )
(map (lambda (x) (gimp-item-set-visible x FALSE))
(vector->list (cadr (gimp-image-get-channels image))) )
(if (= (car (gimp-item-is-layer-mask drawable)) TRUE)
(let ((layer (car (gimp-layer-from-mask drawable))))
(gimp-item-set-visible layer TRUE)
(gimp-layer-set-show-mask layer TRUE) )
(gimp-item-set-visible drawable TRUE) )
(if (= (car (gimp-item-is-layer drawable)) TRUE)
(let loop ((item drawable))
(let ((parent (car (gimp-item-get-parent item))))
(unless (= parent -1)
(map (lambda (x) (gimp-item-set-visible x FALSE))
(vector->list (cadr (gimp-item-get-children parent))) )
(gimp-item-set-visible item TRUE)
(gimp-item-set-visible parent TRUE)
(loop parent) ))))
(if (= (car (gimp-item-is-channel drawable)) TRUE)
(gimp-item-set-visible drawable TRUE) )
(gimp-image-undo-group-end image)
(gimp-displays-flush) )
;; Re-use layer-show-only, but with a channel
(define script-fu-sg-channel-show-only script-fu-sg-drawable-show-only)
;; Register to Channels menu
(script-fu-register "script-fu-sg-channel-show-only"
"Show only"
"Show only current channel."
"Saul Goode"
"Saul Goode"
"November 2011"
"GRAY"
SF-IMAGE "Image" 0
SF-CHANNEL "Channel" 0
)
(script-fu-menu-register "script-fu-sg-channel-show-only"
"<Channels>/"
)
(script-fu-register "script-fu-sg-drawable-show-only"
"Show only"
"Show only current layer."
"Saul Goode"
"Saul Goode"
"November 2011"
"*"
SF-IMAGE "Image" 0
SF-DRAWABLE "Drawable" 0
)
(script-fu-menu-register "script-fu-sg-drawable-show-only"
"<Layers>/"
)