ImageMagick Examples --
Cutting and Bordering
- Index
ImageMagick Examples Preface and Index
Crop (cutting up images in a free form way)
- The basic crop operator
- The Missed Image (from a bad crop)
- Crop an Image with Existing Virtual Canvas
- Removing Virtual Canvas from Results using +repage ***
- Viewport Crop with Virtual Canvas Adjustments
- Crop Relative to Gravity
- Crop a Percentage of an Image
- Tile Cropping, sub-dividing one image into multiple images
- Centered Tile Cropping, leaving remainders around the edge
- Strip Cropping, cropping out rows and columns
- Quadrants, cutting around a single point
- Using Negative Offsets, remove bottom or left edge
- Cropping into roughly Equally Sized Divisions
- Separating Spaced-out Tiling Images
Adding/Removing Image Edges
- Border, adding space around the edge of an image
- Frame, adding 3D-like borders to images
- Shave, removing the edges from images
- Extent, direct image size adjustment
Adding/Removing Rows, Columns and Edges
Advanced Cropping Techniques
Trim, the 'Auto-Crop' Operator
- Using Trim
- Trimming with a Specific Color
- Trimming just One Side of an Image
- Trimming 'Fuzzy' Images -- Low Quality JPEG Images
- Trimming 'Noisy' Images -- Scanned or Video Images
Crop (cutting images down to size)
Crop and Canvas Page
The "-crop
" image operator
will simply cut out the part of all the images in the current sequence at the
size and position you specify by its geometry argument.
magick rose: rose.gif
magick rose: -crop 40x30+10+10 crop.gif
magick rose: -crop 40x30+40+30 crop_br.gif
magick rose: -crop 40x30-10-10 crop_tl.gif
magick rose: -crop 90x60-10-10 crop_all.gif
|
![[IM Output]](rose.gif)

