ImageMagick v6 Examples --
Miscellaneous

Index
ImageMagick Examples Preface and Index
Interpolation (Inter-pixel Color Lookups)
Virtual Pixels (Missed-Image Color Lookups)
Random Spots of Solid Color
Annotate Argument Usage
Splice: Creating a New Image Operator
Border, Frame, and the use of BorderColor
Sequence & List Operator Testing

This page consists of examples which test various aspects of ImageMagick. But which do not properly fit into the discussions on the other example pages (at least not formally).

Also included on this page are some tables demonstrating the results of versions argument with specific IM operators. However other people have also done this, which unless I have something to add, I will not deal with further.

These external IM operator demonstrations and examples include...


Pixel Interpolation or Inter-pixel Color Lookup

The "-interpolate" setting is used when looking up a color in another image, but that 'lookup' falls between the pixels of the source image.

This is done in various image operations, such as the "-fx" (DIY Special Effects Operator), and "-distort" (Generalized Image Distortion Operator), as well as other related operators like the Circular Distortions.

Basically 'interpolation' tells IM how to interpret a Direct Color Lookup from an image, when the point does not exactly match a actual pixel in an image, but falls between the space between pixels.

For example if you look up the color at pixel location 3, 4 you should get the exact pixel color. But what should IM return if you looked up the color of an image at the point 3.23, 4.75? Should you get the pixel color at 3, 4 or 3, 5? or perhaps some a mix of the surrounding pixels colors, and if so how should the colors be merged together. The is exactly what Pixel Interpolation defines.

Quick Method Summary

'Nearest-Neighbour' and 'Integer', will just pick a single pixel color directly from the source image. This preserves original color values of the image but at a cost of aliasing effects, and a less smooth look to images.

'Bilinear' is clearly better than nearest neighbour, generating the color based on the four pixels surrounding the lookup point.

'Bicubic' is a bit better than 'Bilinear', generating the color based on 16 close by pixels colors, to produce a better 'color curve', but at a cost of smoothing any direct hits. However while edges are sharper, other artifacts and oscillations (“ringing”) are produced at these same edges.

In most cases 'Bilinear' interpolation is the best option and is the default method used by IM.

Bilinear

Here are some diagrams explaining how a bilinear interpolation is performed.
[IM Output]


  convert \( xc:red xc:blue +append \) \( xc:yellow xc:cyan +append \) \
          -append -size 100x100 xc: +insert  \
          -fx 'v.p{i/(w-1),j/(h-1)}'    interpolate_bilinear.jpg
[IM Output]


  convert \( xc:white xc:black +append \) \( xc:black xc:white +append \) \
          -append -size 100x100 xc: +insert  \
          -fx 'v.p{i/(w-1),j/(h-1)}'    interpolate_saddle.jpg
[IM Output]
This last image shows how a linear gradient is formed along the edges between the four known points, and then a second linear gradient is formed between those edges. That is the colors between the surrounding pixels is generated using a horizontal and vertical linear gradients. This inturn produces a curved gradient that if you look at it will see a 'saddle' like curved surface.

You can even use this method to more directly generate a 45 degree angled linear gradient, but requires you to specify the middle color for the diagonally opposite corners.

  convert \( xc:blue xc:navy +append \) \( xc:navy xc:black +append \) \
          -append -size 100x100 xc: +insert  \
          -fx 'v.p{i/(w-1),j/(h-1)}'    interpolate_45linear.jpg
[IM Output]

The most important aspect of this default interpolation method, is that the very center pixel of the image will always be an average of all four corner colors, with perfect linear gradients at the edges, and exact color matching at the corners.

Mesh

The "-interpolate" setting of 'Mesh' is a variation of the 'Bilinear' interpolation. Where as 'Bilinear' will produce a 3 dimensional curved surface, 'Mesh' was designed to split the inter-pixel area into two flat triangular surfaces.

The division of the area into two triangles is based on the diagonal with the two 'closest' corner colors.

For details of the 'Mesh' algorithm, see the paper Image Interpolation by Pixel-Level Data-Dependent Triangulation.

For example lets use the same set of corner colors we used above.

  convert \( xc:red xc:blue +append \) \( xc:yellow xc:cyan +append \) \
          -append -size 100x100 xc: +insert   -interpolate Mesh \
          -fx 'v.p{i/(w-1),j/(h-1)}'    interpolate_tri-mesh.jpg
[IM Output]

As you can see the 'Mesh' algorithm produced almost exactly the same set of color interpolations as 'Bilinear'.

However if we reverse the yellow and cyan colors..

  convert \( xc:red xc:blue +append \) \( xc:cyan xc:yellow +append \) \
          -append -size 100x100 xc: +insert   -interpolate Mesh \
          -fx 'v.p{i/(w-1),j/(h-1)}'    interpolate_tri-mesh2.jpg
[IM Output]

This time the 'Mesh' algorithm decided that the 'blue' and 'cyan' colors were the two closest corners, and created a linear gradient diagonally between these two corners. The rest of the colors then form a simple flat triangular gradient from this line to the other two corners.

This may seem like a unusual interpolation, but the method ensures that sharp borders, remain quite sharp, when color images are only slightly resized, rotated or sheared. In fact a Adaptive Resize operation ("-adaptive-resize") uses this fact for small image resizes to reduce excessive blurring of the result.

