Image Processing
HistoStretch.gif (959 bytes) HistoStretchGrays  Lab Report
Using Histogram Stretching to Improve Image Contrast in a Gray-Scale Image
ScreenHistoStretchGraysBoard.jpg (58790 bytes)
Note:  The "Max" value in red is the highest frequency, which is set dynamically.
In the image and histogram above to the left, 23,043 pixels had a "brightness" value of 49.

In the histogram-stretched image and histogram above to the right, 23,043 pixels had a "brightness" value of 165.

The purpose of.this project is to enhance the contrast of a gray-scale image by using histogram stretching.

Materials and Equipment

Software Requirements
Windows 95/98/2000
Delphi 3 - 7 (to recompile)

GIF support to read files requires Anders Melander's TGIFImage and a "GIF" conditional to be set before compilation.  

Hardware Requirements
VGA display with 640-by-480 screen in high/true color display mode


  1. Double click on the HistoStretchGrays.EXE icon to start the program.
  2. Press the Read button.  Select any shades-of-gray or color image.   (BMP, JPG, ICO, EMF or WMF file formats -- GIF images can be read if the program is compiled with the TGIFImage component installed.)  Press the Open button.
  3. If desired, adjust the stretch range by pressing the up or down arrows at the lower left.  (By default the range 1% to 99% is stretched to the full range.)
  4. If desired, adjust the "factor" setting.  (By default, a factor of 1.00 takes the input range and stretches it from 0 to 255.)
  5. Press the "Copy" button to copy to the clipboard, or press "Write" to save the histostreched BMP file to disk.

Each pixel in a  gray-scale image has a brightness from 0 to 255, where 0 is black and 255 is white.  A histogram shows the number of pixels with the various levels of brightness.  The "0" value on the left of histogram shows the number of pixels that are black.  The "255" value on the right of a histogram shows the number of pixels that are white.  The histogram is a probability distribution of the brightness levels.

An image has low contrast when the complete range of possible values is not used.  For example, the "board" image shown above only uses values 11 through 97 of the possible 0 to 255 range.  Inspection of the histogram shows this lack of contrast.

The program automatically converts any color image of any PixelFormat to a pf24bit PixelFormat -- this avoids working with palettes.  Each 24-bit color pixel has 8-bits of red, 8-bits of green and 8-bits of blue.  A color image can be converted to a gray scale value by computing the "Y" value for each color pixel:

    Y = 0.299R + 0.587G + 0.114B

This "Y" value is the grayscale component in the YIQ color space used in NTSC television.  The weights reflect the eye's brightness sensitivity to the color primaries.

Other methods could have been used for this color-to-grayscale conversion.  Often, for convenience, an "Intensity" value is used:  I = (R + G + B) / 3.

Once this "Y" value is computed, this "Y" value is then assigned back to each of the R, G, B components of the color pixel.  RGB(i,i,i), where i = 0..255, yields a grayscale.

Working with gray-scale images in high-color or true-color environment allows the use of all values 0..255 without special API calls to establish a 256 gray-scale palette.  [By default, Windows reserves 20 of the 256 colors in 256-color display mode and a special API call is needed to "reclaim" 18 of the 20 colors.   Two of the colors cannot be redefined, but these colors are "black" and "white" and they are needed for the complete 256-gray-scale palette anyway.]

When you process a gray scale image (like the faces 211.JPG and 319.JPG derived from the "Faces" database) the program displays the number of shades of gray to the right of the Read button:

ScreenHistoStretchGraysFace.jpg (54674 bytes)

When you process a color image (such as the Mandrill.BMP in the Mandrill.ZIP file) the program displays the original number of colors and the resulting number of shades of gray to the right of the Read button:

ScreenHistoStretchGraysMandrill.jpg (74474 bytes)

After reading the image file, the histogram frequency distribution is computed, as well as a number of other statistics.  When a histogram has a single dominant peak, these statistics are often helpful in describing this peak.

The "range of interest" is computed from the histogram based on a percentage parameter.  In the examples shown above, the 1% and 99% values are determined using the histogram.  Normally this "range of interest" (OriginalRange) is stretched to the full 0 to 255 range to improve the contrast of the image.  The percentage value, in effect, defines how many pixels are forced to be at 0 (black) and 255 (white).

The StretchFactor, which is normally 1.00, is used as follows to compute a histogram ScaleFactor:

    StretchedRange := OriginalRange + ROUND( StretchFactor * (255 - OriginalRange) );
    ScaleFactor := StretchedRange / OriginalRange;

The intensity of each pixel is inspected and re-assigned based on this ScaleFactor:

    NewIntensity := ROUND( ScaleFactor * (OldIntensity - OriginalRangeLeft) );

Each NewIntensity value is forced to 0 if below 0, and forced to 255 if above 255.

Notes about the HistoStretchGrays program:

Also see Charles Hacker's Image Processor program that produces a histogram and percentage of dark to light pixels, of an eight bit gray scale Microsoft Windows bitmap.  

Histogram stretching is an effective way of improving the contrast of a gray-scale image.

Histogram stretching a color image by applying the technique shown here to the R, G and B color planes will result in an image with high contrast, but often will introduce undesirable color shifts.  For example, a poor contrast image of a yellow tulip with green leaves when histostretched will show the yellow tulip but most likely will have blue leaves!

Histogram, grayscale, histogram stretching, RGB, YIQ, TPicture, BMP, JPG, GIF, pixel, TRGBTripleArray, Scanline, TBitmap, TImage, THistoArray, TRGBHistoArray, THistogram, GetStatistics method, GetHistogram method, GetPercentileLevel method, min, max, range, mode, median, mean, standard deviation, kurtosis, math unit, NaN, Plural function, RGBTripleToY function, CountColors function, TBits

Delphi 3 - 7 Source and EXE:  HistogramStretchGrays.ZIP

Updated 27 Jun 2003

since 31 May 1999