![[IM Output]](crop.gif)
![[IM Output]](crop_br.gif)
![[IM Output]](crop_tl.gif)
![[IM Output]](crop_all.gif)
![[IM Output]](crop_miss.gif)
magick identify
" on the results of the crop above.
Notice that the size of the displayed image (its Virtual Canvas) has not been effected by
the "-crop
" operation.
The actual image itself has been cropped, and may be smaller, but the canvas
on which the GIF image is displayed is still the same size as the original
canvas.
You will also notice that the size of the actual image produces may not be the
actual size you requested from the crop. It could be very much smaller that
what you expected, as the crop itself was either partially or fully outside
the actual image area being cropped.
You will also notice that the 'offset' of the image on the Virtual Canvas was in many cases also
changed so that the pixels of cropped image is still in exactly the same
position as they were in the original image. That is, the image contents itself
does not move, even though the actual image itself is smaller.
This means if you now modify the smaller image, then overlay the image (using
image layering operators back over the
original, it will fit back exactly where the sub-image originally came from.
That is, IM retains the 'virtual canvas', 'page', or 'layering' information of
the image so as to preserve it for later use. This is especially important
for the correct working for GIF animation handling. For more information on
this see. Deconstruct GIF
Animations.
![]() ![]() |
GIF images make active use of the 'page' or 'virtual canvas', size and
offset information in images cropped by IM. If you don't want this
information remove it with "+repage " immediately after the "-crop ".
Note that many image formats don't save this virtual page/canvas
information information, so saving to such formats automatically removes
it. JPEG is a typical example of a format that removes this info.
The PNG format doesn't make much use of page/canvas info (except in the
multi-png (MNG) format) but it does saves the page offset information
(even negative offsets). IM will also add a small amount of meta-data to
preserve the virtual canvas size for later use by other IM commands.
Because of this preservation, I strongly recommend you still apply a
"+repage " even when
saving to JPEG or other page-less image format when you will not need that
information, as a pre-caution, and to make it obvious you don't what it.
|
Note, the behavior of cropping can be affected by these defines:
trim:percent-background=X% | Set the amount of background that is tolerated in an edge. It is specified as a percent. 0% means no background is tolerated. 50% means an edge can contain up to 50% pixels that are background per the fuzz-factor. |
trim:edges={north,east,south,west} | Only trim the specified edges of the image. |
trim:minSize=geometry | Limit the trim to the specified size. |
type:features=string | Add a font feature to be used by the RAQM delegate during complex text layout. This is usually used to turn on optional font features that are not enabled by default, but can be also used to turn off default font features. Features include those to control kerning, ligature and Arabic. |
type:hinting=false | Disable font hinting. Proper glyph rendering needs the scaled points to be aligned along the target device pixel grid, through an operation often called hinting. One of its main purposes is to ensure that important widths and heights are respected throughout the whole font. (For example, it is very often desirable that the âIâ and the âTâ glyphs have their central vertical line of the same pixel width. Hinting also manages features like stems and overshoots, which can cause problems at small pixel sizes. |
The Missed Image (from a bad crop)
The last image in the above example (EG: "crop_miss.gif
") also
produced special empty image. Such images can be produced by operations such
as Crop, Trim, Layer Comparison, and even GIF Animation Optimizations, that generate
empty or non-sensible results.
For example in the previous example above, the "-crop
" operation missed the actual
image it was cropping, so it produced this special 'missed' image, as well as
some informational warning messages...
The output image, or 'missed' image, is a minimal image, one pixel in size at
a 0 offset, but with original images page or canvas size, as well as any other
meta-data the image may have associated. Here it represents the 'empty' or
'zero sized' image that should have been returned by "-crop
", but as no image format can
output an image of 'zero' dimensions, a single transparent pixel image is used
instead.
Just so you can see more clearly, here is the "identify
" output of the missed image,
as well as a 'IM pixel enumeration' of that single pixel image, showing that
it only contains one single transparent pixel.
This 'missed' image is basically same as creating a "null:
" image but with the original source
images page or virtual canvas size set (but not its offset), and all other
image meta-data, such as GIF animation timing delays. The GIF disposal method
however may be modified to ensure animations remain correct, after cropping.
Basically you need to keep in mind that "-crop
" and other similarly related
operators can produce a special 'missed' image. As such you should plan to
look for the warning message, or this special 'Missed Image' when writing a
script using IM, if such a minimal image is possible and can cause you
problems.
If you don't want the warning message (for example you expect and handle, the
occasionally 'missed' image), you can add a "-quiet
" Operational Control Setting to the command
line. This tells IM to not output informational warning messages, only real
errors.
At this time there is no method to remove any 'missed', or "null:
" images from the current image
sequence. However such a method has been proposed for a future release of IM.
Mail me if you find you need such a method.
Crop an image with existing Virtual Canvas
If an image already has an existing Virtual Canvas, (for example a frame of a GIF animation), then the "-crop
" operation will be
applied relative to the virtual canvas, and NOT to the actual image.
That is, it will try to preserve the offset of the actual pixel data of the
cropped image on the canvas. That is, a specific pixel before the crop should
still be located at the same offset relative to the virtual canvas afterward.
In this way cropping of layered images, or GIF animations will continue to
work right, even though the 'canvas' itself was not cropped.
Here we create an image centered on a page canvas, and we crop it in various
ways. As before the canvas size itself is not modified by the operation.
|
![[IM Output]](paged.gif)

![[IM Output]](crop_page.gif)
![[IM Output]](crop_page_tl.gif)
![[IM Output]](crop_page_br.gif)
![[IM Output]](crop_page_all.gif)
![[IM Output]](crop_page_miss.gif)
![]() |
-quiet
" setting.
Just so you can see just what is going on, lets have a closer look at the
paged crop of the lower right corner of the image. Here I have drawn a
semi-transparent square over the area that was cropped.
magick paged.gif -page 64x64+32+32 -size 32x32 xc:'#fff8' \ -alpha set -background none -mosaic crop_area_br.png |
![[IM Output]](paged.gif)

![[IM Output]](crop_area_br.png)

![[IM Output]](crop_page_br.gif)
Removing Virtual Canvas from Results
If this Virtual Canvas information is not wanted, then you can use the special "+repage
" operator to reset the
page canvas and position to match the actual cropped image.
magick rose: -crop 40x30+10+10 +repage repage.gif magick rose: -crop 40x30+40+30 +repage repage_br.gif magick rose: -crop 40x30-10-10 +repage repage_tl.gif magick rose: -crop 90x60-10-10 +repage repage_all.gif magick rose: -quiet -crop 40x30+90+60 +repage repage_miss.gif |
![[IM Output]](rose.gif)

![[IM Output]](repage.gif)
![[IM Output]](repage_br.gif)
![[IM Output]](repage_tl.gif)
![[IM Output]](repage_all.gif)
![[IM Output]](repage_miss.gif)
-crop
" operator. It
is actually such a common thing to do that you could call it a rule of thumb.
Always use "
Unless you actually need to preserve that info.
The last image in the above is of course the special crop missed image, but I supressed the warning message using the
"+repage
" after any 'crop' like operation.
Unless you actually need to preserve that info.
-quiet
" operational
setting.
![]() ![]() |
For IM version 5 and earlier the "+repage " operation was handled
by a "-page +0+0 " argument sequence, usually just before saving
to format that uses virtual canvas and offset information, such as GIF. But
that was only usable when either reading or writing the image to a file,
preventing its use between multiple image processing operations.
With IM version 6, command line
restructure, the "-page " option became purely an image read/create setting for
use in creating GIF animations and
Layers of Images. As such separate
"-repage " and "-set page " operators were added to allow users to set or change
the virtual canvas information.
|
Viewport Cropping with Virtual Canvas Adjustments
From ImageMagick version 6.2.4-5, you can add a new special flag to the "-crop
" argument. This
flag '!
' will tell crop to adjust the Virtual Canvas information of the
returned image so that it is relative to the area cropped.
In other words, regardless of the resulting size of the actual image cropped,
the canvas and offset of the image returned will be adjusted to match the area
you requested cropped. You can think of this flag as cropping an image to
match a 'window' or 'viewport' of the crop area. Even if half the image is
not visible in that 'window', the virtual canvas and offset of the part
returned will match that 'viewport'.
For example...
magick rose: -crop 40x30+10+10\! crop_vp.gif
magick rose: -crop 40x30+40+30\! crop_vp_br.gif
magick rose: -crop 40x30-10-10\! crop_vp_tl.gif
magick rose: -crop 90x60-10-10\! crop_vp_all.gif
magick rose: -quiet -crop 40x30+90+60\! crop_vp_miss.gif
|
![[IM Output]](rose.gif)

![[IM Output]](crop_vp.gif)
![[IM Output]](crop_vp_br.gif)
![[IM Output]](crop_vp_tl.gif)
![[IM Output]](crop_vp_all.gif)
![[IM Output]](crop_vp_miss.gif)
![]() |
![]() ![]() |
The '! ' character has special significance to some UNIX
shells, like "csh ", and must be escaped with a backslash,
even when placed inside quotes.
|
+repage
". However any partial or
missed cropping of the image, the result will a larger canvas and a possible
offset to the resulting image. As such this is no substitute for doing a
"+repage
" after cropping
to reset page/canvas information.
However you can follow a 'viewport crop' with a Flatten to 'fill out' the images new virtual canvas with real pixels.
That is, you will be left with an image that is guaranteed to be the size of the
requested crop, with any 'missed' areas filled out with the current "-background
" color 'viewport'.
For example when Padding out an Image.
|
![]() |
![]() ![]() |
The '! ' flag can NOT be used when generating multi-image
Tiled crops, or with equal-area tile cropping,
where it has a different meaning. See the appropriate sections below.
|
Crop relative to Gravity
The offset position of the "-crop
" by default is relative to the top-left corner of the image.
However by setting the "-gravity
" setting, you can tell "-crop
" to cut the image relative to
either the center, corner, or an edge of the image.
The most common use of a gravitated crop, is to crop the 'center
'
of an image.
|
![]() |
-gravity
" setting
does not just effect the initial 'zero' position of the crop but it also
effects the direction of the crop offset.
For example if you use a "-gravity
" of 'South
', and offset of
'+0+5
' will offset the crop area upward, instead of downward as
it normally would.
|
![]() |
+repage
" operation so you
can see how the crop area was displaced from the bottom edge of the image.
Also notice that the crop area is not only relative to bottom (southern) edge,
but that the area is center 'justified' to be middle of the bottom edge. This
is done with all gravity effected operations.
Crop a Percentage of an Image
The "-crop
" operator also
understands how to crop an image to just a percentage of its original size.
For example this will half the size of the image.
|
![]() |
![]() ![]() |
If only one size number is given, then that value is used for both the width and height percentages and the final size of the area that is being cropped will be rounded to nearest integer. The offset is not optional. |
|
![]() |
![]() ![]() |
When a crop is given with an offset you must supply an
'x ' symbol in the argument so that the argument can be
interpreted correctly. This is especially important when only a single
number is provided for both width and height of the crop area.
As such you can not use an argument like '50%+30+20 which
is an error, and will result in crop silently doing nothing.
|
|
![]() |
![]() ![]() |
The percentage symbol '% ' can appear anywhere in an argument,
and if given will refer to both width and height numbers. It is a flag
that just declares that the 'image size' parts are a percentage fraction
of the images virtual canvas or page size. Offsets are always given in
pixels.
|
|
![]() |
![]() ![]() |
You can not use percent sizes for tile cropping (see next). As such if the offset is not provided, and a percent size is given (as above) an offset of +0+0 is assumed. |
!
' flag means a "+repage
" is not needed. Caution however is still recommended, for
input images that may also have virtual canvas size and offsets.
Tile Cropping, sub-dividing one image into multiple images
One of the more useful aspects of crop is when you don't give a specific position to the crop command. That is, you give a size, and not a position within the image to crop. In this case instead of generating just one image, crop generates a whole series of images..
|
![[IM Output]](paged.gif)

![[IM Output]](tiles_0.gif)
![[IM Output]](tiles_1.gif)
![[IM Output]](tiles_2.gif)
![[IM Output]](tiles_3.gif)
![]() |
![]() ![]() |
It is a good idea to make sure gravity is turned off using "+gravity ". This is because in
one special case (centered percentage crop) the gravity setting can turn
off tile cropping. Other effects of gravity on tiled cropping is also
undefined.
|
-mosaic
" or
"-flatten
" image
layering operators, (see Layer Flatten) you
can layer these images all on top of each other, restoring the original image.
|
![]() |
-mosaic
".
An alternative is to use "-layers merge
" (see Layer Merge),
which merges the multiple layer images into a new layer image just large
enough to hold all the given images. That is, the virtual canvas is not filled
in, as "-mosaic
" or
"-flatten
" layering
methods would.
|
![]() | |
|
+repage
" then the images no
longer contain the offset from where they were cropped, nor the original size
of the source image. In that case you can re-join all the images together
again using the special 'concatenation
' mode of
"magick montage
". You will need to tell montage how many rows or columns
of images were extracted from the original image.
magick rose: -crop 20x20 +repage +adjoin rose_tiles_%02d.gif montage -mode concatenate -tile 4x rose_tiles_*.gif rose_rejoined.gif |
![]() |
![]() |
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
![]() |
![]() |
rose_tiles_00.gif
" to "rose_tiles_11.gif
", which
simply the sequence number of the tiles in memory. This is not very nice as
the filenames give no easy indication of the actual position each tile belongs
to, or the total number of tiles per row and column.
As of IM v6.4.8-4 you can also use special Filename Percent Escapes to generate and include special labels into the
output filename. Using this with FX
Percent Escapes you can calculate a different 'tile position' for each
image. For example...
magick rose: -crop 20x20 \ -set filename:tile "%[fx:page.x/20+1]_%[fx:page.y/20+1]" \ +repage +adjoin "rose_tile_%[filename:tile].gif" |
![]() |
![]() |
![]() |
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
rose_tile_1_1.gif
" to
"rose_tile_4_3.gif
", which is a much better file naming scheme.
Tricky but it does work.
Unfortunately you can not format the number generated by a Percent Escapes, to include padding
with zeros or specify an exact number of floating point digits. At least not
at this time.
Centered Tile Cropping
In a IM Forum Discussion a request was made to center the tile cropping so as to distributed he 'remainder images' evenly around the edges. By doing this we maximize the effect of the complete tiles by placing them in the center of the image. Of course you also end up with more incomplete edge tiles. The solution was to center the input image on a virtual canvas, that was some multiple of the tile size wanted. For example to tile crop the "rose:
" image (70x46
pixels in size) into the maximum number of full 30x20
tiles, in
the center of the image (and surrounded by reminder tiles) you would do the
following.
- First calculate the number of full tiles you can get from the image
by dividing the image sizes...
70x46 / 30x20 => 2x2 full tiles + remainder
- Now add 2 more rows and columns to hold the remainder images (if needed)
2x2 + 2x2 => 4x4 tile images
- Multiply the tile size by this to get the virtual canvas size.
30x20 * 4x4 => 120x80 canvas size
- Subtract the original image size and divide into two for the centering
offset.
( 120x80 - 70x46 ) / 2 => +25+17
120x80+25+17
.
And here we use the above calculations perform a Centered Tile Crop...
If you want to preserve the original offset location of the tiles, but remove
the centering offset, you can do a relative offset adjustment using
"-repage -25-17\!
" (replacing the "+repage
" in the above).
If you did not add two columns and rows to the number of tiles and thus
generate a negative offset you can effectively ignore the remainder edge
tiles, and only output full and complete tiles that exist in the image.
Basically as the remainders are now 'outside' the calculated virtual canvas
the "-crop
" operator does
not know they were there and ignores them.
Again replacing the "+repage
" in the above, with a relative offset adjustment using the
negated offset values "-repage +5+3\!
" will restore
the original offset locations from which the tiles were cropped.
An alternative for a centered tile crop and ignoring reminders is to simply
replace the virtual canvas setting with an appropriate crop.
magick rose: -gravity center -crop 60x40+0+0 +gravity +repage \ -crop 30x20 +repage rose_ctiles2_%d.gif |
![]() |
![]() |
![]() |
![]() ![]() ![]() ![]() |
Strip Cropping, cropping out rows and columns
With IM version 6.1.1, a "-crop
" was enhanced so that if one of the size arguments missing,
or set to zero, then the missing size argument is set to the size of the image
canvas/page. In most cases this is large enough to cover the image located on
the canvas, if the related offset is also set to zero.
This small change allows you to easily cut out a single row or column from
the image, without needing a huge number like '999999
' to cover
the size of image.
For example, here we extract a simple row and column from our 'paged' rose
image.
|
![[IM Output]](paged.gif)

