- Index
ImageMagick Examples Preface and Index
Converting Color to Gray-Scale
(Making grayscale images)
Level Adjustments
(adjusting the colors in images)
Automatic Level Adjustments
(automatic enhancment of images)
DIY Level Adjustments
(general tinting operators)
Tinting Images
(general tinting operators)
Replacing Colors in an Image
(replacing individual colors)
Recoloring Images with Gradients
Miscellanious Color Operators
(special recoloring operators)
Color modifications to images without changing the overall image itself is
a very common requirement of ImageMagick. Whether it is to lighten or darken
the image, or more drastic color modifications.
|
We will need a test image... Don't worry above how I actually generated this
image, it is not important for the exercise. I did design it to contain a
range of colors, transparencies and other features, specifically to give IM a
good workout when used.
|
|
If you are really interested in the commands used to generate this image
you can look at the special script, "generate_test", I use to create it.
Converting Color to Gray-Scale
Gray scale images can be very useful for many uses. Either as furthering the
processing of the original image, or for use in background compositions.
The best method of converting an image to gray-scale is to just ask IM to
convert the image into a gray-scale
Color
Space representation for the image.
convert test.png -colorspace Gray gray_colorspace.png
|
Note how the blue is much darker than the red, due the weighting to match the
intensity as they seem to appear to the human eye. That is '
red'
is quite a bright color compared to '
blue' which looks darker.
However there a many other methods, and meanings of 'gray-scale'...
For example, you can drain all the color out of the the image by using
"-modulate", to set all
color saturation levels to zero.
convert test.png -modulate 100,0 gray_modulate.png
| |
|
Note how the IM '
green' color I used in my test image is not a
pure green, but the half-bright green defined by the new
SVG -- Scalable Vector Graphics
standard. If you need a pure RGB green you can use the color
'
lime' instead.
Another way is to use the FX DIY operator to
average the three channels together to get a pure mathematical meaning of
gray-scale.
convert test.png -fx '(r+g+b)/3' gray_fx_average.png
| |
|
You can use the same technique to control the weighting of the individual
color channels. For example this is the normal IM meaning of 'gray-scale' for
an RGB image.
convert test.png -fx '0.3*r+0.6*g+0.1*b' gray_diy.png
| |
|
You can also use 'intensity' if you want the same meaning within the "-fx" operator.
convert test.png -fx intensity gray_intensity.png
| |
|
Another technique is to simply add all three channels together and while the
resulting image will not loose information due to 'quantium rounding' effects,
you may loose information about the brightest colors.
convert test.png -separate -background black \
-compose plus -flatten gray_added.png
| |
|
This grayscale image particularly well suited for generating masks from
Difference Images.
However as the
FX DIY operator is interpreted,
it can run very very slowly. For more complex operations you can use the
simpler
Evaluate Operator, "
-evaluate".
For example here is a 2/5/3 ratio gray-scaled image, though I make no attempt
to preserve the transparency channel of the original image.
convert test.png -channel R -evaluate multiply .2 \
-channel G -evaluate multiply .5 \
-channel B -evaluate multiply .3 \
+channel -separate -compose add -flatten gray_253.png
| |
|
  |
The above would suffer from 'quantization' effects for a ImageMagick
compiled at a 'Q8' Quality Level. That
is because the results of the "-evaluate" will be saved into a small 8 bit integer, used for
image values. Only later are those values added together with the
resulting loss of accuracy.
An ImageMagick compiled with 'Q16', or better still the HDRI, quality compile options will produce a
much more exact result.
|
A simular technique can be used to generate a pure mathematical gray-scale,
by directly averaging the three RGB channels equally.
convert test.png -separate -average gray_average.png
| |
|
However as you can see, I did not attempt to preserve the alpha channel of the
resulting image.
Another fast alturnative is to use the "
-recolor" color matrix operator,
which will let you specify the weighting of the three color channels.
convert test.png -recolor '.2 .5 .3
.2 .5 .3
.2 .5 .3' gray_recolor.png
| |
|
Basically the first tree numbers is the channel weighting for the resulting
images red channel, next 3 for green, and the final three numbers for blue.
A much more interesting technique is to extract a variety of different
meanings of brightness, by extracting the appropriate
Color Channel from various
Color Space representations of the image.
The first image is the normal recomended method.
convert rose: -colorspace Gray channel_gray.gif
convert rose: -colorspace CMYK -channel K -negate -separate channel_black.gif
convert rose: -colorspace HSB -channel B -separate channel_brilliance.gif
convert rose: -colorspace HSL -channel B -separate channel_lightness.gif
convert rose: -colorspace YUV -channel R -separate channel_luma.gif
|
|
|
Gray RGB
|
Neg Black CMYK
|
Brilliance HSB
|
Lightness HSL
|
Luma (Y) YUV
|
Note that none of the gray-scale results are quite the same due to
the different meanings of 'brightness' in the various colorspaces.
Alternatively you can use "-type" to tell IM to treat the image as gray-scale, when either
reading or writing the image.
convert test.png -type GrayScaleMatte gray_type.png
| |
|
  |
The "-type" setting is
generally only used when an image is being read or written to a file. As
such its action is delayed to the final write of the image. Its effect is
also highly dependant on the capabilities of the image file format
involved, and is used to override ImageMagicks normal determination during
that process. See the Type examples for
more information.
|
  |