For example if we have a single 'white' corner, 'mesh' assumes that an edge has been found and adjusts the interpolated colors to highlight this edge.

  convert \( xc:black xc:black +append \) \( xc:white xc:black +append \) \
          -append -size 100x100 xc: +insert    -interpolate mesh \
          -fx 'v.p{i/(w-1),j/(h-1)}'    interpolate_tri-mesh3.jpg
[IM Output]

Of course if the colors produce reasonably consistent gradient the 'mesh' interpolation also produces a reasonably consistent gradient.

  convert \( xc:blue xc:navy +append \) \( xc:black xc:black +append \) \
          -append -size 100x100 xc: +insert    -interpolate mesh \
          -fx 'v.p{i/(w-1),j/(h-1)}'    interpolate_tri-mesh4.jpg
[IM Output]

As you can see the result quite a reasonable gradient, though if you look hard you can see the diagonal join of the two separate triangles. The change isn't as smooth as bi-linear (which isn't exactly smooth either), or bi-cubic (very smooth), but these do not try to preserve the sharp edges in resized or distorted images either.

Bicubic

The 'Bicubic' "-interpolate" setting, is more complex, in the determination of the colors between pixels. Basically it does not just look at the colors in the corners of the inter-pixel area, but goes further to look at the colors beyond those near-neighbour pixels.

Basically it fits a curve to the whole area involved, so as to determine the best overall color to use.

Here is a diagrams which probably explains the process better...
[IM Output]

And here is the interpolated colors for our standard four colors.

  convert \( xc:red xc:blue +append \) \( xc:yellow xc:cyan +append \) \
          -append -size 100x100 xc: +insert   -interpolate bicubic \
          -fx 'v.p{i/(w-1),j/(h-1)}'    interpolate_bicubic.jpg
[IM Output]

The above image may look very similar to a 'Bilinear' interpolation, however the result has smooth curve rather than straight lines to produce the interpolated color.

What this image does not show however is the effect of the other pixels surrounding our four near neighbours. For that we need to look at a slightly larger area. For this specific image these pixels are controls by the Virtual Pixel setting.

  convert \( xc:red xc:blue +append \) \( xc:yellow xc:cyan +append \) \
          -append -size 100x100 xc: +insert -interpolate bicubic \
          -virtual-pixel edge \
          -fx 'v.p{3*i/(w-1)-1, 3*j/(h-1)-1}' interpolate_bicubic_edge.jpg
  convert \( xc:red xc:blue +append \) \( xc:yellow xc:cyan +append \) \
          -append -size 100x100 xc: +insert -interpolate bicubic \
          -virtual-pixel white \
          -fx 'v.p{3*i/(w-1)-1, 3*j/(h-1)-1}' interpolate_bicubic_white.jpg
  convert \( xc:red xc:blue +append \) \( xc:yellow xc:cyan +append \) \
          -append -size 100x100 xc: +insert -interpolate bicubic \
          -virtual-pixel black \
          -fx 'v.p{3*i/(w-1)-1, 3*j/(h-1)-1}' interpolate_bicubic_black.jpg
[IM Output] [IM Output] [IM Output]

In a real image the effects of the Virtual Pixels usally only effects results near the very edges of the image. As this image is only 2 pixels wide, the above example is strongly effected. This is not typically a problem when using 'Bicubic' interpolation.

As you can see the curve is strongly influenced by the surrounding colors, resulting in either a very tight sharp color change, or a more blended color change as defined by the surrounding colors.

However you can aso see from 'white' background example above, that a strong change in the surrounding pixel colors, can produce a small areas of that colors inverse or negative. This is a 'ringing' effect and in a typical image is not often seen, and then only at very sharp edges. This effect can be reduced by using a different Color Space rather than RGB.

Spline

Before IM version 6.3.5-3, the "-interpolate" setting known as 'Bicubic' was renamed (after v6.3.5-3) 'Spline'. That was because the implemented algorithm for 'Bicubic' was incorrect.

Here is what 'Bicubic' would have generated in IM version before v6.3.5-3.

  convert \( xc:red xc:blue +append \) \( xc:yellow xc:cyan +append \) \
          -append -size 100x100 xc: +insert    -interpolate spline \
          -fx 'v.p{i/(w-1),j/(h-1)}'    interpolate_spline.jpg
[IM Output]

As you can see the colors in the very corners of the above 'Spline' interpolation are muted, as the interpolated surface does not actually go through the original color of those pixels.

Now this color surface is a 'Bicubic' interpolation, a technique which is also known as a piece-wise bicubic 'spline' curve. However this curve only approaches the original pixel colors in areas of strong color changes.

That is a interpolated lookup of an exact integer pixel position, will not return that actual pixels color, but a slight bluring of the color with the surounding pixels. this is often thought of as bad, which was why this interpolation method was replaced and renamed.

