Index
ImageMagick Examples Preface and Index
|
Resizing Images
Other Specialised Resize Operators
Specific Problems using Resize
Resize Artifacts - How Good is IM Resize?
-
Blocking,
Ringing,
Aliasing,
Blurring
|
Resize Filters
- Interpolated Filters
Point,
Box,
Triangle,
Hermite
Other Interpolation Filters
- Gaussian Blurring Filter
-
Gaussian,
Sigma Expert Control
Other Gaussian-like Filters
Quadratic,
Cubic
- Filter Support Expert Control
- Filter Blur Expert Control
- Gaussian Interpolator Filter
- Sharpen Resized Images -- Photoshop Resize
- Windowed Sinc Filters
-
Sinc,
Hanning,
Hamming,
Blackman,
Bohman,
Kaiser,
Bartlett,
Parzen,
Welsh
- Lanczos Filter
- Windowing Support Size in Lobes
- Lagrange Filter
- Cubic Filters
-
Cubic,
Hermite,
Catrom,
Mitchell
Cubic BC Settings
- Cylindrical Filters -- Filters for Distort
- Interpolated Cylindrical Filters
- Cylindrical Gaussian
- Jinc Windowed Filters
- Lanczos2 Filter
- Sharpened Lanczos2 Filter
- Robidoux Filter
- Robidoux Sharp Filter
- Cylindrical Filters Summary
- Expert Filter Controls
- Summary of Resize filters
- Filter Comparison
-
Best Filter?,
IM Default Filter?
|
We we look at enlarging and reducing images in various ways. The Image
remains intact and whole, but individual points of color merged or expanded to
use up a smaller/larger canvas area.
Note that while this is related to the resolution of an image (number of
pixels per real world length), that is more a product of how the image is
eventually used, and not a true concern of Direct Image Processing.
Resizing Images
The more obvious and common way to change the size of an image is to resize
or scale an image. The content of the image is enlarged or more commonly
shrink to fit the desired size. But while the actual image pixels and colors
are modified, the content represented by the image is essentially left
unchanged.
However resizing images can be a tricky matter. Their are a lot of options
that you need to consider, and to give you the maximum scope of control
ImageMagick provides you with a multitude of options, resize operations
styles, and ways of specifying the new size of the image.
The first and foremost thing you should consider when specifying a image to
resize is...
Do you really want to modify the image?
Resizing will cause drastic changes to the content of the image, and avoiding
or minimizing the change should be of greatest importance. Perhaps just a
slight
Shave of the edges, or a more general
Crop of the image will produce a better and more
desirable outcome than a wholesale resize of the image. It generally will
look better.
The resize operator has been very carefully designed to try to produce the best
possible result for real world images. That is not to say you can't use it for
diagrams, or line drawings, though for that type of image you may need to use
some of the more advanced options we'll look at later.
The resize operator is given an area into which the image should be fitted.
This area is
not the final size of the image (unless a '!' flag is
given) but the maximum size for the final image. IM tries to preserve the
aspect ratio of the image more than the final actual size for the image. That
is, a circle in the input image will remain a circle in the output image.
So let me be clear...
Resize will fit the image into the requested size.
It does NOT fill, the requested box size.
For example here I attempt to fit two source images, one larger image and one
smaller image into a square box 64x64 pixels in size.
convert dragon.gif -resize 64x64 resize_dragon.gif
convert terminal.gif -resize 64x64 resize_terminal.gif
|
As you can see a 64x64 square image was
NOT produced by "
-resize". In fact the images
were only enlarged or reduced enough so as to best fit into the given size.
  |
Resize and transparency posed a problem for ImageMagick before v6.2.4,
producing a black halo effect around light colored objects on transparency.
This was researched and finally fixed from that version onward. For more
detail of this old bug see Resize Halo
Bug
|
Ignore Aspect Ratio ('!' flag)
If you want you can force "
-resize" to ignore the aspect ratio and distort the image so it
always generates an image exactly the size specified. This is done by adding
the character '
!' to the size. Unfortunately this character is
also sometimes used for special purposes by various UNIX command line shells.
So you may have to escape the character somehow to preserve it.
convert dragon.gif -resize 64x64\! exact_dragon.gif
convert terminal.gif -resize 64x64\! exact_terminal.gif
|
Only Shrink Larger Images ('>' flag)
Another commonly used option is to restrict IM so that it will only shrink
images to fit into the size given. Never enlarge. This is the
'
>' resize option. Think of it only applying the resize to
images 'greater than' the size given (its a little counter intuitive).
convert dragon.gif -resize 64x64\> shrink_dragon.gif
convert terminal.gif -resize 64x64\> shrink_terminal.gif
|
This option is often very important for saving disk space for images, or in
thumbnail generation, when enlarging images generally may not desirable as it
tends to produce 'fuzzy' enlargements.
  |
The Only Shrink Flag ('>' flag) is a special character in
Window batch scripts and you will need to escape that character, using
'^>', or it will not work. See Windows Batch Scripting for this and other windowing
particularities.
|
Only Enlarge Smaller Images ('<' flag)
The inverse to the previous flag is '
<', which will only
enlarges images that are smaller than the given size, is rarely used.
The most notable use is with a argument such as '
1x1<'. This
resize argument will never actually resize any image. In other words it's a
no-op, which will allow you to short circuit a resize operation in programs
and scripts which always uses "
-resize". Other than that you probably do not actually want to
use this feature.
One such example of using this 'short circuit' argument is for the "
-geometry" setting of
"
montage". See
Montage and
Geometry, caution needed for more details.
Fill Area Flag ('^' flag)
As of IM v6.3.8-3 IM now has a new geometry option flag '
^' which
is used to resize the image based on the smallest fitting dimension. That
is, the image is resized to completely fill (and even overflow) the pixel area
given.
convert dragon.gif -resize 64x64^ fill_dragon.gif
convert terminal.gif -resize 64x64^ fill_terminal.gif
|
As it stands this option does not seem very useful, but when combined with
either a centered (or uncentered) "
-crop" or "
-extent" to remove the excess parts of the image, you can fit the
image so as to best fill the area specified. Both the resize and the final
image size arguments should be the same values.
Though the "
-crop" is most
logical, it may require an extra "
+repage" to remove virtual canvas layering information. The
"
-extent" does not
require this cleanup, but only allows the use of "
-gravity" for positioning. See
Cutting and Bordering for more information.
convert dragon.gif -resize 64x64^ \
-gravity center -extent 64x64 fill_crop_dragon.gif
convert terminal.gif -resize 64x64^ \
-gravity center -extent 64x64 fill_crop_terminal.gif
|
Also "
-extent" can be
used to pad out images that use the normal resize (with a "
-extent" color setting). See
Thumbnails, Fit to a Given Space
Summary, for more on this type of operation.
  |
The Fill Area Flag ('^' flag) is a special character in Window
batch scripts and you will need to escape that character by doubling it.
For example '^^', or it will not work. See Windows Batch Scripting for this and
other windowing particularities.
|
Percentage Resize ('%' flag)
Adding a percent sign, '%', to the "
-resize" argument causes resize to scale the image by the amount
specified.
convert dragon.gif -resize 50% half_dragon.gif
convert terminal.gif -resize 50% half_terminal.gif
|
Be warned however that the final pixel size of the image will be rounded to the
nearest integer. That is, you cannot generate a partial pixel image!
  |
The Percentage Resize Flag ('%' flag) is a special character in
Window batch scripts and you will need to escape that character by doubling
it. For example '%%', or it will not work. See Windows Batch Scripting for this and
other windowing particularities.
|
  |
All these 'flag' options '!', '<',
'>', '^', '%', and
'@' are just on/off switches for the "-resize" operator. Just the
character's presence (or absence) in the resize argument is what matters,
not their position. They can appear at the start or end of the argument, or
before or after individual numbers (though not in the middle of a number).
That is, '%50' has exactly the same effect as
'50%' though the latter is preferred for readability. Also
'50%x30' actually means '50%x30%' and NOT 50%
width and 30 pixel high as you might think.
This is the case for all IM arguments using a 'geometry' style ('WxH' or
'+X+Y') of argument. However offsets such as '+X+Y' are never treated as
a percentage.
|
Resize a Pixel Area Count Limit ('@' flag)
There is one final "
-resize" option flag. The "at" symbol '
@', will
resize an image to contain no more than the given number of pixels. This can
be used for example to make a collection of images of all different sizes
roughly the same size. For example here we resize both our images to a rough
64x64 size, or 4096 pixels in size.
convert dragon.gif -resize 4096@ pixel_dragon.gif
convert terminal.gif -resize 4096@ pixel_terminal.gif
|
Note that the final image size is not limited to 64 pixels in height or width,
but will have an area that is as close to (but smaller than) this size as IM
can manage. That means one dimension will generally be slightly larger than 64
pixels and one will be slightly smaller.
In some ways this is a ideal compromise for thumbnailing images. See
Area Fit Thumbnail Size.
You can also add the '>' flag to only shrink images that have more than the
calculated number of pixels, while leaving images that are already smaller
than that size.
  |
Unfortunatally the '<', enlarge smaller images, flag is currently ignored
when using 'Area Resize'.
|
Resize During Image Read
The resize operator can also be applied to images immediately after being
read, before it is added to the current image sequence and the next image is
read. That way a minimal amount of memory is needed to read in a lot of
images. See
Image Read Modifiers for more
details.
For example...
convert dragon.gif'[64x64]' read_dragon.gif
convert terminal.gif'[64x64]' read_terminal.gif
|
The only problem with this technique is that no special resize options can be
used, during the image read process.
Other Resize Operators
Geometry
- Resize just the last image
Geometry is a very special option. The operator behaves slightly differently
in every IM command, and often in special and magical ways. The reasons for
this is mostly due to legacy use and should be avoided if at all possible.
First, in "display" it is used to size and position the window of
the image being displayed. This was its original usage and meaning when IM was
first started. It was from this that its other 'resize' capabilities came
about.
For "montage" "-geometry" is a setting that is
saved until all the arguments have been read in. At this point it then
defines the final tile (cell) size (or leaves it up to "montage"
to work out) while the position arguments are used to specify the space
surrounding the tile cells. See Montage
Control Settings.
In "
composite", "
-geometry" is also saved
until the end of arguments have been reached. Then it is used to resize and
position the overlay image (the first image given) before it is overlaid onto
the background image (the second image). For example see
Composite Multiple Images.
As you can see it is used as a 'setting' in most IM commands, but in
"
convert" "
-geometry" is both a special image resizing operator and a
positioning setting.
What it does is to "
-resize" just the
last image in the current image sequence.
This is the
only image processing operator that is designed
specifically to effect just the one image (the last one), in the current image
sequence.
To complicate this special option further, the positional parts of the
"
-geometry" option is
saved by "
convert" command, just as it is in "
composite". That is, any position is
preserved for later use by the "
-composite", to position the 'overlay' image, (the second last
image in the current image sequence) over the 'background' image (the first
image in the image sequence).
For this reason, you should limit the use of "
-geometry" in
"
convert" commands to just before a "
-composite" or "
-layers composite" operations.
To summarize, this operator is only really useful after reading or creating a
second image, just before you perform some type of
Alpha Composition to process with those
images.
For practical examples of using "
-geometry" to resize/position images see
Compositing Multiple Images.
Thumbnail
- Resize with profile stripping
The "-thumbnail"
operator is a variation of "-resize" designed specifically for shrinking very very large
images to small thumbnails.
First it uses "-strip" to
remove all profile and other fluff from the image. It then uses "-sample" to shrink the image down
to 5 times the final height. Finally it does a normal "-resize" to reduce the image to
its final size.
All this is to basically speed up thumbnail generation from very large files.
However for thumbnails of JPEG images, you can limit the size of the image
read in from disk using the special option "-define
jpeg:size={size}" setting. See Reading JPEG Images for more details.
As such this speed improvment is rarely needed for JPEG in thumbnail
generation, though profile stripping is still very important.
For other image formats, such as TIFF, both profile stripping and speed
improvement is still vitally important. As such it is still the recommended
way to resize images for thumbnail creation.
  |
Before IM v6.5.4-7 the "-thumbnail" would strip ALL profiles from the image, including
the ICC color profiles. From this version onward the color profiles will be
preserved. If the color profile is not wanted then "-strip" all profiles.
|
Magnify
- double image size
The "-magnify" option
just doubles the size of an image using the "-resize" operator. Plain and
simple. It is rarely used.
  |