Before IM v6.3.5-9 the above will have removed any transparency in the
written image (equivalent of a "-type Grayscale") due to a bug. This was fixed as soon as I
noted the problem and reported it. (There is a lesson here :-)
|
Level Adjustments
The most basic form of adjustment you can make to images are known as 'level'
adjustments. This basically means taking the individual RGB color values
(or even the matte/alpha channel values) and adjusting them so as to either
stretch or compress those values.
As only channel values are being adjusted, they are best demonstrated on a
gray-scale image, rather than a color image. However if you adjust all the
color channels of an image by the same amount you can use them with color
images, for the purposes of either enhancing, or adjusting the image.
Do not confuse this with the more automatic form of level adjustments, which
we will look at in the next major section of examples below,
Auto-Level Adjustments. This functions will do exactly
the same operation regardless of the actual content of the image. It does not
matter if the image is bright, or dark, or has a blue, or yellow tint. The
operations are blind to the actual image content.
![[IM Graph]](gp_noop.gif)
In demonstrating these operations I will be using a modified "
gnuplot" graph such as shown to
the right, which I generate using a special script "
im_graph_levels". The graph has
a red line which maps the given original 'x' value (representing the
gray-scale value of the top most gradient) to the 'y' value shown. The
resulting color gradient is also shown underneath the input linear gradient.
The graph shown to right is of the IM "
-noop" operator which actually does nothing to an image. As such
each of the image's color values are just mapped to exactly the same value
without change. The lower gradient is thus the same as the upper gradeint.
Image Negation
The simplest and most basic global level adjustment you can make is to negate
the image, using the "
-negate" image operator.
Essentially this makes white, black, and black, white,
, adjusting all the colors to match. That is it will make the color
red, its complemtary color of cyan, and blue, yellow, etc.
You can see this with the mapping graph shown below, as I use the "
-negate" opertator on both the
'test' image and the standard IM 'rose' built-in image. Note how the lower
gradient in the mapping graph image is now reversed, so that black and white
are swapped, and the same reversal apprearing in the negated 'test' image.
convert test.png -negate test_negate.png
convert rose: -negate rose_negate.gif
|
Internally negate is actually rather stupid. It handles the three color
channels independently, and by default ignores the alpha or matte channel.
If this was not the case, you would get a very silly result like this...
convert test.png -channel RGBA -negate negate_rgba.png
|
The image is negated, as you can see by the semi-transparent color gradient.
But as the transparency channel has also been negated you loose all the opaque
colors in the image. This is why the default setting for "
-channel" is '
RGB'.
See
Color Channels for more information.
You can limit the negation to just one channel, say the green color channel.
This may not seem very useful, but at times it is vitality important.
convert test.png -channel green -negate negate_green.png
|
The "
-negate" operator
is actually its own inverse. Doing two negations with the same "
-channel" setting cancels each
other out.
convert negate_green.png -channel green -negate negate_restore.png
|
Negation is extremely common in image processing, particularly when dealing
with gray-scale images as a step before or after other processing options. As
such I recommend you play with it and keep it in mind whenever you are doing
anything, as working with negated images can solve some otherwise difficult
problems.
Direct Level Adjustments
The "
-level" operator is
the more general level adjustment operator. You basically give it two values
a 'black_point' and a 'white_point', as well as an optional third value (gamma
adjustment), which I will look at
later.
What it does is map any color values in the image that is equal to or less
than the 'black_point', and make them black (or a 0 value). Simularly any
color values which are equal to or brighter that the 'white_point' will make
them white (or a Maximum value). The colors in between these two points
are then 'stretched' linearly to fill the complete range of values.
The effect of this is to improve the contrast, enhancing the colors within an
image. For example here is a 25% contrast enhancement of our test image,
using the same values as shown by the graph.
As you commonly adjust both the black and white points by the same amount from
the
0% and
100% amounts, you can just specify the
'black_point' only. The white point will be adjusted by the same amount
inward.
convert test.png -level 25%,75% test_level.png
convert rose: -level 25% rose_level.gif
|
Note that
25% is a hugh contrast enhancement for any image, but
it clearly shows what it does.
You don't have to change both the 'black' and 'white' points. Intstead it is
quite permissible to just adjust only one end of the color range. For example
we can make a very light, or a very dark rose image.
convert rose: -level 0,75% rose_level_light.gif
convert rose: -level 25%,100% rose_level_dark.gif
|
However I again warn you that the colors outside the given range are 'clipped'
or 'burned', and as such will no longer be available for later image
processing. This is the biggest problem with using a "
-level" operator.
![[IM Graph]](gp_level-.gif)
By using a negative value you can do some rough de-contrasting of an image.
What this means is that rather than a providing a color value for the values
to be mapped to 'black' and 'white' and thus stretching out the colros
in between, you instead compress the color values so as to map the imaginary
negative color black or white. The result is a general graying of the image.
convert rose: -level -25% rose_decontrast.gif
| |
|
This method of decontrasting an image however is very inaccurate and not
recommended, unless you have a IM older than version 6.4.2 where you don't
have access to the new
Reversed Level Operator.
![[IM Graph]](gp_level_neg.gif)
You can use the "
-level"
operator to negate an image, just by swapping the 'black' and 'white' point
values given, using "
-level 100%,0".
![[IM Graph]](gp_level_thres.gif)
Or by setting them to the same value, you can effectivally call all the color
values in the image to be thresholded. Using "
-level" to threshold an image is
exactly the same as if you used the "
-threshold" operator with the
value. The mapping graph shown right, shows the results of a
"
-level 50%,50%" operation, and its effect on a grayscale
gradient.
And here is the result of applying this thresholding "
-level" operation on the built-in
rose image. Note that unlike "
-threshold" the image is not converted to a grayscale image as
part of the thresholding, when used with the default "
-channel" setting (see
Thresholding Images).
convert rose: -level 50%,50% rose_level_thres.gif
| |
|
The General nature of level to linearly modiy an image, makes the "
-level" operator a very good for
general gray-scale image, and mask adjustments. Add the fact that you can
modify individual channels as opposed to the whole image, makes it one of the
basic color modification operators availble to IM users.
  |
Be warned that the "-level" operator treats the transpareny channel as 'matte'
values. As such 100% is fully transparent and 0% is opaque. Please take
this into account when using -level with a blurred shape image. This is
most typically done after blurring an 'shape' image, to expand and stretch
the results. For examples of this see Soft Edges, and Shadow
Outlines.
|
  |
