Fred's ImageMagick Scripts



    Licensing:

    Copyright © Fred Weinhaus

    My scripts are available free of charge for non-commercial (non-profit) use, ONLY.

    For use of my scripts in commercial (for-profit) environments or non-free applications, please contact me (Fred Weinhaus) for licensing arrangements. My email address is fmw at alink dot net.

    If you: 1) redistribute, 2) incorporate any of these scripts into other free applications or 3) reprogram them in another scripting language, then you must contact me for permission, especially if the result might be used in a commercial or for-profit environment.

    Usage, whether stated or not in the script, is restricted to the above licensing arrangements. It is also subject, in a subordinate manner, to the ImageMagick license, which can be found at: http://www.imagemagick.org/script/license.php

    Please read the Pointers For Use on my home page to properly install and customize my scripts.

SHADOWHIGHLIGHT


Adjusts the tone in shadow and highlight areas of an image.

Download Script

last modified: August 27, 2020



USAGE: shadowhighlight [-sa samount] [-sw swidth] [-sr sradius] [-ha hamount] [-hw hwidth] [-hr hradius] [-ma mamount] [-ca camount] [-bc bclip] [-wc wclip] infile outfile
USAGE: shadowhighlight [-h or -help]

-sa ... samount ... shadow amount; 0<=integer<=100; default=50
-sw ... swidth .... shadow tone width; 0<=integer<=100; default=50
-sr ... sradius ... shadow radius; float>=0; default=30
-ha ... hamount ... highlight amount; 0<=integer<=100; default=0
-hw ... hwidth .... highlight tone width; 0<=integer<=100; default=50
-hr ... hradius ... highlight radius; float>=0; default=30
-ma ... mamount ... midtone amount; -100<=integer<=100; default=0
-ca ... camount ... color correction amount; -100<=integer<=100; default=0
-bc ... bclip ..... black clip percent; 0<=float<=100; default=0.01
-wc ... wclip ..... white clip percent; 0<=float<=100; default=0.01

PURPOSE: To adjust the tone in shadow and highlight areas of an image.

DESCRIPTION: SHADOWHIGHLIGHT adjusts the tone in shadow and highlight areas of an image. Shadow areas may be lightened and highlight areas darkened using the amount arguments. The tonal width arguments adjust the range of shadow and/or highlight tones that will be adjusted. The radius arguments adjust the regions around each pixel that are used to determine whether a pixel is shadow or highlight. All processing is done in the LAB colorspace. This script attempts to emulate the Photoshop function of the same name.

ARGUMENTS:

-sa samount ... SAMOUNT is the shadow enhancement amount. Values are 0<=integers<=100. The default=50.

-sw swidth ... SWIDTH is the shadow tonal width. Values are 0<=integers<=100. The default=50.

-sr sradius ... SRADIUS is the shadow radius in pixels. Values are floats>=0. The default=30.

-ha samount ... HAMOUNT is the highlight enhancement amount. Values are 0<=integers<=100. The default=50.

-hw swidth ... HWIDTH is the highlight tonal width. Values are 0<=integers<=100. The default=50.

-Hr sradius ... HRADIUS is the highlight radius in pixels. Values are floats>=0. The default=30.

-ma samount ... MAMOUNT is the midtone enhancement amount. Values are -100<=integers<=100. The default=0.

-ca camount ... CAMOUNT is the color correction amount. Values are -100<=integers<=100. The default=0.

-bc bclip ... BCLIP is the black clip percent. Values are 0<=floats<=100. The default=0.01.

-wc wclip ... WCLIP is the white clip percent. Values are 0<=floats<=100. The default=0.01.

REQUIREMENTS: IM 6.7.8.2 or higher, due to the use of the LAB colorspace. However, results were not stable until 6.7.8.8

REFERENCES: http://www.photoshopessentials.com/photo-editing/shadow-highlight/

CAVEAT: No guarantee that this script will work on all platforms, nor that trapping of inconsistent parameters is complete and foolproof. Use At Your Own Risk.


EXAMPLES


Examples

Original
(source)

Arguments:
-sa 100 -ha 50

Arguments:
-sa 100 -ha 100

Arguments:
-sa 100 -ha 0