Like 'Bicubic' it is also effected by the surrounding pixels.

  convert \( xc:red xc:blue +append \) \( xc:yellow xc:cyan +append \) \
          -append -size 100x100 xc: +insert -interpolate spline \
          -virtual-pixel edge \
          -fx 'v.p{3*i/(w-1)-1, 3*j/(h-1)-1}' interpolate_spline_edge.jpg
  convert \( xc:red xc:blue +append \) \( xc:yellow xc:cyan +append \) \
          -append -size 100x100 xc: +insert -interpolate spline \
          -background white  -virtual-pixel background \
          -fx 'v.p{3*i/(w-1)-1, 3*j/(h-1)-1}' interpolate_spline_white.jpg
  convert \( xc:red xc:blue +append \) \( xc:yellow xc:cyan +append \) \
          -append -size 100x100 xc: +insert -interpolate spline \
          -background black -virtual-pixel background \
          -fx 'v.p{3*i/(w-1)-1, 3*j/(h-1)-1}' interpolate_spline_black.jpg
[IM Output] [IM Output] [IM Output]

In a real image the effects of the Virtual Pixels is only at the edges of the image. With real pixels surrounding the inter-pixel area from which the lookup is being made.

Here you can see the effects of the color muting that results from the badly fitting 'spline' curves to the pixel colors. The results is generally fuzzier edges to colored areas, and thin lines. However they also will never exhibit any 'ringing' that you may get with a 'Bicubic' interpolation.

Interpolation Background

As the effects of interpolation are often over larger areas, here is an enlargement of the four main interpolation methods with white or black surrounding pixels.

  for method in   bilinear mesh bicubic spline  ; do
    for vpixel in   white black  ; do
      convert \( xc:red xc:blue +append \) \( xc:yellow xc:cyan +append \) \
         -append -size 100x100 xc: +insert -interpolate $method \
         -virtual-pixel $vpixel \
         -fx 'v.p{3*i/(w-1)-1, 3*j/(h-1)-1}' ip_area_${method}_$vpixel.jpg
    done
  done
[IM Output] [IM Output]
Bilinear
[IM Output] [IM Output]
Mesh
[IM Output] [IM Output]
Bicubic
[IM Output] [IM Output]
Spline

As you can see the surrounding background color has no real effect for 'bilinear' interpolated colors. It looks like it is just overlaid onto whatever background color is present.

You can however see how 'mesh' can decide to use a different triangular division for a different colors 'neighbouring' pixels. This results in some of the interpolated squares being flipped, though only depending on the immediate pixel neighbourhood.

The interpolated curve for 'bicubic' and 'spline' is however strongly effected by the surrounding pixels. Particularly in the test cases involving absolute colors.

And finally 'spline' interpolation is really just a blurred form of 'bicubic'. Just enough blurring to eliminate the 'ringing' color that was generated in the center of the 'bicubic' interpolation.

Interpolation of a Rotated Line

Here I demonstrate the various interpolation methods by creating an image of a vertical line, and using a affine distortion to rotate the line by 17 degrees, then enlarging the view so you can see the anti-aliasing pixels generated.

  convert -size 10x20 xc: -draw 'line 4,0 4,20' \
          -scale 50x100 ip_line_none.gif
  for method in   integer nearestneighbor bilinear mesh bicubic spline;  do
    convert -size 10x20 xc: -draw 'line 5,0 5,20' \
            -interpolate $method -filter point -distort SRT 17 \
            -scale 50x100 ip_line_${method}.gif
  done
[IM Output]
Un-Rotated
==> [IM Output]
Integer
[IM Output]
Nearest
Neighbor
[IM Output]
Bilinear
[IM Output]
Mesh
[IM Output]
Bicubic
[IM Output]
Spline

As you can see the direct color lookup methods 'Interger' and 'NearestNeighbor' produce a highly aliased result. On the other hand 'Bilinear' and 'Mesh' generally produce very good and simular results (more on that later). The 'Bicubic' and 'Spline' are actually the same interpolation method, however 'Spline' produces a distinct blurring of thin lines.

The special setting "filter point" is used to ensure that "-distort" only uses interpolation in determining the final pixel color. Without it "-distort" wold use a Area Resampling method instead of Interpolated Lookup.

Note that I did not use the "-rotate" operator for these examples, as that operator uses a Pixel Shearing method to Rotate Images. As a result pixel interpolation is not used.

See Rotating a Thin Line for an example of using the -rotate" operator in this way, and the resulting pixel level effects.

Interpolation of a Rotated Edge

The results have a slight difference when the edge of an area is beting distorted, compared to that of a single line of pixels.

  convert -size 10x20 xc: -draw 'rectangle 0,0 4,19' \
          -scale 50x100 ip_edge_none.gif
  for method in  integer nearestneighbor bilinear mesh bicubic spline; do
    convert -size 10x20 xc: -draw 'rectangle 0,0 4,19' \
            -interpolate $method -filter point  -distort SRT -17 \
            -scale 50x100 ip_edge_${method}.gif
  done
[IM Output]
Un-Rotated
==> [IM Output]
Integer
[IM Output]
Nearest
Neighbor
[IM Output]
Bilinear
[IM Output]
Mesh
[IM Output]
Bicubic
[IM Output]
Spline

The above generally speaks for itself. 'Bilinear' and 'Mesh' produce reasonably sharp edges for general rotates, while 'Bicubic' will produce sharper edges in images which are enlarged by a distortion. 'Spline' however will produce fuzzier edges.

