(define (three-exposures base-image shadow-file shadow-option highlight-file highlight-option ) ; three-exposures: Load 2 images to create a HDR composed of 3 images ; ; This function loads two additional images into new layers of ; the current one. All new layers will have a layer mask added which ; will consist of the desaturated image loaded into the layer. The "shadow" ; image(s) will also have the layer mask image inverted. ; revision history ; ; v0.00a Apr 25 2017 - initial commit, only adds a default shadow layer. ; v0.00b Apr 25 2017 - wire up shadow layer ; v0.01 Apr 26 2017 - add highlights, release for local testing ; comment variables so that _I_ have a chance of making this work ;-) ;==================================================================== ; the image variables - ; base-image - the main file with the middle exposure, it is ; the current image when you invoke this routine ; highlight-image - the file opened to get details for highlights ; shadow-image - the file opened to get details for shadows ; the layer variables ; base-layer - the initial (middle exposure) image ; highlight-layer - third main layer, added to bring out highlight details ; hmask-layer - desaturated image to use as mask for highlight layer ; shadow-layer - second main layer, added to bring out shadow details ; smask-layer - a desaturated and inverted image, ; to use as the mask for the shadow layer ; the masks - ; highlight-layer-mask - the mask on the highlight layer ; shadow-layer-mask - the mask on the shadow layer ; other global variables - ; floats - a floating selection ; start the code -- ; 0. handle UNDO ; this will allow this script to be undone as a single step ; so for debugging changes it should be commented so that all ; changes are visible in the undo history (gimp-image-undo-group-start base-image) ; 1. create a new layer on the base image, this will be copied for the ; shadow layer ; use active drawable layer, with 0 to avoid creating alpha channel ; first identify which (ihopefully, only) layer to copy for the new layer (define base-layer (car (gimp-image-get-active-drawable base-image))) ; Note that the content of the base-layer can be used for the masks, ; although in practice I eventually decided not to do that be default, and ; so at the moment that is not wired up, ; but it will not be used for the shadow and higlight layers themselves. ; now create a shadow layer (define shadow-layer (car (gimp-layer-copy base-layer 0))) ; give it a name (gimp-item-set-name shadow-layer "Shadow Layer") ; add it to the image (gimp-image-insert-layer base-image shadow-layer 0 0) ; Set opacity to 100% (gimp-layer-set-opacity shadow-layer 100) ; Set the layer mode for the shadow layer - ; default will be normal, else lighten (if (= shadow-option 0) (gimp-layer-set-mode shadow-layer NORMAL) ; else (gimp-layer-set-mode shadow-layer LIGHTEN-ONLY) ) ; load the shadow file so that I can copy the image it contains (define shadow-image (car (gimp-file-load 0 shadow-file shadow-file))) ; Select All on the shadow image (gimp-selection-all shadow-image) ; copy it to the main image (gimp-edit-copy (car (gimp-image-get-active-drawable shadow-image))) ; paste it as a floating selection (define floats (car (gimp-edit-paste ( car (gimp-image-get-active-drawable base-image)) 0))) ; anchor it - this needs a handle for the floating selection (gimp-floating-sel-anchor floats) ; 2. now copy a layer for a shadow mask layer ; create shadow mask from base layer if chosen, else from shadow layer (if (= shadow-option 2) (define smask-layer (car (gimp-layer-copy base-layer 0))) ; else (define smask-layer (car (gimp-layer-copy shadow-layer 0))) ) ; give it a name (gimp-item-set-name smask-layer "Shadow Mask") ; add it to the image (gimp-image-insert-layer base-image smask-layer 0 0) ; Set opacity to 100% (gimp-layer-set-opacity smask-layer 100) ; desaturate it using the default lightness option (gimp-desaturate-full smask-layer 0) ; invert it using lightness which is the default way of inverting (gimp-invert (car (gimp-image-get-active-drawable base-image))) ; add mask to the shadow layer - first add alpha to it (gimp-layer-add-alpha shadow-layer) ; now create the mask (define shadow-layer-mask (car (gimp-layer-create-mask shadow-layer ADD-WHITE-MASK))) ; this and next line seem to be needed, not understood (gimp-layer-add-mask shadow-layer shadow-layer-mask) (gimp-selection-none base-image) ; copy the mask (gimp-edit-copy smask-layer) ; reuse the floats variable for this floating selection (set! floats (car (gimp-edit-paste shadow-layer-mask TRUE))) (gimp-floating-sel-anchor floats) ; now delete the mask layer (gimp-image-remove-layer base-image smask-layer) ; 4. now create a highlight layer (define highlight-layer (car (gimp-layer-copy base-layer 0))) ; give it a name (gimp-item-set-name highlight-layer "Highlight Layer") ; add it to the image (gimp-image-insert-layer base-image highlight-layer 0 0) ; Set opacity to 100% (gimp-layer-set-opacity highlight-layer 100) ; Set the layer mode for the highlight layer - ; default will be normal, else lighten (if (= highlight-option 0) (gimp-layer-set-mode highlight-layer NORMAL) ; else (gimp-layer-set-mode highlight-layer DARKEN-ONLY) ) ; load the highlight file so that I can copy the image it contains (define highlight-image (car (gimp-file-load 0 highlight-file highlight-file))) ; Select All on the highlight image (gimp-selection-all highlight-image) ; copy it to the main image (gimp-edit-copy (car (gimp-image-get-active-drawable highlight-image))) ; paste it as a floating selection (define floats (car (gimp-edit-paste ( car (gimp-image-get-active-drawable base-image)) 0))) ; anchor it - this needs a handle for the floating selection (gimp-floating-sel-anchor floats) ; at this point I have two layers, ; but the highlight layer does not yet have a mask ; 5. now copy a layer for a highlight mask layer ; create highlight mask from base layer if chosen, else from highlight layer (if (= highlight-option 2) (define hmask-layer (car (gimp-layer-copy base-layer 0))) ; else (define hmask-layer (car (gimp-layer-copy highlight-layer 0))) ) ; give it a name (gimp-item-set-name hmask-layer "Shadow Mask") ; add it to the image (gimp-image-insert-layer base-image hmask-layer 0 0) ; Set opacity to 100% (gimp-layer-set-opacity hmask-layer 100) ; desaturate it using the default lightness option (gimp-desaturate-full hmask-layer 0) ; add mask to the highlight layer - first add alpha to it (gimp-layer-add-alpha highlight-layer) ; now create the mask (define highlight-layer-mask (car (gimp-layer-create-mask highlight-layer ADD-WHITE-MASK))) ; this and next line seem to be needed, not understood (gimp-layer-add-mask highlight-layer highlight-layer-mask) (gimp-selection-none base-image) ; copy the mask (gimp-edit-copy hmask-layer) ; reuse the floats variable for this floating selection (set! floats (car (gimp-edit-paste highlight-layer-mask TRUE))) (gimp-floating-sel-anchor floats) ; now delete the mask layer (gimp-image-remove-layer base-image hmask-layer) ; here merge down each layer in turn - "expand as necessary" : ; they should all be identical sizes, but who knows what users might do! ; Hmm, these layers are not defined in current scope ? ; merging visible layers works fine (gimp-image-merge-visible-layers base-image 0) ; and free up the shadow and highlight images (gimp-image-delete shadow-image) (gimp-image-delete highlight-image) ; close off the undo group : for debugging changes, comment this so that ; EVERY change is visible in the undo history (gimp-image-undo-group-end base-image) ) (script-fu-register "three-exposures" ; function name "/Filters/Enhance/Three Exposures" ; menu label "Add images for shadow and highlight exposures to retrieve more detail" ; description "Ken Moffat" ; author "Copyright 2017 Ken Moffat" ; copyright "2017-04-26" ; date created "RGB* GRAY* INDEXED*" ; image type it works on SF-IMAGE "Current image" 0 SF-FILENAME "Shadow Image" "(None)" SF-OPTION "Shadow mask from" '("shadow layer, normal" "shadow layer, lighten only" "base layer, lighten only") SF-FILENAME "Highlight image" "(None)" SF-OPTION "Highlight mask from" '("highlight layer, normal" "highlight layer, darken only" "base layer, darken only") )