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
- 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
|
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.
|
-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 |
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 |
-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
|
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..
|
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.
|
|
|
|
-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
|
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.
|
-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 TilesHere 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 |
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 |
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 |
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.
|
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 |
-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.
|
-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 |
-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 |
-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 |
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 |
|
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 |
-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 |
-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 |
-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 |
-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 |
-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 |
|
-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 hereAs 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.
|