The difference between 'Bilinear' and 'Mesh' is extremely minor in the above cases. The two methods only really generate visible differences in cases of extreme enlargement during the distortion operation. Otherwise you will only see slight barely noticeable changes in pixel intensity.


Virtual Pixels Missed-Image Color Lookup

Many operators, especially Convolution Operators, such as "-blur" as well as General Distortion Operator, like the general DIY operator "-fx", often need to look-up colors which fall outside the boundaries of the image proper.

For example what color should you look-up if you ask for a pixel at -21,-3? Such a pixel does not actually exist as it is outside the images bounds, but the result can have far reaching effects on the overall effect of the operator, especially in the areas near the edge.

The "-virtual-pixel" setting defines what IM should return when accessing a pixel outside the normal bounds of the image.

[IM Output] In the following examples we use "-fx" to 'lookup' all the pixels in and surrounding a small image so we can see what the various "-virtual-pixel" settings return.

To start with this this is the default action...

  convert -size 70x70 xc:  tree.gif \
                  -fx 'v.p[-19,-19]'  virtual_default.gif
[IM Output]

'Edge' "-virtual-pixel" setting is the default setting, so the following should be the same as the previous example. However I'll use a fast image distortion with viewport, so we can see the hidden 'virtual pixels' that surrounds the image.

  convert tree.gif  -set option:distort:viewport 70x70-19-19 \
          -virtual-pixel Edge   -distort SRT 0  virtual_edge.gif
[IM Output]

Basically the closest pixel on the edge of the image to what was requested is returned.

This setting generally has the most minimal impact (in edge effects) when processing images. This is especially important when using Blur, or other Convolution type operators.

It is important to note how the color of the corner pixel is used to completely fill the diagonally adjacent areas. This can result in the corners having a larger effect on various image transformations.

'Tile' VP setting is very useful for wrapping effects across the boundaries of the image.

  convert tree.gif  -set option:distort:viewport 70x70-19-19 \
          -virtual-pixel Tile   -distort SRT 0  +repage virtual_tile.gif
[IM Output]

This lets you ensure that images being transformed remain 'tileable'. For further examples see Modifying Tile Images.

'Mirror' is very similar to 'tile' and may be better for some effects that the default 'edge'.

  convert tree.gif  -set option:distort:viewport 70x70-19-19 \
          -virtual-pixel Mirror   -distort SRT 0  +repage virtual_mirror.gif
[IM Output]

Note that up until IM v6.5.0-1 only the images directly attached to the original image was mirrored. Thi was fixed so the whole virtual canvas space is correctly mirror tiled.

'Transparent' just returns the transparent color for pixels outside the real image bounds.

  convert tree.gif  -matte -set option:distort:viewport 70x70-19-19 \
          -virtual-pixel Transparent   -distort SRT 0  +repage virtual_trans.gif
[IM Output]

The "-matte" operator in the above is required to ensure the image has a matte or alpha channel for the transparent color to fill in correctly. For more information see Controlling Image Transparency.

Without this things the above could return a 'black' color instead of transparent, as the color 'none' or 'fully-transparent black' is the default transparent color. For example...

  convert tree.gif  +matte  -set option:distort:viewport 70x70-19-19 \
          -virtual-pixel Transparent  -distort SRT 0  +repage virtual_trans2.gif
[IM Output]

The 'black', 'white', and 'gray', settings are simular to the previous 'Transparent' setting above. They just return that specific color for any pixel that falls out of bounds.

  convert tree.gif  -set option:distort:viewport 70x70-19-19 \
          -virtual-pixel Black   -distort SRT 0   +repage virtual_black.gif
[IM Output]

  convert tree.gif  -set option:distort:viewport 70x70-19-19 \
          -virtual-pixel Gray   -distort SRT 0   +repage virtual_gray.gif
[IM Output]

  convert tree.gif  -set option:distort:viewport 70x70-19-19 \
          -virtual-pixel White   -distort SRT 0   +repage virtual_white.gif
[IM Output]

If you want any other simple color , then you must define that color in the "-background" setting, and use a 'Background' "-virtual-pixel" setting.

  convert tree.gif  -set option:distort:viewport 70x70-19-19 \
          -virtual-pixel Background  -background coral \
          -distort SRT 0     +repage virtual_bgnd.gif
[IM Output]

The depreciated 'Constant' setting is just an alias for 'background', and should not be used.


'HorizontalTile' VP setting was added to IM v6.4.2-6 as a special form of tiling that is useful for full 360 degree "Arc" and "Polar" distortions. The image is only tiled horizontally, while the virtual pixels above and below the tiles are set from the current "-background" color.

  convert tree.gif  -set option:distort:viewport 70x70-19-19 \
          -virtual-pixel HorizontalTile  -background coral \
          -distort SRT 0     +repage virtual_horizontal.gif
[IM Output]

This lets you ensure that images being transformed remain 'tileable'. For further examples see Modifying Tile Images.

The 'HorizontalTileEdge' (added in IM v6.5.0-1) also tiles the image horizontally across the virtual space, but replicates the side edge pixels across the other parts of the virtual canvas space.

  convert tree.gif  -set option:distort:viewport 70x70-19-19 \
          -virtual-pixel HorizontalTileEdge  -background coral \
          -distort SRT 0     +repage virtual_horizontal_edge.gif
