Fred's ImageMagick Scripts


    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:

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


Modifies an image so that its (grayscale) histogram has either a Gaussian or Uniform distribution

Download Script

last modified: December 19, 2022

USAGE: redist [-s shape] [-m colormodel] [-c channel] [-g graytype] [-f factor] [-G] [-L] [mean[,lo[,hi]]] infile outfile
USAGE: redist [-h or -help]

-s . shape ....... redistribution shape - choice of Gaussian or Uniform;
.................. default is Gaussian
-m . colormodel .. processing (color) model; default=RGB
-c . channel ..... channel number to process; channel=0,1,2;
.................. default -> see below
-g . graytype .... type of grayscale image to use when colormodel=RGB;
.................. choices are: gray, rec601, rec709, lightness,
.................. brightness, ave, luminance, demodhsl, demodhcl.
-f . factor ...... factor the contrast gain limiting factor; smaller values
.................. will limit contrast gain more; values above about 3 will
.................. produce no contrast limit; float>=0;
.................. default is no threshold
-G ............... display the grayscale histogram (graph) with
.................. distribution function overlay
-L................ save the lookup table image; if saved, it will
.................. be named redist_lut.png
mean ............. desired mean for Gaussian distribution;
.................. mean in range 0 to 100; default=60
lo ............... desired 1 sigma roll-off point of distribution on the
.................. low side of the Gaussian peak; lo > 0; default=60
hi ............... desired 1 sigma roll-off point of distribution on the
.................. high side of the Gaussian peak; hi > 0; default=60

PURPOSE: To modify an image so that its (grayscale) histogram has either a Gaussian (sometimes called normal or bell-shaped) distribution or a Uniform (constant height) distribution. The latter is equivalent to histogram equalization.

DESCRIPTION: REDIST is designed to apply an intensity mapping transformation to an image such that the resulting image's grayscale histogram has a specified distribution shape (Gaussian or Uniform). For colormodel not equal to RGB, it first converts the image to that color space via the colormodel parameter and processes the intensity-like channel. For colormodel=RGB, it converts the image to an appropriate intensity-like channel as specified by graytype. Either way it computes the intensity-like channel's cumulative histogram. The script then generates the integral of the specified distribution scaled to the last value in the cumulative histogram. For each value in the image's cumulative histogram, it finds the closest value in the integral and then looks to see what its graylevel value is. It uses those graylevel values as the y-value in a mapping transformation whose x-values range from 0-255. This mapping transformation is expressed as a 1-D image and used with the IM function -fx or -clut to transform the input image. For colormodel not RGB, it process only the intensity-like channel and then recombines the channels and converts back to RGB. For colormodel RGB, it applies the transformation to each channel of the RGB image. If a graph is desired, it is normally just viewed. However, a default parameter in the program can be set to allow it to be saved as outfilename_graph.gif. To end the script, close/quit the graph image.


-h or -help ....... displays help information.

-s SHAPE defines the desired distribution shape, which can be either Gaussian (also known as normal or bell-shaped) or Uniform (constant height). The default is Gaussian if -s shape is not specified.

-m COLORMODEL defines the color model to use for the processing of an RGB color image into a grayscale image in order to compute the required cumulative histogram. If a colormodel other than RGB or GLOBAL is specified, then the image is first transformed into that color space and an intensity-like channel will then be used to compute the cumulative histogram. If RGB is selected, the RGB image is converted to an appropriate grayscale according to the graytype. This grayscale image is then used to generate the cumulative histogram. If GLOBAL is selected, then the combined cumulative histogram from all the channels is computed. The default value is RGB when colormodel is not provided. Note that results vary between the different color models.

-c CHANNEL defines which channel to use for the histogram processing. Values for channel may be 0, 1 or 2, which correspond to those generated by the conversion to that color space. For RGB, this is R=0, G=1, B=2. For HSL, this is H=0, S=1, L=2. The same goes for the other color spaces. This will override the default value which is set for most colorspaces to the most intensity-like channel. For HSL and HSB, this is channel 2. For all others except RGB and GLOBAL, this is channel 0. For GLOBAL, all channels will be combined to compute the histogram.

-g GRAYTYPE defines the type of grayscale image to use when colormodel=RGB. The choices are: gray (same as rec609luma; YUV, YIQ, YCbCr channel 1; HCL channel 2), rec709 (which is rec709luma), lightness (from HSL channel 2), brightness (from HSB channel 2), ave (from OHTA channel 1), luminance (from LAB channel 1), demodhsl (demodulate in HSL colorspace) and demodhcl (demodulate in CHCL colorspace). The default=gray. Note that gray is the same as rec601luma prior to IM and is the same as rec709luma for IM forward.