A "Minify()" function is also often available in API's that halve the size
of images in the same way as the "Magnify()" function of those API's.
However "-minify" is not available from the command line API,
at least not at the time of writing.
|
Resample
- Changing an image's resolution
Just as in the previous alternative resize operators, "-resample" is also a simple
wrapper around the normal "-resize" operator.
Its purpose however is to adjust the number of pixels in an image so that when
displayed at the given Resolution or Density
the image will still look the same size in real world terms. That is, the
given image is enlarged or shrunk, in terms of the number of pixels, while the
image size in real world units will remain the same.
It is meant to be used for images that were read in from, or will be written
out to, a program or device of a particular resolution or density. This is
especially important for adjusting an image to fit a specific hardware output
device, whether it is a display, or printer, or a postscript or PDF image
format of a specific resolution. Just remember the real world size of the
image does not change, only its resolution and of course the number of pixels
used to represent the image.
For example, suppose you had an image that you scanned at a 300dpi (dots per
inch). The image was saved with this resolution (density) or when you read it
into IM, you specified it as a 300dpi image (using "
-density"). Now you decide to
display it on a screen that has a resolution of 90dpi, so you do a
"
-resample 90". IM will now resize the image by 90/300 or to 30%
of the images original size and set the images new density to 90dpi. The
image is now smaller in terms of the number of pixels used, but if displayed
on a 90dpi display will appear at the same physical size as the original image
you scanned. That is, it now has a resolution appropriate for a 90dpi
display, so it will be displayed to the user at its original real world size.
A "
-units" setting (with
arguments '
PixelsPerInch' or '
PixelsPerCentimeter')
may be required in some situations to get this operator to work correctly.
This setting can also be important for output to Postscript and PDF image
file formats.
Note that only a small number of image file formats (such as JPEG, PNG, and
TIFF) are capable of storing the image resolution or density with the image
data.
For formats which do not support an image resolution, or which are
multi-resolution (vector based) image formats, the original resolution of the
image must be specified via the "
-density" attribute (see
Density
Image Meta-data) before being read in. If no density attribute has been
set IM will assume it has a default density of 72dpi. Setting the density
AFTER reading such an image will only affect its output resolution, and not
affect its final size in terms of pixels.
Sample
- Resize by row/column replication/deleting
The "-sample" resize
operator is the fastest resize operator, especially in large scale image
reduction. In fact it is also even faster than the "-scale" operator (see next).
When enlarging or magnifying an image, they both do pixel replication to
generate rectangular 'blocks' of pixel colors. However when shrinking an image
"-sample" just simply
deletes rows and columns of pixels.
Because whole rows and columns of pixels are simply removed, "-sample" will generate no new or
additional colors. This fact can be important for some image processing
techniques such as resizing GIF animations.
However directly deleting pixel rows and columns can result in rather horrible
results, especially for images containing thin lines (in terms of width in
pixels).
For example, here I draw a line but then reduce the image size resulting in
only a line of dots. This is a typical effect of image sampling.
convert -size 150x60 xc: -draw 'line 0,59 149,0' line_orig.gif
convert line_orig.gif -sample 50x20 line_sample.gif
|
Scale
- Minify with pixel averaging
The "-scale" resize
operator is a simplified, faster form of the resize command.
When enlarging an image, the pixels in the image are replicated to form a
large rectangular blocks of color. Which is great for showing a clean
unblurred magnification of an image.
For example here is a magnified view of one of the built-in tile patterns...
convert -size 8x8 pattern:CrossHatch30 -scale 1000% scale_crosshatch.gif
| |
|
Generally a single percentage value that is a multiple of 100% is used for the
image enlargement so as to ensure all pixels are enlarged by the same amount,
otherwise you can have different size pixel rows and columns producing large
scale Moiré pattern.
For example here I badly scaled a smooth looking '50% gray checks' pattern,
using a size that was not a multiple of the original images size.
convert pattern:gray50 scale_gray_norm.gif
convert pattern:gray50 -scale 36 scale_gray_mag.gif
| |
|
When shrinking images, neighbouring pixels are averaged together to produce a
new colored pixel. For example scaling an image to 50% of its original size
will effectively average together blocks of 4 pixels to create a new pixel
(assuming the image size is a multiple of 2 as well).
Caution is advised however as a scale reduced image can also generate
Moiré patterns, unless the new image is an exact integer reduction (a
technique known as 'binning'), which also requires the original image size to
be some exact integer multiple of the final size.
Also a real-world photograph that has been heavily minified using "
-scale" tends to look overlay
sharp, with aliasing ('staircase') effects along sharp edges.
Finally, Cristy reports that the algorithm is designed to loop over rows of
pixels then columns, which is inverted to that of "
-resize". This may allow
"
-scale" to handle a "
mpc:" disk cached image better.
While this image resize operator is completely separate to the "
-resize" operator to make it
faster, the "
-resize"
operator can generate the same results by using a '
Box'
Resize Filter (see below).
The pixel averaging of "
-scale" allows it to generate 'pixelated' images you typically see
used for hiding faces, or 'naughty' parts of images. You basically reduce the
size of the image to average the pixels, then enlarge again back to the
image's original size.
convert rose: -scale 25% -scale 70x46\! rose_pixelated.gif
|
You can use a mask to combine the above pixelated image with the original
image, so as to 'hide' a much smaller 'naughty' bit present in the original
image. See the
Protect Someones Anonymity
example for a demonstration of using this technique.
Adaptive Resize
- Small resizes without blurring
The "-adaptive-resize" operator uses the special Mesh Interpolation method to resize images.
For example here I resize a simple line, using first a normal "
-resize", then again using
"-adaptive-resize".
convert -size 50x50 xc: -draw 'line 0,49 49,0' line_orig2.gif
convert line_orig2.gif -resize 80x80 line_resize.gif
convert line_orig2.gif -adaptive-resize 80x80 line_adaptive.gif
|
If you look at a magnification of the two results...
You can see the
Adaptive Resized image on the
right is a lot cleaner looking and less blurry than the image produced on the
left using the normal "
-resize" operator.
Basically the operator avoids the excessive blurring that a "
-resize" operator can produce
with sharp color changes. This works well for slight image size adjustments
and in particularly for magnification, And especially with images with sharp
color changes. But when images are enlarged or reduced by more than 50% it
will start to produce aliasing, and Moiré effects in the results.
These effects were originally noted by
dognose on a
IM Forums
Discussion.
I've noticed that it can be significantly faster, up to twice as
fast on big resizes. I've also noticed that the resulting image can
be a lot different. It seems that adaptive-resize makes the new
image much sharper than regular resize.
For thumbnail generation, the sharpening is too strong, resulting in
some aliasing effect being added to the resulting image. It is thus
better suited to small scale resize adjustments such as generating a
smaller image for display on web pages.
You can also generate the exact equivalent result using a
Distort Resize operation but with the options
"-filter point
-interpolate mesh". That is, resizing the image using
a simple
Mesh Interpolation lookup method, rather
than a more complex resampling filter.
Interpolative Resize
- Resize using an Interpolation Method
The "-interpolative-resize" operator is practically identical to
the previous Adaptive Resize operator.
However in this can you can specifically select the interpolation method that
is used.
This is new for IMv7
Liquid Rescale
- Seam Carving
Just as Sampling an image resizes by directly removing
or duplicating whole columns and rows from an image, the special IM operator
"
-liquid-rescale" also removes or duplicates columns and rows of
pixels from an image to reduce/enlarge an image. The difference is that it
tries to do so in a more intelligent manner.
Firstly, instead of removing a simple line of pixels, it removes a
'
seam' of pixels. That is, the column (or row) that could zig-zag
through the image, at angles up to 45 degrees.
Secondly it tries to remove seams that have the '
least importance' in
terms of the image's contents. How it selects this is in terms of the image's
energy, or more simply, the amount of color changes a particular 'seam'
involves. The 'seam' with the least amount of changes will be removed first,
followed by higher 'energy' seams, until the image is the size desired.
For more detailed information of liquid resizing and seam carving see,
Wikipedia: Seam Carving,
the
YouTube Video
Demo, and the
PDF
paper: Seam Carving for Content-Aware Image Resizing.
Here for example is the IM logo as it is resized smaller using the IM "
-liquid-rescale"
operator.
convert logo: -resize 50% -trim +repage logo_trimmed.jpg
convert logo_trimmed.jpg -liquid-rescale 75x100%\! logo_lqr.jpg
convert logo_trimmed.jpg -sample 75x100%\! logo_sample.jpg
|
Original
|
|
Liquid Resize
|
Sampled
|
Notice how "
-liquid-rescale" preserved the complex wizard, while squeezing up
the less complex stars and title part of the image. It also squeeze the right
foot of the wizard slightly, producing a little jaggedness in the edge of the
cloak, just as it did to the wizard's thin but simple wand.
On the other hand the
Sample Resize image, simply
removed equally spaced columns of pixels, which resulted in the whole image
becoming equally distorted. The stars are not preserved intact and all the
edges have distinct but uniform
aliasing effects.
Basically "
-liquid-rescale" will produce a generally better looking
'squeezed' image without generating extra 'mixed colors' or blurring of the
image. However you can get some slight but localized aliasing effects in one
spot (the wizards wand in this case) rather than spreading that effect across
the whole image.
It will also expand images, by 'doubling' up the seams found within the image.
convert logo_trimmed.jpg -liquid-rescale 130x100%\! logo_lqr_expand.jpg
|
As you can see tries to first double the amount of space between the various
objects (where it can), spreading them out. Though in this case the left most
star and the 'm' becomes distorted as the 'seams' going through these 'low
energy' regions become grouped together.
Note however it will only double each seam once, and as such the technique
starts to break down when images are expanded too much. A better method is
often to resize the image larger first, then use liquid rescaling to reduce it
to the desired size. Or to use "
-liquid-rescale" in
multiple smaller steps.
To show the effect of "
-liquid-rescale" better here is an animation, as the same image is
resized down to a very thin image, then enlarged again. This animation was
created using the shell script
animate_lqr.
Again notice how it tries to preserve the most complex parts of the image, as
the image gets compressed into a smaller and smaller area. That is, the
spaces in the title are preferentially compressed first, then the wizard's
arm, then the right side of the wizard, leaving the most complex middle part
of the wizard for the very end.
Especially look at how the stars get pushed together before they are finally
effected by the resampling pixel removal that liquid rescaling implements. (See
problems next)
You can think of liquid rescaling as trying to compress an image, like a
sponge, with the open areas being compressed first leaving the bulky and more
structured parts for last.
Seam Carving Problems
Liquid Resize, or Seam Carving, works purely by removing whole pixels from the
image. As such, like
sampling, it will not generate or
merge colors together, and straight lines and patterns within the image may
become heavily distorted by the operation. Basically it can result in serious
Aliasing Effects, unless some method of smoothing is
also applied.
Generally however the aliasing effects will be grouped and localised to the
less complex areas of the image rather then spread thought the image. this is
the only reason it works so well!
As a 'seam' can zig-zag through the image, the seams, can and often appear to
go around complex objects, removing the space between the objects before
attempting to compressing the objects themselves. Note for example how the
word 'Image' in the above demonstration appears to get shoved under the other
letters in the title without too much distortion. However this side to side
movement limited to 45 degree angles.
For images with 'busy' backgrounds, and less 'busy' foreground objects such as
photos containing peoples faces, the energy function can assume that the
foreground object is less important that the background. This results in some
serious detrimental side effects, that may require human intervention to
resolve.
  |
Liquid Rescaling, is currently a highly experimental operation added for IM
v6.3.8-4. It requires the "liblqr" delegate library to be installed before it will work for you.
At this time no expert user controls have been provided. Controls such as to
modify the content energy function used, or use a user provided
preservation/removal filter (adjusting that energy function), or access to
the intermediate seam carved images, and functions that the library also
provides. It is assumed that such controls will be provided in sometime in
the future, as users demand them, and we get more internal control of the
library functions.
WARNING Do not expect this to remain, exactly as it is currently
implemented. It is highly experimental, and is expected to change and
expand in functionality.
|
Distort Resize
- free-form resizing
All the above resize methods all have one limitation which we touched on
earlier, they will round the size of the new image to an integer number of
pixels, then map the old image's pixels to the new pixel array.
This has two effects. First when resizing to a very small size the X scale may
not exactly match the Y scale of the resulting image (a slightly different
aspect ratio). This difference is minor, and unless you get very small it is
usually not noticeable.
The other effect is that you cannot resize an image to fit an area that
contains a partial pixel edge, which can be important in further processing,
such image overlays.
It also means you cannot use resize to just shift (translate) an image half a
pixel to the right (without actual resize) even though the algorithm could
quite easily do this.
With IM v6.3.6 the General Distortion
Operator "
-distort"
will let you do this and more, using its
Scale-Rotate-Translate distortion method. You can also do this using an
Affine distortion based on movements of
control points.
Note however that because the edge of the image can contain partial pixels,
the final image will probably be 2 to 3 pixels larger than you probably would
expect. The extra surrounding pixels will be mixed according to the current
Virtual Pixel setting, which you typically
set to be transparent.
For example here I resize the rose image to 90% (
.9) of its
original size, without rotation (
0), shrinking it around the
center of the image (the default control point if not specified)...
convert rose: -matte -virtual-pixel transparent \
+distort SRT '.9,0' +repage rose_distort_scale.png
| |
|
It may not look like an improvement, in fact it has fuzzy edges, but it is an
exact resize without adjustments for a final integer image size, just as you
requested. Because of this the edges are fuzzy as the pixel colors are being
spread over fractions of a pixel size, and not just to whole integers.
Note that I used the 'plus' form of "
+distort" to allow this image's
processing operator to set the final images size and offset on the
Virtual Canvas correctly, for further processing
and layering. If this offset is not desired it can be removed using "
+repage" operator. But if left in
place then the actual images location on the larger canvas will be preserved,
allowing you to exactly position the image correctly with its 'fuzzy edges'.
Here I resized it so the top left corner (
0,0) was moved .5
pixels to the right (to
.5,0) and the rest of the image scaled
around that control point...
convert rose: -matte -virtual-pixel transparent \
+distort SRT '0,0 .9 0 .5,0' +repage rose_distort_shift.png
| |
|
Note that as the top edge did not actually move, it remained relatively sharp,
while all the other edges became fuzzy. Here is a pixel magnification
of the top corner, showing the transparency that was added by distort to
provide sub-pixel resizing...
convert rose_distort_shift.png -crop 15x15+0+0 +repage \
-scale 600% rose_distort_shift_mag.png
| |
|
You can see that the top edge remained sharp, while the left (and all other
edges) are now semi-transparent.
And that is the point. You have exact control of the resize, and the final
sub-pixel location of the resulting image. Not just a quantized fit of the
resized image to an integer number of pixels. That is, the distort is an exact
re-scaling and positioning of the image to fractions of a pixel, allow you to
fit it precisely into other images.
This can become especially important when doing video work, where an imprecise
resize of embeded images can produce 'jarring' effects.
  |
Technically, image resizing is a simplified form of Image Distortion, both of which are techniques of image resampling.
It's very fast 2-pass filtering technique, is limited to
orthogonally aligned pixel dimenstions, and whole number of pixels in the
final result.
|
Affine, Transform
As of IM v6.4.2-8 the older "
-affine" setting used with either "
-transform" or "
-draw" operators, provide a similar
free-form resize capability. However in reality it is equivalent to a calling
"
+distort" with an
'
AffineProjection'
distortion method. As such all the previous Distort notes apply.
It does require more mathematics by the user to use. Making it even harder to
use. Generally you are better off using the above distortion method, which
provides a number of alternative methods of specifying an affine distortion.
Distort vs Resize
If you actually want to do a direct comparison between using
Distort vs
Resize you
will need to specifically limit the distortion of the image, so as to exactly
match the resized image you care comparing it to. This is not a simple task.
To make this easier a special
Resize Distortion
Method was added to IM v6.6.9-2.
Here for example I greatly enlarge the built-in "
rose:" using
a fast
Resize, and then using
Distort...
convert rose: -filter Lanczos -resize 300x rose_resize.png
convert rose: -filter Lanczos -distort Resize 300x rose_distort.png
|
Resize (Lanczos - Sinc)
|
Distort (Lanczos - Jinc)
|
If you look along the bottom edge of the rose, you will see that the
Distort Operator actually produced a better
cleaner result than the
Resize Operator. The rest of
the image is practically identical to the human eye, even when compared using
a "
flicker_cmp" script.
However remember that
Distort is much
slower than
Resize, as it uses a more freeform
technique, without the speed optimization that resize uses.
  |