[IM Output]

These two VP methods were added for better handling of full circle 'Arc' and 'Polar' distortions where the en-circled image 'wraps around' and joins together end to end.


Simularly the 'VerticalTile' VP setting (also added IM v6.4.2-6) as a tiles the image vertially only, with the current "-background" color used to fill in the sides of the image.

  convert tree.gif  -set option:distort:viewport 70x70-19-19 \
          -virtual-pixel VerticalTile  -background coral \
          -distort SRT 0     +repage virtual_vertical.gif
[IM Output]

The 'VerticalTileEdge' was added in IM v6.5.0-1, and replicates the side edge pixels across the rest of the virtual canvas space.

  convert tree.gif  -set option:distort:viewport 70x70-19-19 \
          -virtual-pixel VerticalTileEdge  -background coral \
          -distort SRT 0     +repage virtual_vertical_edge.gif
[IM Output]

Also as IM v6.5.0-1 'CheckerTile' was added which only tiles the as if filling in one set of colored squares of a checkerboard. The other squares will be simply filled with the background color.

  convert tree.gif  -set option:distort:viewport 70x70-19-19 \
          -virtual-pixel CheckerTile  -background coral \
          -distort SRT 0     +repage virtual_checker.gif
[IM Output]

By making background transparent and overlaying that image over a another fully-tiled image same size you can layer the two tilings to produce an interleaved checkerboard pattern of the two images.

  convert -size 96x96 tile:balloon.gif \
          \( tree.gif -matte  -set option:distort:viewport 96x96 \
             -virtual-pixel CheckerTile  -background none \
             -distort SRT 0 \) \
          -flatten  virtual_checker_2.gif
[IM Output]


There also a couple of more unusual "-virtual-pixel" settings.

'random', just picks a random pixel from the image to use. With "-blur" this lets you use a rough average image color in the resulting edge effects it produces.

  convert tree.gif  -set option:distort:viewport 70x70-19-19 \
          -virtual-pixel Random   -distort SRT 0  +repage virtual_random.gif
[IM Output]

Note that the pixel value is not consistant, and will produce a different effect for each lookup. So a specific pixel location will contribute a different value to associated pixel a convolvution it is involved with.

Basically this works on the principle that the color pixels returned will be merged together producing a average color. That however does not always happen.

'dither' however returns a ordered dithered pattern of colors basied on pixels within 32x32 pixels of the requested position.

That means that once you have progressed beyond 32 pixels from the image, the result will be again just the corner pixel color of the image. It is a bit like 'edge' but involving more pixels, and covering just a bit more area.

To show this we need to show the image on a larger virtual canvas.

  convert tree.gif  -set option:distort:viewport 120x120-44-44 \
          -virtual-pixel Dither   -distort SRT 0  +repage virtual_dither.gif
[IM Output]

In the above you can see that the yellow from the sun in one corner of this 32x32 pixel image manages to be selected all the way up the far lower-right corner, but no further. That is the limit of the 32 pixel 'neighbourhood' for the ordered dither color selection. If this image was larger, the yellow sun color would not reach the other corners.

Basically 'dither' is a more orderly form of 'random' close into the image, but once you process further than 32 pixels from the image proper, it becomes more like 'edge'.


Virtual Pixel and Infinities

You can see the effects of "-virtual-pixel" much more clearly in the results the General Distotion Operator, and especally with a Perspective distortion, allowing you to create a distorted view lookup out toward an infinite distance.

For example here I show the results of a "-virtual-pixel dither" settings, on a perspective view of the tree. This shows how this setting can effect the pixels returned all the way out to infinity.

  convert tree.gif -mattecolor DodgerBlue   -virtual-pixel dither \
          -set option:distort:viewport  150x100-50-50 \
          -distort perspective '0,0 9,0  31,0 38,0  0,31 0,18  31,31, 40,18' \
          perspective_dither.gif
[IM Output]

Try the above with other "-virtual-pixel" settings to get a better idea of how they work. Some other examples can also be seen in Viewing Distant Horizons.

Note that the 'sky' in the above view is actually generated by the "-mattecolor" invalid distortion color, and not generated from the "-virtual-pixel" setting.

Virtual Pixel Colors

None of the "-virtual-pixel" methods actually return a different or composite color to what is already present within the image, unless that color was specifically requested via one of the solid color methods: 'background', 'transparent', 'background', 'black', 'white', 'gray'; That is no new colors are ever generated, though one specific color could be added (two for the general Distortion Operator).

Of course if the requested pixels are being Pixel Interpolated, or Area Resampled, such as in the perspective distorted view above, then those methods may merge the colors returned according ot the "-virtual-pixel" setting chossen.

Virtual Pixel Effects on Operators

Here I explore the effects of the effects of "-virtual-pixel" setting with various operators.

"-blur"...

  convert -size 70x70 xc:lightblue  -fill black -draw 'circle 35,65 25,55' \
          -virtual-pixel edge   -blur 0x8     vp_blur.png
[IM Output]


    convert -size 70x70 xc:lightblue  -fill black -draw 'circle 35,65 25,55' \
            -virtual-pixel mirror  -blur 0x8  vp_blur_2.png