Note you can also use various "-evaluate" mathematical methods to achieve the same results for
-level both + and - forms) however if more than two operations are needed
care must be taken to ensure you do not 'clip' any important data from the
image. You do not have that problem with the "-level" operator.
See Evaluate Math Operator for
examples of using this simplier operator.
|
Reversed Level Adjustments
As of IM version 6.4.2 the
Level Operator was expanded
to provide a 'reversed' form "
+level" (note the 'plus'). Alturnativally you can use the original
"
-level" form of the
operator but add a '
!' to the level argument given (for older API
interfaces).
The arguments for this varient is exactly the same, but instead of stretching
the values so as to map the 'black_point' and 'white_point' to 'black' and
'white', it maps 'black' and 'white' to the given points. In other words
"
+level" is the exact
reverse of "
-level".
For example here we map 'black' to a 25% gray, and white to 75% gray,
effectivally de-contrasting the image in a very exact way.
convert test.png +level 25% test_level_plus.png
convert rose: +level 25% rose_level_plus.gif
|
If you compare the above "
+level 25%" operation with the use
of a a negative de-contrasting, "
-level -25%" operator we
showed previously, you will see that are not the same. The 'plus' version
produces a much stronger de-contrasted image (it is greyer), but does so by
mapping to the exact values you give the operator, and not the 'immaginary'
values the 'minus' form used. This exact value usage is important, and one of
the reasons why the 'plus' form of the operator was added.
Of course a '
25%' is again a very large value, and it is not
recommended for use with typical image work.
Note that the "
-level"
and "
+level", are in
actual fact the exact reverse of each other when given the same argument.
That is one maps values to the range extremes, while the other maps from the
range extremes.
However while you can use one to 'undo' the other, the result may not be
exactly the same, due to 'clipping' and 'quantum rounding' effects on the
image values.
For example here we compress the colors of the test image using "
+level", then decompress them
again using "
-level", so
as to restore the image close to its original appearence.
convert test.png +level 20% -level 20% test_level_undo.png
|
The two images appear to be very very simular, and as I am using a high
quality 'Q16' version of IM, you will be hard
pressed to notice any difference at all. However the values may not be
exactly the same (especially with a Q8 version of IM), as you have
effectivally compressed, the un-compressed the image, which can produce some
'rounding' effects (unless you use a floating point
HDRI version of ImageMagick).
Unfortunatally doing these two operations in the oppisite order (stretch, then
compress the color values) produces a very different result...
convert test.png -level 20% +level 20% test_level_undo2.png
|
Notice how the center values of the color range are restored correctly, but
the bright and dark ends have been clipped during the stretching by the
"
-level" operator. Then
when the "
+level"
operator was applied the 'clipped' or 'burned' values was moved to the given
grey levels, effectivally clipping the brightest and darkest pixels to
specific values. This can be a extremely useful technique.
One other useful aspect of the "
+level" operator is that you can completely compress all the color
values in an image to the same gray-scale level.
convert test.png +level 30%,30% test_level_const.png
|
By specifying levels according to the values of specific colors for each
individual channel, you can effectivally convert a greyscale gradient into a
specific color gradient. However this is rather difficult to calculate and
do. As such as of IM v6.4.2 a "
-level-colors" operator has
been provided that will let you specify the black and white points in terms of
a specific colors, rather than 'level' values. See
Level by Color below.
Level Gamma Adjustments
Both the above "
-level"
varients also allow you to use a third setting. The 'gamma' adjustment value.
By default this is set to a value of
1.0', which does not do any
sort of mid-tone ajustment of the resulting image, producing a pure linear
mapping of the values from the old image to the new image.
However by making this value larger, you will curve the resulting line so as
to brighten the image, while shrinking that value will darken the image.
For example here I use just the 'gamma' setting to brighten and darken just
the mid-tones of the image.
convert rose: -level 0%,100%,2.0 rose_level_gamma_light.gif
convert rose: -level 0%,100%,0.5 rose_level_gamma_dark.gif
|
Values generally range from 10 for a blinding bright image, to .2 for very
dark image. As mentioned a value of
1.0 will make no 'gamma'
changes to the image. However the special value of '
2.0' (see
above) can be used to get the square root of the images normalized color.
Both versions of the "
-level" operate handles 'gamma' in the same way. This means can
combine the level adjustment of the 'black' and 'white' ends, with a
non-linear 'gamma' adjustment. You can also only adjust a single channel of
an image. For example, here we give an image a subtile tint at the black end
of just the blue channel, while using gamma to preverse the mid-tone color
levels of the image.
convert test.png -channel B +level 25%,100%,.6 test_blue_tint.png
|
This specific example, could be used to tint a weather satalite photo, where
only the sea is pure black, while land is more grey.
The "
-gamma" operator is
also provided, and has exactly the same effect as the 'gamma' setting in the
"
-level" operator.
However it will let you adjust the 'gamma' adjustment level for each
individual channel as well.
For example here we brighten the image differently for each individual RGB
channel.
convert rose: -gamma 0.8,1.3,1.0 gamma_channel.gif
| |
|
As you can see this can be used to do some subtile tinting and color
adjustments to an image, or correct images with contain too much of a specific
color.
  |