![[IM Output]](strip_column.gif)
![[IM Output]](strip_row.gif)
|
![[IM Output]](crop.gif)

![[IM Output]](strips_0.gif)
![[IM Output]](strips_1.gif)
![[IM Output]](strips_2.gif)
![[IM Output]](strips_3.gif)
-quiet
" setting. This
is not recommended unless you are expecting such an event, and are prepared
for it, such as in a script.
![]() ![]() |
It is possible for an image to be positioned such that it does not even
appear on its own page or virtual canvas, or be so large that the page
canvas can only contain a small window or part of the image.
In such rare cases, strip cropping without any size arguments will get the
image sub-division wrong, and produce respectively, missed images, or smaller tiles of only the parts within the virtual
canvas bounds.
The "-crop " operator
however will not be fixed to handle these rare special cases, as doing so
will prevent its use in other cases, such as those exampled below.
If this is a problem for you, sanitize the page offsets of the image before
cropping by using "+repage " to remove the virtual canvas before attempting to
generate the tile images.
|
divide_vert
". This program will let you divide up an image
according to horizontal 'gaps' of solid single color. For example, if given
an image of simple text, it will divide it into alternating images of 'lines'
and 'gaps'. A simple option lets you remove those gaps.
Quadrants, cutting around a single point
As any of the crop size numbers are missing then they are replaced with the size of the image canvas of the image you are cropping. This should in most cases result in the whole of the image in that dimension becoming part of the crop result. This allows, with cautious use of the arguments, is the ability to crop and image into quarters around a specific point (with that specific pixel placed as the top-right pixel of the bottom-left quadrant image). You do not need to know how big the image is to do this. For example, here I crop the image into quadrants around the point 30,40
|
![[IM Output]](paged.gif)