[IM Output]

Note in the following how the image can be cross contaminated using "-blur" with the "-virtual-pixel" setting of 'tile'. Of course if the image was tilable to start with this may be desired.

  convert -size 70x70 xc:lightblue  -fill black -draw 'circle 35,65 25,55' \
          -virtual-pixel tile  -blur 0x8  vp_blur_3.png
[IM Output]

Setting a specific color for the "-virtual-pixel" in the image has some very interesting effects and posibilities.

  convert -size 70x70 xc:lightblue  -fill black -draw 'circle 35,65 25,55' \
          -virtual-pixel background  -background blue \
          -blur 0x8     vp_blur_4.png
[IM Output]


  convert -size 70x70 xc:lightblue  -fill black -draw 'circle 35,65 25,55' \
          -virtual-pixel transparent  -channel RGBA  -blur 0x8 \
          -background red  -flatten       vp_blur_5.png
[IM Output]

Note how the 'red' background I placed behind the image is visible around the edges where the resulting blurred image has become semi-transparent.

"-gaussian" has the same basic results as "-blur"...

  convert -size 70x70 xc:lightblue  -fill black -draw 'circle 35,65 25,55' \
          -virtual-pixel background   -background blue \
          -gaussian 0x8     vp_gaussian.png
[IM Output]

"-radial-blur", however produces more interesting border effects...

  convert -size 70x70 xc:lightblue \
     -virtual-pixel background  -background blue \
     -radial-blur 0x30    vp_radial.png
[IM Output]

This last with the default 'transparent edge' will probably generate a smooth edge, when used with larger radial blur angles. It may produce a cleaner 'vignette' or soft edging overlay image, than other techniques.

"-motion-blur" can be badly effected by edge effects.
It is made worse by the fact that "-motion-blur" does not current understand the use of "-channel" for limited its effects to specific channels.


  convert -size 70x70 xc:none  -virtual-pixel edge \
     -fill yellow  -stroke red  -strokewidth 3 -draw 'circle 45,55 35,45' \
     -channel RGBA -motion-blur 0x12+65  vp_motion.png
[IM Output]


  convert -size 70x70 xc:none  -virtual-pixel transparent  \
     -fill yellow  -stroke red  -strokewidth 3  -draw 'circle 45,55 35,45' \
     -channel RGBA -motion-blur 0x12+65  vp_motion_2.png
[IM Output]


  convert -size 70x70 xc:none  -virtual-pixel background -background blue \
     -fill yellow  -stroke red  -strokewidth 3  -draw 'circle 45,55 35,45' \
     -channel RGBA -motion-blur 0x12+65  vp_motion_3.png
[IM Output]

Implosion Effects of Virtual Pixels

Here are some more interesting examples of various large value implosions using various "-virtual-pixel" settings.

  for v in edge tile mirror dither random gray; do
    for i in 2 5 10 50 500; do \
      convert koala.gif -virtual-pixel $v \
              -implode $i  implode_${v}_${i}.gif
    done
  done
Implode EdgeTileMirror DitherRandomGray
2 [IM Output] [IM Output] [IM Output] [IM Output] [IM Output] [IM Output]
5 [IM Output] [IM Output] [IM Output] [IM Output] [IM Output] [IM Output]
10 [IM Output] [IM Output] [IM Output] [IM Output] [IM Output] [IM Output]
50 [IM Output] [IM Output] [IM Output] [IM Output] [IM Output] [IM Output]
500 [IM Output] [IM Output] [IM Output] [IM Output] [IM Output] [IM Output]

The 'dotty' nature of the above results is a direct result of the direct 'interpolated sampling' used by the "-implode" operator. See Direct Interpolated Lookup. This may change in a future version of IM, using Area Resampling. For now you will need to use a Super Sampling technique to improve results.

