Fred's ImageMagick Scripts



    Licensing:

    Copyright © Fred Weinhaus

    My scripts are available free of charge for non-commercial 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

TONEMAP4


Enhances the shadows and/or highlight regions in an image using a dual gamma function plus an extra processing function.

Download Script

last modified: July 14, 2015



USAGE: tonemap4 [-m method] [-k kind] [-t threshold] [-b bri] [-c con] [-s sat] [-e edge] [-r ramp] [-b blur] [-s shadows] [-h highlights] [-w window] [-g gvals] [-l log] [-A] [-C] infile outfile
USAGE: tonemap4 [-help]

-m ... method ....... method of dual gamma processing; ramp (r) or
..................... adaptive (a); default=ramp
-k ... kind ......... kind of extra processing; none (n), equalize (e),
..................... gaussian (g), space (s), or retinex (r);
..................... default=retinex
-t ... thresh ....... threshold for separating shadow and highlight
..................... regions; integers between 0 and 100; default is
..................... the mean graylevel of the brightness channel
-b ... bri .......... brightness enhancement percent; integer between
..................... -100 and 100; default=0
-c ... con .......... contrast enhancement percent; integer between
..................... -100 and 100; default=0
-s ... sat .......... saturation enhancement factor; float>0;
..................... default=0.6
-e ... edge ......... edge enhancement amount; float>=0;
..................... default=0
-r ... ramp ......... ramp amount in pixels for method=ramp; integer>=0;
..................... default=20
-B ... blur ......... blur amount for method=adaptive; float>0;
..................... default=3
-S ... shadows ...... desired shadow brightness in range 0 to 100 used
..................... for autogamma processing; also can be used to
..................... increase/decrease brightness in shadows;
..................... default=50
-H ... highlights ... desired highlight brightness in range 0 to 100 used
..................... for autogamma processing; also can be used to
..................... increase/decrease brightness in highlights;
..................... default=70
..................... positive or negative integer; default=0
-w ... window ....... window size as percent of image dimensions for
..................... kind=space; float>0; default=12.5
-g ... gvals ........ gaussian redistribution mean,lo,hi values for
..................... kind=gaussian; integers>0; default=60,60,60
-l ... log .......... amount of scaling for log preprocessing expressed as
..................... exponent for power of 10; default=0 (none)
-A .................. preprocessing to apply autolevel stretch; default is
..................... not to apply autolevel stretch
-C ... colorproc .... preprocessing to change colorspace to: RGB, sRGB; ..................... default is no change

PURPOSE: Enhances the shadows and/or highlight regions in an image using a dual gamma function plus an extra processing function.

DESCRIPTION: TONEMAP4 the shadows and/or highlight regions in an image using a dual gamma function plus an extra processing function, which can be either: none, equalize (histogram equalization), gaussian (histogram redistribution), retinex (multiscale method) or space (spatially adaptive contrast enhancement). The image is first converted to HSB colorspace. Then the channels are separated. The brightness channel is then thresholded to separate the shadow and highlight regions. The thresholded image is used as a mask against the brightness image to find the mean values in the two regions. These mean values are then used to compute appropriate gamma values, which are then applied separately to the brightness channel. These two modified brightness images are merged either by a ramped blending or by an adaptive blending based upon the local variances in the two modified brightness images. The resulting megerd brightness image is then combined with the hue and (optionally enhanced) saturation channels. Finally the resulting image is converted back to RGB.

ARGUMENTS:

-m method ... METHOD of dual gamma processing; ramp (r) or adaptive (a). The default=ramp.

-k kind ... KIND of extra processing. The choices are: none (n), equalize (e), gaussian (g), retinex (r) or space (s). Equalize is a histogram equalization. Gaussian is gaussian histogram redistribution. Retinex is multiscale enhancement. Space is a spatially adaptive contrast enhancement. Generally, retinex and none work the best, but for certain images, one or more of the other approaches may also work as well or better. The default=retinex.

-t threshold ... THRESHOLD for separating shadow and highlight regions. Values are integers between 0 and 100. The default is the mean graylevel of the brightness channel.

-b bri ... BRIGHTNESS enhancement percent. Values are integers between -100 and 100. The default=0

-c con ... CONTRAST enhancement percent. Values are integers between -100 and 100. The default=0

-s sat ... SATURATION enhancement factor. Values are floats>0. A value of sat=1 is no change. The default=0.6

-e edge ... EDGE enhancement amount. Values are floats>=0. The default=0

-r ramp ... RAMP amount in pixels for method=ramp. Values are integers>=0; The default=0

-B blur ... BLUR amount for method=adaptive. Values are floats>0. The default=0

-S shadows ... desired SHADOW brightness in the range 0 to 100, which is used for autogamma processing. It can also can be used to increase or decrease brightness in shadows, though generally it does not need to be adjusted. The default=50

-H highlights ... desired HIGHLIGHT brightness in the range 0 to 100, which is used for autogamma processing. It can also can be used to increase or decrease brightness in shadows, though generally it does not need to be adjusted. The default=50