![[IM Output]](quadrant_tl.gif)
![[IM Output]](quadrant_tr.gif)
![[IM Output]](quadrant_bl.gif)
![[IM Output]](quadrant_br.gif)
Using Negative Offsets, remove bottom or left edge
Their is no reason that you can not use a negative offset with "-crop
". In fact at times it can
have very definite benefits.
For example lets take our paged rose image and progressively crop it
with larger negative offsets. We will not supply an image size to "-crop
" argument, so it will default
to the images canvas size.
|
![[IM Output]](paged.gif)

![[IM Output]](neg_offset_1.gif)
![[IM Output]](neg_offset_2.gif)
![[IM Output]](neg_offset_3.gif)
![[IM Output]](neg_offset_4.gif)
![[IM Output]](neg_offset_5.gif)
-chop
" operator but
without a "-gravity
"
setting. See Chop, Removing Edges.
Of course by using "-crop
"
you may need to use a "+repage
" operator to adjust the canvas/page information, where a
"-chop
" automatically
performs such an adjustment. That's life.
Cropping into roughly Equally Sized Divisions
The biggest problem with Tile Cropping is that you can only define the final size of each tile. This works great when the image size is an exact multiple of the desired tile size, but as you have seen if this is not the case you can end up with 'short' tiles on the right and bottom edges. For example lets again divide the built in rose image, but try to divide it into 3x3 tiles. The original image is 70x46 pixels so divided by 3 make each tile 23x15 pixels... Well as you can see this did not work, because the rose image can not be exactly divided into 3 equally sized tiles. In this case you end up with a 1 pixel 'short' tile. Even if you expand the size of the tile to 24x16 pixels, you will still end up with a tile that is 2 pixels 'shorter' than the other tiles. This situation gets worse as the number of tiles wanted gets larger. For example try sub-dividing a length of 100 into 30 tiles. It is impossible. You either use a length of 3 and get 34 tiles, or 4 and get 25 tiles. Getting exactly 30 equal sized tiles is impossible! As of IM v6.5.8-9 you can now add the special '@
' flag to the
"-crop
" argument. This
flag tells the "-crop
"
operator to try its best to equally divide the image into the number of
tiles given. For example...
The result is that the image was divided into tiles which have slightly
different sizes. However the tile size will differ by 1 pixel at the most!
Check it out!
As a bonus, you can also sub-divide the image so that each tile will
'overlap' its neighbours. You do this by not only using a '@
'
flag but also specifying the number of pixels of overlap you want.
For example lets divide the rose into quarters but with a 20 pixel overlap.
Again all the pieces will only differ in size by one pixel at the most! Though
in this case the resulting images are the same size, as the rose can divide by
2, equally. That however would not be the case if the overlap or the image was
an odd number in size. In that case the bigger element will be along the top
and left edge. With three tiles however the bigger (or smaller) element will
be placed in the middle!
You can even use a negative overlap to 'skip' exactly that many pixels between
tiles! Exactly how you should apply the operator depends on exactly what
pixels you want to 'overlap', or 'skip'. And that depends on the 'edge'
characteristics of the image (see Separating
Spaced-out Tiling Images below).
As with any use of the "-crop
" operator, it is recommended you use a "+repage
to remove the 'page'
offset if it is not wanted. But the cropped image offset information can be
very useful, which is why it is preserved. You can for example use it to name
the output files, or find out the size and locations of the tiles that IM
calculated.
Note that equal sized tile cropping, is the only situation in which the
"-crop
" operator ignores
the actual virtual canvas of the image when figuring out what part of the
image is cropped. That is, the calculations for tile cropping is based on
real image size rather than virtual canvas size. Even so the final tile
offsets will still be relative to the original virtual canvas.
This crop option can also be used as an alternative to the Shave Operator for 'paged' images.
![]() ![]() |
Before IM version v6.6.1-0, equal-sized tile cropping for images with a virtual canvas offset was broken. |
Separating Spaced-out Tiling Images
Often you have an image that has fixed sized tiles which are separated by a fixed amount of space. The new '@
' flag crop operator will let
you more easily crop out those tiles, either including or skipping the
surrounding space.
The main problem however is that while the 'tile' images have a fixed amount
of space around them the amount of space around the edge is usually not so
fixed. This produces three basic styles of edge characteristics to a set of
'spaced' images. and each type need to be handled slightly differently.
Montaged Tiles
Here the original images were simply given a fixed sized border before being
appended together. The result is that you will always have an even number of
pixel spacing between tiles. More importantly the 'edge spacing' is exactly
half the spacing that was placed between the tiles.
This is in fact how the "montage
"
spaces the tiling 'cells', and it was using this command the example shown
image below was generated.
As the images were just simply tiled together you can use either a normal Tile Cropping (if you know the tile size), or use Equal Sized Cropping (if you know the number of
tiles), to separate the sub-images and the surrounding border.
There is basically no overlap between the tiles, and a simple Shave Operator, can then be used to remove that border from the resulting
tiles.
magick montage.gif -crop 5x1@ +repage +adjoin montage_%d.gif magick montage_?.gif -shave 3x3 montage-3_%d.gif |
![]() |
![]() |
![]() ![]() ![]() ![]() ![]() |
![]() |
![]() ![]() ![]() ![]() ![]() |
@
' and '!
' flags.
Note that the images on the edges of this sub-division are slightly shorter
than the images in the middle. This is why this special 'mode' of operation
is NOT the default, even though it is actually simpler than the previous
spaced-out tile category.
Also note that when using both '@
' and '!
' flags,
a single tile crop (vertically in this case) does not have any effect, as both
the top and the bottom of the tile are 'edges', and thus has no 'edge space'
to be removed.
Again by using a negative value for the overlap, you can tell IM not to
include the overlapping (spacing) area in the tile crop results.
![]() ![]() |
The '! ' character has special significance to some UNIX
shells, like "csh ", and must be escaped with a backslash,
even when placed inside quotes.
|
Adding/Removing Image Edges
Border, adding space around the image
Often you simply want to add a little working space around the edge of an image, but you don't want to need or depend on knowing the size of an image to do so. Now there are many ways to add extra space to an image, outside of direct space additions, including appending blank images or labels, composing 'Src
'
overlays, or even just positioning the
image on a larger canvas. But these methods usually need at least some
idea of how big the image you are working with actually is.
One of the simplest form of image space additions is "-border
" operation. The color of
the space added is "-bordercolor
" setting. Here is some straight forward examples..
magick rose: -bordercolor SkyBlue -border 10x10 border.gif magick rose: -border 15x6 border_default.gif magick rose: -bordercolor LimeGreen -border 10x0 border_sides.gif magick rose: -bordercolor Tomato -border 0x10 border_topbot.gif magick rose: -alpha set -bordercolor none -border 10 border_none.gif |
![[IM Output]](border.gif)
![[IM Output]](border_default.gif)
![[IM Output]](border_sides.gif)
![[IM Output]](border_topbot.gif)
![[IM Output]](border_none.gif)
none
", but for this to work as expected we needed to
ensure the image actually contained a 'matte' or 'alpha' channel.
Also note that is the vertical and horizontal border sizes are the same
you can omit the second number in the border, using just a single number.
![]() ![]() |
As shown above the default color used by the "-border " operator is a light
gray as it matches nicely the default grey page color of web pages on the
WWW.
|
|
![]() |
-border
" creates a new image of
the right size, then overlays the original source image over this new
background.
This is itself a very useful operation in ImageMagick, for setting the
background of transparent and semi-transparent images. That is, the seemingly
useless "-border 0
" operation is, in IM version 6, a very useful
one. For example...
Of course there are lots of other ways to Remove
Alpha Transparency.
![]() ![]() |
The fact that adding a border to images with transparency, also by default fills the transparent background of the image, has been the cause of some debate amongst IM users and the development team. A summary of this debate is given on Border, Frame and use of BorderColor. |
Border and Alpha Composition
The overlay of the image onto the bordercolor canvas is controlled by the "-compose
"
setting, which by default is set to 'Over
' alpha compositing. If it is set to come other
setting, the "-border
"
operation may produce unexpected results.
For example, here are some of the more interesting uses of "-compose
" with the "-border
" image operator, when
applied to an image containing some transparent areas.
The choice between using 'Over
' and 'Copy
'
essentially decides if you want to preserve the transparency in the image or
not.
For example, here is the same 'star' image with transparency, but this time the
border was added without destroying the images transparency.
|
![]() |
Src
' compose will add a
transparent border to an image (if it has an alpha channel), regardless of the
current "-bordercolor
" setting. Basically the background canvas "-border
" generated is ignored.
The 'Dst
' may not seem to be very
useful, but can be used to generate a canvas the same size (or a little
bigger) than the original image. The original image is only used to determine
the final size of the canvas. For more examples see Canvases Sized to an Existing Image.
For more information on the various "-compose
" methods see the Alpha Compositing Examples.
Border and Virtual Canvas
When "-border
" is
applied to an image containing a virtual canvas, it will still add the border
around the actual image on that virtual canvas, and NOT around the whole
canvas.
Note that the size of the virtual canvas was also increased by twice the
border thickness to accommodate the added border.
This of course means you can not simply add a Border to
a typical GIF animation directly, unless you want to actually identify the
individual sub-frames of the animation (for example see the script Animation Frame Montage which uses this as
an option to 'frame' the overlay images). If you want to add a border, you
should Coalesce the animation first to
remove any Frame Optimizations it may
have first.
Frame, adding a 3D-like border
The "-frame
" operator is
very similar to "-border
", and if you look at the first example image generated
below, you will find that it will produce exactly the same result, except it
used the "-mattecolor
"
rather than "-bordercolor
". Note "-bordercolor
" is still used
in the generation framed images, see below.
To use "-frame
" properly
you need to supply four arguments to the command, instead of just 2. The extra
arguments specify the width of the 'outside' and 'inside' bevels of the frame
being produced.
Here are some examples of using the "-frame
" operator with various settings.
magick rose: -frame 10x10 frame.gif magick rose: -frame 15x6+2+2 frame_wierd.gif magick rose: -mattecolor SkyBlue -frame 6x6+2+2 frame_blue.gif magick rose: -mattecolor Tomato -frame 10x10+5+5 frame_red.gif magick rose: -frame 10x10+10+0 frame_rasied.gif magick rose: -frame 10x10+6+0 frame_rasied_part.gif magick rose: -frame 10x10+0+6 frame_sunken_part.gif magick rose: -frame 10x10+0+10 frame_sunken.gif |
![[IM Output]](frame.gif)
![[IM Output]](frame_wierd.gif)
![[IM Output]](frame_blue.gif)
![[IM Output]](frame_red.gif)
![[IM Output]](frame_rasied.gif)
![[IM Output]](frame_rasied_part.gif)
![[IM Output]](frame_sunken_part.gif)
![[IM Output]](frame_sunken.gif)
magick rose: -frame 10x10+3+3 frame_normal.gif magick rose: -frame 3x3+3+0 -frame 7x7+3+0 frame_popped.gif magick rose: -frame 7x7+0+3 -frame 3x3+0+3 frame_pressed.gif magick rose: -frame 3x3+3+0 -frame 4x4 -frame 3x3+0+3 frame_inverted.gif |
![[IM Output]](frame_normal.gif)
![[IM Output]](frame_popped.gif)
![[IM Output]](frame_pressed.gif)
![[IM Output]](frame_inverted.gif)
![]() ![]() |
The default "-mattecolor " is a slightly darker gray than that of the default
setting of "-bordercolor ". This also allows it to match the default gray
color of web pages on the WWW (used by early browsers such as
"mosaic " and "netscape ". (See below)
|
![]() ![]() |
While "-frame " may
actually use the "-mattecolor " color, it also generates four more extra colors
from this base for use in drawing the frame. That is, five related colors
will likely be added to an image, not just one.
|
magick montage
"-like
framed image complete with text label.
|
![]() |
-mattecolor
" for the frame
"-frame
" and then
'underlay' an interesting pattern (such as a Fractal Plasma Canvas), to produce a
more colorful frame.
|
![]() |
Frame and Alpha Composition
Frame is closely related to the "-border
" operator. Not only is a frame drawn using the "-mattecolor
", but this
operator will also make use of the "-bordercolor
" setting to
define the background on which the frame is initially drawn.
Now for images which have no transparency, the "-bordercolor
" will not be
visible, as it is overlaid by the image itself. But for images that do
contain some transparent areas, the background color does become visible.
|
![]() |
-frame
"
acts as if you take your image and overlay it on a picture frame with a solid
color background. As such any part of your image that is transparent will be
replaced by the "-bordercolor
" which by default is a light grey color.
![]() ![]() |
The fact that adding a frame to images with transparency, also by default fills the transparent background of the image with the bordercolor has caused some debate amongst IM users and the Development team. A summary of this debate is given on Border, Frame and use of BorderColor. |
-bordercolor
" such as
'none
'.
|
![]() |
-compose
"
method called 'Copy
'.
|
![]() |
![]() ![]() |
The use of "-bordercolor" as the background image for both "-border " and "-frame " was added to IM with
version 6.1.4. Before this the background canvas generated consisted of a
black canvas onto which the border, or frame was drawn.
This use of black was especially bad for the "magick montage "
command which makes heavy usage of the internal "-frame " function in its internal
processing. (See Montage Background and
Transparency Handling)
|
-frame
" operator, like "-border
", also uses the "-compose
" setting to define how
the source image is overlaid onto the background frame.
The use of a "-compose
"
setting of 'Copy
' becomes very
important if you also want to use the "-bordercolor
" setting in
"magick montage
" frames. See Montage
Background and Transparency Handling for more details.
Frame and Virtual Canvas
As with Border and Virtual Canvas frame is also applied around the actual image on that virtual canvas, and NOT around the whole canvas.
|
![[IM Output]](paged.gif)

![[IM Output]](paged_framed.gif)
Shave, removing edges from an image
The reverse of the "-border
" or "-frame
" operators, is "-shave
", which if given the same arguments, will remove the space
added by these commands.
magick border.gif -shave 10x10 shave.gif magick border.gif -shave 10x0 shave_sides.gif magick border.gif -shave 0x20 shave_topbot.gif |
![[IM Output]](border.gif)

![[IM Output]](shave.gif)
![[IM Output]](shave_sides.gif)
![[IM Output]](shave_topbot.gif)
-chop
" operator instead. (See the Chop
Examples below).
As before all the operators "-border
", "-frame
", and "-shave
", only effect the real image on the virtual canvas
and not the virtual canvas itself.
|
![[IM Output]](paged.gif)