The 'edge' setting is the more usual and default setting that is use, to avoid most of the weird effects. The others (exept for 'background' essentually produce a replicated pattern from the existing pixels in the image, and effects are highly variable.

Also note how the argument requires a expotential increase in size for simular increases in effects.

Also for arguments larger than about 200 a black circle may appear in the center of the resulting image. This is caused by the computers mathematical limit being reached. Using such large values is an effect we do not recommend you use.


Random Spots of Solid Color

By blurring a "plasma:fractal" canvas, then reducing the colors to very low values you can produce simple images containing random areas of different colors. However the results are highly variable depending on the final number of colors requested and the Virtual Pixel setting (see above).

I had two choices for the initial random image in this experiment. A Fractal Plasma Image, and a Random Noise Image.

The Random Image will by its nature produce a image which can (with a 'tile "-virtual-pixel" setting) create a better tilable image. Where as the Plasma Image tends to create rectangular like edges to its spots of color.

On the other hand the Plasma Image produces fairly nice pastel colored spots, or blobs. While the Random Image tends to produce horrible shades of mid-tone gray. because of this I chose to use the Plasma Image for these experiments.


  convert -size 80x80 plasma:fractal -normalize   spot_start.gif
  #convert -size 80x80 xc: +noise Random  \
  #        -virtual-pixel tile  -blur 0x5  -normalize  spot_start.gif

  for n in 2 3 4 5; do
    for v in  edge mirror tile white black; do
      convert spot_start.gif -virtual-pixel $v -blur 0x10 \
              +dither -colors $n  spot${n}_${v}.gif
    done
  done
Num Colors EdgeMirrorTileWhiteBlack
2 [IM Output] [IM Output] [IM Output] [IM Output] [IM Output]
3 [IM Output] [IM Output] [IM Output] [IM Output] [IM Output]
4 [IM Output] [IM Output] [IM Output] [IM Output] [IM Output]
5 [IM Output] [IM Output] [IM Output] [IM Output] [IM Output]

The first three images has very specific effects on how the color 'spots' interact with the edges of the image. 'Edge' and 'Mirror' tends to cause the colors to join the edges at 90 degree angles.

A 'Random' or 'Dither' setting has simular but stronger attachments of the color blobs to the edges of the image, though both also introduces some sharp edge effects close to the image edges. A second blur-quantize cycle may be needed to clean up and smooth the edges of the spots.

The 'Tile' setting tends to allow the spots to wrap around the image. However as the source Plasma image is not itself tilable, the result is a general color change near the rectangular edge. If the tilable Random image was used as the source, then the spots of colors would completely disregard the borders of the image.

By using a 'White' or 'Black' background virtual-pixel setting, the spots of color tend to be centered in the image proper. How well this 'centering' occurs depends on just how different original random image was relative to the 'background color' used.

The size of the "-blur" basically effects the size and smoothness of the blobs. A small blur producing lots of small spots, a large blur, such as we used in the above, producing a single more circular spot of color.


You can also produce a completely different set of colors and interactions by using a different color quantization color space. For example here I repeat the last example (reducing to 5 colors) from above but use some more unusal "-quantize" color spaces for color selection. (See Color Quantization and ColorSpace)
Color Space EdgeMirrorTileWhiteBlack
RGB [IM Output] [IM Output] [IM Output] [IM Output] [IM Output]
YIQ [IM Output] [IM Output] [IM Output] [IM Output] [IM Output]
HSL [IM Output] [IM Output] [IM Output] [IM Output] [IM Output]
XYZ [IM Output] [IM Output] [IM Output] [IM Output] [IM Output]
OHTA [IM Output] [IM Output] [IM Output] [IM Output] [IM Output]

Remember all the above images were all generated from the same randomized source image. The different effects you see are the results of different ways reducing the number of colors in the image.

You can see how the "-virtual-pixel" setting defining what pixel colors blur sees the areas beyond the image bounds has a strong influence on shapes of the color areas.


Annotate Argument Usage

IM Version 6 provided a new command line option for text drawing "-annotate" which bypasses the older "-draw" method to use the Annotate() API directly. This provides some new features to command line users.

For this example I choose Arial Black font, for its straight lettering so that the rotation should be quite clear.

    convert -font ArialB -pointsize 24 -gravity center \
            -size 55x55 xc:white -annotate 0x0+0+0 'Text' \
            annotate_source.jpg
[IM Output]

The format of this option is...
  -annotate {SlewX}x{SlewY}+{X}+{Y} 'Text String' 
The X and Y offset of the above is the gravity effected position of the annotated text that is to be drawn.

However the SlewX and SlewY represents a form of rotation. If both of these values are the same then a normal rotation is performed. But if they differ, some very interesting effects can result..

[IM Output]

As you can see some of the arguments resulted in no text being drawn, basically when the text would have been drawn all in a single line. This is to be expected.

However you can see that we can draw the text flipped, flopped, rotated, italicized, in all manner of ways. A most useful image operator.


Splice: Creating a New Image Operator

Just after the first release of ImageMagick version 6, a discussion developed in response to a question on the ImageMagick Mailing List. The question involved adding extra space (rows and columns) into the middle of an image.

The example below is the complex set of commands that resulted from this discussion, using the heavy magic of IM version 6, and detailed exactly what should be done.

From this example the "-splice" operator was created (for details see examples in Splicing and Chopping Rows and Columns into Images). As such this command line is the defining operations of this new command, and both should work in exactly the same way.


  convert rose:  -size 20x10 xc:blue   -background blue \
          \( -clone 0  -crop 40x0 +repage +clone -insert 1 +append \) \
          -swap 0,-1 +delete \
          \( -clone 0  -crop 0x30 +repage +clone -insert 1 -append \) \
          -delete 0 -delete 0    splice_rose_seq.gif
[IM Output]

In the above we split up the rose into lots of vertical slices, then insert a spacing image into that sequence, before appending them all together again. Basically we added a vertical column of pixels into the rose image.

Then replacing our original image with the modified one, we repeated the same operations, but horizontally. A little clean up of working images and we are done.

This example also highlighted to the mailing list the usefulness of the new ordered command line handling and the image sequence operations of version 6 ImageMagick. In older releases of IM, this would have required a large number of separate commands and temporary images to achieve the same result.


Border, Frame, and the use of BorderColor

Their is a continuing raging debate, that "-bordercolor" should only be used to only add border to images with the "-border" or "-frame". That is may users think it should not be used to set the background behind images with transparency.

For example, under IM this sets the transparent areas of the star image to the "-bordercolor" and completely ignores the "-background" color setting.

  convert star.gif -bordercolor LimeGreen   -background Gold \
                   -border 10       star_border.gif
[IM Output]

The main reason "-bordercolor" is used to set the background of transparenent images is because this makes "montage" come out in a nice way when given a random set of images which could contain transparencies, with minimal settings from the user.

    montage star.gif  -frame 6  -geometry '64x64+5+5>' star_montage.gif
[IM Output]

If the transparency was preserved then the "montage" results above would not look nearly as good.

That does not mean that you can't preserve the transparency of images when using "-border" or "-frame" operators. It just means you need to supply a extra "-compose" setting to tell IM to preserve the transparency.

  convert star.gif  -bordercolor LimeGreen \
          -compose Copy  -border 10   star_border_copy.gif
  montage star.gif  -bordercolor LimeGreen \
          -compose Copy -background None    -frame 6 \
          -geometry '64x64+3+3>'   star_montage_copy.gif
[IM Output]
[IM Output]

For more information on preserving a images transparent background, while adding a "-border" or "-frame", see adding borders. and for "montage", see montage background and transparency handling examples.

One alturnative that has been suggested was to set image area background in these operators to the "-background" color, but this will interfer with its use in "montage".

You can of course always flatten the image yourself, before any extra frame or border is added. In that case the use of "-compose Copy" becomes irrelevent.

  montage star.gif -background Gold -flatten \
          -frame 6  -geometry '64x64+5+5>' -size 16x16 \
          -bordercolor LimeGreen  -background SeaGreen \
          star_montage_texture.gif
[IM Output]

It is just a lot easier to use a "-compose" setting, to preserve the transparency, rather that have border preserve it and cause other problems. It may not be obvious to new users, but then that is what these example pages are all about.


Sequence & List Operator Testing

All the following commands should produce exactly the same image, but all images are produced in slightly different ways, demonstrating the new, IM version 6, Image Sequence Operators.


  convert eye.gif news.gif  storm.gif  +append  list_test_01.gif
[IM Output]

  convert \( \) eye.gif news.gif  storm.gif  +append  list_test_02.gif
[IM Output]

  convert eye.gif news.gif  storm.gif \( \) +append  list_test_03.gif
[IM Output]

  convert \( eye.gif news.gif  storm.gif \) +append  list_test_04.gif
[IM Output]

  convert \( eye.gif news.gif  storm.gif  +append \) list_test_05.gif
[IM Output]

  convert eye.gif \( news.gif storm.gif +append \) +append list_test_06.gif
[IM Output]

  convert \( eye.gif news.gif +append \) storm.gif +append  list_test_07.gif
[IM Output]

  convert \( storm.gif -flop \) \( news.gif -flop \) \( eye.gif -flop \) \
          +append -flop  list_test_08.gif
[IM Output]

  convert \( eye.gif -rotate 90 \) \( news.gif  -rotate 90 \) \
          \( storm.gif -rotate 90 \) -append  -rotate -90   list_test_09.gif
[IM Output]

  convert eye.gif tree.gif news.gif storm.gif   -delete 1 \
          +append list_test_10.gif
[IM Output]

  convert eye.gif tree.gif news.gif storm.gif  -delete -3 \
          +append list_test_11.gif
[IM Output]

  convert eye.gif news.gif storm.gif tree.gif   +delete \
          +append list_test_12.gif
[IM Output]

  convert news.gif storm.gif eye.gif  -insert 0  +append list_test_13.gif
[IM Output]

  convert eye.gif storm.gif news.gif  -insert 1  +append list_test_14.gif
[IM Output]

  convert storm.gif news.gif eye.gif   -swap 0,-1  +append list_test_15.gif
[IM Output]

  convert eye.gif storm.gif news.gif   +swap  +append list_test_16.gif
[IM Output]

  convert eye.gif storm.gif news.gif   \( -clone 1 \) \
          -delete 1   +append list_test_17.gif
[IM Output]

  convert eye.gif -negate \( +clone -negate \) news.gif  storm.gif \
          -delete 0   +append list_test_18.gif
[IM Output]

  convert storm.gif news.gif eye.gif \( -clone 2,1,0 \) \
          -delete 2,1,0   +append  list_test_19.gif
[IM Output]

  convert storm.gif news.gif eye.gif \( -clone 2-0 \) \
          -delete 0-2   +append  list_test_20.gif
[IM Output]

  convert {balloon,medical,present,shading}.gif  -delete 0--1 \
          {eye,news,storm}.gif   +append  list_test_21.gif
[IM Output]

  convert balloon.gif -delete 0,0,0,0,0,0,0,0,0 \
          eye.gif news.gif  storm.gif  +append  list_test_22.gif
[IM Output]

  convert {balloon,medical,present,shading}.gif {eye,news,storm}.gif \
          -delete 0--4   +append   list_test_23.gif
[IM Output]

  convert eye.gif news.gif storm.gif \
          -delete 0--4   +append   list_test_24.gif
[IM Output]

  convert storm.gif news.gif eye.gif -reverse +append  list_test_25.gif
[IM Output]


Created: 6 November 2004
Updated: 13 March 2008
Author: Anthony Thyssen, <A.Thyssen@griffith.edu.au>
Examples Generated with: [version image]
URL: http://www.imagemagick.org/Usage/misc/

a