The real difference in the above two images is that the Distort Operator uses a two dimensional Elliptical Area Resampling filter
method (also known as cylindrical filtering or resampling) for its image
processing. This is slower than the one dimensional, two pass resampling
method used by all the other resize methods shown in this section. It is
also why it produced a better result along the diagonal bottom edge of the
enlarged rose image above. It is not limited to just horizontal and
vertical filtering.
|
Resize Problems
Resizing with Colorspace Correction
While resize works very well, most people do not use it correctly. Not even
me.
Images are typically not stored using a 'linear' colorspace. See
Human Color Perception for details,
but saved using a nonlinear "sRGB" colorspace, or with gamma correction.
The problem is that resize (like most other image processing operators)
is a mathematically linear processor, that assumes that image values
directly represent color brightness. which as I said is typically not the
case.
The colorspace "sRGB" is basically contains a gamma correction of roughly 2.2.
Actually it is more complex than that involving two separate curves. See
wikipedia, sRGB and
W3org, sRGB the Default
Colorspace of the Internet.
As of version 6.7.5 ImageMagick follows this convention and sets the default
colorspace of images (at least for most image file formats) to be sRGB. This
means we simply need to use the "
-colorspace" to transform the image to a linear space before doing
the resize.
  |
Using color correction on a low-quality Q8 version of IM (see Quality) is not recommended due to the loss
of precision such a low memory quality provides.
|
The NASA image "
Earth's
City Lights" is a very extreme case where non-linear colorspace effects
have a big impact on the results of resizing the image.
Here we directly resize the image without colorspace correction...
convert earth_lights_4800.tif -resize 500 earth_lights_direct.png
|
And here we convert from a non-linear sRGB, to linear RGB, then resize them,
and convert it back again...
convert earth_lights_4800.tif -colorspace RGB -resize 500 \
-colorspace sRGB earth_lights_colorspace.png
|
As you can see the 'lights' in the images are much much brighter as they are
not so heavilly influenced by the non-linear colorspace of the source image.
Though most images does not have as great a impact as can be seen in the
above. It also does not make a lot of difference if you later save the image
in a color limited image file format such as GIF or PNG8.
Note that when using JPEG you should also provide a correct
Color Profile for the image being saved,
though image programs are expected to assume sRGB colorspace if one is not
provided.
The same correct colorspace handling also applies to the use of distort
(elliptical filter), image blurring, and can have great effects on image
quantization, dithering and ordered dithering.
Also see
Color Processing Real
Images and
Drawing with Gamma and Colorspace
Correction.
 |
 |
|
In versions of IM older than v6.7.5, in which the default input colorspace was
'RGB', and 'sRGB' actually meant "converted to
linear-RGB". The result was the two labels were swapped! Wierd but
true.
Because of this older versions of ImageMagick would need to do the
above colorspace correction with those colorspace names swaped. Like this...
convert earth_lights_4800.tif -colorspace sRGB \
-resize 500 -colorspace RGB earth_lights_colorspace.png
|
*** This example is depreciated ***
Note that the "-colorspace RGB" operation was not actually
needed, as it was automatically performed when saving to PNG image file
format. If I wanted to force PNG to save the image using a linear colorspace,
I could use "-set colorspace RGB" to prevent that automatic
transformation.
The above example was developed from a IM discussion Forum Discussion
Correct Resize, this was not only
on colorspace (and gamma) resizes, but also using Distort for resizing.
|
Resize with Gamma Correction
This is how to correctly resize images using gamma correction only.
convert earth_lights_4800.tif -gamma 0.454545 \
-resize 500 -gamma 2.2 earth_lights_gamma.png
|
An alternative to the gamma inverse operation "
-gamma 0.454545"
is to use "
-evaluate POW 2.2".
Note that gamma correction is only a rough match to properly converting images
from/to sRGB colorspace, but it is so close that you would be hard pressed to
see any difference between colorspace vs gamma correction.
Gamma correction also does not play around with the IMv6 miss-named RGB/sRGB
colorspace settings, so may be a better choice when the exact version may be
unknown.
You may also like to look at the "
-auto-gamma" operator, which
tries to adjust gamma to produce a linear-RGB image, with equal amounts of
light and dark (in linear space).
Resizing to Fill a Given Space
Basically: Resizing a large image to completely fill a specific image size but
cropping any parts of the image that do not fit.
  |
As of IM v 6.3.8-3 a new resize flag '^' will let you do this
directly as a single resize step. These examples represents an alternative
method that can be used for users with older versions of IM.
See Resize Fill Flag above.
|
The solution is rather tricky, as the normal user requirement when
resizing images is to fit the whole of an image into a given size. As the
aspect ratio of the image is preserved, that leaves extra, unused space in the
area you are trying to fill.
Here we try to resize an image to fill a 80x80 box.
convert logo: -resize 80x80\> \
-size 80x80 xc:blue +swap -gravity center -composite \
space_resize.jpg
| |
|
In the above we added a backdrop canvas to pad out the unused parts of the
resize box to show the space we wanted the image to fill, but it wasn't
filled, as it preserved the image's aspect ratio.
Now if all your images are either landscape style (they are wider than they
are high) then you can of course just resize the image to fit either the
height or width of the area, then use "
-crop" to cut the image to fit it exactly.
convert logo: -resize x80 \
-gravity center -crop 80x80+0+0 +repage space_crop.jpg
| |
|
The problem is that, the above will only handle landscape style images. It
will fail badly if the image is portrait style (higher than it is wide).
This of course can be solved in a script by first getting the image's
dimensions, and then picking the right method to fit the image into the space
needed. But a better solution would be to have IM do all the work for all
images.
The solution within IM is to process the image by resizing each of the images
dimension separately. Then picking the larger image of the two results.
To make this easier, resize itself has a built-in test option which will only
resize an image if that would make the image larger. This allows use a very
nifty solution to our problem.
convert logo: \
-resize x160 -resize '160x<' -resize 50% \
-gravity center -crop 80x80+0+0 +repage space_fill.jpg
| |
|
In the above, the second resize in the series will only resize if the width
produced by the first resize was smaller than the area we are trying to fill.
The specific order of the resizes (height first, then width) was chosen, as
most images are photographs which are usually longer horizontally. With the
above ordering, such a case will result in the second resize operation being
skipped.
If your images are more often portrait images (longer vertically) then change
the arguments to resize the image by height first, then width. For example...
convert logo: \
-resize 160x -resize 'x160<' -resize 50% \
-gravity center -crop 80x80+0+0 +repage space_fill_2.jpg
| |
|
The result of both of these examples should be very similar, and the command
will work for both landscape and portrait styles of image, though it works
better for one sort.
The biggest problem with this method is that the image is now being resized 2
to 3 times, producing extra blurring and other possible artifacts in the final
result. To reduce this, the initial resizes are performed at double the final
dimensions, which assumes the original image is at least 3 or more times the
size of the final desired result. Not a problem for thumbnail production, but
something to keep in mind.
Resizing Line Drawings
Under Construction
Doing a strong resize of an image containing thin lines can represent a big
problem...
Resizing images to very small thumbnails, causes thin lines that are only a
few pixels wide to fade and disappear into the background. This can get so
bad that I have seen thumbnails of a line drawing which looked pretty much
blank. That is, every detail of the original drawing 'disappeared'.
If this is problem there are a few techniques that can help...
- Resize then adjust contrast to make lines more visible.
Though this will make the lines more aliased and staircased, and does
have its limits.
- Blur and threshold the image (a method very similar to morphological
'dialate' or 'erode') so as to produce make single pixel lines about 300%
thicker. Now after resizing by 1/3 the image will be smaller but the
lines will remain just as strong and visible as before.
If you need to resize by more than this, you can do the thickening and
resizing in multiple increments. though as the spacing between the lines
shrinks you may find you end up with more of a 'blob' than a line drawing.
That is you may get the opposite problem. Adjusting the ratio of
thickening to resize however should produce an acceptable result.
- Separate the line edging in an image from the areas of solid colors, and
resize each by the above methods. Afterward the two parts can be merged
back together again, allowing you to preserve the line edging of the
image.
This will in effect reproduce the effect you often get when resizing
vector images.
- Convert image to a vector, then resize. This can be trcky but also can
produce the best possible result for resizing line drawings.
If you come up with some way of effectively resizing line drawings please
let me (and other IM users) know about it.
Resize Artifacts
- How good is IM Resize
Image resizing has to combat a very difficult problem. How do you reduce an
array of values, into a smaller, or larger array of values so that it look
good to our eyes. A lot of things can go wrong while attempting to do this,
but they fall into four basic categories..
Blocking
Essentially, if you enlarge an image simply by replicating pixels, you will
create larger rectangular blocks of pixels. In fact magnifying images using
either "
-scale" or
"
-sample" does exactly
that, producing an enlarged pixelated image.
For example here I scale a small image, generating large blocks of color
rather that a nice smooth image. Next to that is a 'resized' version, and
finally one with a Gaussian filter to blur it a little more than normal to try
to remove some of the blockiness.
convert storm.gif -scale 200% storm_scaled.gif
convert storm.gif -resize 200% storm_resized.gif
convert storm.gif -filter Gaussian -resize 200% storm_resized_gas.gif
|
The primary cause of 'blocking' is either badly anti-aliased source image (as
in the above example), or not enough smoothing (color mixing) between pixels
to improve the overall look of an image.
It is also typically seen when a very low resolution image is being resized
to a much larger scale or for use on a high resolution device, such as shown
above. Typically the most common place this is seen is in the use of a low
resolution bitmap image in user generated newsletters and magazines that
were then printed on very high resolution laser printers. The newsletter
looks great on screen, but 'blocky' on the printed page.
This situation is very hard to fix, and generally best avoided, by using a
much higher resolution clipart, or a freely scalable vector image (such as
SVG, and WMF format images).
Ringing
Ringing is an effect you often see in very low quality JPEG images
close to sharp edges. It is typically caused by an edge being
over compensated for by the resize or image compression algorithm, or a
high quality filter being used with a bad support size.
Here for example I use a special option to select a raw Sinc filter, on
an very sharp color change. I also repeated the operation using IM's
default resize operator, with its default filter selection for image
enlargements.
convert -size 8x16 xc:'#444' xc:'#AAA' +append gray_edge.gif
convert gray_edge.gif -filter Sinc \
-resize 100x100\! gray_edge_ringing.gif
convert gray_edge.gif -resize 100x100\! gray_edge_resize.gif
|
The above shows quite clearly the over compensation produced by the use of
a raw resize filter, without any of the optimization IM provides. The
second image, produced by the default IM enlargement filter also shows a
very slight ringing effect, but it is barely noticeable.
Here is another example of the ringing effect, this time as produced by a
single pixel, on a large gray background.
convert -size 1x1 xc: -bordercolor '#444' -border 4x4 \
-filter Sinc -resize 100x100\! dot_sinc.gif
| |
|
This image also clearly shows the secondary effects generated by the use
of a one dimensional filter. That is, the ringing effect is strongest in
horizontal, and vertical (orthogonal) direction, with 45 degree secondary
ringing.
These effects are not normally visible, and only seen here because of the use
of the use of a raw '
Sinc' filter with enlargements. Typically
this type of filter is not used for image enlargements.
Aliasing and Moiré Effects
Aliasing effects are generally seen as the production of 'staircase' like
effects along edges of images. Often this is caused either by raw sampling of
the image such as using "
-sample", or overly sharpening of the image during resizing. A
staircasing effect is most noticeable in strong minification of images, though
is rarely seen in IM.
However, aliasing also has other effects, in particular large scale
Moiré patterns appearing in images containing some type of pixel level
pattern. These low level patterns often produce large scale Moiré
patterns, including: patterns of parallel lines, cloth weaves (silk exhibits
this effect in real life!), as well as brick and tile patterns in photos of
brick buildings, fences, and paving.
![[IM Output]](rings_sm_orig.gif)
For some examples of resized images producing strong Moiré effects see
the
Wikipedia,
Moiré Pattern Page.
The classic way of checking if a resize will produce aliasing problems, is by
minifying a
Rings Image (see right). This
image will often show Moiré effects when any form of resize is applied
at any scale. Web browsers in particular show such Moiré effects when
displaying such an image due to the use of a ultra fast (but often poor)
resizing technique.
Here I show the 'rings' image resized using the strongly aliasing "
-sample" operator, the block
averaging "
-scale"
operator and the normal default "
-resize".
convert rings_sm_orig.gif -sample 100x100 rings_sample.png
convert rings_sm_orig.gif -scale 100x100 rings_scale.png
convert rings_sm_orig.gif -resize 100x100 rings_resize.png
|
As you can see all the resize methods did produce some Moiré
effects, though IM's default resize operator produces the least amount of
this undesirable secondary patterns in the final image.
To show the effects of only a slight resize, I cropped the corner from the
Large Rings Image, the result of which is
shown first, and then reduced its size by just 5%.
convert rings_lg_orig.png -crop 105x105+0+0 rings_crop.png
convert rings_crop.png -sample 100x100 rings_crop_sample.png
convert rings_crop.png -scale 100x100 rings_crop_scale.png
convert rings_crop.png -resize 100x100 rings_crop_resize.png
|
cropped original
|
|
sample
|
scale
|
resize
|
As you can see even a slight resize will show up any aliasing a resize
operator may have. In fact if you look closely you may even seen a very light
Moiré effect in the unscaled crop of the original starting image, which
is produced from the limitations of only using a raster image at a density
suitable for display on a computer screen. That is how sensitive this test
image is in showing aliasing effects caused by shrinking images.
Blurring
Most people are familiar with blurring that can be generated by the use of
"
-resize". In fact
this is probably the number one complaint about any resize image, and with
good reason. Usually a very small resize will tend to produce a blurred
image, and resizing it again will only make it worse.
The problem is that when you resize an image you are changing the image stored
as a 'grid' or array of pixels (known as a 'raster') to fit a completely
different 'grid' of pixels. The two 'grids' will not match except in very
special cases, and as a result, the image data has to be modified to make it
fit this new pattern of dots. Basically it is impossible to directly resize
an image and expect it to come out nicely, though a reasonable result can be
achieved.
The result is a usually a slight blurring of the pixel data. The better
the resize algorithm, the less blurring of sharp edges there is.
However some resize filters, especially ones designed specifically for
enlarging images, often add a lot more blurring than necessary. This is to
combat '
Blocking' artifacts, and was in fact
demonstrated above, by using a '
Gaussian' filter.
For image minification however a blurred edge is often used to avoid '
Ringing' artifacts at sharp edges and reduce possible
Aliasing effects. This however is a poor man's
compromise and one that IM tries hard to avoid.
Even so, a special expert
Filter Blur setting
can be used to adjust the blurring that a filter provides. However be
warned that while a number smaller than 1.0 is supposed to reduce blurring,
it can also make it worse, depending on the exact filter and the resize
ratios that are being used. No guarantees can be given.
  |