-w window ... WINDOW is the moving window percentage of image size for kind=space. Values are floats>0 and are nominally between 5 and 20. Larger or smaller values can mitigate ringing. Larger values narrow ringing and smaller values broaden or diffues ringing. The default=12.5

-g gvals ... GVALS are the gaussian redistribution mean,lo,hi values for kind=gaussian. Values are comma separated integers>0. The default=60,60,60.

-l log ... LOG is the amount of scaling for log preprocessing expressed as exponent for power of 10. Generally this will only be needed for HDR images with very high dynamic range that require log processing in IM HDRI mode. The default=0 (no log processing).

-A ... Optional AUTOLEVEL preprocessing step. Generally this will only be needed for HDR images with very high dynamic range that require log processing in IM HDRI mode.

-C colorproc ... COLORPROC is an optional preprocessing step to convert the input image from some other colorspace to either RGB or sRGB. This seems to be needed for HDR Radiance images in XYZ colorspace (.hdr suffix) prior to a bug fix in .hdr images in IM 6.7.2.0. The choices are: RGB and sRGB. The default is no change. Note that somewhere between IM 6.7.5.5 and IM 6.7.6.7, colorspace RGB and sRGB were swapped to correct their meaning.

REQUIREMENTS: redist, space and retinex scripts. Also IM 6.5.9-0 to support the -brightness-contrast function.

NOTE: kind=space will be slow due to the use of -fx when not in HDRI mode.

Note: For IM 6.7.5.5 or higher, in order to reproduce some of the examples below, one may have to add, remove or change -C arguments, due to the swap of the meaning of -colorspace RGB and -colorspace sRGB. Also if -c is not none for .hdr images, then some parameter changes may be needed. For more details, see http://www.fmwconcepts.com/imagemagick/tonemap4/tonemap_tests.txt

Reference for adaptive method:
http://www.ieice.org/proceedings/ITC-CSCC2008/pdf/p457_A4-3.pdf

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

(Processed With Q16 HDRI IM 6.7.2.x Compile)


Example 1

Original Displayed As JPEG
(Actual EXR Image Used)
(source image web site)

Arguments:
-m ramp -k none -b 10 -e 2

Arguments:
-m adaptive -k none -b 10 -e 2

Arguments:
-m ramp -k retinex -b 5

Arguments:
-m adaptive -k retinex -b 5



Example 2

Original Displayed As JPEG
(Actual EXR Image Used)
(source image web site)

Arguments:
-m ramp -k none -b 5 -c -5 -e 2

Arguments:
-m adaptive -k none -b 8 -c -10 -e 2

Arguments:
-m ramp -k retinex -b 10 -c -5

Arguments:
-m adaptive -k retinex -b 15 -c -5

Arguments:
-m ramp -k space -b 10 -e 3 -w 5



Example 3 -- variation in type -- OHTA vs YUV

Original Displayed As JPEG
(Actual EXR Image Used)
(source image web site)

Arguments:
-m ramp -k none -b 10 -e 2

Arguments:
-m adaptive -k none -b10 -e 2 -B 5

Arguments:
-m ramp -k retinex -b 15

Arguments:
-m adaptive -k retinex -b 15 -B 5

Arguments:
-m ramp - k space -b 10 -w 40

Arguments:
-m adaptive -k space -b 10 -B 5 -w 40



Example 4

Original Displayed As JPEG
(Actual EXR Image Used)
(source image web site)

Arguments:
-m ramp -k none -b 10 -c 10 -e 2

Arguments:
-m adaptive -k none -b 10 -c 10 -e 2

Arguments:
-m ramp -k retinex -b 20

Arguments:
-m adaptive -k retinex -b 20

Arguments:
-m ramp -k space -b 10 -c 20 -w 40

Arguments:
-m adaptive -k space -b 10 -c 20 -w 40

Arguments:
-m ramp -k equalize

Arguments:
-m adaptive -k equalize

Arguments:
-m ramp -k gaussian -g 60,120,120

Arguments:
-m adaptive -k gaussian -g 60,120,120



Example 5

Original Displayed As JPEG
(Actual HDR Image Used)
(source image web site)

Arguments:
-m ramp -k none -b 5 -e 3 -l 3 -A

Arguments:
-m adaptive -k none -b 10 -e 3 -l 3 -A

Arguments:
-m ramp -k retinex -b 10 -e 1 -l 3 -A

Arguments:
-m adaptive -k retinex -b 10 -e 1 -l 3 -A

Arguments:
-m ramp -k space -e 1 -l 3 -A

Arguments:
-m adaptive -k space -b 5 -e 1 -l 4 -A



Example 6

Original Displayed As JPEG
(Actual HDR Image Used)
(source image web site)
(NOTE: Processed after .hdr bug fix at IM 6.7.2.0)

Arguments:
-m ramp -k none -c 30 -e 3 -l 4 -A

Arguments:
-m adaptive -k none -c 30 -e 3 -l 4 -A