![[IM Output]](paged_border.gif)

![[IM Output]](paged_frame.gif)

![[IM Output]](paged_shave.gif)
-shave
it will
not modify the canvas size of the resulting image.
![]() ![]() |
Before IM version v6.6.1-0, equal-sized tile cropping for images with a canvas offset (such as the above) was broken. |
Extent, Direct Image Size Adjustment
After some discussions, an operator to directly adjust the final size of an image size was added to IM version 6.2.4. The "-extent
" operator.
If the image size increases, space will be added to right or bottom edges of
the image. If it decreases the image data is just junked or cropped to fit
the new image size. In both cases the top left area of the image will likely
remain unaffected.
magick rose: -background skyblue -extent 100x60 extent_enlarge.gif magick rose: -background skyblue -extent 40x40 extent_shrink.gif magick rose: -background skyblue -extent 100x40 extent_wider.gif magick rose: -background skyblue -extent 40x60 extent_taller.gif |
![[IM Output]](extent_enlarge.gif)
![[IM Output]](extent_shrink.gif)
![[IM Output]](extent_wider.gif)
![[IM Output]](extent_taller.gif)
-background
" color of any new
areas added to the image.
![]() ![]() |
Before IM version v6.3.2, "-extent " just cleared the memory of any new areas to zero, or
straight black. It did not fill the areas with "-background " color.
|
-extent
" will use the "-gravity
" to define where the areas added/removed are positioned
relative to the original image.
magick rose: -gravity north -extent 100x80 extent_north.gif magick rose: -gravity south -extent 100x80 extent_south.gif magick rose: -gravity east -extent 100x80 extent_east.gif magick rose: -gravity west -extent 100x80 extent_west.gif magick rose: -gravity center -extent 100x80 extent_center.gif magick rose: -gravity center -extent 40x80 extent_center2.gif |
![[IM Output]](extent_north.gif)
![[IM Output]](extent_south.gif)
![[IM Output]](extent_east.gif)
![[IM Output]](extent_west.gif)
![[IM Output]](extent_center.gif)
![[IM Output]](extent_center2.gif)
-repage
", though it does 'flatten' the image with the current
"-background
" color.
You can even use offsets, which basically means the Extent
Operator is simply a straight forward Crop with
background padded fill, regardless of position.
|
![]() |
-extent
"
works by using the same 'overlay' technique that both the Border and Frame operators uses. As such by
default using it with an image containing transparency will replace the
transparency with the current "-background
" color.
|
![]() |
-compose
" method, or set the
"-background
" color
to 'None
'.
Adding/Removing Rows, Columns and Edges
Splice, adding rows, columns and edges
The "-splice
" operator is
new to IM version 6, see Splice, example of
the creation of a new image operator.
It basically provides the much needed ability to add a row, column of space
into the middle or one edge of an image. The color for the space inserted
comes from the "-background
" color setting.
magick rose: -background blue -splice 20x10+40+30 splice.gif magick rose: -background blue -splice 20x0+40+0 splice_column.gif magick rose: -background blue -splice 0x10+0+30 splice_row.gif magick rose: -background blue -splice 20x10 splice_topleft.gif |
![[IM Output]](rose.gif)