Arguments:
-sa 0 -ha 100

Arguments:
-sa 100 -ha 100 -ma 100

Arguments:
-sa 100 -ha 100 -ma -100

Arguments:
-sa 100 -ha 100 -ca 100

Arguments:
-sa 100 -ha 100 -ca -100



What the script does is as follows for border=black at the top/bottom edges:

  • Extracts the L channel of LAB colorspace and optionally clips the image to create a grayscale image
  • Converts the input to LAB colorspace and processes the L channel according to the shadow amount
    and a half sigmoidal-contrast and reverts back to sRGB colorspace
  • Applies a blur and soft black-thresholds the grayscale image
  • Puts the modified grayscale image into the alpha channel of the shadow processed image
  • Converts the input to LAB colorspace and process the L channel according to the highlight amount
    and a half sigmoidal-contrast and reverts back to sRGB colorspace
  • Applies a blur and soft white-thresholds the grayscale image
  • Puts the modified grayscale image into the alpha channel of the highlight processed image
  • Applies a 50/50 blend composite of the shadow and highlight processed images
  • Optionally applies a symmetric sigmoidal-contrast to the blended image to adjust the midtones
  • Optionally converts the input to LAB colorspace and processes the AB channels according to the
    the color correction amount and a symmetric sigmoidal-contrast

This is equivalent to the following IM commands

  • convert -quiet -regard-warnings "$infile" +repage "$tmpA1"
  • convert $tmpA1 -colorspace LAB -channel R -separate +channel -contrast-stretch $bclip,$wclip% $tmpG1
  • if [ "$samt" != 0 ]; then
    srad=`convert xc: -format "%[fx:$srad/3]" info:`
    samt=`convert xc: -format "%[fx:$samt/20]" info:`
    proc="+sigmoidal-contrast $samt,100%"
    convert $tmpA1 -colorspace LAB -channel R $proc +channel -colorspace sRGB \
    \( $tmpG1 -blur 0x${srad} -black-threshold $swid% -level ${swid}x100% -negate \) \
    -alpha off -compose copy_opacity -composite $tmpS1
    else
    convert $tmpA1 $tmpS1
    fi
  • if [ "$hamt" != 0 ]; then
    hrad=`convert xc: -format "%[fx:$hrad/3]" info:`
    hamt=`convert xc: -format "%[fx:$hamt/20]" info:`
    proc="+sigmoidal-contrast $hamt,0%"
    hwid2=$((100-hwid))
    convert $tmpA1 -colorspace LAB -channel R $proc +channel -colorspace sRGB \
    \( $tmpG1 -blur 0x${hrad} -white-threshold $hwid2% -level 0x${hwid2}% \) \
    -alpha off -compose copy_opacity -composite $tmpH1
    else
    convert $tmpA1 $tmpH1
    fi
  • if [ "$mamt" = "0" ]; then
    mproc=""
    else
    mtest=`convert xc: -format "%[fx:sign($mamt)]" info:`
    if [ $mtest -eq -1 ]; then
    mamt=`convert xc: -format "%[fx:abs($mamt)/20]" info:`
    mproc="-colorspace LAB -channel R +sigmoidal-contrast ${mamt}x50% +channel -colorspace sRGB"
    else
    mamt=`convert xc: -format "%[fx:abs($mamt)/10]" info:`
    mproc="-colorspace LAB -channel R -sigmoidal-contrast ${mamt}x50% +channel -colorspace sRGB"
    fi
    fi
  • if [ "$camt" = "0" ]; then
    cproc=""
    else
    ctest=`convert xc: -format "%[fx:sign($camt)]" info:`
    if [ $ctest -eq -1 ]; then
    camt=`convert xc: -format "%[fx:abs($camt)/20]" info:`
    cproc="-colorspace LAB -channel BG +sigmoidal-contrast $camt,50% +channel -colorspace sRGB"
    else
    camt=`convert xc: -format "%[fx:abs($camt)/20]" info:`
    cproc="-colorspace LAB -channel BG -sigmoidal-contrast $camt,50% +channel -colorspace sRGB"
    fi
    fi
  • convert $tmpH1 $tmpS1 -define compose:args=$blend -compose blend -composite $mproc $cproc $outfile