Arguments:
-m ramp -k retinex b 10 -c 30 -e 3 -l 4 -A

Arguments:
-m adaptive -k retinex b 10 -c 30 -e 3 -l 4 -A

Arguments:
-m ramp -k space b 10 -c 10 -e 3 w 2 -l 4 -A

Arguments:
-m adaptive -k space b 10 -c 10 -e 3 w 2 -l 4 -A

Arguments:
-m ramp -k equalize b 10 -c -20 -e 3 -l 4 -A

Arguments:
-m adaptive -k equalize b 10 -c -20 -e 3 -l 4 -A

Arguments:
-m ramp -k gaussian b 10 -c -20 -e 3 -g 60,120,120 -l 4 -A

Arguments:
-m adaptive -k gaussian b 10 -c -20 -e 3 -g 60,120,120 -l 4 -A



What the script does is as follows for method=ramp:

  • Processes the image with optional log enhancement,
    converts to the HSB colorspace and separates channels
  • Thresholds the brightness channel and ramps it as a mask image
  • Applies the the mask image and its complement to the brightness channel
    and computes the means of each, which are then used to compute gamma
    values for the shadow and highlight regions
  • Applies the gamma values to the shadow and highlight images and then blends them using the mask
  • Combines the processed brightness image with hue and enhanced saturation
    channels and converts back to RGB.

This is equivalent to the following IM commands for method=ramp:

  • if [ "$autolevel" = "yes" ]; then
    alevel="-auto-level"
    else
    alevel=""
    fi
  • if [ "$log" != "0" ]; then
    log=`convert xc: -format "%[fx:10^$log]" info:`
    proc0="-evaluate log $log"
    else
    proc0=""
    fi
  • computeGammas()
    {
    img=$1
    mask=$2
    if [ "$sgamma" = "" -o "$hgamma" = "" ]; then
    # get mean of mask
    meanm=`convert $mask -format "%[fx:mean]" info:`
    if [ "$sgamma" = "" -a "kind" != "highlights" ]; then
    # get mean of shadows
    means=`convert $img \( $mask -negate \) \
    -compose multiply -composite -format "%[fx:mean/(1-$meanm)]" info:`
    fi
    if [ "$hgamma" = "" -a "$kind" != "shadows" ]; then
    # get mean of highlights
    meanh=`convert $img $mask \
    -compose multiply -composite -format "%[fx:mean/$meanm]" info:`
    fi
    # get gamma of shadows and hightlights
    if [ "$sgamma" = "" -a "$kind" != "highlights" ]; then
    sgamma=`convert xc: -format "%[fx:log($means)/log($shadows/100)]" info:`
    tests=`convert xc: -format "%[fx:$sgamma<=0?1:0]" info:`
    [ $tests -eq 1 ] && sgamma=`convert xc: -format "%[fx:log(255*$meanh)/log(255*$shadows/100)]" info:`
    fi
    if [ "$hgamma" = "" -a "$kind" != "shadows" ]; then
    hgamma=`convert xc: -format "%[fx:log($meanh)/log($highlights/100)]" info:`
    testh=`convert xc: -format "%[fx:$hgamma<=0?1:0]" info:`
    [ $testh -eq 1 ] && hgamma=`convert xc: -format "%[fx:log(255*$meanh)/log(255*$highlights/100)]" info:`
    fi
    fi
    }
  • convert -quiet -regard-warnings "$infile" -alpha off $cproc $alevel $proc0 +repage "$tmpA1"
  • convert $tmpA1 -colorspace HSB -separate $tmpA1
  • if [ "$thresh" = "" ]; then
    thresh=`convert $tmpA1[2] -format "%[fx:100*mean]" info:`
    fi
  • ramping="-blur ${ramp}x65000"
  • if [ "$kind" = "none" ]; then
    tproc=""
    elif [ "$kind" = "equalize" ]; then
    tproc="convert $tmpA2 -equalize $tmpA2"
    elif [ "$kind" = "space" ]; then
    tproc="space -m 0 -w $window -g 5 $tmpA2 $tmpA2"
    elif [ "$kind" = "retinex" ]; then
    tproc="retinex $tmpA2 $tmpA2"
    elif [ "$kind" = "gaussian" ]; then
    tproc="redist $gvals $tmpA2 $tmpA2"
    fi
  • convert $tmpA1[2] -threshold ${thresh}% $ramping $tmpA2
  • computeGammas $tmpA1[2] $tmpA2
  • convert $tmpA1[2] -gamma $sgamma $tmpA3
  • convert $tmpA1[2] -gamma $hgamma $tmpA4
  • convert $tmpA3 $tmpA4 $tmpA2 -compose over -composite $tmpA2
  • $tproc
  • convert $tmpA1[0] \
    \( $tmpA1[1] -evaluate multiply $sat \) \
    \( $tmpA2 -brightness-contrast $bri,$con -sharpen 0x$edge \) \
    -set colorspace HSB -combine -colorspace RGB \
    $outfile