Before IM v6.3.6-3 the Filter Blur setting
was called "-support", which was very misleading in exactly what it did.
This option has been depreciated and is no longer available.
|
The better method of fixing bluring effects cause by resize is to re-filter
the image using a sharpening operator. See
Sharpen
Resized Images below for more details.
IM Resize vs other Programs
A practical comparison of IM's default resize operator to a number of other
programs in resizing a real-world image has been provided by, Bart van der
Wolf at...
Specifically, in summary for IM resize...
Although the amount of sharpening is a matter of taste, the
lack of aliasing artifacts produces the cleanest, most natural looking image
of them all.
He also goes on to look at a 'rings' test, to directly compare various
Photoshop resize methods against ImageMagick...
These articles shows just how important doing resize correctly (and using the
right filtering methods) is to image processing. We look this at more closely
in the next section.
WARNING: These filter comparisons were made before IM Resize filters were
overhauled for IM v6.3.7-1, and as such the results for
Windowed Filters such as '
Hanning'
and '
Blackman' are incorrect.
Resize Filters
The "
-filter" setting is
the key control on how the "
-resize" algorithm, as well as "
-distort", works to produce a
clean result with the minimum of
Resize Artifacts,
as shown above.
This has been a topic of intense study during the late 1980's, and from which
Paul Heckbert, a major researcher in
this field, produced and publicly released his "
zoom" image resizing program. This program became the
father of most image resizing programs used today, though many programs
implement it properly, as it is easy to get it wrong.
In many ways, these filters are closely related to
Convolving Images, and even the
Blurring Kernel. They even suffer from the
similar problems. However filters are designed to improve the look of the
final result when resizing, or otherwise distorting an image.
The names of the filters are a veritable "who's who" of image processing
experts and mathematicians of the past century (or more). They are usually not
a description of the filter, but just a label of the person who either first
published the filter (or filter family), or did the most research into that
filter. This however makes it much harder to know whether
a '
Lagrange' filter (named after Joseph-Louis Lagrange) is better
than, say, a '
Catrom' filter (named after Edwin Catmull and
Raphael Rom).
Here I will explain the major aspects of Filters. It is not vital that you
learn these things, but I decided to document a summary of what I learnt,
after completing research in this area, as part of a major overhaul and
expansion of the IM resize filter system, (IM 6.3.7-1).
Special thanks goes to
Fred Weinhaus for his help in the research during the re-development of
the Resize Filters. He was especially eager for the addition of the '
Lagrange' family of filters, which did not exist
in IM resize before this overhaul.
How filters work
When resizing an image you are basically trying to determine the correct value
of each pixel in the new image, based on the pixels in the original source
image. However these new pixels do not match exactly to the positions of the
old pixels, and so a correct value for these pixels needs to be determined
in some way.
What is done is to try to use some type of weighted average of the original
source pixel values to determine a good value for the new pixel.
The real pixels surrounding the location of the new pixel forms
a 'neighbourhood' of contributing values. The larger this neighbourhood is
the slower the resize. This is a technique called
Convolution.
The amount each real neighbouring pixel (known as a 'sample') contributes to
produce the final pixel is determined by a weighting function. This is the
'
filter' that you can select using the "
-filter" setting. That filter in
turn generally has an ideal neighbourhood size, which is known as the filter's
'
support', though it is also known as its '
window'. A
pre-defined two dimensional '
filter' is also known as a '
convolution
kernel'.
FUTURE: some diagrams may be helpful here
The design of these weighting functions, or 'filters' is a very complex
business involving some complex mathematics, frequency analysis, and even
Fourier transforms. A good starting point if you are interested in this is
Wikipedia: Nyquist–Shannon sampling theorem. However, you really don't
need to go that far to understand existing filters and their effects on
images.
The Filters
Interpolated Filters
The simplest type of resize filter functions are
Interpolative methods.
These take a specific pixel location in the source image and try to simply
determine a logical color value of the image at that location based on
the colors of the surrounding pixels.
As there is only ever a fixed and minimal number of pixels involved, this type
of filter is a very fast method of resizing or otherwise distorting images.
However, this is also the filter's downfall, as it will not merge a larger
number of pixels together to form an image that is greatly smaller than the
original image. That in turn can result in strong
Aliasing and Moiré Effects.
Interpolation is usually only used for 'point' sampling images, when image
scaling is either not known or needed. For example, when rotating image or
minor distortions, the image's scaling or size does not change, and as such an
interpolation can produce a reasonable result, though not a very accurate one.
For more information see IM's
Interpolation
Setting.
It is not however suitable for general image resizing.
Point
Using a "
-filter"
setting of '
Point' basically means to use an unscaled
interpolation filter. For the
Resize Operator, it will
just select the closest pixel to the new pixels position, and that is all. But
for the
Distort Operator it will force the
use of interpolation over the whole image. See
Image Filters in the Distort Operator
for more detail.
This means that the
Resize Operator will simply use the
color of an actual pixel in the source image will be used. No attempt will be
made to merge colors or generate a better color for the resulting image. As
a result using
"-filter point -resize ..." will
produce the same result as "
-sample", though the latter is faster as it code is specifically
designed to resizing images by point sampling.
Here I start with a 10x10 pixel hash pattern and reduce it in size, before
scaling so that you can see the result.
convert -size 10x10 pattern:gray50 checks_10.gif
convert checks_10.gif -filter point -resize 9x9 checks_point-1.gif
convert checks_10.gif -filter point -resize 8x8 checks_point-2.gif
convert checks_10.gif -filter point -resize 7x7 checks_point-3.gif
convert checks_10.gif -filter point -resize 6x6 checks_point-4.gif
convert checks_10.gif -filter point -resize 5x5 checks_point-5.gif
|
|
|
Point-1
|
Point-2
|
Point-3
|
Point-4
|
Point 50%
|
All that is really happening is that single rows and columns of pixels are
removed across the image. Even at this level, you will get extreme
blocking and
aliasing in the
resulting image, and can in specific cases like the above produce a completely
unrealistic result.
As such, a '
Point' filter, or the faster equivelent
Sampling Operator, is not recommended for normal image
resizing.
Box
The '
Box' filter setting is exactly the same as
'
point' with one slight variation. When shrinking images it will
average, and merge the pixels together. The smaller the resulting image the
more pixels will be averaged together. In other words the filter is 'scaled'.
The "
-scale" resize
operator was again optimised to do exactly this.
![[IM Output]](graph_filter_box.gif)
Here is a graph of the filter's weighting function, from which you can see why
it is called a '
Box' filter.
Basically any pixel that falls inside the 'Box' will be directly used to
calculate the color of the new pixel. Now as the filter is only 1/2 a pixel
wide, and that means for an image that is not actually being resized, only one
pixel the closest pixel, will be used. In other words when no scaling is
involved (or only magnification) the nearest pixel to the new location will
form the color of the new pixel.
However if an image is being made smaller, more of the source image will be
compressed into the bounds of that 'box'. The result is that more pixels will
be averaged together to produce the color for the pixel in the smaller image.
For example here is an enlarged view of a checkerboard pixel pattern
as it is being slowly compressed using a '
Box' filter.
convert checks_10.gif -filter box -resize 9x9 checks_box-1.gif
convert checks_10.gif -filter box -resize 8x8 checks_box-2.gif
convert checks_10.gif -filter box -resize 7x7 checks_box-3.gif
convert checks_10.gif -filter box -resize 6x6 checks_box-4.gif
convert checks_10.gif -filter box -resize 5x5 checks_box-5.gif
|
|
|
Box-1
|
Box-2
|
Box-3
|
Box-4
|
Box 50%
|
As you can see, more and more pixels become merged together as the image is
resized smaller using a '
Box' filter, but that the merger occurs
in specific, equally spaced, rows and columns. This causes all sorts of
artifacts and Moiré or
Aliasing effects when
both shrinking images and enlarging.
This is also why it is recommended that '
Box' filtering or
equivelent
Scale Operator is only used for 'binning'
images, that is, reduce images by integer multiples to ensure that every pixel
in the result is an average of the same number of neighbouring pixels (the
'bin'). The resulting image will thus remain clean looking, just as in the
final image above.
When enlarging both '
Point' and '
Box' filters
produce the same 'pixel replication' of rows and columns, as both will result
in a simple 'nearest-neighbour' selection.
convert -size 5x5 pattern:gray50 checks_5.gif
convert checks_5.gif -filter box -resize 6x6 checks_box+1.gif
convert checks_5.gif -filter box -resize 7x7 checks_box+2.gif
convert checks_5.gif -filter box -resize 8x8 checks_box+3.gif
convert checks_5.gif -filter box -resize 9x9 checks_box+4.gif
convert checks_5.gif -filter box -resize 10x10 checks_box+5.gif
|
|
|
Box+1
|
Box+2
|
Box+3
|
Box+4
|
Box+5
|
Triangle
![[IM Output]](graph_filter_triangle.gif)
The '
Triangle' or '
Bilinear' interpolation filter just takes the interpolation of the
nearest neighbourhood one step further. Instead of just directly averaging
the nearby pixels together, as '
Box' does, it weights them
according to how close the new pixels position is to the the original pixels
within the neighbourhood (or '
support' region). The closer the new
pixel is to a source image pixel, the more color that pixel contributes.
This produces a more global averaging of colors when images are being reduced
in size.
convert checks_10.gif -filter triangle -resize 9x9 checks_tri-1.gif
convert checks_10.gif -filter triangle -resize 8x8 checks_tri-2.gif
convert checks_10.gif -filter triangle -resize 7x7 checks_tri-3.gif
convert checks_10.gif -filter triangle -resize 6x6 checks_tri-4.gif
convert checks_10.gif -filter triangle -resize 5x5 checks_tri-5.gif
|
|
|
Tri-1
|
Tri-2
|
Tri-3
|
Tri-4
|
Tri
|
As you can see as the corner pixels were near perfect matches to the corners
of the original image they are more visible, but toward the middle where none
of the nearby pixels exactly match up with the new pixel being generated, you
get a more average color of the whole neighbourhood.
The result for the checkerboard pixel pattern is a tendancy to fade in and out
of a average gray color.
However as the '
support neighbourhood is larger, more pixels will be
involved when you enlarge the image. Thus producing averaging of colors when
generating the pixels being added to the image.
convert checks_5.gif -filter triangle -resize 6x6 checks_tri+1.gif
convert checks_5.gif -filter triangle -resize 7x7 checks_tri+2.gif
convert checks_5.gif -filter triangle -resize 8x8 checks_tri+3.gif
convert checks_5.gif -filter triangle -resize 9x9 checks_tri+4.gif
convert checks_5.gif -filter triangle -resize 10x10 checks_tri+5.gif
|
|
|
Tri+1
|
Tri+2
|
Tri+3
|
Tri+4
|
Tri+5
|
For large scale enlargements the result acts as if a gradient of colors
was added between each and every pixel. For example, here I generate a
very small image with a single white pixel (the display is an enlarged view).
I then enlarge that image enormously.
convert xc: -bordercolor black -border 2x0 pixel_5.gif
convert pixel_5.gif -filter triangle -resize 300x pixel_triangle.gif
|
Single Pixel Image
(magnified)
|
|
Triangle Filter Enlarged
|
If you were to graph the colors in the above image (using the "
im_profile" script), you will see a
replica of the triangular filter graph.
Profile of Image
As you can see the central pixel was merged with the neighbouring pixels to
produce a linear gradient of colors between those points.
All the interpolation filters, produce similar gradient patterns between
neighbouring pixels and is also the reason why they are so well suited to
image enlargements.
Other Interpolation Filters
![[IM Output]](graph_interpolation.gif)
To the right I have graphed the various interpolation filters, except for
'
Point' which is a very special case of '
Box'.
Other interpolation filters include '
Hermite' which is
very similar to triangle in results, but producing a smoother round off in
large scale enlargements. Click on the
graph on the right to see a graph
of these three filter functions.
![[IM Output]](graph_lagrange_interpolate.gif)
The '
Lagrange' filter has been called a 'universal'
interpolation filter. By varying the 'support' size (See the
support expert setting below), it can generate
all the previously looked at interpolation filters (except
'
Hermite'). The default settings (a Lagrange order 3 filter as
shown as the purple line) provides a variation of the 'bicubic' type of
interpolation. (see below).
As an interpolation filter the default '
Lagrange' filter (order =
3, support = 2.0) works very well, though with some minor
ringing effects. However the sharp gradient change is often notable on
very large scale image enlargements.
More on the
Lagrange Filter later.
![[IM Output]](graph_filter_catrom.gif)
The '
Catrom' (Catmull-Rom) filter is another filter that
produces a 'bicubic' type of interpolation function over a larger area. This
filter will also produce a reasonably sharp edge, but without a the pronounced
gradient change on large scale image enlargements that
a '
Lagrange' filter can produce. This in turn will reduce the
amount of noticeable
blocking effects, but does so
at the cost of increased
ringing effects in the
resulting image.
What does make a '
Catrom' filter more interesting is that it is
almost an identical cubic equivelent of a 2-lobe '
Lanczos' filter, which is probbaly the most commonly used
Windowed-Sinc Filter (see below).
We will also look at this filter more closely later in
Cubic Filters.
Interpolation and IM's Interpolate Setting
The
Interpolate setting of IM which is
used to produce an unscaled 'point' lookup of images in operators like the
FX DIY Operator ("
-fx") and
Color Lookup Replacement Operator ("
-clut"), and some older
Circular Distortion functions are based on
these simple interpolation resize filters. However they are currently
implemented using separate code and also have different setting names.
These
Interpolation Settings include:
'
NearestNeighbor',
implementing the '
Point' (or unscaled '
Box') filter,
and '
BiLinear' to get an
unscaled '
Triangle' filter.
ASIDE: At this time the smoothed triangle filter 'Hermite' has
not been directly implemented as an Interpolation Setting, which is a shame as it is quite a good
interpolation filter. The 'Catrom' filter is also not available.
However there is some confusion as to just what resize filter should be used to
implement a 'Bicubic' (16 pixel
interpolation) Interpolation Setting. Many
programs implement the 'Catrom' filter to produce a smoother
gradient but with more ringing, while others, including IM, implement the
'Lagrange' (Lagrange order 3) filter.
  |
Before IM version 6.3.5-3, the Interpolation
Setting 'Bicubic' was based
on a very blurry 'B-Spline' filter (the IM 'Cubic' filter, see below).
That interpolation setting has now been renamed to 'Spline', with the 'Bicubic' setting now based on the
default Lagrange-3 (support=2.0) filter as discussed above.
|
Gaussian Blurring Filters
In the complex mathematics of Fourier Transforms into frequency domains,
resize filters are meant to remove any high frequency noise that may be
present. This noise is caused by the sampling of a real world image into
pixels, and when you resize an image, that noise appears as aliasing and
Moiré effects.
Because of this the Gaussian Bell Curve became a natural early candidate as a
resizing or resample filter, as it is the ideal model of real world effects.
Gaussian
![[IM Output]](graph_filter_gaussian.gif)
The
Gaussian filter is a very special filter that generates that same
'bell curve' shape in the frequency domain. This makes it very useful as an
image filter as it guarantees a good removal of this high frequency noise in a
highly controllable way.
However if you examine the filter graph, you will see that at a distance of
one pixel from the sampling point, you have a non-zero value. In fact it is
quite a high value indeed. This results in a huge amount of blurring of the
individual pixels, even when no resize is actually performed.
For example here I have resized the standard IM logo using a Gaussian filter
and again using the normal IM filter ('
Lanczos' in this case,
which we will look at later)
convert logo: -filter Gaussian -resize 150x logo_gaussian.png
convert logo: -resize 150x logo_normal.png
|
If you look closely you will see that the left '
Gaussian'
filtered image is more blurry than the normal resize. Especially with regard
to the detail of the smaller stars around the wand and on the wizard's hat.
This blurring of the image is the trade off you get for removing all the
aliasing effects in image reduction, as well as all
blocking effects on image enlargement. It will also,
never produce any
ringing effects (when applied
perfectly). But all that is at the cost of extreme
blurring for the resulting image.
In fact, during large scale enlargements, this filter will generate round
dots, rather than square looking dots. For example, here I greatly enlarge a
3x3 pixel image with a single dot in the center.
convert xc:red -bordercolor yellow -border 1 \
-filter Gaussian -resize 99x99 -normalize dot_gaussian.jpg
| |
|
As you can see a single pixel enlarges into perfectly circular dot. Only
Gaussian and Gaussian-like filters will do this.
Gaussian Sigma Expert Control
You can control the Gaussian Filetr directly using a a special
expert option "
-define
filter:sigma={value}" to specify the actual 'sigma' value of the
Gaussian curve.
By default this value is '
0.5' which is also the same size as the
Box Filter.
This expert option was added to allow for the creation of very very small
Gaussian Blurs, without reducing the
Filter's
Support range (see below).
However increasing the 'sigma' could cause the filter to become clipped. As
such when increasing the 'sigma' value the default 'support'
(
2.0), to also be increased by a similar amount. this only
happens on increases in the default 'sigma' value. The
Support Expert Setting can be used to override,
but it is typically not necessary.
  |
The 'filter:sigma' expert option only works for the Gaussian Filter. No other filters are effected by
this expert control.
A more generalised control, for other filters can be achievd using Blur Filter Expert Control which we will look at
later.
|
Other Gaussian-like Filters
![[IM Output]](graph_gaussian.gif)
If you study the comparative graphs to the right you will see that
'
Quadratic' filter as well as the slightly more complex
'
Cubic' filter follow the weighting curve of the
'
Gaussian' filter quite well. And being polynomial functions they
are also a lot faster to calculate, which was why they were originally
invented.
While '
Quadratic' is very slightly more blury than the
Gaussian Filter, the '
Cubic' filter will
produce more blurry result, about equivelent to a
Sigma setting of approximatally '
6.5'. This makes
'
Cubic' the most blurry filter provided without modifications.
Examining the graphs you will see that like the
Gaussian
Filter and unlike
Interpolation Filters
they have a non-zero value at a distance of 1.0 from the sampling point. This
causes the nearby pixels to merge their colors, and is the cause of the
blurring you see. The '
Cubic' filter having the highest value at
the 1.0 distance producing the largest amount of blurring in any resized (or
distorted) image.
This extra blurriness removes the last of any 'blocking' effects that may be
present in large scale enlargements. And could be used with a
Sharpen Resized Images technique to enlarge line
drawing with very little 'staircase effects' in the results.
The '
Mitchell' filter is also
shown in the comparison graph. This filter also has a some blurring at the
1.0 distance from the sampling point, which also makes this filter slightly
blurry, much like the other filters we have seen. However it also has some
negative weighting in its curve, which while producing
ringing effects (see
Window Sinc Filters
later), offsets that bluriness near sharp edges.
Filter Support Expert Control
The gaussian filter is known as a IIR (Infinite Impulse Response) filter,
which simply means that the response 'curve' it uses never reaches zero. That
is, no matter how far away from the sampling point you get, you will still
have some non-zero contribution to the result from very distant pixels.
In mathematical terms this is actually a good thing, as it means the result is
much more mathematically perfect. In practical application it is very bad, as
a infinite filter requires you to use a weighted average of every pixel in the
original image, to generate each and every new pixel in the destination image.
That means that large images will take a very very long time to resize
perfetly using this filter.
However for the '
Gaussian' filter anything beyond a range of
about 2 pixels (4 times its default 'sigma' setting) from the sampling point
will generally produce very little effect in terms of the final result, and as
such can be generally be ignored. This range is known as the filter's
'
support window' and is the program's practical limit for the filter.
![[IM Output]](graph_gaussian_support.gif)
If you really want, you can change the 'support' of a filter using the special
expert setting "
-define
filter:support={value}".
For example here I resize a image with a single pixel using the smaller
support value of 1.25 (see the
resulting
graph right).
By using the smaller '
support' setting, the 'step' was moved to
the 1.25 position. That in turn, results in a larger 'stop' in the filter's
profile, and results in an 'aliasing' effect that you can see close
to the center of the enlarged image (the wiggle near the 'peak' of the graph)
as well as a sudden 'drop' at the edges of the filter's 'support' limits.
You can think of 'support' as being a sliding 'window' across the pixels being
averaged together to produce the enlarged image result. As the support
size is 1.25, the filter's total support area is 2.5 pixels wide (unscaled
during image enlargements), as such you can have either 2 or 3 pixels involved
in the horizontal resizing phase.
As each pixel enters or leaves this support 'range' as it slides across the
image being generated, the sudden 'stop' in the filters 'curve' causes
a slight jiggle to appear in filter-weighted average that is returned. That
is, at these points, a pixel is being added or removed from the total number
of pixels being averaged together according to the filter weighting curve.
This in turn produces four such 'jiggles' or 'zig-zags' in the resized image,
An initial two on the outside edges when the single white pixel enters/leaves
the support range, and a second pair of jiggles as a second black pixel
(making a three pixel weighted average) enters/leaves the support range.
If there wasn't such a sudden 'stop' in the filter, that is, the filter goes
to zero at the support limit setting, then you would not see the 'jiggles' and
you would not have the visible effect.
Using a support size set to an integer or half-integer (such as the default
'support' setting for a '
Gaussian' filter of '2.0') would always
ensure that whenever a new pixel enters the support range, another pixel is
leaving, so that the same number of pixels is always part of that average.
That would remove the two 'center' jiggles, but it will not not remove the
initial jiggles on the outside, marking the support limits.
Even sharp slope changes (discontinuities) in the filter, such as you get from
a
Triangle, or a
Lagrange
filter can generate visible artifacts in the resulting image.
  |
Previous to IM v6.3.6-3 the 'support' for the Gaussian filter was set to this
value of '1.25' producing Ringing
effects in enlargements (such as shown above). For this reason the 'support'
for gaussian was changed to produce a much smaller step (and far less
ringing) by using larger default 'support' of '1.5', with very
little speed reduction in the algorithm.
As of IM v6.6.5-0 the default 'support' setting for Gaussian was increased
to a value of '2.0'. This has little effect on the overall
speed of the filter, but makes the 'stop' practically non-existant. It also
simplified filter coding for other special uses of this filter, specifically
for EWA distortions, and variable blur mapping.
|
Note however that if you use a very large support setting then of course more
pixels will need to be averaged together making the resize operation slower,
without any real improvement in results. Only the
Windowed Sinc/Jinc and
Lagrange filters can
generally produce a better result by using a support window that is larger
than 2.0.
Remember these are 'expert' options, and as such you are more likely to make
things worse rather than better by using these options. That is why they are
not a simple command line option, but provided via the special "
-define" option. Of course you
are welcome to play, just as I have done above, so as to try and understand
things better, and IM provides these options so that you can do just that.
Filter Blur Expert Control
A special expert option, "
-define filter:blur={value}" can be used to adjust amount
of blurring that a filter provides. A value of '
1.0' producing
the default action, while smaller and larger values adjust overall
'blurriness'.
Basically this linearly enlarges or shrinks the filter's curve along the
X axis (distance of pixel form the sampling point), and typically make
a filter more or less blurry, overall.
Using a smaller setting results in the filter's function (and its support
window) becomming smaller. For
Gaussian and
Gaussian-like filters the effect is as if you
multiplied the filters 'sigma' value (default=0.5) by this 'blur' factor.
This setting will also enlarge or shrink the filters
Support Window by the same amount so as to prevent clipping, but this can
be overridden using the
Support Expert Filter
Setting.
For example, here I resize an image with three different 'blur' settings,
using a
Gaussian-like Cubic Filter..
for blur in 0.5 1.0 1.5; do \
convert logo: -define filter:blur=$blur -filter Cubic \
-resize 150x logo_blur_$blur.png; \
done
|
blur 0.5
|
|
blur 1.0
|
|
blur 1.5
|
As you can see, this special setting will let you control the overall
blurriness of the result for '
Cubic' filter.
As the size of the 'support window' is also scaled by the
Filter Blur setting, using small values can cause it
to become so small, or produce such small values, that for some pixels the
'resampling' can 'miss' all the pixel values in the source image.
This will produce 'black' areas in images. For example...
convert rose: -define filter:blur=0.01 -filter Gaussian \
-resize 100x100 rose_black_bars.png
| |
|
Even increasing the support will in many cases produce a similar effect, as
most filters will only produce zero weightings for pixels that fall outside
their 'natural' support range. The only filters this does not apply to are
the
Sinc/Jinc Windowed Filters and the
Box Filter.
Similar effects can be seen with
Cylindrical
Filters.
The
Lagrange Filters uses
Support Expert Filter Setting to determine the appropriate 'order' to fit
into the 'suport window', and thus polymorphs into various other forms (see
below).
  |
Using this setting with filters containing negative weightings (basically
any of the filters we will look at below) can produce inverse sharpening and
blurring effects, and disproportionatally stronger aliasing effects. In rare
cases it can even generate infinite weighting effects.
Caution and expertise is required to use this special option with such
a filter.
|
  |
Before IM v6.3.6-3 the 'filter:blur' define was mistakenly
set by the option "-support", which was very misleading in
exactly what it did. This option has been depreciated, and no longer
available.
|
Gaussian Interpolator Filter Varient
![[IM Output]](graph_blurred.gif)
A
Blur Control value of '
0.75' on
Gaussian-like Filters, or using a
Sigma Control value of '
0.375' for the
Gaussian Filter will generate a variation I call a
Gaussian Interpolator.
This sharpened gaussian filter as similar properities as a
Interpolation Filter Bt without any sharp
stops, or other gradient changes that can be noticable in enlarged images. In
this respect it is much like the "
Hermite" filter (see graph), but with a less symetrical skew that
seem to work better.
convert logo: -filter Gaussian -resize 150x logo_gaussian.png
convert logo: -define filter:blur=0.75 -filter Gaussian \
-resize 150x logo_gaussian_interpolate.png
|
Gaussian
|
|
Gaussian Interpolator
(blur=0.75 or sigma=0.375)
|
In fact I find it make the gaussian filter produce much more acceptable
results, which is not too sharp, and not to blurry.
However reducing the
blurring of the filter will
enhance the
aliasing effects, thus more likely to
generate large scale Moiré effects from low pixel level patterns. That
is the trade off.
convert rings_crop.png -filter gaussian -resize 100x100 rings_gaussian.png
convert rings_crop.png -filter gaussian -define filter:blur=0.75 \
-resize 100x100 rings_gaussian_interpolate.png
|
Gaussian
|
|
Gaussian Interpolator
(blur=0.75 or sigma=0.375)
|
Sharpen Resized Images
-- Photoshop Resize Technique
Rather than reducing the
Blur Setting (or for
Gaussian its
Sigma Setting) of a filter, the
better technique for producing sharper images, is to simply
Sharpen the image after the resize has been
complete.
Typically this is done using the special and weirdly named,
Unsharp Operation, which contains even more
controls to control the quality of the results.
For example, lets 'unsharp' the results of the very blurry '
Cubic' filter, and compare it to using a similar
Blur Expert Control...
convert logo: -filter cubic -resize 150x logo_cubic.png
convert logo: -filter cubic -resize 150x \
-unsharp 0x1 logo_cubic_unsharp.png
convert logo: -define filter:blur=0.75 -filter cubic \
-resize 150x logo_cubic_blur_sharp.png
|
Cubic
|
|
Unsharped
|
Blur-Sharpened
|
As you can see sharpening the image after the resize produces far better
results than trying to use the
Blur Expert
Control. You get a very good sharp image without any aliasing, ringing or
even dimming of effects, such as can be seen in the stars in the above
example.
While a
Cubic Filter is not particularly good filter to
begin with, this method of sharpening (actually 'unsharping') will work for
ANY filter, without posible side-effects you may get with using the
Blur Control. It also provides more controls to
fine-tune the result.
In actual fact this is what '
photoshop' does to improve the
quality of its resized images, though I do not know what settings it uses for
the
Unsharp Operation. A technique known as
USM
The "
GIMP default for unsharp is
equivelent to
"-unsharp 5x0.5", But remember their
really is no need to specify the radius in ImageMagick. so a value of
"-unsharp 0x0.5" is better.
A IM forum post about
Image
Resizing suggests using
"-unsharp
0x0.75+0.75+0.008" as being good for images larger than 500
pixels .
While an Open Photography Forum discussion
Downsampling with ImageMagick suggests
"-unsharp
1.5x1+0.7+0.02".
Windowed Sinc Filters
Sinc Filters
Mathematics has determined that the ideal filter for resizing images is either
the
Sinc() function. (See
Nyquist-Shannon sampling theorem).
![[IM Output]](graph_sinc.gif)
The
Sinc() being mathematically perfect has some special features that
I would like to point out. First at every integer distance from the weighting
function for the filter becomes zero. This is very important as it means that
the filter does not blur the image more than necessary (unlike
Gaussian Filters). It also means if an image is
resampled without resizing (a "no-op" resize) the image remains completely
uneffected by the filter.
The
Jinc() function is closely related to
Sinc(), and has
properities that make it useful as a filter for 2-dimentional filtering, such
as used by the
General Image Distortion
Operator. More about this function later in
Cylindrical Filters. For now just note that it could also be used as the
base function for
Windowed Jinc Filters.
The other major difference between this and previous filters we have looked at
is that some of the weightings have negative effects. That is, they will
subtract some of the nearby color pixels from the final color in each pixel in
the image.
This may seem a little strange, but it results in a very strong sharpening of
the edges of objects. Unfortunately any negative weights generally need to be
offset by positive weights further along the curve, which produces the wave
like function you see.
This extra 'lobe' of positive weights causes
ringing
artifacts in images which contain lots of sharp boundaries, such as in high
contrast line drawings, if the filter is applied improperly.
Windowing Functions
Unfortunately this function is also IIR (Infinite Impulse Response) function,
That is to say it has effects going all the way to infinities, just like the
Gaussian Filter previously.
This means that to use 'Sinc', you would need to generate a weighted average
of every pixel in the image (and beyond) in order to create the best
representation for each and every new pixel in the destination image. This is
prohibitively expensive, making the direct use of these perfect filters
impractical.
But unlike the
Gaussian Filter, the 'Sinc' function
does not just taper down to near zero a short distance from the sample point.
In fact, even at 10 pixels away (see graph above) from the sampling point, you
can get an appreciable effect on the final result. However resizing an image
using a filter that has a support distance of 10 would require an averaging of
at least 20x20 or 400 pixels per pixel in the final result. And that would
produce a very slow filtered resize.
As a consequence, using a raw form "
Sinc" filter not recommended,
and almost never used, though by using
Expert
Filter Controls IM will not prevent you from doing this, if that is what
you really want to do.
What is recommended and provided are 'windowed' forms of the Sinc function,
which have been developed by image processing experts, that can be used to
'limit' the infinite Sinc (and Jinc) functions to a more practical size.
These
Windowing Filters include filters such as; '
Blackman',
'
Bohman', '
Hanning', '
Hammming'
'
Lanczos'. '
Kaiser', '
Welsh',
'
Bartlett', and '
Parzen'.
How Windowed Filters Work
![[IM Output]](graph_sinc_windowing.gif)
For example, the graph to the right shows three functions (click to get an
enlarged view). The red function is the mathematically ideal
Sinc()
function, which stretches off to infinity. The green function is a "Hanning"
windowing function (based on a simple Cosine() curve . This is multiplied
with the
Sinc() to modulate the more distant components of the filter,
reaching zero (or near zero) at the edge of the support window (typically 4.0
in ImageMagick).
Basically by selecting '
Hanning' for the "
-filter" selection you are in
reality selecting the '
Hanning()' '
Windowing Function' for
either the '
weighting function' such as '
Sinc()' (or
'
Jinc()').
As such, '
Windowed Filters' are really two functions. Either the Sinc
or the Jinc function (depending on the image processing operator), and the
'windowing function' you have specifically selected as the filter to use. (See
Expert Filter Controls below).
  |
Before v6.3.6-3, IM made the grave mistake of actually using the windowing
functions directly as the filter's weighting function. This in turn caused
all these filters to produce badly aliased images,
when used for resizing. As a consequence the filters were often
mis-understood or rarely used by IM users. This has now been fixed.
|
The Various Windowing Filters
![[IM Output]](graph_windowing.gif)
To the right is a graph of all the various windowing functions that IM has
available at the time of writing (more was added later). Yes, there are a lot
of them, as windowing functions have been the subject of intense study by
numerous signal processing experts.
Each of the windowing functions will be expanded to cover the 'support' range
that is being used for the windowed-sinc filter.
![[IM Output]](graph_windowed_sinc.gif)
And to the right is the resulting windowed-sinc filters that would be used by
selecting those window functions. All of the windowed filter functions will
generally use a support of 4.0 for Sinc (4 lobes). The '
Lanczos'
filter is an exception (normal default support is 3.0), but is graphed using
a 4.0 support for comparison purposes.
As you can see all the windowed filtered functions produce a muted form of the
original
Sinc() function that is also shown. And other than the amount
of
ringing a specific filter generates there is often
very little to distinguish one windowed filter from another.
Probably one of the best windowed filters is '
Lanczos'.
While other people swear by the '
Blackman',
'
Bohman', '
Hanning' and the slightly
atypical '
Hamming' windowing functions. All this
functions are based on the use of Sinc, Sine or Cosine functions in their
formulation, which supposedly ensures the function has a good frequency
response.
The other windowing filters include '
Welsh' (parabolic),
'
Parzen' (cubic), '
Bartlett'
(triangular or linear), and '
Kaiser' (bessel).
Many of these windowing functions are used as resampling filters in their own
right. For example the '
Bartlett' windowing function is actually
the same mathematical function used for a '
Triangle' filter, and
the '
Bilinear' interpolation filter. These are usually much
simpler to calculate, which is why they were used as windowing functions, but
they are typically not regarded to be as good as the other image filter
functions, due to their poor 'frequency response'.
You can look at more detailed definitions and graphs of most of these various
windowing functions, and their results in the Fourier Frequency Spectrum on
Wikipedia, Window
function.
I myself have not found a great deal of difference in results between these
various windowing function. From my reading of research papers the results
seems to be more of a qualitative opinion of their suitablity, rather than
anything concrete. Consequently, my feeling is that just about any windowing
function can be used, though you are better sticking to the most popular
'
Lanczos' filter.
Lanczos Filter
We have mentioned the '
Lanczos' filter a number of times
already. It is probably the most well known of the
Windowed Filters, which falls in the middle of the range of windowed
filters we have seen. Essentially it does not 'roll-off' too fast, or to
slow, and has a good frequency response in the resulting fourier transform.
The '
Lanczos' filter basically uses the first 'lobe' of the
Sinc() function, to window the
Sinc() function. That is, the
filter's weighting function is used to set the filter's own windowing function.
Many people see this as being a good reason to select it over the many other
Windowed Sinc Filters. l
By default IM defines the '
Lanczos' filter as having 3 'lobes'.
Most the other
Windowed Filters default to
4 'lobes'.
![[IM Output]](graph_lanczos_filters.gif)
However a 2-lobed '
Lanczos2' filter has also been provided
which many people prefer as it will avoid most of the
Ringing Artifacts that can be generated by such functions.
The '
Catrom' (actually the 'Catmull-Rom Filter'), is almost an
exact duplicate of the '
Lanczos2' filter though as it is a
Cubic Filter it is much faster to generate
mathematically, though that is not a concern with the way IM handles filters
internally.
Windowing Size in Lobes
As I mentioned, the underlying Sinc (and Jinc) filter function is actually
infinite in size. Though by default IM limits them using the specified
windowing method to a much smaller, more practical size.
However there may be some situations where you really want to try and get a
much better, more exact resizing of the image using a much larger, and slower
window (support) size. That can even be done quite simply using the
Filter Support expert control, just as we did for
Gaussian-like filters.
The windowing function itself will (in most cases) reduce the Sinc (and Jinc)
to zero over the
support setting range. But as
the windowing function is scaled to fit the 'support' window, the resulting
filter function will also change.
![[IM Output]](graph_lanczos_lobes.gif)
For example, to the right I have graphed the '
Lanczos' windowed
filters, against the
Sinc() function as a reference, using various
'support' settings from 2 to 8. Note that the actual size of the filter is
limited by the actual support size used. The smaller the 'support' the faster
the filter, but the less exactly the function follows the mathematically ideal
Sinc() function.
Look closely at each of the graphed curves. The 'green' (support=2) curve
only has the main central peak, plus one negative 'lobe' (Equivelent to
a '
Lanczos2' filter). After this the function is just zero, and
not used. The next 'purple' (support=3, and the default
'
Lanczos' filter) curve, has a much larger first negative 'lobe',
then a smaller positive 'lobe'. This continues on with more lobes being
added, as the support size increases by integer increments. The additional
lobes are smaller and smaller in height, producing less and less influence on
the final result, but with the initial 'lobes' becoming higher (more
influence).
For best effect you would use a support setting, to generate a filter with
that many up/down 'lobes' in it. That is you would have the windowing
function, and thus the 'support' of the filter will end at a 'zero-crossing'.
However while the
Sinc() function has 'lobe' (zero-crossings) at
integer 'support' settings, the
Jinc() weighting function does not.
This presents a problem for users wanting to adjust the support window for
a filter being used with the
Distort operator. In
fact,
Jinc() has 'zero crossings' at highly
irrational numbered
positions. These zero crossings are very difficult to work out without being
a mathematics expert. See
Windowed Jinc Cylindrical
Filters below for more details.
To make it easier to set a filter in terms of the number of 'lobes' another
special setting was created, "
-define filter:lobes={integer}'.
If the filter is being used by a 2 dimensional image resampling operator such
as the
General Distortion Operator, which
requires the use of a
Jinc() base function, it will look up a table of
the first 20 zero crossings for the filter, and set the '
support' setting to that value. This means you
don't have to try to find the appropriate support setting for the
Jinc() function, just specify the number of lobes you want to use.
Because of this it is better to specify Windowed Sinc or Jinc filters in terms
of the number of 'lobes' you want the filter to contain, rather than specifing
a more direct '
support' setting. If neither
Sinc() or
Jinc() functions are used for the filter definition,
then the the '
filter:lobes' setting is used to calculate the
appropriate '
support' setting for the filters
usage.
Note however that a '
filter:support' setting will override any
'
filter:lobes' setting given, so it is better to only define the
latter expert option.
Lagrange Filter
Just as the '
Gaussian' filter is a
mathematically slow function (not that it affects the overall speed very much
thanks to IM's caching of results), the
Sinc/Jinc Windowed Filters are even slower and more complex to compute
due to the need to compute both a weighting function and a windowing function.
Because of this the '
Lagrange' filter generates a
piecewise cubic polynomial function to approximate a windowed filter. (See
Wikipedia: Lagrange
Polynomial). Just as
Windowed Filters are
adjustable according to the
Support Setting,
the '
Lagrange' filter also will adjust itself according to that
setting.
The default
support setting of 2.0 generates a
'
Lagrange' filter (order 3) that is commonly used as a '
Bicubic' interpolation method. This
filter is quite good for both enlargement and shrinking of images. with
minimal
blocking and
ringing
effects and no
blurring effects.
  |
The Support Expert Control is really
defining the 'order' of the Lagrange filter that should be used. That is,
the default 2.0 support Lagrange filter, generates a Lagrange filter of
order 3 (order = support × 2 - 1, thus support=2.0 => Lagrange-3
filter). This is why you can really only use a setting in half-integer
sizes.
As such, to get a Lagrange order 4 filter you would use the option
-define filter:support=2.5
|
![[IM Output]](graph_lagrange_windowed.gif)
With larger
support settings, the
'
Lagrange' filter generates
Windowed Sinc Filters without needing a complex trigonometric function
calculation, or even additional windowing functions. The larger the support
setting the closer the filter emulates a
Sinc() function, but also
the slower the calculation. (see graph of larger support Lagrange filters
left).
![[IM Output]](graph_lagrange_interpolate.gif)
Using smaller
support settings and the
'
Lagrange' filter emulates most of the various
Interpolated Filters. That is, a support size
of '
0.5' will generate the '
Box' filter, and
'
1.0' a '
Triangle' filter.
The
support setting is limited to adjustments
by half-integers, and using any other support factor is not very productive.
![[IM Output]](graph_lagrange_even.gif)
The other half-integer support, Lagrange Filters (generating even orders),
produce a very disjoint set of filter weightings, and much like the
'
Box' filter, they can produce some strong
blocking resize artifacts. On the other hand for small scale resize this
can ensure that images keep sharp for very small resize adjustments.
These 'even' ordered '
Lagrange' filters actually highlight the
main disadvantage of using this filter, which is that the weighting function
is not a 'smooth' gradient. In large scale enlargements this means you can get
visible changes in the generated gradient. This is rarely a problem however,
except in those extreme cases.
Basically it represents a filter that universally emulates the best filter for
the current given '
support' setting, regardless
of how big or small that setting is. It is 'the' self-windowing resize
filter.
  |
The 'Lagrange' filter was not fully
defined and usable until IM version v6.3.7-1.
|
Cubic Filters
As many image experts were trying to find a better and faster-to-calculate
filter for image resizing, a family of filters evolved, and became known as
Cubic Filters. These are much like the
Lagrange
Filters shown previously, and were made up of a smaller fixed set of
piece-wise sections. However unlike Lagrange filters the pieces were designed
to fit together to form a smooth curve, to reduce sharp
blocking effects.
![[IM Output]](graph_cubics.gif)
Shown in the graph left are four such 'smooth' cubic filters that are
pre-defined within IM, and well known for use as resize filters.
The '
Cubic' filter emulates a
Gaussian Blurring Filter. This curve is also known as a 'B-Spline'
interpolation curve, and is also used if drawing lines and animated motions of
objects in time.
Also shown is '
Catrom', or more correctly the 'Catmull-Rom
Filter' or 'Keys Cubic Convolution' which generates a smooth non-blurring form
of
Interpolation Filter.
And finally the '
Hermite' Cubic filter, which is type of
smoothed
Interpolation Filter.
But there were many other families of Cubic Filters that were being proposed
by various experts, to try to reduce the
Resize
Artifacts that were being seen in images. For example there is the whole
'B-Spline' family of cubics providing various degrees of filtering between
blurring ('
Cubic') and
blocking ('
Hermite').
Then there was the 'Cardinal' family, which produces filters compromising
between
blocking and
ringing
artifacts and from which the 'Catmull-Rom Filter' ('
Catrom')
evolved as a balanced compromise of these artifacts.
These two families then merged to form the '
Keys Cubic Filter Family',
which linked the 'Catmull-Rom Filter' (Keys
α = 0.5) with the
'B-Spline Cubic Filter' (Keys
α = 0.0). This family of filters
also has the special properity of preserving any linear (affine) gradient that
may exist across the image.
Confused by the variety? Of course you are. So was everyone else!
The problem is that the results of filters are often very subjective,
dependant on the image, and the restrictions of the 'family' you are using.
Just what made a good filter really depended on who you asked and what image
you were processing.
Mitchell-Netravali Filter
Into this, Don P. Mitchell and Arun N. Netravali, came out with a paper, '
Reconstruction Filters in Computer Graphics', which formulated two
variables known as 'B' (as used for 'B-spline' curves) and 'C' (as used for
the 'Cardinal' curves and equivalent to the 'Keys' filter
α
value). With these to values you can generate any smoothly fitting
(continuious first derivative) piece-wise cubic filter.
![[IM Output]](../img_diagrams/cubic_survey.gif)
More importantally they then surveyed a group of 9 image processing experts,
to classify the
Artifacts produced by slightly
enlarging images using various values. The results of that survey are shown in
the diagram to the right. The 'green' area represented values the experts
regarded as producing an acceptable result, while the various other areas
produce the various types of
Artifacts.
This image is important, as it really shows the relationships between the
various
Artifacts and the various different types
of filters that can be produced.
You can also see from the results why the 'Keys' family of filters became so
important, as one of the better methods of generating good cubic filters. Its
filters basically fell in a line directly through the area regarded as
'acceptable' by image processing experts.
From this survey, Mitchell and Netravali determined that the best filter was a
'Keys' family filter, which fell in the middle of the acceptable area, using
B,C values of 1/3,1/3. This filter is now known as the 'Mitchell-Netravali
Filter' and is available in IM as the '
Mitchell' filter
setting. Basically it is a compromise of the acceptable effects of the resize
artifacts. It is also the default filter used for IM image enlargements.
All the built-in IM Cubic filters: '
Mitchell',
'
Robidoux', '
Catrom', '
Cubic', and
'
Hermite'; have also been marked in the above diagram, showing
what those experts thought of those specific filters. Also shown are the
lines representing the 'B-Spline', 'Cardinal' and 'Keys' filter families.
Internally all these filters only differ by the pre-defined B,C settings of
the filter, in fact IM uses the same internal function to generate all cubic
filters, only with different B,C settings, for those filters.
Cubic B,C Expert Controls
You can use the special expert settings to set the B,C settings that a
Cubic Filter is using. To do this you need to
select any one of the four Cubic filters, and the desired '
b' and
'
c' expert settings. For example...
-filter Cubic
-define filter:b=value
-define filter:c=value
The expert settings will override the internal defaults for the given filter
when it is used by a resize or distort operator. As such the order of the
above options does not matter, as long as you have "
-define" or "
-set" all the global expert settings
desired before the image processing operator is used.
If one of the '
b' or '
c' settings has not been
defined or set, its value will be calculated from the other value on the
assumption that you are wanting a 'Keys' family filter (along the dotted line
in the Mitchell-Netravali Survey diagram). Remember the '
c' is
equivalent to the Keys
α setting, while '
b' can be
thought of as a cubic spline 'blur' setting.
These expert settings provide a good way for users to 'tune' their image
resizing to get exactly what they want (whether they are using
Resize or
Distort.
The '
b' setting is easier of the two to understand. Just think of
'b' as 'bluriness'. A value of b=0 is the very sharp (Catmull-Rom filter),
which tends to produce strong
Ringing and
Aliasing or Moiré Effects. A value of b=1 tends to
produce a overly blurry (the Cubic, gaussian-like filter) effect. Users can
then adjust this value to find a filter that they find 'good to them'.
To the right is a table of the B,C values for the specifically 'named' Cubic Filters.
Remember 'Hermite' is the only built-in cubic filter that does
not form part of the 'Keys' filter family. It has the smallest support
('1.0') of all the BC Cubic filters, and does not contain
a negative lobe. This makes it a simple interpolation filter that is a sort
of smoothed 'Triangle' filter. It also makes a good
interpolation function.
| |
| Filter | B blur |
C Keys α |
| Hermite | 0.0 | 0.0 |
| Cubic | 1.0 | 0.0 |
| Catrom | 0.0 | 1/2 |
| Mitchell | 1/3 | 1/3 |
| Robidoux |
0.3782 | 0.3109 |
Robidoux Sharp |
0.2620 | 0.3690 |
|
The '
Robidoux' and '
RobidouxSharp' filters are very similar to
'
Mitchell', but rather than the result of a survey, they were
determined mathematically for special use as a
Cylindrical Filter. The '
Robidoux'
filter for example is the default filter used by the
General Distort Operator (see below).
  |
The 'Parzen' windowing filter also uses the 'Cubic'
filter as its windowing function. As such you can re-define this windowing
filter in terms of B,C expert options. How useful this is, and what effect
it has on the resulting windowed Sinc (or Jinc), is unknown, and not
recommended.
|
Cylindrical Filters
- for Distort
As we have touched on a number of times already, the
Distort Operator uses the filter setting to
resample images in a slightly different way to the
Resize
Operator.
Specifically
Distort applies the filter
using the 'radial' distance between the 'sample point' and the actual pixels
within the sampling area of the source image, to determine weights of each
pixel and thus the final color at the sample point.
Resize in contrast, resizes the image twice using
orthogonally aligned filters. Once in the X direction, and then again in the
Y direction, it is thus limited to simple rectangular resizing of images, and
does not involve the use of
Virtual-Pixels.
That is to say
Distort applies the filters
to produce '
Cylindrical' shapes rather than 'Box' shapes, so as to
allow free-form distortions of images, including rotations and variable
scaling (stretching and compression) in any direction, not just along the X or
Y axis.
Because of this the filters themselves often need to be adjusted or are
designed specifically for this type of usage.
Interpolated Cylindrical Filters
Here I use a '
Box' filter to enlarge a single
pixel image by 30 times using the equivalent
Resize and
Distort operators.
convert xc: -bordercolor black -border 1 \
-filter Box -resize 3000% dot_resize_box_.png
convert xc: -bordercolor black -border 1 \
-filter Box +distort SRT 30,0 dot_distort_box_.png
|
Resize
|
Distort
|
As you can see when the '
Box' filter is used
as a Cylindrical filter you get a circle (or a cylinder in 3 dimensions).
However because of the way the filter is handled you get some areas where two
pixels are sampled (equally) to produce a perfect mid-tone gray.
You can think of a cylindrical box filter converting the source image into
a whole set of overlapping circlular pixels that are blended (not added)
together.
Here is a more colorful example of the results of expanding an image using
a 'Cylindrical Box' filter for enlargement...
convert \( xc:red xc:white xc:black +append \) \
\( xc:blue xc:lime xc:white +append \) \
\( xc:black xc:red xc:blue +append \) -append \
-filter Box +distort SRT 30,0 color_box_distort.gif
| |
|
With a distorted image, these circular pixels are also distorted into
a set of overlapping ellipses. For example...
convert \( xc:red xc:white xc:black +append \) \
\( xc:blue xc:lime xc:white +append \) \
\( xc:black xc:red xc:blue +append \) -append \
-alpha set -virtual-pixel transparent -filter Box \
+distort Perspective '0,0 0,0 0,3 0,90 3,0 90,30 3,3 90,60' \
color_box_distort.png
| |
|
  |
The support 'radius' for a cylindrical 'Box' filter is
increased from '0.5' to '0.707'
(sqrt(2)/2). This ensures the filter will always find at least
one source pixel in the circular sample area (diagonally). This is the
minimum practical support size for any cylindrical filters.
No other filter has this coverage problem, requiring a increase in support.
|
  |
If the support is not at least '0.707', then you may get areas
of your image in which the filter 'misses' all source pixels.
This is bad and should not happen. In some old versions of IM the result
would be areas of black (no color source), while at the moment such areas
are replaced with a more direct unscaled interpolated lookup of
the sampling location.
The result is that using too small a support for the box filter can generate
some fairly wierd looking images, when enlarged. For example...
convert \( xc:red xc:white xc:black +append \) \
\( xc:blue xc:lime xc:white +append \) \
\( xc:black xc:red xc:blue +append \) -append \
-filter Box -define filter:support=0.4 \
+distort SRT 30,0 color_box_distort_bad.png
| |
|
The circles is the result of the box filter, which in enlaregment can see
only one pixel in that area, and thus produce only one color. The other
areas are the result of not finding any pixel within the support bounds of
the filter (a bad resampling), and as such IM falls back to using
a interpolated lookup, according to the current Pixel Interpolation Setting.
FUTURE: Perhaps a alternative fallback setting could be provided to provide
a specific color when no pixels are found during resampling.
Using a larger support setting also produces interesting patterns. As
'circles' become larger, and more pixels will become blended together. At
a support of 1.0 or larger every resample will be a 'box' or 'average'
blending of at least two pixels. For example...
convert \( xc:red xc:white xc:black +append \) \
\( xc:blue xc:lime xc:white +append \) \
\( xc:black xc:red xc:blue +append \) -append \
-filter Box -define filter:support=1.0 \
+distort SRT 30,0 color_box_distort_overlap.png
| |
|
|
Here is a comparison of a number of the interpolation filters. Gray colors
are used so that you can see over and under shoots. The top line
using a orthogonal resize, while the bottom line uses a cylindrical
distortion.
for filter in box triangle hermite lagrange catrom
do
convert xc:gray80 -bordercolor gray20 -border 2 \
-filter $filter -resize 2000% dot_resize_$filter.png
convert xc:gray80 -bordercolor gray20 -border 2 \
-filter $filter +distort SRT 20,0 dot_distort_$filter.png
done
|
Box
|
Triangle
|
Hermite
|
Lagrange
|
Catrom
|
You can see how the results are similar but with different syles of
Artifacts being generated, both internally and
externally (ringing), by the two different ways in which the filter is being
applied. The internal artifacts is especially evident in the
'
Triangle' filter.
However remember that interpolation filters are not particularly good for
extreme minification (shrinking) of distorted images, but they are very good
for magnification (enlarging).
Cylindrical Gaussian
The one filter which produces no difference in results between an
orthogonal 'resize' and a cylindrical 'distort' forms, is the special
'Gaussian' filter...
convert xc:red -bordercolor yellow -border 1 \
-filter Gaussian +distort SRT 33,0 -normalize dot_distort.jpg
| |
|
This is actually one of the special proprieties of this filter, and one of the
reasons why most cylindrical resampling implementations use it as the default
filter.
Just as it is for orthogonal resize, a '
Gaussian' filter will
produce absolutely no
Aliasing Artifacts in the
resulting image, even when you apply it to the special 'rings' image. But as
before the cost of this is a blurry result, even if little or no distortion is
actually involved.
Similarly as given in the discussion on the
Sigma
Expert Control, you can also use this filter as a type of interpolated
filter.
  |
As of IM v6.6.5-0, IM no longer used this filter, by default for Image Distortions. Instead another filter
'Robidoux' filter specifically
designed to produce a sharper result is used.
In any case, before this version distortions were also very blurry due to
a mistake in its implementation. Upgrade if you have an older version and
want to use Image Distortions.
|
  |
Before IM v6.6.7-6, IM would use a slightly larger 'sigma' value for
a Cylindrical Gaussian, of 1/sqrt(2) or approximatally 0.707, instead of
1/2. This resulted in a slightly more blurry result, which was to reduce
posible Aliasing Artifacts.
This was a mistake which was created by following a research papers
recommendations, concerning the need for a larger support for a Cylindrical Box Filter. This version removed
that mistake, which now means you should get equivelent results with either
resize or distort, when the gausian filter is used.
Having said that I personally find using this slightly larger sigma value
does smooth out any 'blocking' artifacts along diagonal edges when doing
enlargements of line drawings. I would counterate this with level
adjustment or sharpening. This is not recommended for photos.
|
Windowed Jinc Cylindrical Filters
![[IM Output]](graph_jinc.gif)
The
Jinc() function (sometimes incorrectly called
a '
Bessel' filter) is the 'Sinc' equivalent for use with
a cylindrical filtering operation. Though very similar and closely related to
Sinc(), it is designed to filter a rectangular array of values using
a radial or cylindrical distance, rather than only in orthogonal (axis aligned)
directions.
If you look at the provided graph of the
Jinc() function, you will find
that its first 'zero-crossing', representing first ring of near neighbours,
falls between the values of 1.0 (for orthogonal neighbours) and the square
root of 2. That is the zero crossing has an approximate value of
'
1.2196699'.
The way
Jinc() function works is that if the sampling point is equal to
an actual pixel value, the
Jinc() function will assign a positive value
to the slightly closer orthogonal neighbouring pixels, but then assign
a similar negative value to the slightly further diagonal neighbours, and so
on as it move further though the 2 dimentional array of values. As a result,
when no scaling (distortion) is performed the contributions of the neighbours
should, in general, cancel each other out.
This is why the
Jinc filter is mathematically the preferred solution to
cylindrical resampling of a square array, and thus the 'ideal' filter for
Distort elliptical resampling method (EWA). This is not
to say it is a 'perfect' filter from a human point of view.
Because of this selecting any
Windowed Filter
while using the
Distort Operator, will substitute
the normal '
Sinc()' function with the equivalent '
Jinc()'
function.
As the
Jinc() function has zero crossings are at non-integer positions,
it is very important to specify the filters support in terms of special
Lobes Support Setting introduced above for
Windowed Sinc Filters.
The biggest problem with using a 'Windowed Jinc' filter is when the source
image contains a pixel level hash pattern (such as provided by
"
pattern:gray50", see
Built-In Patterns). In this situation all the orthogonal neighbours are
different to diagonal neighbours, and as a result, the image becomes heavily
blurred by the '
Jinc()' function.
However just about any other pattern, such as lines, edges, corners, all
remain quite sharp and clear when using a 'Windowed Jinc' filter, making it
still a good function to use.
This 'problem' can be a good thing, as it means that 2-dimentional cylindrical
Jinc derived filter can be used as method of removing strong pixel hash type
patterns from images, such as those generated by a
Color Reduction Dither, without greatly
effecting the sharpness of the rest of the image. That is it could be used as
a 'Dither Removal Method'.
To Add; examples of hash pattern effects using a cylidrical lanczos.
Distort and Filters in the No-Op case
Ideally, no-op distortion should return exactly the same image. Resize
(Sinc-Sinc) Lanczos, Lanczos2, Catrom, Hermite, Triangle, and many other
resize filters do have this property. On the other hand smoothing or blurring
filters, like Gaussian, Cubic, and Quadratic will blur an image if applied to
a nearly no-op case. Note that even the resize filter default, Mitchell, also
contains some blur in it. Mitchell-Netravali is basicaly a blend of B-spline
'Cubic' smoothing filter and the Cublic two-lobe sinc equivelent Catmull-Rom
filter.
The resize operator will short-circuit itself, so as to do nothing for the
no-op case. As such you will never see a actual no-op resize from IM.
While most resize filters will preserve images in the no-op case. Cylindrical
(distort) methods, will basically never produce a perfect no-op distortion.
Any no-op distort will distort the colors of an image, even though the image
itself is not distorted.
What happens is that by using a cylindrical filter, the contribution of
orthogonal neighbourhood pixels will be different to that for diagonal
neighbourhood pixels. They are essentually different distances from the
lookup point (centered on an actual pixel for the no-op case. The 'Jinc'
function tries to reduce this color distortion by canceling out the
contributions of the orthogonal neighbours with that of the diagonal
neighbours.
In the worst case, a 'pixel level hash', every diagonal pixel neighbour is
different to every orthogonal pixel neighbour. In this case the filter
weightings will enhance rather than cancel the contributions. As a result
this type of image will tend to produce very sever color distortions for
a no-op distortion of any image containing a 'pixel level hash'.
The actual number of lobes of a Windowed Jinc filter, has a enormous bearing
on the results as well. With 2 lobes, a 'pixel level hash' has a tendancy to
be preserved, While 3 lobes tend to cancel out the hash and produce a uniform
average color result. The contribution of the windowing method applied to the
Jinc function, will however distort this 'cancelation' effect produced with an
even number of lobes. Essentually a no-op distortion generally generates
quite bad color bluring effects.
To Add: examples of different 2 and 3 lobe filters
The question thus arises of how to tune the distort filters so as to minimize
the color distortions generated by the filter for a no-op distortion. The way
Nicolas Robidoux decided to do this was by selecting a blur (rescaling of the
support of the filter kernel) that tends to preserve orthogonal edges as much
as posible.
Lanczos2 - 2-lobed Lanczos
For the '
Lanczos' filter the '
Sinc()' function used
both the weighting and windowing of the filter is replaced with
'
Jinc()'. As such a 'Cylindrical Lanczos' will select a "Jinc windowed
Jinc" of the same number of lobes. This technique was first advocated by
Andreas Gustafsson, in thesis on
Interactive (Local)
Image Warping (page 24). He specifically used a 2-lobed Cylindrical
Lanczos (Jinc windowed Jinc) filter which he named '
Lanczos2D'.
It is really just a cylindrical '
Lanczos' (Jinc-Jinc) filter with
a '
filter:lobes=2 expert setting. See the
graph above, and as IM filter automatically
switches between using
Sinc(), and
Jinc() functions as
appropriate, it is not just for a '2D' (cylindrical) use. As such the filter
is simply named '
Lanczos2', and was included in IM
v6.6.4-10, specially for use in distortions.
LanczosSharp - A slighly sharpened Lanczos
It was observed that windowing a
Jinc() function leads to much blurrier
EWA distort results, than analogous windowed
Sinc() function, in the
orthogonal resize results. This was particularly the case for mild
distortions. Basically, the
Jinc() function has some special
properties, and windowing the
Jinc() function messes up those specific
and desirable properities.
With some calculation, Nicolas Robidoux, Professor of Mathematics at
Laurentian University, was able to work out a slightly sharper version of
a 3-lobed Cylindrical Lanczos, now available as
'
LanczosSharp', that to some extent fixed the problem for
distorting images.
However the resulting filter still has the strong blurring of low level 'pixel
hash' patterns, of
Windowed Jinc Cylindrical Filters.
Lanczos2 Sharpened
![[IM Output]](graph_cylindrical.gif)
The same problem was more severe in '
Lanzcos2' filters, so
Nicolas also produce a sharper '
Lanczos2Sharp' filter,
using a slightly larger
Blur Expert Control. This
resulted in a filter with only minimal blurring for vertical or horizontal
lines in a 'no distort' case.
This sharpened filter results in a small shift of the zero point, so that it
is now located at approximatally '
1.1684'. This may not seem
like much but it makes a huge difference in the amount of blur the filter
generates for images with little to no distortion.
example 2 and 2 sharp images
Robidoux Cylindrical Filter
![[IM Output]](graph_robidoux.gif)
Almost at the same time, experiments were showing that using a
Mitchell-Netravali filter as a cylindrical filter was
producing near equivalent 'sharp' results for the 'no distort' case. And yet
the filter has no relationship to its use as a cylindrical filter, as it was
selected by a 'social study' for orthogonal (resize) filtering.
The '
Mitchell' filter was especially good at preserving low-level
'pixel hash' patterns, which normal
Windowed Jinc Filters
destroyed in cylindrically filtered images.
Nicolas then found that by a bizarre coincidence that '
Mitchell'
was extremely close to the 'sharpened' form of '
Lanzcos2' filter
discussed above.
This in turn lead to him developing a
Keys Cubic
Filter which preserves vertical (and horizontal) lines perfectly. Also
this new filter does so at a lesser computational cost, as a cubic function is
very cheap to compute than a Jinc function.
This cubic filter has been added to IM as the '
Robidoux'
filter, as of IM v6.6.5-0, and is also the default filter used by
Distort and its
Elliptical Weighted Resampling method, specifically due to its
minimal-blur propriety for images with only minimal distortion.
I have marked this filter on the "
Cubics Map" generated by the
Mitchell-Netravali
Survey, so you an see just how closely related to the '
Mitchell' filter it is. It would in fact make
a reasonable filter for either orthogonally resized or cylindrically distorted
images.
Robidoux Sharp Cylindrical Filter
The '
RobidouxSharp' filter is a slightly sharper version
of the '
Robidoux' filter, though some
feel that the results are too sharp.
It is designed specifically so as to preserve images containing pure black and
white pixels with the minimum of error, in the "no-distort" case.
Specifically that the weightings the orthogonal neighbouring pixels, exactly
match the negative weightings of diagonal neighbouring pixels in
a 'no-distort' case.
By coincidence the '
Mitchell' filter
happens to fall almost exactly between the '
Robidoux' filter and the '
RobidouxSharp' filter, and all belong to the
Cubic Keys family of filters, whcih was never
actually designed for EWA filtering, but seems to work well.
As such users can select from any of these three filters to control the
blur-sharpness of results in near 'no-distort' situations.
Cylindrical Filter Summary
FUTURE: Examples of various Cylindrical Filters
Nicholas Robidoux in the long on goinf forum discussion
Proper Scaling of a Jinc Filter in EWA
gives this as a summary...
|
If Robidoux is too soft and RobidouxSharp too aliased, I suggest that you
try Mitchell (with distort Resize), which is pretty much halfway.
Because JPEG involves a (Discrete) Cosine Transform, I am not surprised that
the filters based on Fourier considerations (Lanczoses et al, whether resize
with Sinc or distort with Jinc) generally do better than those based on
"good approximations of smooth functions" (those based on Keys cubics:
Robidoux, Mitchell, RobidouxSharp, CatRom, whether with resize or distort),
but that their advantage appears to be less with PNGs (which don't destroy
information through the Fourier domain).
|
Expert Filter Controls
In the various sections above I introduce a large number of special 'expert'
controls, which will allow you to modify the various filters in various ways.
You define these expert settings using
Global
Define Setting" (or equivelent
Set
Option).
A full summary of all the expert option in the
IM Command Line Options
Reference Page for "
-filter".
The "
-filter" setting is
in fact only used to lookup and set the expert controls appropriately so as to
define the given 'named' resize filter. The above settings will override
those default values as specified above, at the time filter is setup for
a specific resize or distortion image processing operation.
  |
The "-filter" setting
'Point' completely bypasses all the above filter setup, and degenerates into
an unscaled 'Nearest Neighbor' direct lookup (resize), or interpolated
lookup (distort). Thus this named filter setting effectively turns off the
scaled image lookup filter completely.
|
Now while they are available. I would like to make one final point.
Unless you are an expert (or just playing) -- It is best NOT use them!
There are few people who are expert at image processing, and unless you know
exactly what filters do and how changing them effect the filtering operation,
all you are likely to do is destroy the effectiveness your image processing,
and produce a bad looking result.
That is not to say users should not use them, and many IM Examples do make use
of them, but it is usually done to provide some special effect. When a special
option is used the reason for its use is also explained, and you should stick
to the recipe given for that effect.
You are of course welcome to use them and you can generate some very
interesting and highly unusual effects by making use of them.
The 'verbose' Filter Control
The setting "
filter:verbose" is perhaps your best friend in
figuring out and understanding the other filter controls.
For example you can verify that the Lanczos filter is defined in terms of
a Sinc windowed Sinc support 3.
convert null: -filter Lanczos -define filter:verbose=1 -resize 2 null: |\
grep '^#'
|
Note that internally the Lanczos filter is defined in terms of a fast
polynomial equivelent 'SincFast' (4 lobe) function, rather than a full 'Sinc'
function which is defined in terms of far more computationally intensive
Trignometric Library functions.
Here we see that the Lanczos filter is defined as a Jinc windowed Jinc filter
when used with as a cylindrical (
EWA
Algorithm) "-distort" filter.
convert null: -filter Lanczos -define filter:verbose=1 \
-distort SRT 0 null: | grep '^#'
|
The '
filter:verbose' setting is the only way users can check on
exactly what the final resultant filter is, due to the use of the various
expert settings.
Extract the data of a Welsh Windowed Sinc Filter...
convert null: -filter Welsh -define filter:verbose=1 \
-resize 2 null: > filter_welsh.dat
|
Or the raw Welsh Windowing Function that was used in the above, with the
window function scaled a support range of 0 to 1.
convert null: -define filter:filter=Box \
-define filter:window=Welsh \
-define filter:support=1.0 \
-define filter:verbose=1 \
-resize 2 null: > window_welsh.dat
|
You can then plot that data with the "
gnuplot" command (like I did in
Windowed Sinc
Filters above)...
gnuplot
set grid
plot "window_welsh.dat" with lines
|
Other Examples of Expert Filter Controls
Create a 'Raw 8 lobed Sinc' filter can be set using...
-define filter:filter=Sinc
-define filter:lobes=8
|
Use the Blackman windowing function directly as a filter (as IM did by
mistake, before v6.3.6-3).
-define filter:filter=Blackman
-define filter:support=4.0
|
The windowing function will default to 'Box' when undefined.
A 'Box' windowing function will result in no windowing of the base filter
function. For example a 'Gaussian' filter by default has a 'Box' windowing
function.
Force the use a raw Jinc function using...
-define filter:filter=Jinc
-define filter:window=Box
-define filter:lobes=3
|
A 12 lobed 'Lanczos' windowed filter clipped to just the first 8 lobes of the
resulting windowed filter...
-filter Lanczos
-define filter:win-support=12
-define filter:support=8
|
This makes it about four times faster, by ignoring the 'tail' of the resulting
windowed-sinc filter but may have some minor artifacts as a result.
Using Gaussian to 'blur' an image! This is equivelen to a -gaussian 5x2
operation!
-filter Gaussian
-define filter:sigma=2
-define filter:support=5
-distort SRT 0
|
Note: you can not use a no-op resize for this, as it short circuits.
Create a different filter from the 'Mitchell-Netravali' survey.
-cur-its Cubic
-define filter:b=0.5
-define filter:c=0.5
|
Create your own 'Keys Cubic' filter with α value of 0.4...
-filter Cubic
-define filter:c=0.4
|
Any use of the expert options are at your own risk. They are not meant for
production use, but as a method for exploring or producing tricky or otherwise
impossible resize functions. Use at your own peril!
Summary of Resize Filters
The following is my own personal view after studying, recoding, and
documenting all the above filters available in ImageMagick. If you think I
may be wrong or like to express your opinion, I invite you to express your
views on the IM forum, and invite me to respond.
Interpolation Filters, such as
'
Hermite', are ideal when greatly enlarging images, producing a
minimum of blur in the final result, though the output could often be
artificially sharpened more in post-processing.
Gaussian-like Blurring Filters, such as
'
Mitchell', work best for images which basically consist of line
drawings and cartoon like images. You can control the
blurring versus the
aliasing effects of the
filter on the image using the special
Filter Blur
Setting.
Windowed Sinc/Jinc Filters, and the
Lagrange equivalent are the best filters to use with
real-world images, and especially when shrinking images. All of them are very
similar in basic results. A larger support, or better still, lobe count
setting, will generally produce an even better result, though you may get more
ringing effects as well, but at a higher calculation
cost.
The
Cubic Filters are a mixed bag of fast and
simple filters, of fixed support (usually 2.0) which produces everything from
the '
Hermite' smooth interpolation filter, the qualitatively
assessed '
Mitchell' for image enlargements, the very blurry
Gaussian-like '
Cubic' filter, or a sharp, windowed-sinc type of
filter using '
Catrom'.
Generally if the resize results are acceptable as is, leave things alone,
as you are more likely to make things worse, not better.
Filter Comparison
Enlargement
To give a final comparison, here I present a selection of 12 representative
resize filters. The image is an enlargement of an aliased step in a one pixel
wide line, on a dark gray background. The original image itself 'aliased' so
you should be able to see how well various filters remove any existing
aliasing effects.
convert -size 10x6 xc:grey20 +antialias -draw 'fill white line 4,0 5,5' \
-filter {filter_type} -resize 100x {result}
|
The above starts with the
Interpolated
Filters and continues with the
Gaussian
Blurring Filters, showing how much blurring these filters produce, and in
doing so remove the 'aliasing' in the original image. No ringing is produced
by these filters.
The second line starts with three
Windowed Sinc
Filters showing the heavy ringing effects they can produce. Remember
these filters are really designed for shrinking images, not enlarging. This
continues into the '
Lagrange' using its default 'interpolating'
setting, and '
Catrom' interpolated cubic filter.
The final image is the '
Mitchell' filter showing what the
'experts' subjectively agreed was the best 'ideal' filter to use for
enlarging images, with a minimal of all four
Resize
Artifacts present in the final result.
I myself agree with their findings, but only for enlargements.
This is why '
Mitchell' is the default 'enlargement' filter used by
IM.
Shrinking
To get an idea of the
aliasing effects, here I shrink
the crop of
Large Rings Image that we made
earlier (
105x105 pixels in size), to see what sort of
Moiré effects each of the same 12 representative filters generates.
convert rings_crop.png -filter {filter_type} -resize 100x {result}
|
As you can see
Interpolated Filters filters
are very heavily aliased. On the other hand the blurring effects of the
Gaussian Blurring Filters tend to remove the
Moiré effects from the resulting image, though with a general blurring
of the resulting image. The '
Gaussian'
Filter itself does show a barely noticeable aliasing effect caused by its
infinite (IIR) filter being clipped by the
Filter
Support Setting, but that is very minor.
On the other hand the
Windowed Sinc Filters
produce a very sharp looking image with only a very light circular morié
effect, of about equal intensity across all three representative filters.
This is probably a 'display' effect rather than a resize filter effect.
Finally the other cubic filters also show some morié effects, with the
'
Mitchell' showing the least effect, presumably because of the
slight blurring that it has incorporated into the filter.
Here is another comparison, but this time heavily shrinking a
Smaller Rings Image smaller.
convert rings_sm_orig.gif -filter {filter_type} -resize 100x {result}
|
As you can see the
Interpolated Filters
produce lots of
aliasing artifacts, while the
Gaussian Blurring Filters tend to blur out more
lines than the others. But all the other filters tend to produce a reasonable
job.
The Best Filter?
That is something you will need to work out yourself. Often however it depends
on what type of image and resizing you are doing.
For enlarging images '
Mitchell' is probably about the best filter
you can use, while basically any of the
Windowed
Filters (default is '
Lanczos') are good for shrinking images,
especially when some type of low level pattern is involved. However if you
have no patterns, but lots of straight edges (such as GIF transparency), you
may be better off using sharpened
Gaussian
Filter or again a '
Mitchell', so as to avoid strong ringing
effects.
The '
Lagrange' filter is also quite good, especially with
a larger
Filter Support Setting, for shrinking
images.
For those interested I recommend you look at the IM User
Discussion topic
a way to compare
image quality after a resize? which basically shows that their is no way
of quantitatively determining "The Best Filter", only a qualitative or
subjective "Best Filter".
The choice is yours, and choice is a key feature of ImageMagick.
IM's Default Filter...
It is for these reasons that '
Mitchell' is the default filter for
enlargement, as well as for shrinking images involving transparency, or images
containing a Palette (or colormap). However the '
Lanczos' will
be used in all other cases, that is shrinking normal images (typically
photographs).
For
Distort, the filter setting defaults
to the '
Robidoux' filter which was specifically designed to
minimize image blurring when no actual distortion takes place.
You can of course override these choices.
Created: 15 March 2004
Updated: 26 Arpil 2012
Author: Anthony Thyssen,
<A.Thyssen@griffith.edu.au>
Examples Generated with:
![[version image]](version.gif)
URL: http://www.imagemagick.org/Usage/resize/