![[IM Output]](splice.gif)
![[IM Output]](splice_column.gif)
![[IM Output]](splice_row.gif)
![[IM Output]](splice_topleft.gif)
![]() ![]() |
If the background color is not set, IM will attempt to determine this
value from the image itself. This means that for some images it may be
white (the normal default), on others it may black, or for the GIF format
it could be whatever background color was set to when that image
was saved.
What this basically means is that if you don't set "
-background ",
before using an operator that uses it. |
-splice
" operator is ideal for
adding space to just one edge of an image. Which edge is determined by using
the "-gravity
" option
and the splice geometry setting.
magick rose: -background blue -splice 0x10 splice_top.gif magick rose: -gravity south \ -background blue -splice 0x10 splice_bottom.gif magick rose: -background blue -splice 20x0 splice_left.gif magick rose: -gravity east \ -background blue -splice 20x0 splice_right.gif magick rose: -gravity southeast \ -background blue -splice 20x10 splice_botright.gif |
![[IM Output]](splice_top.gif)
![[IM Output]](splice_bottom.gif)
![[IM Output]](splice_left.gif)
![[IM Output]](splice_right.gif)
![[IM Output]](splice_botright.gif)
|
![]() |
Chop, removing rows, columns and edges
The natural inverse of "-splice
" is the much older "-chop
" operator. Given the same
argument as "-splice
"
and the same "-gravity
"
setting, "-chop
" will
restore the image to its original form.
magick splice.gif -chop 20x10+40+30 splice_chop.gif magick splice_chop.gif -chop 20x10+30+20 chop.gif magick chop.gif -background grey \ -splice 20x10+30+20 chop_splice.gif |
![[IM Output]](splice.gif)