One of the most important things when resizing, filtering or modifying
images (even more important anything else) is to do it in linear space, so
if your image is gamma corrected, you should transform it to linear space,
scale and then transform back to gamma space.
|
One less obvious use of "
-gamma" is to zero out specific image channels (See
Other Channel Seperation Methods).
Or color an image completely 'black', 'white' or some other primary color.
See
Primary Colored Canvases.
Level Adjustment by Color
The "
-level-colors" operator was added to IM v6.2.4-1. Essentually it
is exactly the same as the
Level Operator we discussed
above, but with the value for each channel specified as a color value.
That is the "
-level-colors" option will map the given colors to 'black' and
'white' and stretching all the other colors between then linearly. This
effectivally removes the range of colors given from the image.
This is actually not very useful, and waiting for some good examples, so I'll
leave it at that for now.
The plus form of the operator "
+level-colors" is extremely useful as it will map the 'black' and
'white' color to the given values compressing all the other colors linearly.
For example lets map '
black' and '
white' to
'
green', and '
gold'...
convert test.png +level-colors green,gold levelc_grn-gold.png
|
As you can see the grayscale gradient is remapped into the a gradient bound by
the colors given, and although colors outside a gray-scale range are also
modified, they will also follow the basical style of the color range
specified. This makes the "
+level-colors" operator an extremely useful on.
Here are a few more examples, of using this to adjust or 'tint' a colorful
image, rather than a gray-scale image.
convert rose: +level-colors navy,lemonchiffon levelc_faded.gif
convert rose: +level-colors firebrick-gold levelc_fire.gif
convert rose: +level-colors 'rgb(102,75,25)'-lemonchiffon levelc_tan.gif
|
Note that you can use either '
,' or '
-' as the color
name seperator, which is useful is you want to specify a color such as the
"
rgb(...)" in the above and have IM work seperate the colornames
correctly. If you leave out one, or both of the color names, the missing
color will default to '
black' or '
white' as
appropriate.
If you specify the same color for both the new 'black' and 'white' points,
then you will effectivally set all the colors in the image to that color.
For example, lets turn the test image '
dodgerblue'
convert test.png +level-colors dodgerblue,dodgerblue levelc_blue.png
| |
|
In other words the "
+level-colors" is a general linear color replacement and linear
tinting operator.
Note also that while this operator can be used with the matte/alpha channel by
setting an appropriate "
-channel" value, you will also need to set the gray-scale gradient
into the matte/alpha channel so that color replacement can be performed
correctly.
Sigmoidal Non-linearity Contrast
From a PDF paper on '
Fundamentals of
Image Processing' (page 44) they present a alturnative from the linear
contrast control with gamma correction known as '
sigmoidal non-linearity
contrast control'.
The result is a non-linear, smooth contrast change (a 'Sigmoidal Function' in
mathematical terms) over the whole color range, preserving the white and black
colors, much better for photo color adjustments.
The exact formula from the paper is very complex, and even has a mistake, but
essentially requires with two adjustment values. A threshold level for the
the contrast function to center on (typically '
50%'), and a
contrast factor ('
10 being very high, and '
0.5' very
low).
  |
For those interested, the corrected formula for the 'sigmoidal
non-linearity contrast control' is...
(1/(1+exp(β(α-u)))
- 1/(1+exp(β)))
/ (1/(1+exp(β(α-u))/(1+exp(β))))
Where α is the threshold level, and β the contrast
factor to be applied.
The formula is acutally very simple expotential curve, with the bulk of
the above formula is designed to ensure that 0 remains 0 and 1 remains
one. That is the graph always goes though the points 0,0 and 1,1. And the
point of the highest gradient is at the given threshold.
|
Here for example is a "
-fx"
implementation of the above formula, resulting from a very high contrast value
of '
10' and a '
50%' threshold value. These values
have been rolled into the floating point constants, to speed up the function.
convert test.png -fx '(1/(1+exp(10*(.5-u)))-0.0066928509)*1.0092503' \
sigmoidal.png
|
Lucky for us IM v6.2.1 had this complex function builtin as a new operator
"-sigmoidal-contrast", allowing a much simpler application.
convert test.png -sigmoidal-contrast 10,50% test_sigmoidal.png
| |
|
As a bonus IM also provides the inverse, a 'sigmodial contrast reduction'
function (as plus '+' form of the operator), which if applied
with the same arguments restores our original image (almost exactly).
convert test_sigmoidal.png +sigmoidal-contrast 10,50% \
test_sigmoidal_inv.png
| |
|
And here we apply it to the rose image...
convert rose: -sigmoidal-contrast 10,50% rose_sigmodial.gif
| |
|
I did say '
10' was a very heavy contrast factor. In fact anything
higher than this value can be considered to me more like a fuzzy threshold
operation, rather than a contrast enhancement.
For a practical example of using this operator see the advanced
"Gel" Effects Example, where it is used
to sharpen the bright area being added to a shaped area color.
miscellanious Contrast Operators
Under Construction
-contrast and +contrast
Rather usless minor contrast adjustment operator
-threshold
Threshold the image, any value less than or equal to the given value is
set to 0 and anything greater is set to the maximum value.
Note that like level, this is a channel operator, but if the default
'channel setting' is used only the gray-scale intensity of the image is
thresholded producing a black and white image.
convert rose: -threshold 45% x:
You can force normal channel behaviour, where each channel is thresholded
individually buy using "-channel All"
convert rose: -channel All -threshold 45% x:
-black-threshold
-white-threshold
This is like -threshold except that only one side of the threshold value is
actually modified.
For example, here anything that is darker than 30% is set to black.
convert rose: -black-threshold 30% x:
convert rose: -white-threshold 50% x:
These operators however do not seem to be channel effected, so may only be
suitable for gray-scale images!
Then
-colorize, and -tint
-opaque -transparency floodfill -fuzz
-recolor
Automatic Level Adjustments
Being able to adjust the color range of a gray scale image can be crucial to
general image manipulation. This is generally known as Histogram Adjustment.
The following are just some of the methods that can be used to do this.
FUTURE:
-normalise
Try to stretch the image uniformly across all color channels so as to
enhance the image.
The channel operator can be used to 'disconnect' the uniformity across
all channels, or alturnativally you can seperate and normalize each
channel individually. However when recombined you may find you get some
color distortion due to each channel being stretched out unequally.
Normalizing a intensity, or equivelent channel in some other colorspace
can also be used to ensure correct normalization of the image without
color distortions, though this is a much more trickier method.
See also equalize, and (future) -equalize-gaussian, also look at fred
Wienhaus's scripts for various methods of image enhancements.
In reality this operator is equivelent to "-contrast-stretch 2%,99%"
Which menas at least 2% of the darkest color values will be set to zero
(black) while the top 1% of the brigthest pixels will be set to maximum
(white) all the other pixels in the image are the stretched out to fill
the whole range from black to white.
If you do not which to 'burn' those top and bottom pixels, use
"-contrast-stretch 0" to do a more 'logical normalize' of the image,
without clipping or burning the top and bottom values.
-contrast-stretch
normalize the image so that the given percentage of pixels in a greyscale
image are mapped to black and white respectivally.
That is -contrast-stretch 5% will make at least 5% of all pixels in a
greyscale image black, and at least 5% of the pixels white.
NOTE that -normalize is defined as -contrast-stretch 2%,99%
If you really want a 'true' normalize using the exact minimum and maximum
values, use -contrast-stretch 0
ASIDE: This currently does the value remapping using 'binned' color
values, as as a result produces a slightly distorted 'stretch'.
We are endevoring to have this fixed to stretch the color values using
the internal -level operator.
Example: an image that does not span the histogram. You
can show a histogram plot or list. Then do -contrast-stretch 0% to
show that the min and max of the image are now at black and white,
resp. I think this is a good example as it stretches the histogram
just enough to span the range as opposed to normalize with clip or
burns or whatever you want to call it by 2% on the low end and 1% on
the high end.
People need to know that they can stretch the image to just exactly span
the histogram and do not have to use -normalize and lose data.
-linear-stretch
Seems to be exactly the same as -contrast-stretch but with a
complemented second argument. That is
-linear-stretch 10%,10% is equivelent to -contrast-stretch 10%,90%
however -linear-stretch 0 is a no-op
also -linear-stretch uses the level function for stretching where
-contrast-stretch and -normalize does not.
It is still unclear exactly how it differs from -contrast-stretch.
-equalize histogram equalization of the image
When one wishes to compare two or more images on a specific basis, such
as texture, it is common to first normalize their histograms to a
"standard" histogram. The most common histogram normalization technique
is histogram equalization where one attempts to change the histogram so
that all the histogram colors are spread out equally over all brightness
values. This would correspond to a brightness distribution where all
values are equally probable. Unfortunately, for an arbitrary image, one
can only approximate this result.
Is it a image comparision technique?
Expand or Normalize gray-scale
To expand the gray scale image so it occupies the full range of gray values
(maximize contrast) is straight forward using the "
-normalize" operator. That
is, the lightest gray becomes white and darkest gray, black.
Here we create a gray-scale gradient, and expand it to the full black and white
range.
convert -size 150x100 gradient:gray70-gray30 gray_range.jpg
convert gray_range.jpg -normalize normalize_gray.jpg
|
  |
For practical reasons to do with JPEG color inaccuracies (see JPEG Color Distortion for more details)
and scanned image noise, "-normalize" does not expand the very brightest and darkest
colors, but a little beyond those values. That is it is equivelent to a
"-contrast-stretch" with a value of '2%,99%' (see
below).
This means if highest and lowest color values are very close together,
"-normalize" will
fail, an no action will be taken.
If you really want to expand the exact brightest and darkest color values
to their extremes use "-contrast-stretch" with a value of '0' instead.
|
Up until IM version 6.2.5-5, "
-normalize" worked purely as a grayscale operator. That is each of
the red, green, blue, and alpha channels were expanded independently of each
other according to the "
-channel" setting.
As of IM version 6.2.5-5, if only the default "
+channel" setting
'
RGB' is given, then "
-normalize" will tie together
all the color channels, and normalizes them all by the same amount. This
ensures that any grayscale that is in the image, remains grayscale. However if
non-grayscale colors are present, it may not expand the image to produce a
pure white or black level.
For example here we added some extra colors (a blue to navy gradient) to our
normalization test image.
convert -size 100x100 gradient:gray70-gray30 \
-size 50x100 gradient:blue-navy +append color_range.jpg
convert color_range.jpg -normalize normalize.jpg
|
As you can see from the last example, for color images "
-normalize" maximized all the
channels together so one channel has a zero value, and another channel has a
maximum value. That is, no black pixels were generated, as all the added blue
colors already contains 'zero' values in the 'red' and 'green' channels. As
such the lower bounds of the image did not expand.
If you want the old "-normalize" behaviour, you will need to use a different "-channel" setting than the
default 'RGB' setting. For images that contain no alpha (or
matte) channel, you can just use the 'all' channel setting.
convert color_range.jpg -channel all -normalize normalize_all.jpg
| |
|
Alturnativally, you can normalize each channel as seperate images using the
"-separate" operator
(as of IM v6.2.9-2), then "-combine" them back into a single image again.
convert color_range.jpg -separate -normalize -combine normalize_sep.jpg
| |
|
The results of the above turns the grayscale areas of the image yellow
As the '
red' and '
green' channels lightened.
The '
blue' channel however is only darkened slightly.
This brings use to an important point
Normalise is really a grayscale operator,
caution is needed when used with color images.
contrast-stretch -- controlled normalize
The "
-contrast-stretch" (added IM v6.2.6), is a more controlled version
of "
-normalize". It
first finds the maximum and minimum bounds in the image, as normal, but then
shifts those bounds further inward by the given amount of color inward before
selecting the colors that will be mapped to white and black.
In other words it is still a "
-normalize" type of operator, but then ignores the most extreme
colors by the amount given (generally as a percentage of gray scale).
For example this will replace both the top and bottom 15% of colors with their
extremes (white and black), stretching the rest of the color to improve the
overall contrast.
convert gray_range.jpg -contrast-stretch 15% stretch_gray.jpg
|
And here I just grab the brightest 5% of colors, stretching them linearly, and
making all other colors black.
convert gray_range.jpg -contrast-stretch 95x100% stretch_black.jpg
| |
|
This can be quite useful, to find bright points in images. It is a bit like a
normalized version "
-black-threshold" operator, but with the other colors stretched to
fill the full color range, rather than just turning the thresholded color
black.
Note that "
-contrast-stretch" is not a true contrast operator, as it
normalizes the image first. If you want to improve the contrast of an image
by a fixed amount that is independent of the actual images current content,
then you should use "
-level" instead.
DIY Level Adjustments
Mathematical Linear Histogram Adjustments
The various basic forms of "
Level Adustments shown above
linearly adjust the colors of the image.
These changes can be applied mathematically as well. For example by
multiplying the image with a specific color, we set all pure white areas to
that color. So lets just read in our image, create an image containing the
color we want, then multiply the original image with this color using the IM
free-form "
-fx" or
DIY Operator.
convert test.png -size 1x1 xc:Yellow \
-fx 'u*v.p{0,0}' fx_linear_white.png
|
By getting "
-fx" to read the
color from a second '
v' image makes it easy to change the color,
without needing to convert colors to RGB values for use in the mathematics.
If you were using a fancy graphical image processing package like "
Gimp" and "
Photoshop" the above operation would have been applied to an image
by adjusting the images color histogram graph 'curve'.
![[IM Output]](fx_linear_white_plot.gif)
For example to the right is a "
gnuplot" generated graph (See the script "
im_histogram") of the
mathematical formula showing what happens to just one of the three RGB
channels. The original color (green line) is remapped to a darker color (red
line) linearly.
Linearly tinting the black colors is also quite simple. For example
to linear map '
black' to a gold like color
'
rgb(204,153,51)', (while leaving '
white' as
'
white'), would require a mathematical formula such as...
result = 1-(1-color)*(1-intensity)
This formula negates the colors, multiples the image with the negated color
wanted, and negates the image back again. The result is tinting of the black
side of the gray scale, leaving white unchanged.
convert test.png -size 1x1 xc:'rgb(204,153,51)' \
-fx '1-(1-v.p{0,0})*(1-u)' fx_linear_black.png
|
A "
gnuplot" histogram graph of the
remapping formula is also displayed in the above for your reference.
With a slightly more complicated formula you can linearly replace both the
'
black' and '
white' end of the grayscale with
specific colors.
convert test.png -size 1x2 gradient:gold-firebrick \
-fx 'v.p{0,0}*u+v.p{0,1}*(1-u)' fx_linear_color.png
|
The "
-size 1x2 gradient:color1-color2" in the above is only used
to generate a two color pixel image for the "
-fx" formula to reference. The first
color replaces white, while the second replaces black, while all others are
interpolated between these two. As is typical of a gray-scale operator, each
RGB channel is treated as a separate gray scale channel, though the linear
interpolation is different for each channel.
This by the way is exactly equivelent to the
Level
Adjustments by Color operator "
+level-colors"
However unlike "+level-colors", the colors to use can of course come from any
image source, even the original image itself, or just inserted directly in the
formula. For example...
convert test.png -fx "yellow*u+green*(1-u)" fx_linear.png
| |
|
Mathematical Non-linear Histogram Adjustments
While linear color adjustments are important, and faster methods ar available,
there are many situations where a linear 'level' adjustment, is not what is
wanted, and this is where the "
-fx"
DIY Operator, becomes more
useful.
Well an alternative formula for linear adjustment is "
-fx
'v.p{0,1}+(v.p{0,0}-v.p{0,1})*u'", which has the advantage that the
'
u' can be replaced by a single random function
'
f(u)' to produce non-linear color change.
This lets you do more interesting things. For example what if in the last
example you wanted to push all the colors toward the '
black'
side, resulting in the image being a more '
firebrick' color.
convert test.png -size 1x2 gradient:gold-firebrick \
-fx 'v.p{0,1}+(v.p{0,0}-v.p{0,1})*u^4' fx_non-linear.png
|
In a more practical example, Adelmo Gomes needed a color adjustment for a
automated
Weather Map Recoloring script he was developing.
In this case he wanted to tint pure black parts of the image to a .25 blue,
but leave the rest of the gray-scale alone, especially the white and mid-tone
grays of the image. Only the blue color needed such adjustment, which he
currently was doing by hand in an image editor.
For example you could use a quadratic formula like '
u^2' to tint
the black end of the histogram to a '
.25' blue color. Only the
blue channel needs to be modified, so the value was inserted directly into
the formula.
convert test.png -channel B -fx '.25+(1-.25)*u^2' fx_quadratic.png
|
However while this produced a reasonable result it does darken the mid-tone
grays slightly, producing a sickly off-yellow color.
To avoid this a 'exponential' function can be used instead, to give better
control of the tinting process.
convert test.png -channel B -fx '.3*exp(-u*4.9)+u' fx_expotential.png
|
Again the graph show how blue channel was modified to give black a distinctive
dark blue tint.
The second value ('
4.9') is the falloff back to a linear
'
+u' graph. The smaller this value is the slower the fall off,
and the more linear the adjustment becomes. The larger the value, the more
dramatic the 'fall-off'. The value may need to be adjusted for different
color values, so this is not a good general formula for general black color
tinting, but perfect for tinting weather maps.
Generally if you can express the color adjustment you want mathematically, you
can then use "
-fx" operator
to achieve the results you want.
'Curves' Adjustments
![[popup]](curves_gui.gif)
Normally in a graphical photo editor you would be presented with a histogram
'curves' chart such as I have shown to the left. The user can then edit the
'curve' by moving four (or more) control points, and the histogram adjustment
function will follow those points.
The control points generally specify that the first grayscale level is after
adjustment to become the second grayscale level. So a point like 0.0,0.2
basically means that a 0% gray (black) should after adjustment be a 20% gray
level.
Now IM does not allow you to directly specify 'control points' to generate a
'curve' adjustment, what it wants is the mathematical formula of that 'curve'
generated. Lucky for us there are programs that can generate that curve
formula from the control points, including "
gnuplot",
"
fudgit", "
mathematica", and "
matlab", as well as many more mathematical software packages.
The following is one method you can use to generate the formula from four
control points using "
gnuplot" which is a standard extra package
you can install on most linux distributions (and is available for Windows
too)...
( echo "0.0 0.2"; echo "1.0 0.9"; \
echo "0.2 0.8"; echo "0.7 0.5"; ) > fx_control.txt
( echo 'f(x) = a*x**3 + b*x**2 + c*x + d'; \
echo 'fit f(x) "fx_control.txt" via a, b, c, d'; \
echo 'print a,"*u^3 + ",b,"*u^2 + ",c,"*u + ",d'; \
) | gnuplot 2>&1 | tail -1 > fx_funct.txt
|
|
Control Points
|
|
|
| |
Gnuplot Fitted FX Function
  |
Note that the number of parameters ('a' to 'd'
in above) needed for curve fitting, must equal the number of control
points you provide. As such if you want five control points you need to
include another 'e' term to the function.
If your histogram curve goes though the fixed control points
0,0 and 1,1, you really only need two parameters
as 'd' will be equal to '0', and
'c' will be equal to '1-a-b'.
|
As you can see from the extra "
gnuplot" generated image above,
the function generated fits the control points perfectly. Also as it generated
a "
-fx" style formula it can be used
as is as an IM argument.
For example...
convert test.png -fx "`cat fx_funct.txt`" fx_funct_curve.png
| |
|
To make it easier for users to convert control points into a histogram
adjustment function, I have created a shell script called "
im_fx_curves" to call
"
gnuplot", and output a nicer looking polynomial equation of the
given the control points. Gabe Schaffer, also provided a perl version (using a
downloaded "
Math::Polynomal" library module) called "
im_fx_curves.pl" to do
the same thing. Either script can be used.
For example here is a different curve with 5 control points...
im_fx_curves 0,0.2 0.3,0.7 0.6,0.5 0.8,0.8 1,0.6 > fx_curve.txt
|
Or you can use it to generate linear histogram adjustment functions, by using
only two control points, which do not need to be the black and white points
either.
im_fx_curves -p 20,60 80,10 > fx_linear.txt
|
Note that in the above I used a '
-p' option, allowing me to
specify the control points as percentiles of gray scale levels, which is
easier for us humans to handle.
The function produced above is only useful as a grayscale adjustment, you can
not normally use this method to convert a grayscale into a specific color
gradient, as we did above in
Linear Histogram
Adjustments. Of course you can tint or add color to the result afterward.
For a practical example of this method is detailed in the advanced
"Aqua" Effects example.
Remember a complex "
-fx"
functions, are very slow as it is being interpreted by IM three to four times
for every pixel. If you plan to use a complex "
-fx" function such as this, over a lot of images, you can speed it
up enormously by converting the
Function into a CLUT
(see below).
Tinting Images
Uniformly Color Tinting Images
Typically tinting an image is achieved by overlaying the image with very
specific color that is made semi-transparent (dissolved) by a certain amount.
This can be done using a
Evaluate
Operator or
Blend Images techniques, but
these are not simple to use.
Lucky for us a simpler method of overlaying a uniform color over an image is
available by using the "
-colorize" image operator. This operator overlays the current
"
-fill" color, dissolved by
the percentage argument, over the current image in memory. The alpha channel
of the original image is preserved, with only the colors being tinted by the
dissolved overlay color.
For example lighten an image (gray scale or otherwise) we use "
-colorize" to overlay a
semi-transparent white image. The argument given defined how transparent the
overlay color is.
convert test.png -fill white -colorize 50% gray_lighten.png
|
Similarly we use a '
black' fill color to darken an image.
convert test.png -fill black -colorize 50% gray_darken.png
|
To gray both ends of the image toward the mid-tones, you would use a specific
gray fill color. The color '
gray50' is the exact middle color of
the RGB color spectrum.
convert test.png -fill gray50 -colorize 40% gray_grayer.png
|
The "
-colorize"
operator also allows you to specify dissolve percentages for each of the three
color channels separately. This is useful for linearly darkening (or
lightening) an image in a special way.
Midtone Color Tinting
While a "
-colorize"
operator applies the "
-fill" color to tint all the colors in an image linearly, the
"
-tint" operator applies
the "
-fill" color in such
a way as to only tint the mid-tone colors of an image.
The operator is a grayscale operator, and the color is moderated or enhanced
by the percentage given (0 to 200). To limit its effects it is also adjusted
using a a mathematical formula so that it will not effect black and white.
but have the greatest effect on mid-tone colors of each color channel.
A "
-tint 100" essentially will tint a perfect gray color so that
it becomes the current fill color. A lower value will tint it to a darker
color while a higher value will tint to a lighter shade of that color.
convert test.png -fill red -tint 40 tint_red.png
|
The green color in the test image is not a true RGB green, but a Scaled Vector
Graphics '
green', which is only half as bright as a true green
color. As such it is also a mid-tone color, and thus is effected by the
"
-tint" operator, becomming
darker, unlike red and blue color spots of the test image.
Also you can tint the individual color components, by using a comma separated
list of percentages. For example "
-tint 30,40,20,10". This
however can be tricky to use and may need some experimentation to get right.
The tinting operator is perfect to adjust the results of the output of
"
-shade", (See
Shade Overlay Highlight Images), such
as the examples in
3d Bullet Images.
  |
The "-tint" operator
works by taking the color and percentages given then then adjusting the
individual colors in the image according to the "-fill" colors intensity, as per
the following formula. (see graph right)
f(x)=(1-(4.0*((x-0.5)*(x-0.5))))
A quadratic function, the result of which is used as vector for the existing
color in the image. As you can see gives a complete replacement of the color
for a pure mid-gray, with no adjustment for either white or black.
|
You can also use "
-tint"
to brighten or darken the mid-tone colors of an image. This is sort of like a
'gamma adjustment' for images, though not exactly.
For example using a tint value greater than 100 with a '
white'
color will brighten the mid-tones.
convert test.png -fill white -tint 130 tint_lighter.png
|
While a value less than 100 will darken colors.
convert test.png -fill white -tint 70 tint_darker.png
|
As "
-tint" uses the color as
a 'vector' in color space, a "
-fill" color of '
black' will have no effect on the
result, as it produces a zero color vector.
Of course their are other ways of color tinting images...
DIY Color Tinting
One of the biggest problems with "
-tint" is that it is a grayscale (or vector) operator. That is
it handles each of the red,green,blue channels completely seperatally to each
other. That in turn means that a primary and secondary color like
'
blue' or '
yellow' are not effected by "
-tint".
However thanks to the "
-fx" you can create your own tinting method, by using it to create
a color overlay so that it works in a simular way to the "
-colorize" operator. (see
Uniformly Color Tinting Images).
For example here I convert an images 'intensity' or grayscale
brightness level into a 'mid-tone tinting overlay' image to tint grayscale
midtone 'gold'.
convert test.png \( +clone -matte -channel A \
-fx 'tint=intensity-.5; (1-4*tint*tint)*a* 1.0' +channel \
-fill gold -colorize 100% \) -composite tint_diy.png
| |
|
Note that while simular to "
-tint" it uses the "
-colorize" overlay method instead of a color vector approach, so
primary colors are also tinted '
gold' leaving only
'
white' and '
black' colors as is.
The final '
1.0' is equivelent to a 100% level of tinting, so you
can reduce that figure to moderate the amount of tinting. You can also change
the '
intensity' to other things like '
lightness',
for other tinting methods.
Of course please let me know what you come up with.
Overlay Color Tinting
The special
Alpha Composition methods
'
overlay' and '
hardlight' was actually designed with
color (and pattern) tinting in mind. This compose also will replace mid-tone
grays leaving black and white highlights in the image alone.
For example here I quickly generate a colored overlay image, and compose it
to tint the original image.
convert test.png \( +clone +matte -fill gold -colorize 100% \) \
-compose overlay -composite tint_overlay.png
| |
|
As you can see the alpha composition does not preserve any transparency of the
original image, requiring the use of a second alpha composition operation to
fix this problem.
convert test.png \
\( +clone +matte -fill gold -colorize 100% \
+clone +swap -compose overlay -composite \) \
-compose SrcIn -composite tint_overlay_fixed.png
| |
|
Alturnativally as we are generating a solid color overlay from teh source
image, you can leave the alpha channel in the source image intact, to active
the same result.
convert test.png \( +clone -fill gold -colorize 100% \) \
-compose overlay -composite tint_overlay_alpha.png
| |
|
This is much more linear than the quadratic funtion used above, and like
"
-tint" is applied to each
channel of the image separately such that primary and secondary colors are
also left unchanged. The 'SVG green' color is of course effected as it is a
half bright green.
Also if you want to actually control the level of tinting, you will
need to adjust the overlay image's transparency level.
And finally unlike the other tinting methods I have shown so far, you are not
limited to tinting a simple color, but can tint the grays using a image, or
tile pattern.
convert test.png \
\( -size 150x100 tile:tile_disks.jpg \
+clone +swap -compose overlay -composite \) \
-compose SrcIn -composite tint_overlay_pattern.png
| |
|
This however is getting outside the scope of basic color handling so I'll
leave image tinting at that.
  |
The alpha composition method 'HardLight' will produce the same results as 'Overlay' but with the source and
destination images swapped.
This could have been used instead of the "+swap" in the last
two examples.
|
Replacing Colors in Images
Replace a Specific Color
The "
-opaque" and
"
-transparent"
operators are designed for replacing one color in an image with another.
For example to replace a '
blue' color with say '
white'
you would use a command like this...
convert balloon.gif -fill white -opaque blue balloon_white.gif
| |
|
Basically any color that was 'blue' has been replaced with the current
"
-fill" color.
However as of IM v6.2.7, this operator limited by the -channel setting. As
such to convert a color (say blue) to transparency you will need to specify a
"
-channel" to include
the alpha channel in the output changes, You will also need to ensure the
image has a 'matte' or alpha channel too.
convert balloon.gif -matte -channel RGBA \
-fill none -opaque blue balloon_none.gif
| |
|
Because replacing a color with transparency is such a common operation the
above has its own special replace with transparency operator "
-transparent".
convert balloon.gif -matte -transparent blue balloon_trans.gif
| |
|
As of IM version 6.3.7-10, the 'plus' versions of these operators invert the
color selection. That is the colors that do NOT match the given color will be
replaced. For example here I replace any color that is NOT black, with white,
leaving just the black borders of this image.
convert balloon.gif -fill white +opaque black balloon_borders.gif
| |
|
This may not seem like much, but when you combine it with a
Fuzz Factor see below, this becomes very powerful.
Before IM v6.3.7-10, the inverse operation required the use of some trickiness
using image masks. Basically you replace the color you want to preserve with
transparency, then "
-colorize" all the other colors to the desired color to create an
overlay mask. This is then overlaid on the original image to 'mask out' the
colors that did not match!
convert balloon.gif \
\( +clone -matte -transparent black \
-fill white -colorize 100% \) \
-composite balloon_mask_non-black.gif
| |
|
As you can see the 'plus' form of the operator simplified the 'not this color'
operation enormously.
For more advanced replacement techniques, I suggest you look at
Transparency Masking.
  |
Be warned that as all matching colors (especailly 'fuzzy matched colors',
see below) are replaces with a single uniform color, you will not get any
anti-aliasing of the edges of the colored areas. This can have a
detremental effect to the look off any non-cartoon like images.
This type of color replacement is not designed with practical real world
images in mind, but more for image masking effects. Caution is advised.
|
Replace using a Image Color
You can also use
Draw Color Replacement to
recolor images based on colors present in the image itself, rather than a
specific color.
convert present.gif -fill red -draw 'color 0,0 replace' present_blue.gif
| |
|
Note that I never specified the color to be replaced, only the location of the
color to be replaced. It is the color at that location that is used for
'matching' what areas is to be filled, regardless of what that color is.
You can see in the above example the problem with color replacement, the
specific color may appear in other places that you intend, giving us a line of
red pixels within the 'present' image above.
Transparency also presents no problem...
convert present.gif -matte -fill none \
-draw 'color 0,0 replace' present_none.gif
| |
|
However unlike "
-opaque"
and "
-transparent"
the
Draw Color Replacement, does not let you
invert the 'matching colors' to be replaced.
Draw also has a special
Matte Replacement, where
only the transparency of the fill color is replaced. That is you can make
all matching colors transparent, or semi-transparent, without actually
changing the color of the pixel itself. With the appropriate file format of
course.
convert present.gif -matte -fill '#00000080' \
-draw 'matte 0,0 replace' present_semi.png
| |
|
This becomes much more useful when a
Fuzz Factor is also
specified.
The biggest advantage of using "
-draw" is that you can also replace the color with a tile pattern.
For example..
convert present.gif -tile pattern:left30 \
-draw 'color 0,0 replace' present_tile.gif
| |
|
Floodfill Draw
The
Draw Color methods also provide you with a
simple method of replacing a color by 'floodfilling'. that is rather than
replacing ALL the matching colors within the image, you can select just the
colors which are 'connected to' or 'attached' to the specified point in the
image.
Again the specified point given sets the starting (or center) of the colors
which are to be replaced.
convert present.gif -fill red -draw 'color 0,0 floodfill' present_fill.gif
| |
|
Note that the red areas which was not 'attached' to the 0,0 pixel was note
replaced.
For background replacing that can be a problem, but the solution is just as
easy. Expand the image slightly so the floodfill can 'leak' into the image
from all directions, then remove that extra space when finished.
convert present.gif -bordercolor white -border 1x1 \
-fill red -draw 'color 0,0 floodfill' \
-shave 1x1 present_bgnd.gif
| |
|
Of course you can adjust what colors are 'matched' using the
Fuzz Factor control setting below, which is especially important for
JPEG images.
Floodfill Operator
The "
-floodfill"
operator was added to make floodfilling slightly easier, especially when you
what to exactly specify the 'center' color for the
Fuzz
Factor.
convert logo.gif -fill red -fuzz 5% -floodfill +10+10 white result.gif
This will replace any color that within 5% of 'white' to 'red' that is
directly part of the area surrounding the seed pixel 10,10.
Note that the 'seeding pixel' must itself be close enough to 'white' to match
otherwise no action will be taken. This 'do nothing if no match' is
particularly useful to ensure that the color of the area specified is the
expected color.
Again if you are attempting to replace a background color, adding a border
for the floodfill to 'leak from is a good idea.
-bordercolor white -border 1x1 \
-fill red -fuzz 5% -floodfill +0+0 white \
-shave 1x1
However only the 'draw' version can replace colors with a tile pattern rather
than a specific color.
-tile tile_rings.jpg -bordercolor white -border 1x1 \
-draw 'color 0,0 floodfill' -shave 1x1
For more advanced background removal techniques I suggest you look at
Transparency Masking.
Fuzz Factor - Matching Similar Colors
The overall results of just selecting a single color to replace, as shown in
the previous examples is usually not very nice. The edges or areas of solid
colors generally have a mix of colors at the edge, due to anti-aliasing (See
Anti-Aliasing for more information. As such
you should avoid direct color replace if possible.
EXAMPLE: floodfill
You can improve the selection of the area being recolored, by setting a
"
-fuzz" factor setting.
Here for example we tell IM that other colors 'close' to the one selected is
also OK to be replaced.
EXAMPLE: fuzzy floodfill
As you can see we now replaced even the pixels closer to the edge of the
image. This isn't perfect and replacing the backgrounds of images like this
is a difficult task. For more on this specific problem see
Re-adding Transparency to an Image.
The fuzz factor, technically represents a 'similarity' match in
multi-dimensional spherical distance between colors, using whatever color
space the image is using.
Well okay lets try that in plain English. You have a specific color. Another
color will be treated as being same as the first color if the difference
between these two colors is less than the currently fuzz factor setting.
A "
-fuzz" setting of
'
200' represents a distance of 200 units in the current color
depth of the IM being used, for a IM Q16 (16 bit quality for color store)
this is quite small, for a IM Q8 this is VERY large, and will cause a lot of
colors to match each other.
Here for example I change all the colors that are within 3000 color units of
'blue' to white. With my Q16 ImageMagick programs, that
represents about the distance from 'blue to 'navy
blue' (about 25% as a percentage, see below).
convert colorwheel.png -fuzz 30000 -fill white -opaque blue opaque_blue.jpg
| |
 |