## Histograms

Trial and error, the classic method of learning, is applicable also to
G'MIC. When using it as a command line program, it is a little more work than
with a regular GUI program, since you need to read the documentation to find
out what things can be experimented with. And after having tried a command it
is also useful to figure out what it did. Here image histograms can help.

G'MIC can generate histograms, but they are not immediately useful for our
purposes. The `histogram` command will generate an image that is 1 pixel
high, and of custom width. In this image the brightness of each individual pixel
corresponds to how common pixels of a certain brigthness were in the original
image. Compare with the histogram bars in regular histogram. It is as if looking at the
histogram from above, where higher bars gets lighter. However, when
viewed in a image viewer, this is hard to comprehend - it will look like a
greyscale fading between white black and grey in a pattern depending on the
source image. 

To visualize this better, the histogram image can be given as argument to a
plot command. The plot command will generate a graphical plot of a
mathematical expression. The expression language is quite capable but in this
case we only need to use a very simple function. 

     gmic image.jpg -histogram 256 -plot 3

Here, the `histogram` command will create a histogram image, 1x256 pixels in
size, with pixel values depending on the relative frequency in the source
image (image.jpg). 256 basically means that we want to see 256 levels, which
is the highest that makes sense for a JPG image since it is a 8-bit format. 

Next we plot the data, using a plot of type "histogram" (type 3). There are other
types, such as points or splines. 

The result is a nice, interactive histogram, showing how brightness is
distributed in the image.

![Native histogram][h1]	

There is another way to generate histograms that combines the different
color channels using a kind of trick.
G'MIC uses [GraphicsMagick](http://www.graphicsmagick.org/) to read
and write image formats. GraphicsMagick in turn supports ImageMagick
metaformats, including a special format that represents an image histogram.

These details do not matter that much though. To generate a histogram for an
image, you do

       gmic image.jpg -o histogram:name-of-file-for-histogram.miff

This will generate a file called name-of-file-for-histogram.miff, which is a
file of the less well known 
[MIFF format](http://en.wikipedia.org/wiki/Magick_Image_File_Format), 
an ImageMagick invention. Viewing the histogram is easy:

      gmic name-of-file-for-histogram.miff

![Contrast-less image, histogram][n2]	

The MIFF file will be quite big - it will contain the image in a form that
takes lots of space to store, and the actual histogram will be a small addition
in that big file. So if you want to keep it, it makes sense to convert it to a
more well known and space-efficent format:

     gmic name-of-file-for-histogram.miff -o histogram.png

With this knowledge we can explore some fundamental G'MIC commands. 

## Normalization

Normalization is a process that adjusts the pixel values in an image so that
it better utilizes the available values. For example in a JPG image, the red,
green and blue colors can be represented with values between 0 and 255.
Looking at the image histogram, this means shifting the
bars along the x-axis. The goal is usually to use as much as possible of the
available pixel values for the "important" pixels in the image. 

This is easier to explain with an example. The example image we will use is
the one we are already familiar with - an image that has been processed with
dcraw and had gamma applied, but not been further processed. In this form, it 
lacks contrast, and looks pretty dull. 

![Contrast-less image][n1]	

If we look at its histogram we can see that there are unused values both in
the upper and lower part of the histogram:

![Contrast-less image, histogram][n2]	

When we normalize this image we need to tell G'MIC by how much. This can be
done in different ways, for example using percentages:

     gmic normalizationexample.jpg -n 15%,85% -o normalizationexample-normalize15%-85%.jpg

`-n` is short for `-normalize`. 
This will adjust the darker parts of the histogram 15% "upwards", towards
brigher values, while pulling the higher, brigher values "downwards", making
them darker. The resulting image is not improved, on the contrary:

![Even less contrast][n3]	

and it is evident from the histogram that we moved the values in the wrong
direction!

![Even less contrast, histogram][n4]	

So let's move the values in the opposite direction:

     gmic normalizationexample.jpg -n -15%,115% -o normalizationexample-normalize-15%-115%.jpg

The results is improved contrast but with... hmm let's say surprising if not
horrible effects - the coal started glowing and set the boat on fire!

![More contrast][n5]	

Looking at the histogram, we can see what has happened. It looks like the
darker values got pushed out from the lower (left) end of the histogram, and
appeared at the higher end. See the spike in the far right. These pixels got
maximized for some colors but not for others, depending on the original
value. The result is colored and unwanted artifacts in the image.

![More contrast, histogram][n6]	

We need to prevent this from happening and we can accomplish this by cutting
off pixels prior to normalizing them. So, for this we use the `cut` command,
shortened `-c`:

    gmic normalizationexample.jpg -c 15%,85% -o normalizationexample-cut15-85.jpg 

This will "cut off" the lowest 15% of the histogram and the highest 15% as
well. Afterwards, the histogram will be empty in these regions. However,
cutting the histogram does not mean that the pixels somehow disappeared. Note that in
the lower (left) end of the histogram, a high spike represents all those cut
off pixels that were not allowed to be that dark. They got a highter brightness
since they obviously need to have a value, they got the darkest allowed
one. On the right side, the same thing happened but it is hard to see in the
histogram. Blame all the dark coal for that - there is so much of it that the
relative height of the histogram had to change to fit the leftmost bar,
representing it all. 

![Cut pixels][n7]	

![Cut pixels, histogram][n8]	

Studying the image and comparing it with the original we can easily see that
with our own eyes. The shades, such as the darkest parts of the coal, or the
darkness within the cabin has been replaced with a dull grey, and we have
still not achieved an improved image.

But now it is turn to combine the normalization and cut commands, in order: 

    gmic normalizationexample.jpg -c 15%,85% -n -15%,115% -o normalizationexample-cut15-85-normalize-15%-115%.jpg	

So, we first cut the pixel values, and normalize the image to "stretch back"
the histogram with approximately the same amount. Finally we have an image
with enhanced contrast without appearant artifacts:

![Contrast stretched image][n9]	

![Contrast stretched image, histogram][n10]	

Now, to save some future work, we can implement this operation as a G'MIC
custom command. This way of increasing contrast is often called `contrast_stretch`:

       #@gmic contrast_stretch : cut_low[%], cut_high[%], normalize_low[%], normalize_high[%] : Stretch contrast of image.
       contrast_stretch :
          -e "Stretching contrast of image$?."
          -v - -repeat @#
          -c  $1,$2 -n $3,$4	
          -mv[-1] 0 -done -v +

Put this in a command file and apply it applied as

gmic -m /path/to/commandfile image.jpg -contrast_stretch 15%,85%,-15%,115%

to increase the contrast of your images.


[h1]:  tutorialimages/nativehistogram.png
[n1]:  tutorialimages/normalizationexample.jpg
[n2]:  tutorialimages/normalizationexample-hist.png
[n3]:  tutorialimages/normalizationexample-normalize15%25-85%25.jpg
[n4]:  tutorialimages/normalizationexample-normalize15%25-85%25-hist.png
[n5]:  tutorialimages/normalizationexample-normalize-15%25-115%25.jpg	
[n6]:  tutorialimages/normalizationexample-normalize-15%25-115%25-hist.png	
[n7]:  tutorialimages/normalizationexample-cut15-85.jpg
[n8]:  tutorialimages/normalizationexample-cut15-85-hist.png
[n9]:  tutorialimages/normalizationexample-cut15-85-normalize-15%25-115%25.jpg
[n10]: tutorialimages/normalizationexample-cut15-85-normalize-15%25-115%25-hist.png