![[IM Output]](splice_chop.gif)

![[IM Output]](chop.gif)

![[IM Output]](chop_splice.gif)
-splice
" and "-chop
" so as to 'clear' a row or
column (or both) from the middle of an image without using draws or overlays.
Chop is more commonly used to cut of a single edge from an image, using
gravity to select that edge. For example...
magick frame_red.gif -chop 0x10 chop_top.gif magick frame_red.gif -chop 10x0 chop_left.gif magick frame_red.gif -gravity East -chop 10x0 chop_right.gif magick frame_red.gif -gravity South -chop 0x10 chop_bottom.gif |
![[IM Output]](frame_red.gif)

![[IM Output]](chop_top.gif)
![[IM Output]](chop_left.gif)
![[IM Output]](chop_right.gif)
![[IM Output]](chop_bottom.gif)
-chop
" for removing a single edge, you can in fact use the more
universal "-crop
" operator
instead. This does not require the use of "-gravity
" to get the bottom or
right edges, however does require you to "+repage
" the canvas of the image
afterward.
magick frame_red.gif -crop +0+10 +repage crop_edge_top.gif magick frame_red.gif -crop +10+0 +repage crop_edge_left.gif magick frame_red.gif -crop -10+0 +repage crop_edge_right.gif magick frame_red.gif -crop +0-10 +repage crop_edge_bottom.gif |
![[IM Output]](frame_red.gif)

![[IM Output]](crop_edge_top.gif)
![[IM Output]](crop_edge_left.gif)
![[IM Output]](crop_edge_right.gif)
![[IM Output]](crop_edge_bottom.gif)
-crop
" is not given an image area to remove, it will default to the
size of the image canvas (not the actual image but the images virtual canvas).
This means you can (for simple images) remove image edges by just offsetting
the crop area being cut.
The method of using "-crop
" to 'chop' image edges, was discovered and published by Don
Sheythe, and after some discussion was deemed to be a 'feature'
of IM, and thus included here.
Advanced Cropping Techniques
Crop to a Given Aspect Ratio
You can crop images to fit a specific aspect ratio, but it is tricky and uses some DIY mathematical techniques. For example you can write a script to do the calculations and then do the Crop. Or in IM v6 you can so calaculations with the Distort Viewport, to extract the desired part of the image during a No-Op Distortion, as described in Centered Square Crop. However in ImageMagick version 7, you can now do mathematical calculations directly in commands like "-crop
" and "-extent
", thus by-passing the need miss-use "-distort
".
This is discussed in detail in the IM Developers Forum Crop to Aspect Ratio.
Trim, the 'Auto-Crop' Operator
The "-trim
" operator
is a very close relation to the highly versatile "-crop
" operator discussed above. However instead of supplying an argument, this
operator attempts to remove any borders or edges of an image which did does
not change in color or transparency. In other words it removes the 'boring'
bits surrounding an image.
![]() ![]() |
Note that in ImageMagick version 5 and before, an auto-crop operation was
achieved by using a '0x0 ' argument to the "-crop " operator. This is no
longer the case, as 'zero' size arguments in crop now denote 'infinite' or
'to the limit of the image size'.
As such a ' |
For example, here we take the IM logo, which we resize, and 'trim' or
'auto-crop' all the surrounding extra space in the logo.
-crop ", "-trim " will retain the
canvas size of the image. This means that the numerical arguments of the trim
can be extracted, to allow for further processing, or adjustment of the
of the image processing (see Trimming "Noisy" Images
for an example of doing this).
|
![]() |
However if you don't care about this information, just junk it by resetting the
page information of the image either using a "+repage " operator, or saving to a
format that does not save canvas information (such as the JPEG format). Here
we do both, to make it clear, that we are junking the canvas information.
|
![]() |
-trim
" operator sees
a minor color change, so it did not trim as close to the image as we would
have expected.
If the image is all one color, then "-trim
" will trim the image down to a minimal single pixel
transparent Missed Image. This is logical and
prevents more serious problems if the image was left as is.
Trimming with a Specific Color
One of the most worrisome problems with "-trim
", especially in automated image processing scripts, is that
trim can be a little unpredictable. It does not for example limit itself to
just a specific color, or even one color. As such you should easily trim much
more than you expect.
For example lets do a simple trim of a simple image of striped colors.
magick -size 32x32 xc:red xc:green xc:blue +append stripes.gif magick stripes.gif -trim +repage stripes_trimmed.gif |
![[IM Output]](stripes.gif)

