diff options
Diffstat (limited to 'plug-ins/script-fu/scripts/blend-anim.scm')
-rw-r--r-- | plug-ins/script-fu/scripts/blend-anim.scm | 242 |
1 files changed, 242 insertions, 0 deletions
diff --git a/plug-ins/script-fu/scripts/blend-anim.scm b/plug-ins/script-fu/scripts/blend-anim.scm new file mode 100644 index 0000000..517b1c5 --- /dev/null +++ b/plug-ins/script-fu/scripts/blend-anim.scm @@ -0,0 +1,242 @@ +; GIMP - The GNU Image Manipulation Program +; Copyright (C) 1995 Spencer Kimball and Peter Mattis +; +; 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 3 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. +; +; You should have received a copy of the GNU General Public License +; along with this program. If not, see <https://www.gnu.org/licenses/>. +; +; +; blend-anim.scm version 1.03 1999/12/21 +; +; CHANGE-LOG: +; 1.00 - initial release +; 1.01 - some code cleanup, no real changes +; 1.02 - use gimp-message to output an error message if called +; with less than three layers +; 1.03 - only call blur plugin when blut-radius >= 1.0 +; +; Copyright (C) 1997-1999 Sven Neumann <sven@gimp.org> +; +; +; Blends two or more layers over a background, so that an animation can +; be saved. A minimum of three layers is required. + +(define (script-fu-blend-anim img + drawable + frames + max-blur + looped) + + (define (multi-raise-layer image layer times) + (while (> times 0) + (gimp-image-raise-item image layer) + (set! times (- times 1)) + ) + ) + + (let* ( + (max-blur (max max-blur 0)) + (frames (max frames 0)) + (image (car (gimp-image-duplicate img))) + (width (car (gimp-image-width image))) + (height (car (gimp-image-height image))) + (layers (gimp-image-get-layers image)) + (num-layers (car layers)) + (layer-array (cadr layers)) + (slots (- num-layers 2)) + (bg-layer (aref layer-array (- num-layers 1))) + (max-width 0) + (max-height 0) + (offset-x 0) + (offset-y 0) + ) + + (if (> num-layers 2) + (begin + (gimp-image-undo-disable image) + + (if (= looped TRUE) + ; add a copy of the lowest blend layer on top + (let* ((copy (car (gimp-layer-copy + (aref layer-array (- num-layers 2)) TRUE)))) + (gimp-image-insert-layer image copy 0 0) + (set! layers (gimp-image-get-layers image)) + (set! num-layers (car layers)) + (set! layer-array (cadr layers)) + (set! slots (- num-layers 2)) + (set! bg-layer (aref layer-array (- num-layers 1))))) + + ; make all layers invisible and check for sizes + (let* ((min-offset-x width) + (min-offset-y height) + (layer-count slots)) + (gimp-item-set-visible bg-layer FALSE) + (while (> layer-count -1) + (let* ((layer (aref layer-array layer-count)) + (layer-width (+ (car (gimp-drawable-width layer)) + (* max-blur 2))) + (layer-height (+ (car (gimp-drawable-height layer)) + (* max-blur 2))) + (layer-offsets (gimp-drawable-offsets layer)) + (layer-offset-x (- (car layer-offsets) max-blur)) + (layer-offset-y (- (cadr layer-offsets) max-blur))) + (gimp-item-set-visible layer FALSE) + (set! max-width (max max-width layer-width)) + (set! max-height (max max-height layer-height)) + (set! min-offset-x (min min-offset-x layer-offset-x)) + (set! min-offset-y (min min-offset-y layer-offset-y)) + (set! layer-count (- layer-count 1)))) + (set! offset-x (- (car (gimp-drawable-offsets bg-layer)) + min-offset-x)) + (set! offset-y (- (cadr (gimp-drawable-offsets bg-layer)) + min-offset-y))) + + ; create intermediate frames by merging copies of adjacent layers + ; with the background layer + (let* ((layer-count slots)) + (while (> layer-count 0) + (let* ((frame-count frames) + (lower-layer (aref layer-array layer-count)) + (upper-layer (aref layer-array (- layer-count 1)))) + (while (> frame-count 0) + (let* ((opacity (* (/ frame-count (+ frames 1)) 100)) + (blur (/ (* opacity max-blur) 100)) + (upper-copy (car (gimp-layer-copy upper-layer TRUE))) + (lower-copy (car (gimp-layer-copy lower-layer TRUE))) + (bg-copy (car (gimp-layer-copy bg-layer TRUE)))) + (gimp-image-insert-layer image bg-copy 0 0) + (gimp-image-insert-layer image lower-copy 0 0) + (gimp-image-insert-layer image upper-copy 0 0) + (gimp-item-set-visible upper-copy TRUE) + (gimp-item-set-visible lower-copy TRUE) + (gimp-item-set-visible bg-copy TRUE) + (gimp-layer-set-opacity upper-copy (- 100 opacity)) + (gimp-layer-set-opacity lower-copy opacity) + (gimp-layer-set-opacity bg-copy 100) + (if (> max-blur 0) + (let* ((layer-width (car (gimp-drawable-width upper-copy))) + (layer-height (car (gimp-drawable-height upper-copy)))) + (gimp-layer-set-lock-alpha upper-copy FALSE) + (gimp-layer-resize upper-copy + (+ layer-width (* blur 2)) + (+ layer-height (* blur 2)) + blur + blur) + (if (>= blur 1.0) + (plug-in-gauss-rle RUN-NONINTERACTIVE + image + upper-copy + blur + TRUE TRUE)) + (set! blur (- max-blur blur)) + (gimp-layer-set-lock-alpha lower-copy FALSE) + (set! layer-width (car (gimp-drawable-width + lower-copy))) + (set! layer-height (car (gimp-drawable-height + lower-copy))) + (gimp-layer-resize lower-copy + (+ layer-width (* blur 2)) + (+ layer-height (* blur 2)) + blur + blur) + (if (>= blur 1.0) + (plug-in-gauss-rle RUN-NONINTERACTIVE + image + lower-copy + blur + TRUE TRUE)))) + (gimp-layer-resize bg-copy + max-width + max-height + offset-x + offset-y) + (let* ((merged-layer (car (gimp-image-merge-visible-layers + image CLIP-TO-IMAGE)))) + (gimp-item-set-visible merged-layer FALSE)) + (set! frame-count (- frame-count 1)))) + (set! layer-count (- layer-count 1))))) + + ; merge all original blend layers but the lowest one + ; with copies of the background layer + (let* ((layer-count 0)) + (while (< layer-count slots) + (let* ((orig-layer (aref layer-array layer-count)) + (bg-copy (car (gimp-layer-copy bg-layer TRUE)))) + (gimp-image-insert-layer image + bg-copy + -1 + (* layer-count (+ frames 1))) + (multi-raise-layer image + orig-layer + (+ (* (- slots layer-count) frames) 1)) + (gimp-item-set-visible orig-layer TRUE) + (gimp-item-set-visible bg-copy TRUE) + (gimp-layer-resize bg-copy + max-width + max-height + offset-x + offset-y) + (let* ((merged-layer (car (gimp-image-merge-visible-layers + image CLIP-TO-IMAGE)))) + (gimp-item-set-visible merged-layer FALSE)) + (set! layer-count (+ layer-count 1))))) + + ; merge the lowest blend layer with the background layer + (let* ((orig-layer (aref layer-array (- num-layers 2)))) + (gimp-item-set-visible bg-layer TRUE) + (gimp-item-set-visible orig-layer TRUE) + (gimp-image-merge-visible-layers image CLIP-TO-IMAGE)) + + ; make all layers visible again + (let* ((result-layers (gimp-image-get-layers image)) + (num-result-layers (car result-layers)) + (result-layer-array (cadr result-layers)) + (layer-count (- num-result-layers 1))) + (while (> layer-count -1) + (let* ((layer (aref result-layer-array layer-count)) + (name (string-append _"Frame" " " + (number->string + (- num-result-layers layer-count) 10)))) + (gimp-item-set-visible layer TRUE) + (gimp-item-set-name layer name) + (set! layer-count (- layer-count 1)))) + + (if (= looped TRUE) + ; remove the topmost layer + (gimp-image-remove-layer image (aref result-layer-array 0)))) + + (gimp-image-undo-enable image) + (gimp-display-new image) + (gimp-displays-flush) + ) + + (gimp-message _"Blend Animation needs at least three source layers") + ) + ) +) + +(script-fu-register "script-fu-blend-anim" + _"_Blend..." + _"Create intermediate layers to blend two or more layers over a background as an animation" + "Sven Neumann <sven@gimp.org>" + "Sven Neumann" + "1999/12/21" + "RGB* GRAY*" + SF-IMAGE "Image" 0 + SF-DRAWABLE "Drawable" 0 + SF-ADJUSTMENT _"Intermediate frames" '(3 1 1024 1 10 0 1) + SF-ADJUSTMENT _"Max. blur radius" '(0 0 1024 1 10 0 1) + SF-TOGGLE _"Looped" TRUE +) + +(script-fu-menu-register "script-fu-blend-anim" + "<Image>/Filters/Animation/Animators") |