; 210_effects_water-reflection.scm ; last modified/tested by Paul Sherman [gimphelp.org] ; Thursday, 07/02/2020 on GIMP 2.10.20 ;================================================== ; ; Installation: ; This script should be placed in the user or system-wide script folder. ; ; Windows 7/10 ; C:\Program Files\GIMP 2\share\gimp\2.0\scripts ; or ; C:\Users\YOUR-NAME\AppData\Roaming\GIMP\2.10\scripts ; ; ; Linux ; /home/yourname/.config/GIMP/2.10/scripts ; or ; Linux system-wide ; /usr/share/gimp/2.0/scripts ; ;================================================== ; ; 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 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 . ; ;============================================================== ; Original information ; ; Copyright (C) 2005-2007 Otavio Correa Cordeiro (otavio gmail com) ; Create a reflection effect like Apple iWeb does.. ; ; 02/11/2014 - re-worked by Paul Sherman from reflection to water-reflection, ; incorporates the script to build displacement map v.1.2.1 ; Written by Andrey Lebedenko (Lucidlook) 2009 ; plus a lot of other changes... ; ; modified by Paul Sherman to work in GIMP 2.4.2 on 11/30/2007 ; ; modified by David Cummins and Paul Sherman Dec 2007, tested on GIMP-2.4.3 ; * added user settings to control the height of the generated reflection, ; the gradient mask starting point (presented as Fade Rate %), and options ; to keep the generated reflection as a separate layer, or on a single layer ; either transparent or flattened. ; * added code to "play nice" with the current GIMP environment: colors and ; gradient prior selections are preserved, as well as the original layer ; name (handled using careful stack order). ; generated layers are constrained around the original layer. ; * simplified some of the internal logic so repeated calculations are done ; only once, reformatted, organised the code, added comments, etc. ; * flattened on start (to avoid errors) ; * undo ability functional ; ; Wed Oct 1 22:14:40 EDT 2008 ; Modified to remove deprecated procedures as listed: ; gimp-flip ==> gimp-drawable-transform-flip-simple ; added extra parameters ; also flushed before undo-end ;============================================================== (define (draw-line layer x-from y-from x-to y-to) (let* ( (points (cons-array 4 'double)) ) (aset points 0 x-from) (aset points 1 y-from) (aset points 2 x-to ) (aset points 3 y-to ) (gimp-pencil layer 4 points) ) ) (define (210-water-reflection theImage theLayer userFade rateBlue wavy ) (let* ( (work-image 0) (new-layer 0) (map-layer 0) (mirrored-layer 0) (image) (i 0) (RGBImage) (num_layers 0) (layer_ids) (current_layer) (ripple-layer 0) (theDisplay) (mask) (red-component 0) (green-component 1) (blue-component 2) (alpha-component 5) ) (define originalWidth (car (gimp-image-width theImage))) (define originalHeight (car (gimp-image-height theImage))) (gimp-image-undo-group-start theImage) (if (not (= RGB (car (gimp-image-base-type theImage)))) (gimp-image-convert-rgb theImage)) ; (gimp-selection-all theImage) (gimp-selection-none theImage) (set! theLayer (car(gimp-image-merge-visible-layers theImage 0))) (gimp-context-set-background '(255 255 255)) (gimp-context-set-foreground '(0 0 0)) ;preserve original settings (define old-bg (car (gimp-context-get-background))) (define old-fg (car (gimp-context-get-foreground))) (define old-grad (car (gimp-context-get-gradient))) ;calculate color for start of gradient fade (define fadeStart (* (- 100 userFade) 2.55)) (define fadeColor (list fadeStart fadeStart fadeStart)) (define reflectionScale 1) (define stackPos (car(gimp-image-get-item-position theImage theLayer))) (define newWidth originalWidth) (define newHeight (* originalHeight (+ reflectionScale 1))) (define gradX (/ originalWidth 2)) (define gradY1 (* originalHeight reflectionScale)) (define gradY2 (* originalHeight reflectionScale -1)) (gimp-image-resize theImage originalWidth newHeight 0 0) (define new-layer (car (gimp-layer-copy theLayer 1))) (gimp-image-insert-layer theImage new-layer 0 (+ stackPos 0)) (gimp-item-set-name new-layer "Reflection") (gimp-layer-set-offsets new-layer 0 originalHeight) (gimp-item-transform-flip-simple new-layer ORIENTATION-VERTICAL TRUE 0.0) (define new-mask (car (gimp-layer-create-mask new-layer 0))) (gimp-layer-add-mask new-layer new-mask) (gimp-context-set-foreground fadeColor) (gimp-edit-blend new-mask FG-TRANSPARENT-MODE LAYER-MODE-NORMAL-LEGACY GRADIENT-LINEAR 100 0 REPEAT-NONE FALSE FALSE 0 0 TRUE gradX originalHeight gradX gradY2) (gimp-layer-remove-mask new-layer MASK-APPLY) (gimp-image-set-active-layer theImage new-layer) ; (plug-in-ripple RUN-NONINTERACTIVE theImage new-layer 32 2 1 0 0 TRUE TRUE) (if (= wavy TRUE) (plug-in-ripple RUN-NONINTERACTIVE theImage new-layer 40 3 0 0 0 TRUE TRUE)) (define mirrored-layer (car (gimp-image-merge-visible-layers theImage EXPAND-AS-NECESSARY))) (plug-in-autocrop RUN-NONINTERACTIVE theImage mirrored-layer) ;============ Now we work on the water layer...====================== (define image (car(gimp-image-new originalWidth originalHeight RGB))) ; (set! image (car (gimp-image-new orig-width orig-height RGB))) (set! map-layer (car (gimp-layer-new image originalWidth originalHeight RGB-IMAGE "Displacement map" 100 LAYER-MODE-NORMAL-LEGACY ))) ; Add new layer (gimp-image-add-layer image map-layer 0) (set! theDisplay (car (gimp-display-new image))) (gimp-context-set-background '(255 255 255)) (gimp-context-set-foreground '(0 0 0)) (gimp-drawable-fill map-layer BACKGROUND-FILL) (gimp-layer-set-lock-alpha map-layer TRUE) (while (< i 6) (plug-in-rgb-noise RUN-NONINTERACTIVE image map-layer 0 1 0.2 0.2 0.2 0) (set! i (+ i 1)) ) (plug-in-gauss-iir 1 image map-layer 5 TRUE TRUE) (gimp-image-set-component-active image green-component FALSE) (gimp-image-set-component-active image blue-component FALSE) (plug-in-emboss 1 image map-layer 0 50.0 10 -5) ; horizontal (gimp-image-set-component-active image red-component FALSE) (gimp-image-set-component-active image green-component TRUE) (plug-in-emboss 1 image map-layer 90 50.0 10 -5) ; vertical (gimp-image-set-component-active image red-component FALSE) (gimp-image-set-component-active image green-component FALSE) (gimp-image-set-component-active image blue-component TRUE) (gimp-edit-bucket-fill-full map-layer FG-BUCKET-FILL LAYER-MODE-NORMAL-LEGACY 100 255 FALSE TRUE SELECT-CRITERION-COMPOSITE 0 0) (gimp-image-set-component-active image red-component TRUE) (gimp-image-set-component-visible image red-component TRUE) (gimp-image-set-component-active image green-component TRUE) (gimp-image-set-component-visible image green-component TRUE) (set! i 1) (while (<= i 2) (gimp-perspective map-layer TRUE 0 0 originalWidth 0 (- 0 originalWidth) (* originalHeight 4) (* originalWidth 2) (* originalHeight 4)) (gimp-layer-scale map-layer (* originalWidth 3) originalHeight FALSE) (gimp-layer-scale map-layer (* originalWidth 3) (+ originalHeight 10) FALSE) (gimp-image-crop (car(gimp-drawable-get-image map-layer)) originalWidth originalHeight 0 0) (set! i (+ i 1)) ) (gimp-drawable-transform-scale-default map-layer (- 0 originalWidth) 0 (* originalHeight 4) originalHeight TRUE TRUE) (gimp-image-crop (car(gimp-drawable-get-image map-layer)) originalWidth originalHeight 0 0) (set! mask (car (gimp-layer-create-mask map-layer ADD-WHITE-MASK))) (gimp-layer-add-mask map-layer mask) (gimp-edit-blend mask FG-BG-RGB-MODE LAYER-MODE-NORMAL-LEGACY GRADIENT-LINEAR 100 0 REPEAT-NONE TRUE FALSE 1 0 TRUE 0 0 0 originalHeight) ; mask to selection ( mask-to-selection ) : (gimp-selection-load mask) (gimp-image-set-component-active image red-component TRUE) (gimp-image-set-component-active image green-component FALSE) (gimp-image-set-component-active image blue-component FALSE) ; fill with grey (gimp-context-set-foreground '(128 128 128)) (gimp-edit-bucket-fill-full map-layer FG-BUCKET-FILL LAYER-MODE-NORMAL-LEGACY 100 255 FALSE TRUE SELECT-CRITERION-COMPOSITE 0 0) (gimp-selection-none image) (gimp-context-set-foreground '(0 0 0)) (gimp-context-set-background '(255 255 255)) (gimp-edit-blend mask FG-BG-RGB-MODE LAYER-MODE-NORMAL-LEGACY GRADIENT-LINEAR 100 0 REPEAT-NONE TRUE FALSE 1 0 TRUE 0 0 0 (round(* originalHeight 0.2)) ) ; mask to selection ( mask-to-selection ) : (gimp-selection-load mask) (gimp-image-set-component-active image red-component FALSE) (gimp-image-set-component-active image green-component TRUE) (gimp-image-set-component-active image blue-component FALSE) ; fill with grey (gimp-context-set-foreground '(128 128 128)) (gimp-edit-bucket-fill-full map-layer FG-BUCKET-FILL LAYER-MODE-NORMAL-LEGACY 100 255 FALSE TRUE SELECT-CRITERION-COMPOSITE 0 0) (gimp-layer-remove-mask map-layer MASK-DISCARD) (gimp-selection-none image) (set! RGBImage (car (plug-in-decompose RUN-NONINTERACTIVE image map-layer "RGB" TRUE))) ; since we decompose, we no loner need original map (gimp-display-delete theDisplay) ; delete blue channel/layer (set! num_layers (car (gimp-image-get-layers RGBImage))) (set! layer_ids (cadr (gimp-image-get-layers RGBImage))) (set! i 0) (while (< i num_layers) (set! current_layer (vector-ref layer_ids i)) (if (= i 0) ; red ; (gimp-drawable-set-name current_layer "X") (gimp-image-remove-layer RGBImage current_layer) ) (if (= i 1) ; green (gimp-drawable-set-name current_layer "Y") ) (if (= i 2) ; blue (gimp-image-remove-layer RGBImage current_layer) ) (set! i (+ i 1)) ) (gimp-edit-copy-visible RGBImage) (gimp-image-delete RGBImage) (gimp-edit-paste mirrored-layer FALSE) (gimp-floating-sel-to-layer (car (gimp-image-get-floating-sel theImage))) (set! ripple-layer (car (gimp-image-get-layer-by-name theImage "Pasted Layer"))) (gimp-layer-set-opacity ripple-layer 30) (gimp-layer-set-mode ripple-layer HARDLIGHT-MODE) (gimp-layer-translate ripple-layer 0 (/ originalHeight 2)) (cond ((= rateBlue 1) (gimp-context-set-background '(70 70 30)) ) ((= rateBlue 2) (gimp-context-set-background '(60 70 90)) ) ((= rateBlue 3) (gimp-context-set-background '(50 70 110)) ) ((= rateBlue 4) (gimp-context-set-background '(40 50 150)) ) ((= rateBlue 5) (gimp-context-set-background '(30 50 200)) ) ) (gimp-image-flatten theImage) (define final-layer (car (gimp-image-get-active-layer theImage))) (gimp-image-select-rectangle theImage CHANNEL-OP-ADD 0 (- originalHeight 2) originalWidth 4) (plug-in-waves RUN-NONINTERACTIVE theImage final-layer 0.4 0.0 40 0 0) (gimp-selection-none theImage) ;restore original settings (gimp-context-set-foreground old-fg) (gimp-context-set-background old-bg) (gimp-context-set-gradient old-grad) (gimp-displays-flush) (gimp-image-undo-group-end theImage) )) (script-fu-register "210-water-reflection" "Water Reflection" "Reflection -- extends lower section of an image as a reflection of the original image." "Original author Otavio Cordeiro, later edited by David Cummins and Paul Sherman" "Paul Sherman " "Last updated Tuesday, 02/11/2014" "*" SF-IMAGE "Image" 0 SF-DRAWABLE "Drawable" 0 SF-ADJUSTMENT "Reflection Fade Rate (%)" '(70 0 100 10 20 0 0) SF-ADJUSTMENT "Blue Amount on Water" '(2 1 5 1 1 0 0) SF-TOGGLE "Wavier Reflection" FALSE ) (script-fu-menu-register "210-water-reflection" "/Script-Fu/Effects")