![[IM Output]](stripes_trimmed.gif)
-trim
"
trimmed not just one color but two colors! In an automatic script, this can be
very bad and produce unexpected results.
If you know what color you want to trim from an image, then the better way is
to add a small one pixel wide "-border
" of that color to the image. Lets take
'red
' in this case.
magick stripes.gif -bordercolor red -border 1x1 \ -trim +repage stripes_trim_red.gif |
![[IM Output]](stripes.gif)

![[IM Output]](stripes_trim_red.gif)
-border
" like this also will change the canvas offset that
"-trim
" took great pains
to preserve.
As such if you look at the result without removing the virtual canvas
information you can see that image was shifted.
|
![]() |
border_widthx2
) and offset (subtract
border_width
)when trimming a specific color.
|
![]() |
-trim
" operation itself
preverved the image location correctly. It is as you can see a rather
un-wieldly adjustment.
Alternatively if you do not care about the canvas size (typical in a layered
image) you can use a far simplier Relative
Repage to only adjusted the image's position on the enlarged canvas.
|
![]() |
Trimming Just One Side of an Image
As you saw above "-trim
"
will trim as many sides as it can. Even going so far as removing two different
colors from different sides (or if very carefully arranged, four colours could
have been removed). This makes it a little more difficult when you want to
restrict the trimming to just one side.
To guarantee that we only trim one side we need to add some color stripes to
the other side to protect the other three sides.
Here is the process step-by-step for trimming just the 'left' or 'west' side
of the 'border' image we created previously. I used much thicker stripes than
is necessary so you can see them better in this example. Normally a single
pixel width is all that is needed.
magick border.gif -gravity East \ -background white -splice 5x0 \ -background black -splice 5x0 trim_protect.gif magick trim_protect.gif -trim +repage trim_oneside.gif magick trim_oneside.gif -gravity East -chop 5x0 trim_west.gif |
![[IM Output]](border.gif)

![[IM Output]](trim_protect.gif)

![[IM Output]](trim_oneside.gif)

![[IM Output]](trim_west.gif)
|
![]() |
-gravity
" settings used in the
previous example is not needed and the setting defaults to a
'North-West
' setting for images.
|
![]() |
Trimming with fuzzy color selection -- Low Quality JPEG Images
Because JPEG is 'lossy' the colors in the image is generally not a single color but slightly varying band of different colors. because of this "-trim
" will often fail for JPEG or
real world images.
FUTURE: Example of failure here
As such you need to tell ImageMagick that colors that are not-exactly the
same, but are reasonally close should be treated as being the same. Adding
a very small "-fuzz
"
setting will do this.
magick image.jpg -fuzz 1% -trim +repage image_fuzzy_trim.jpg |
-border
" operator. The border will of course always match the
color to be trimmed, so will always be removed by "-trim
".
FUTURE: Example of fuzzy border trim here
Trimming 'Noisy' Images -- Scanned Images
A similar problem is faced with scanned images, where scanners often produce small single pixel errors, caused by dust, dirt, slight variations in the scanner, or just electronic noise picked up by the reader. The pixels errors however this case is usually too big for a small fuzz factor to overcome, so different technique is needed to trim such images. The simplest solution, though often least practical is to take multiple scans of the same image, or multiple frames in a still sequence of video), then averaging the results to reduce the interference. However this will not remove dust specks on the scanner or help when only a single image or frame is available, making this method impractical in most cases. A practical solution is a two step one. With a copy of the image, process it in some way to de-emphasize single pixel errors, or scanner dust, while enhancing the effect of large blocks of highly contrasting colors. By then using "-trim
" on this
copy, and examining exactly what it did, you can then "-crop
" the original unmodified
image by the same amount.
Their number of methods of de-emphasizing single pixel errors. These include
"-blur
", "-median
", or even using Basic Morphology Operators to remove
specific details, such a text and thin lines.
This the 'blur' method gives two main controls:-
- The "
-blur
" sigma radius, or the "-median
" convolution radius, which determines the size of dust specks you want to ignore. Note that both these values can be a floating point number so you have a fine control over the amount of the blur applied. For more information on blurring see Blurring Images.- The second control is the "
-fuzz
" color factor that controls the amount of color change matched by the "-trim
" operator. That is, how close to the desired image you want the trim to get. - The "
![]() ![]() |
You may need to check the Virtual Pixel
setting to enure that you get the right 'edge effects' with the blur.
Alternatively you can add a wide border of the same background color to
image before blurring and adjusting the offset results appropriately.
This may be better for more accurate results from both "-blur " and "-trim " operators.
|
-trim
" had internally used
a "-crop
" argument of
'89x121+78+23
'. This is the actual size of the trimmed image,
and its offset on the virtual canvas, and presumably the location of the major
(single) object we are looking for within the image.
This can then be used on the original image, which has not been blurred.
|
![]() |
This can be done in a single line, using a little bit of extra 'UNIX shell
scripting', and some formating of the results of that first command.
-format " setting used to control
the output of "info: ".
|
![]() |
![]() ![]() |
The above uses an UNIX command line shell feature for 'command-substitution'
method using back-quotes '`...` ' to insert the generated
"-crop " argument into
the outer "magick " command.
You can do this in a Windows Batch Script,
using a special FOR..DO construct. Follow the above link for
details.
|
The method could be improved by expanding the area trimmed by a small amount
(10 pixels in 4 four directions), using some FX Escape to do the mathematics...
|
![]() |
In IMv7 (using the "magick " command) you can do it all in one
command, saving the calculated trim size in a setting for later use.
|
![]() |