-f factor ... FACTOR is the contrast gain limiting factor. Smaller values will limit contrast gain more; values above about 3 will produce no contrast limit. Values are floats>=0. The default is no contrast gain limitation. The factor is used to combine the histogram count mean and standard deviation to compute a maximum threshold for the histogram counts in order to limit the contrast. The threshold=countmean+factor*countstd.

-G ... displays graph of intensity mapping function.

-L ... Save the lookup table image. If saved, it will be named redist_lut.png

MEAN is the desired center point for the peak in the Gaussian distribution. It is an integer in the range of 0 to 100 (graylevel %). Its default value is 60.

LO is the desired 1 sigma roll-off point on the low side of the distribution, expressed as pixels from the peak. This is where the Gaussian shape has dropped to 61% of its maximum value. The range between the peak and this point, will contain 34% of all the pixels in the image. It is an integer which is greater than zero. Its default is 60.

HI is the desired 1 sigma roll-off point on the high side of the distribution, expressed as pixels from the peak. This is where the Gaussian shape has dropped to 61% of its maximum value. The range between the peak and this point, will contain 34% of all the pixels in the image. It is an integer which is greater than zero. Its default is 60. If LO is provided, but not HI, then HI will be set equal to LO.

REQUIRES: NetPBM PGM format intermediate image. See

NOTE: Thanks to Anthony Thyssen for the suggested changes from shell calculations for the histograms to the use of AWK. This has produced a 10x performance speed up.

NOTE: Thanks to Alan Gibson (user snibgo) for the techniques to limit contrast gain by capping any histogram bin count above a threshold.

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 - Gaussian Distribution

(All Histograms From Other Approaches Were Generated From The Lightness Channel)

Lena Image

Original Image

Artificially brightened
and contrast lowered
convert lena.jpg -fx /
".724u+.310" lena_poor.jpg

-G -m HSL

-G -m HSB

-G -m RGB

Zelda Image

Original Image

-G -m HSL

-G -m HSB

-G -m RGB

-G -m OHTA

Zelda Image Comparison To Other Systems' Autolevels

Original Image

-G -m HSL




Zelda Image Comparison To Other ImageMagick Options

Original Image

-G -m HSL



-gamma 2.5

Zelda Image Comparison To Fred's Omnistretch Script

Original Image

-G -m HSL

-acc 1

-acc 3

-cc 0.6,8

Zelda Image Parameter Variations

Original Image

-G 50,40,40
(lower contrast)

-G 50,60,60
(medium contrast)

-G 50,80,80
(higher contrast)

Chinese Checkers Image Parameter Variations
(Photo Provided By Anthony Thyssen)

Original Image

-G -m HSL 60,60,60
(symmetric sigma)

-G -m HSL 60,60,35
(asymmetric sigma
to limit gain
in bright areas)

Zelda - All Three Channels Modified Successively

Original Image

-G -m RGB -c 0
-G -m RGB -c 1
-G -m RGB -c 2

EXAMPLES - Uniform Distribution

Zelda Image

Original Image

-G -s uniform -m HSL

-G -s uniform -m RGB


COMMENT: Some ImageMagick, Photoshop and other applications process each channel of the image separately; whereas, redist uses a common histogram to process all channels of the image, thereby keeping the colors in sync.

What the script does is as follows for the case of Gaussian shape and HSL colormodel:

  • Convert the image to HSL
  • Extract the L (Lightness) channel as the grayscale
    representation for the image
  • Generate a 256 bin cumulative histogram from this
    grayscale image
  • Compute a 256 bin Gaussian function for the specified mean, hi
    and lo values
  • Integrate (sum) the function and normalize it to the number of
    pixels in the image
  • For each bin in the cumulative histogram, get the cumulative
    histogram count and find the bin in the integral with the same
    or closest value
  • create a 256 pixel 1-D lookup table image whose intensity value
    is the bin value retrieved in the previous step (normalized to 65535)
  • Apply the LUT to the Lightness channel
  • Merge the new Lightness channel with the old Hue and Saturation
    channels and convert to an RGB image

This is equivalent to the following IM commands:

  • # separate channels of infile
  • convert $infile -colorspace HSL -channel R -separate $tmp0
  • convert $infile -colorspace HSL -channel G -separate $tmp1
  • convert $infile -colorspace HSL -channel B -separate $tmp2
  • # create lut
  • echo "P2 $len 1 $maxval\n ${lutArr[*]}" | convert - -scale 256x1! $tmp3
  • # process Lightness channel
  • convert $tmp2 $tmp3 clut $tmp2p
  • # combine H,S and new L channels and convert to RGB
  • convert $tmp0 -colorspace HSL $tmp0 -compose CopyRed -composite $tmp1 \
    -compose CopyGreen -composite $tmp2p -compose CopyBlue \
    -composite -colorspace RGB $outfile