- Index
ImageMagick Examples Preface and Index
Solid Color Canvases
(for image manipulations)
Gradients of Colors
(canvases of smooth color changes)
Randomized Canvases
(for randomized background images)
Tiled Canvases
(canvases using a repeating images)
Canvases are used by ImageMagick both as a starting image for drawing on,
backgrounds to overlay images with transparent areas, or even just as part of
general image processing. They can be a solid color, or a range of colors,
or even a tile of a smaller image. Here we look at some of the more common
methods of generating a canvas image.
Solid Color Canvases
Direct Generation
Generating a canvas of a specific color and size is very simple to do, and is
used all the time...
convert -size 100x100 xc:khaki canvas_khaki.gif
|
|
|
If you have already created a canvas, but need one in a different color you
can replace that color using the "-opaque" operator.
convert canvas_khaki.gif -fill tomato -opaque khaki canvas_opaque.gif
| |
|
You can even grab a single pixel from an existing image, and expand it to the
canvas size you want. We use "
-scale" for a simple and fast resizing of the single pixel.
Here we grab a rose color from the built-in "rose:" image.
convert rose: -crop 1x1+40+30 +repage -scale 100x100 canvas_pick.gif
| |
|
Create Image of same size
One most basic techniques when using ImageMagick is to generate a canvas the
same size as some existing image. This can be done by converting that
existing image into the canvas need, but preserving the images original size.
Naturally IM provides a large number of ways to do this, usually as a side
effect of other image operations. But only one method currently stands out
from the rest and is obvious in its intent.
|
We will need a test image... Don't worry above how I actually generated this
image, it is not important for the exercise. I did design it to contain a
range of colors, transparencies and other features, specifically to give IM a
good workout when used.
If you are really interested in the commands used to generate this image
you can look at the special script, "generate_test", I use to create it.
|
|
Overlay a Specific Color
The general way of creating a canvas the same size as an existing image is to
use "-draw" to
reset all the colors in the current image to the current "-fill" color.
convert test.png -fill Sienna -draw 'color 0,0 reset' color_reset.gif
|
|
|
This has the advantage that any meta-data the image may contain (such as
comments or profiles) is also preserved.
Another way is to use "-colorize" to overlay the fill color but with a fully opaque
value. However this will preserve the original images alpha channel, unless
you remove it first, using "+matte".
convert test.png +matte -fill Peru -colorize 100% color_colorize.gif
|
|
|
This is probably the best method for images without transparency.
Other methods are more complex as it involves using special
Alpha Composition to force various operators to
replace the image with the desired color. This technique only works with
image operators that use "
-compose", to replace the existing image, with the desired color.
Or you can use "-border"
(See Adding a Border), using the "-bordercolor" as the color
source.
convert test.png -bordercolor Wheat \
-compose Dst -border 0 color_border.gif
|
|
|
This last method has the added advantage of also letting you slight enlarge
the image canvas, which makes it doubly useful.
  |
The "-border" method
of generating canvases will not work with versions of IM before version
6.1.4. Before this the background generated by the "-border" operator was not a
simple solid color, but a black canvas surounded by the border color. Not
very useful.
|
A more flexible method of canvas generation was provided with the new IM
version 6 "-fx" operator.
You will also need to use the "+matte" operator to turn off the input images matte channel as by
default "-fx" will not
handle that channel.
convert test.png +matte -fx Gold color_fx_constant.gif
|
|
|
The "-fx" operator will even
let you do a little color mathematics. For example how about a dark gold
color...
convert test.png +matte -fx "Gold*.7" color_fx_math.gif
|
|
|
All the above methods can not only fill using a fully-opaque color, but can
also use semi-transparent colors. However it is a good idea to ensure the
image you are using has a matte channel using the "
-matte" operator before hand.
Here for example we create a canvas that a semi-transparent red. However
when overlaid on the web pages 'bluish' background we get a off purple color.
convert test.png -matte -fill '#FF000040' -draw 'color 0,0 reset' \
color_semitrans.png
|
|
|
Also for the "
-fx" operator
you will need to set "
-channel" to use all four '
RGBA' color channels.
Using an Extracted Color
But what if you also don't know exactly what color you need. For example you
want to pick a color already used in the source image.
No problem, we can use the 'pick a color from image' technique we used above
to generate a tile image (Pick a single pixel using "
-crop", then expanded it to a
reasonable tile size using "
-sample".
The trickiness with this method, is to use the special "
mpr:"
(Magick Program Register) to save the image in a named memory source. The
"
-tile" image reader can
then read the image from that source. This tile can then be tiled over the
canvas using "
-draw"
command to reset all pixels to this tile pattern.
convert test.png -crop 1x1+100+75 +repage -scale 32x32 \
-write mpr:tile +delete -tile mpr:tile \
test.png -draw 'color 0,0 reset' color_tiled.gif
|
(More details of this can be see in Tiled Canvases
section of this page)
|
|
Another way is to just create a canvas that is large enough to overlay your
image completely. This however can be very very slow, especially for very
large images. You also need to figure out just how big to make your overlay
image, which can be a tricky matter in itself!
Lets grab the red pixel from the image this time.
convert test.png -crop 1x1+50+75 +repage -scale 200x200 \
test.png +swap -compose copy -composite color_compose.gif
|
|
|
|
|
Rather than actually extracting the pixel from the image, you can just
reference that pixel, and copy it using the new "
-fx" operator.
Just for something different lets pick a light grey semi-transparent pixel
from the image to copy. Of course we need to tell this operation to not only
copy the RGB values but also the alpha or matte transparency of the image.
convert test.png -channel RGBA -fx 'p{40,10}' color_fx_image.png
|
|
|
The color doesn't need to come from the same image, but from any image in the
current image sequence (all images of which are replaced in the operation).
Here we picked a bluish colored pixel from the built-in "rose:"
image.
convert test.png rose: \
-channel RGBA -fx 'v.p{12,26}' color_fx_pick.gif
|
|
|
Of course with the "
-fx"
operator you can further modify the color, using straight mathematics, merging
other colors, or color sources, or just about anything you like.
This technique of using colors from a separate image, can be taken a step
further to recolor images based on a range of colors supplied by the separate
image (EG: an indexed color image table). See
Color Lookup Tables for details.
Other Canvas Techniques
Their lots of other ways of generating canvases of very specific colors, but
they are rather obtuse. As such without some heavy commenting, it may not be
obvious which you are doing when you look at your IM script months or years
later.
I don't recommend these techniques, but are useful to know if you are using
older less flexible versions of IM.
Black Canvas
Traditionally you can create a black canvas by using "-threshold", and then turn off
the matte channel.
convert test.png -threshold 100% +matte black_threshold.png
|
|
|
The new "-fx" operator
provides a more obvious way of creating a black canvas by clearing all the
pixels to zero. However you will also need to reset the matte channel to make
it fully opaque.
convert test.png -fx 0 +matte black_fx.png
|
|
|
However the "-evaluate"
version of this should be faster, particularly on larger images.
convert test.png -evaluate set 0 +matte black_evaluate.png
|
|
|
A less obvious way is to 'posterize' the image will too few color levels,
resulting in only one color being used, black.
convert test.png -posterize 1 black_posterize.png
|
|
|
White Canvas
The traditional way is again using "-threshold". The value however must be a negative number, just to
be sure that all colors will be mapped to white, in all versions of IM.
convert test.png -threshold -1 +matte white_threshold.png
|
|
|
You can of course set the pixel values directly using the "-fx" operator.
convert test.png -fx 1 +matte white_fx.png
|
|
|
However the "-evaluate"
version of this should be faster, particularly on larger images.
convert test.png -evaluate set 100% +matte white_evaluate.png
|
|
|
Or negate some other black canvas generation method.
convert test.png -posterize 1 -negate white_posterize.png
|
|
|
Transparent Canvas
Probably the most important canvas you want to generate from a existing image
is a transparent canvas.
Here we make a fully-transparent black canvas using "-compose
Clear" with any overlay image (a single pixel "null:" in
this case).
convert test.png null: -compose Clear -composite trans_compose.png
|
|
|
The more important transparent canvases is when you only want to clear the
alpha or matte channel, but preserve the original RGB colors existing in the
image.
Here we use the "-draw matte" operator to replace the matte
channel value with that of the "-fill" color setting. In this case transparent.
convert test.png -fill none -draw 'matte 0,0 reset' color_matte.png
|
|
|
We can also to this more directly with the "-fx" operator.
convert test.png -channel A -fx 0 trans_fx.png
|
|
|
Naturally the "-evaluate"
version of this should be faster, particularly on larger images.
convert test.png -channel A -evaluate set 0 trans_evaluate.png
|
|
|
Another way to just make the image fully transparent is to use "-threshold" but again
limiting its effects.
convert test.png -channel A -threshold -1 trans_threshold.png
|
|
|
Actually in this case we are mathematically dealing with a 'matte' channel,
using threshold to set it to the maximum value, rather than zero, as we did
with the "
-fx" operator.
This is why a '
-1' was used in the above, rather than
100%'. (See
Channels and Masks
examples page.)
The original RGB colors are still present in the last set of images above.
That is the original colors of the image are still present, they have just
been made transparent.
For example, here we read in one of the above images and ask IM to turn off
the matte/alpha channel in the image so as to make the colors visible again.
convert trans_fx.png +matte trans_fx_matte.jpg
|
Note however that not all image formats, and very few image operation will
preserve the not fully-transparent RGB colors that are still present in the
image.
|
|
As mentioned before, and worth repeating, many of the above methods rely on an
image already having a matte channel. If it doesn't, add one using the
"
-matte" image operator.
If the image did not have a matte (or alpha) channel, then this operator will
also ensure the generated channel is set to fully opaque.
Gradients of Color
As you saw above you can create canvases of solid colors easy enough. But
sometimes you want something more interesting. And ImageMagick provides a
large number of special image creation operators that will let you do this.
The full list of these creation operators are listed on the
ImageMagick formats.
It is difficult however to find all the good image generators available in IM
as they are all mixed up with the specific image file formats. And then
not all the options and capabilities are detailed. I will try to rectify
that.
One of the most common image creation operators is gradient. For example...
convert -size 100x100 gradient: gradient.jpg
|
|
|
As you can see by default "
gradient:" will create an image with
white at the top, and black at the bottom, and a smooth shading of grey across
the height of the image.
But it does not have to be only a grey-scale gradient, you can also generate
a gradient of different colors by either specifying one color, or both.
convert -size 100x100 gradient:blue gradient_range1.jpg
convert -size 100x100 gradient:yellow gradient_range2.jpg
convert -size 100x100 gradient:green-yellow gradient_range3.jpg
convert -size 100x100 gradient:red-blue gradient_range4.jpg
convert -size 100x100 gradient:tomato-steelblue gradient_range5.jpg
convert -size 100x100 gradient:black-none gradient_trans.png
|
Notice that when given a single color the second color will be either
'
white' or '
black', which ever produces the largest
color distance from the given color. As such '
blue' produces a
'
blue-white' gradient, while '
yellow' generated a
'
yellow-black' gradient.
  |
Gradients can not currently be specified at other angles or involving
more than two colors. However as this ability is in integral part of SVG
gradients, this situation will likely change, with a major improvement in
gradient options.
|
  |
"gradient:" currently does not make use of the "-colorspace" setting.
They are generated only in RGB space, so multi-color 'rainbow' gradients
(using HSV space) are not possible.
|
Some particularly nice gradients include...
convert -size 10x120 gradient:snow-navy gradient_ice-sea.jpg
convert -size 10x120 gradient:gold-firebrick gradient_burnished.jpg
convert -size 10x120 gradient:yellow-limegreen gradient_grassland.jpg
convert -size 10x120 gradient:khaki-tomato gradient_sunset.jpg
convert -size 10x120 gradient:darkcyan-snow gradient_snow_scape.jpg
| |
|
As of IM v6.2.9-8 the "gradient:" image creation operator
understands the use of transparent and semi-transparent colors.
convert -size 100x100 gradient:firebrick-none gradient_transparent.png
| |
|
Of course as I used semi-transparent pixels in this gradient, I needed to use
the PNG image format, rather than JPEG.
  |
Before IM v6.2.9-8 you would have to resort to using a greyscale gradient
as an alpha channel mask to a solid color image, to produce the same
effect. See 'CopyOpacity' composition method, and Using Masks with Images for such
techniques.
|
  |
As of IM v6.3.1 the algorithm used to generate gradients now produce a
perfect gradients, with all the pixels of each row in the image being
assigned the same color.
Before this version the "gradient:" operator worked by
ignoring the width of the image, and just assigning the next increment of
color, going row-by-row from top-left corner to the bottom-right of the
image. This gradient generation method, allowed you easilly create a one
pixel high horizontal gradient. That of course is no longer the case, and
all examples of this usage has been removed from IM examples to avoid
confusion.
The result in these older versions was a vertical gradient, just as it is
now, but not a perfect one. Usally this fact was only important in
special case such as test images, and image distortion maps.
|
Gradients in other Colorspaces
While gradient currently can not generate gradients in directly in another
Color Spaces, (only RGB gradients can be
created) you can transfer gradients into a different color space to generate
interesting effects. For example a linear gradient copied into the 'Hue' of a
'
HSB' image can produce a rainbow gradient.
convert -size 30x600 xc:'#0F0' -colorspace HSB \
gradient: -compose CopyRed -composite \
-colorspace RGB -rotate 90 gradient_rainbow.jpg
|
Also see
Combining Channel Images for an
explaination, as well as an example of creating
Color Wheel image.
Distorted Gradients
Rotated Gradient
Now you don't have to restrict yourself to just a vertical gradient. By
increasing the size of the gradient image (multiply by the square root of 2 or
1.42), then rotate it 45 degrees, and crop the image to its final size, you
can make a diagonal gradient.
convert -size 142x142 gradient: -rotate -45 \
-gravity center -crop 100x100+0+0 +repage \
gradient_diagonal.jpg
| |
|
This actually should become much simplier in a future version of IM, as
generating gradients at any angle and in a user defined style is part of
SVG -- Scaleable Vector Graphics
requirements, which IM is working to include.
All the above gradients are linear. That is the colors follow a smooth
straight line across the RGB color space, between only two colors. But that
is not the only sort of gradient you can generate.
Warped Gradient
The gradient can also be twisted up...
convert -size 100x100 gradient: -swirl 180 gradient_swirl.jpg
| |
|
You can also wrap the gradient into a circle using the
General Distortion operator...
convert -size 100x100 gradient: -distort Arc '180 0 50 0' \
gradient_circled.jpg
| |
|
Histogram Adjusted Gradient
You can create a non-linear gradient by applying some form of histogram
adjustment to a linear gradient.
For example you can use a
Sigmoidal
Contrast function to create a more natural looking gradient.
convert -size 100x100 gradient: -sigmoidal-contrast 6,50% \
gradient_sigmodial.jpg
| |
|
This type of gradient is especially good for generating photo overlaps, using
Composite Mask.
(FUTURE: link to an photo
overlay examples, yet to be created)
Resized Gradient
One trick that was brought up on the
ImageMagick Mailing
List by Glenn Randers-Pehrson, was to create a very small image, two
pixels across, then expand that to the image size needed using "
-resize".
The "
-resize" operator
trys to smooth out enlarged images, to make them look better at the larger
scale. It is this smoothing that we use to generate a non-linear gradient.
For example here we generate the small image using a 'portable bitmap' (or
PBM format) image and feed it into IM for enlargement.
echo "P1 1 2 0 1 " | \
convert - -resize 100x100\! gradient_resize.jpg
|
|
|
  |
Some shells like 'csh' and variants, can not handle the '!'
character in the above resize geometry setting very well -- not even in
quotes. Hence the backslash '\' character may be needed.
Caution is advised.
|
The gradient produced is not linear, with a smooth start and finish to the
colors given, making those colors much more pronounced, than you would get
using a normal gradient.
A simple way to generate that initial two pixel image is actually with
gradient itself! This lets you specify the colors directly. Of course that
will limit you to a vertical gradient, unless you rotate the result as well.
convert -size 1x2 gradient:khaki-tomato \
-resize 100x100\! gradient_resize2.jpg
|
|
|
Of course you are not limited to just a single dimension, with this technique.
Here I use a four pixel 'portible greymap' (or PGM image format) to generate a
2-dimensional gradient.
echo "P2 2 2 2 2 1 1 0 " | \
convert - -resize 100x100\! gradient_resize3.jpg
|
|
|
As you can see this diagonal gradient is not very linear when compared to
the rotated diagonal gradient above.
  |
The Network Portible Bitmap
image formats, are very versitile for generating images from scripts.
They can generate bitmaps (P1), greymaps (P2), and pixmaps (P3), in both
ASCII (see above) and binary (P4,P5,P6) formats. Also the quality, or
color range used in each image is completely controlable, allowing you to
use any number range you like to specify the images (see above).
ASIDE: I was the one to make the 1995 release of NetPBM, so I have
experience using this format in script image generators I have created in
the past.
|
The "-resize" operator
smooths the color between these pixels according to the current "-filter" setting. By adjusting that
parameter (see Resize Filter), you
can make the resize gradient more edge to edge in effect.
convert -size 1x2 gradient: \
-filter Cubic -resize 100x100\! gradient_resize4.jpg
|
|
|
Here is rough "Rainbow Gradient" created using the 'resize' technique.
convert xc:black xc:red xc:yellow xc:green1 xc:cyan xc:blue xc:black \
+append -filter Cubic -resize 600x30\! gradient_rs_rainbow.jpg
|
Interpolated Lookup Gradients
Another method of generating gradients is to use the special "
-interpolation" setting, when
using a "
-fx" operator. This
setting is used to determine the pixel color returned when the pixel lookup is
not a integer, and thus falls between two or four different pixel values.
The default setting of '
bilinear' for example will linearly
determine the color for a lookup that falls between two pixels.
convert -size 600x30 xc: \( +size xc:gold xc:firebrick +append \) \
-fx 'v.p{i/(w-1),0}' gradient_interpolated.jpg
|
Here the lookup X position '
i/(w-1)' goes from '
0.0'
to '
1.0' over the second two pixel image. The floating point
number produces a perfect linear gradient.
Interpolated lookup gradients can also be expanded to 2 dimensions, and
generate square linear gradients, just as easily as purely one dimensions
gradients. Here are examples of the default '
bilinear' "
-interpolate" setting.
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)}' gradient_bilinear.jpg
| |
|
Of course this is the same result as using the '
Triangle'
"
-filter" shown above for
Resized Gradients above, but a LOT slower.
The '
mesh' "
-interpolate" setting however is not available as a
Resize Filters. It is a special
2 dimensional interpolation that divides with intra-pixel area into
two flat linear triangles, hinged along the diagonal connecting the corners
with the minimal color difference.
By making the two diagonal corners the same color, you end up with two joined
diagonal gradients.
convert \( xc:red xc:gold +append \) \( xc:gold xc:green +append \) \
-append -size 100x100 xc: +insert -interpolate mesh \
-fx 'v.p{i/(w-1),j/(h-1)}' gradient_mesh.gif
| |
|
As the two diagonally opposite yellow corners are the same, a diagonal of
yellow was used to join them. With the other colors linearly mapped to those
triangles.
For more information on the "
-interpolate" setting see
Interpolation Setting.
Roll your own gradient
New to ImageMagick version 6 is the "
-fx" operator. This operator lets you define your own gradients
or other image generation, based on the current pixel position.
As this operator requires an image to work with, you can generate your
gradients or other images to match that image. That is you don't have to know
the size of the image to generate a gradient for it!
For example you can easily generate a linear gradient, sized correctly for
the image you may be working on.
convert rose: -fx 'i/w' gradient_fx_linear.gif
| |
|
You can even generate some neat non-linear gradients.
convert rose: -fx '(i/w)^4' gradient_fx_x4.gif
| |
|
convert rose: -fx 'cos(pi*(i/w-.5))' gradient_fx_cos.gif
| |
|
How about a 2-dimensional circular radial gradient.
convert -size 100x100 xc: \
-fx 'rr=hypot(i/w-.5, j/h-.5); 1-rr*1.42' \
gradient_fx_radial.gif
| |
|
  |
The "-fx" function
'rr=hypot(xx,yy)' was added to IM v6.3.6 to speed up the very
commonly used expression 'rr=sqrt(xx*xx+yy*yy)' It also meant
that we no longer need to make extra assignments such as
'xx=i/w-.5' when creating a radial gradient.
|
Note how I use some assignment expressions to simplify the calculation of the
distance from center of the image, then convert it to a gradient. This
feature was added in IM v6.3.0.
The value '
1.42' (or
sqrt(2)) in the above controls
the overall size of the gradient relative to the images dimensions. In this
can the diagonal distance to the corner.
You can even remove the 'sqrt()' (built into the
'hypot()' function) from the expression to make a more
interesting spherical gradient, which can be useful for 3D Shading Effects.
convert -size 100x100 xc: \
-fx 'xx=i/w-.5; yy=j/h-.5; rr=xx*xx+yy*yy; 1-rr*4' \
gradient_fx_spherical.gif
| |
|
Using a high power function, you can give photos a fade off effect around the
rectangular edges of the image. Adjust the power value '4' to
control the amount of fading.
convert -size 100x100 xc: \
-fx '(1-(2*i/w-1)^4)*(1-(2*j/h-1)^4)' \
gradient_fx_quad2.gif
| |
|
Here is a angular gradient, whcih is interesting in itself.
convert -size 100x100 xc: \
-fx 'aa=atan2( j-h/2+.5, i-w/2+.5 )/pi/2; aa>0 ? aa : aa+1' \
gradient_fx_angular.gif
| |
|
Note that the '
atan2()' function returns a angle in radians from
-PI to +PI (see its manpage), so its output needs to be be scaled and
translated to correctly fit a 0.0 to 1.0 color range. This is why the above
looks so much more complex than it really is.
This last example can be generated faster by
Warping
a linear gradient using the
generalized
Distortion Operator. For an example see the
Color Wheel Example.
More Complex DIY Gradients
Of course an FX function can generate color gradients. For example here is a
gradient basied on distance ratios, using an extremely complex FX expression.
convert -size 100x100 xc: +size xc:red xc:yellow \
-fx 'ar=hypot( i/w-.8, j/h-.3 )*4;
br=hypot( i/w-.3, j/h-.7 )*4;
u[1]*br/(ar+br) + u[2]*ar/(ar+br)' \
gradient_dist_ratio.gif
| |
|
And this is a three point triangular gradient using the same distance average
method.
convert -size 100x100 xc: +size xc:red xc:blue xc:green1 \
-fx 'ar=hypot( i/w-.5, j/h-.1 );
br=hypot( i/w-.1, j/h-.7 );
cr=hypot( i/w-.9, j/h-.9 );
zz=br*cr+ar*cr+ar*br;
u[1]*br*cr/zz + u[2]*ar*cr/zz + u[3]*ar*br/zz' \
gradient_triangular.gif
| |
|
The above however is not what I was actually after, as it produces too much
of an averaged color result, between the colored points. Can anyone help me
fix it?
Randomized Canvases
Plasma Gradients
While gradients provide a smooth range of colors, another image creation
operator "
plasma:" provides a different sort of gradient. One
that is ideally suited to generating a random backdrop of color for your
images.
First of all I should point out that "
plasma:" is a randomized
image. As such it can and will produce a different image every time it is run.
For example here we generate three separate 'standard' plasma images, and each
image is different from each other, even though the same command was used to
generate them.
convert -size 100x100 plasma: plasma1.jpg
convert -size 100x100 plasma: plasma2.jpg
convert -size 100x100 plasma: plasma3.jpg
|
You can also see that plasma images are also a type of randomized gradient
of colors, and like "
gradient:" started with white at the top and
black at the bottom.
What isn't well document is that you can specify color for the plasma gradient
in the exact same way as you can for linear gradients above.
convert -size 100x100 plasma:blue plasma_range1.jpg
convert -size 100x100 plasma:yellow plasma_range2.jpg
convert -size 100x100 plasma:green-yellow plasma_range3.jpg
convert -size 100x100 plasma:red-blue plasma_range4.jpg
convert -size 100x100 plasma:tomato-steelblue plasma_range5.jpg
|
You can also see that a mid-tone colors like '
tomato' and
'
steelblue', tend to work better than pure colors like
'
red' and '
blue'. That is because contain at least
some colors from all three color channels, allowing the plasma image operator
more scope in the colors generated.
By using the same color twice with plasma you can produce a background that is
predominantly that color, but with a random splotches of colors close to that
of the original color.
convert -size 100x100 plasma:black-black plasma_black.jpg
convert -size 100x100 plasma:grey-grey plasma_grey.jpg
convert -size 100x100 plasma:white-white plasma_white.jpg
convert -size 100x100 plasma:yellow-yellow plasma_yellow.jpg
convert -size 100x100 plasma:tomato-tomato plasma_tomato.jpg
convert -size 100x100 plasma:steelblue-steelblue plasma_steelblue.jpg
|
Again as you can see, mid-tone colors will generate more varieties of color in
the resulting image, than a extreme color, like black, white, or yellow.
The '
grey' plasma in the above is particularly nice giving a
iridescent 'mother-of-pearl' like effect, basically as grey has total freedom
in the colors that the "
plasma:" will generate.
Normalizing a prefect 50% grey plasma will produce a particularly uniform
multi-color plasma image, over the full range of colors, including white and
black.
convert -size 100x100 plasma:grey50-grey50 -normalize plasma_grey_norm.jpg
| |
|
Alternatively you can just spread the contrast of the colors to just make
them bolder, but without going to extremes.
convert -size 100x100 plasma:grey50-grey50 \
-sigmoidal-contrast 8x50% plasma_grey_contrast.jpg
| |
|
Compare this image with the 'fractal plasma' images below.
Fractal Plasma
The plasma generator also has a special fractal mode, producing highly
colorful effects. The color generated are enhanced to produce more
exaggerated color changes.
convert -size 100x100 plasma:fractal plasma_fractal1.jpg
convert -size 100x100 plasma:fractal plasma_fractal2.jpg
convert -size 100x100 plasma:fractal plasma_fractal3.jpg
|
Also like the constant color plasma's above they are more uniform across the
whole image.
Plasma in general I often find a little 'noisy'. As such it will often benefit
from a little smoothing using "
-blur".
Here I have have smoothed out the noise from the middle plasma image above.
convert plasma_fractal2.jpg -blur 0x2 plasma_smooth.jpg
| |
|
You can use "-paint" to
create random blotches of color.
convert plasma_fractal2.jpg -blur 0x1 -paint 8 plasma_paint.jpg
| |
|
Or make the colors more pronounced and circular using the "-emboss" image operator, after
using "-blur" to remove
the low level noise.
convert plasma_fractal2.jpg -blur 0x5 -emboss 2 plasma_emboss.jpg
| |
|
Reversing the "-blur" by
using "-sharpen" can
produce a more pastel color pattern.
convert plasma_fractal2.jpg -blur 0x5 -sharpen 0x15 plasma_sharp.jpg
| |
|
I actually find generating a swirled plasma gradient to be particularly nice,
as a background pattern.
convert -size 160x140 plasma:fractal \
-blur 0x1 -swirl 180 -shave 20x20 plasma_swirl.jpg
| |
|
Greyscale Plasma
Now the plasma generator will always generate color, even on a pure black
solid color. However it is often useful to generate a pure grey-scale plasma.
Well there are two simple ways of doing this.
The simplest way is to take the plasma image and converted it to grey scale.
convert -size 100x100 plasma:fractal -blur 0x2 \
-colorspace Gray plasma_greyscale.jpg
| |
|
Another way is to copy one of the color channel over the other two, for a
stronger, single layer, effect.
convert -size 100x100 plasma:fractal -blur 0x2 \
-channel G -separate plasma_grey_copy.jpg
| |
|
A final technique is to use "-shade" on the plasma.
convert -size 100x100 plasma:fractal -blur 0x5 \
-shade 120x45 -normalize plasma_grey_shade.jpg
| |
|
You'd probably think you would get a lot of light and shadow effects, but the
raw plasma is so random, that "
-shade" only seems to produce a more 'mottled plasma' effect.
Instead of using a fractal plasma, with its highly exaggerated color changes,
you can create a grey-scale plasma using the constant color plasma method. As
a side effect, this method also allows you to control the overall brightness
of the grey-scale plasma image generated.
convert -size 100x100 plasma:black-black \
-blur 0x2 -colorspace Gray plasma_grey0.jpg
convert -size 100x100 plasma:grey25-grey25 \
-blur 0x2 -colorspace Gray plasma_grey1.jpg
convert -size 100x100 plasma:grey50-grey50 \
-blur 0x2 -colorspace Gray plasma_grey2.jpg
convert -size 100x100 plasma:grey75-grey75 \
-blur 0x2 -colorspace Gray plasma_grey3.jpg
convert -size 100x100 plasma:white-white \
-blur 0x2 -colorspace Gray plasma_grey4.jpg
|
If this is not quite bold enough, use the channel copy method of grey-scaling
the plasma image.
convert -size 100x100 plasma:black-black \
-blur 0x2 -channel G -separate plasma_grey5.jpg
convert -size 100x100 plasma:grey25-grey25 \
-blur 0x2 -channel G -separate plasma_grey6.jpg
convert -size 100x100 plasma:grey50-grey50 \
-blur 0x2 -channel G -separate plasma_grey7.jpg
convert -size 100x100 plasma:grey75-grey75 \
-blur 0x2 -channel G -separate plasma_grey8.jpg
convert -size 100x100 plasma:white-white \
-blur 0x2 -channel G -separate plasma_grey9.jpg
|
These grey-scale plasma images are very useful for further processing,
allowing you to generate other image effects.
For example, look at the page on
Background
Images for a huge number of examples where the plasma fractal was used
to produce lots of interesting effects.
Seeding or Repeating a Plasma Image
Remember "
plasma:" can produce areas of near pure black or pure
white, or any other color (though it isn't likely to be pure). And while it
is unlikely you will get a image that is all in one color, it is also a
possible outcome. So when you get a good result you may like to save it, for
later re-use.
Because of this, scripts using plasma images, may like to include options to
generate and re-use such randomized images. That is you may like to separate
the plasma image generation from other parts that use that image, to allow
re-use.
A simplier technique however is to 'seed' or initialize the IM random number
generator so that 'plasma:' will generate the same 'randomized'
image. That way you can tune a script or program to produce a good or
interesting coloration or effect, over and over.
convert -size 100x100 -seed 4321 plasma: plasma_seeded.jpg
| |
|
The above image will never change, so unless I change the "
-seed" number I will always have a
'red' area in the bottom-right corner.
Interestingly using the same seed with different initializing color gradients
can produce a set of images which while random, are simular in their internal
pattern.
convert -size 100x100 -seed 4321 plasma:grey-grey plasma_rnd1.jpg
convert -size 100x100 -seed 4321 plasma:white-blue plasma_rnd2.jpg
convert -size 100x100 -seed 4321 plasma:green-yellow plasma_rnd3.jpg
convert -size 100x100 -seed 4321 plasma:red-blue plasma_rnd4.jpg
convert -size 100x100 -seed 4321 plasma:tomato-steelblue plasma_rnd5.jpg
|
As you can see the same pattern of colors is present in all the above images,
though different color bases can highlight or obsure some of the underlying
shared pattern.
Just one final word of warning. Other IM operators can also use the random
number generator, such as the "
-fx" '
rand()' function, the "
-virtual-pixel"
'
random' setting the "
-random-threshold" dither
operator, and the "
-noise"
operator. As such is a good idea to seed the generator immediatally before
your specific use of the random number generator.
As of IM v6.3.4-3, you can also re-randomize the generator using "
+seed". So placing it after your
'seeded plasma' will ensure that any later operators using random numbers will
correctly generate a randomized result.
By default the seed is randomized when IM starts, so you normally do not need
to randomize it yourself using "
+seed" to get a random result.
Problems using Plasma
One problem you should avoid with "
plasma:" images, is generating
them with a high aspect ratio. It tends to distort the normal plasma color
effects, pulling the colors out into needle-like streaks.
convert -size 200x50 plasma: plasma_high_aspect.jpg
|
There is no simple solution to this, so unless this is what you are wanting,
caution is advised.
There is also a definate top-left to bottom-right diagonal warp in the plasma
image that should not exist. That is there is some sort of 'spatial bias'
flaw in the algorithm.
For example as Thomas Maus <thomas.maus_AT_alumni.uni-karlsruhe.de>
pointed out if you mirror and append the same plasma image, you will always
see a distinct 'V' in the resulting image...
convert -size 60x60 plasma: \( +clone -flop \) +append plasma_flaw.jpg
|
This should not happen. But the problem seems to be too deep to be able to fix
without basically completely re-writing the whole plasma generator function.
Random Noise Images
As of IM v6.5.0 you can generate a purely random image from an existing image
using Noise Generator, "+noise" method 'Random'.
convert -size 100x100 xc: +noise Random random.png
| |
|
If your IM is older than this you can still generate a pure random noise image
using the slower DIY FX Operator, "-fx".
convert -size 100x100 xc: -fx 'rand()' random_fx.png
| |
|
Now these purely random images are themselves not very useful. But as a source
image for various image transformations, they will allow you to generate
a wide variety of different images.
For example by
Blurring the image
and
Color Adjusting the result, you can create
a mottled pattern of random color.
convert random.png -virtual-pixel tile -blur 0x1 -normalize random_1.png
convert random.png -virtual-pixel tile -blur 0x3 -normalize random_3.png
convert random.png -virtual-pixel tile -blur 0x5 -normalize random_5.png
convert random.png -virtual-pixel tile -blur 0x10 -normalize random_10.png
|
Note however without the
Virtual Pixel Setting
the "
-blur" operator will
have strong edge effects, which are best avoided.
As a bonus by changing the "
-virtual-pixel" setting to '
tile', the randomised
image remains tilable, with the colors wrapping across the image boundaries.
This tiling ability is something that currently not possible with a random
Plasma Images and is a inherent result of pure random
images being so random to start with.
Now each of the three
Color Channels of
the image can be thought of as separate random gray-scale image, and these
channels can be merged together in various ways.
For example you generate a mask of random dots by first
Thresholding a color channel
('
G' or the green channel), and separating it out as a gray-scale
image.
convert random.png -channel G -threshold 5% -separate \
+channel -negate random_mask.png
| |
|
As each color is a linearly random value, the threshold percentage used in the
above directly defines the density of pixels selected.
You can go further and use one color color channel to select random values
from another color channel channel (the '
R' or red channel), by
using various
Image Composition methods.
convert random.png -channel G -threshold 5% -channel RG \
-separate -compose Screen -composite random_white.png
convert random.png -channel G -threshold 5% -negate -channel RG \
-separate -compose Multiply -composite random_black.png
convert random.png -channel G -threshold 5% -negate -channel RG \
-separate -compose CopyOpacity -composite random_trans.png
|
Further processing, particularly on the black background version, will let you
enlarge the dots based on their gray-scale intensity, or generate streaks, and
or star flares, from those dots. See
Star
Generators for examples of such processing.
Like
Seeded Plasma Images you can also use the
"
-seed" setting to
pre-initialise the random number generator. This allows you to generate the
same random image(s) repeatably for a particular machine, just as you can for
plasma images.
For more examples of using random images, see
Background Images, or have a look at generating randomised canvases see
Random Spots of Solid Color.
Tiled Canvases
Tile images can be very large or very small, are designed to fit together
side-by-side and vertically to cover large areas of space.
Thanks to the World Wide Web, there as been an explosion of tile images
available for use (finding what you want is another matter). Below are a set
of tiled images which I copied from
Anthony's Icon Library
for use through out these example pages.
bg.gif
|
tile_aqua.jpg
|
tile_water.jpg
|
tile_rings.jpg
|
tile_disks.jpg
|
tile_weave.gif
|
Currently there are quite a number of way in which you can tile an image, over
a large area.
You can "
-tile" any image so
as to completely replace the original background image (using the
"
Copy" compose operator). (For more details see
Tile Compositing).
composite -tile tile_weave.gif -size 60x60 xc:none tile_copy.gif
| |
|
Another way is to read in the tile image using "tile:", and
tile it to a specific size.
convert -size 60x60 tile:tile_weave.gif tile_size.gif
| |
|
You can use this to generate a tiled image much larger than you need, then use
"-composite" to overlay
it over the original image. If the tile image is partially transparent then
a 'Over' "-compose" method will need to be
specified. It is a very slow method of tiling, particularly for large images,
and you have the problem of determining just how big an image you need to
create for the overlay.
convert test.png -size 200x200 tile:tile_disks.jpg \
-composite tile_over.gif
| |
|
A more advanced method is to use "-fx" to tile over an image. This however makes use of a special
"-virtual-pixel"
setting to define what pixel color to use when a operator references a pixel
outside the boundaries of the actual image. See virtual Pixels for details.
convert test.png tile_aqua.jpg -channel RGBA \
-virtual-pixel tile -fx v tile_fx.gif
| |
|
This however is even slower than the previous method. But you can also use
"
-distort" as a faster
method of tiling, with unusual warping options. See
General Distortion Operator.
Finally by specify a tile as 'tile fill pattern' for the "
-draw" operator, you can draw the
tile image over another image, to create any shape or figure you like.
This is because the "
-tile" setting will override any the "
-fill" color setting used by draw.
See
MVG Drawing Settings.
convert -size 60x60 xc: -tile tile_weave.gif \
-draw "circle 30,30 2,30" tile_draw.gif
| |
|
This only works for "
-draw", and operators like "
-annotate" that also make use
of "
-draw" to perform
their function. It will not work for image operators that use "
-fill" color directly, like
"
label:", "
caption:", and "
text:".
However "-draw" has
built-in to it some special color primitives,
such as completely resetting all the pixels in the image to the fill color, or
tile pattern (if set).
convert test.png -tile tile_water.jpg -draw "color 0,0 reset" \
tile_test.gif
| |
|
This is actually exactly the same method as used by some
Solid Color Canvases methods using a
Specific
Color, Only here we used "
-tile" instead of a "
-fill" color.
Tiling with an Image already In Memory
Tiling an image you have in memory (created or modified) is not straight
forward. Although a few methods are known.
- Using a "Memory Program Register"
- The most straight forward method is to save the the image into a special
'In Memory' file format "
mpr:",
or named 'memory program register'.
From this register you can then either use a "-tile" setting, or use the
special "tile:" image file reader, both of which can only be
set from a 'saved' image file format.
For example using "tile:" to create a tiled image of a
specific size...
convert tree.gif \
-write mpr:tile +delete \
-size 100x100 tile:mpr:tile \
tile_mpr.gif
| |
|
Or use it to set the "-tile" fill pattern for the various "-draw" operations...
convert tree.gif -write mpr:tile +delete \
granite: -tile mpr:tile -draw 'circle 64,64 10,50' \
tile_mpr_fill.gif
| |
|
The name given after "mpr:" can
be anything you like, it is only a label on where the image was saved in
memory. It can even be a plain number, color, or source filename.
- Clone/Append In-Memory Tile
- If you are not worried about the exact size of the tiled image, you can
just append the image together multiple times.
For example here we tile the image in a 3x3 array.
convert tree.gif \
\( +clone +clone \) +append \
\( +clone +clone \) -append \
tile_clone.gif
| |
|
This method of tiling has the advantage of allowing you to flip-tile
(mirror tile) the image.
convert tree.gif \
\( +clone -flop +clone \) +append \
\( +clone -flip +clone \) -append \
tile_clone_flip.gif
| |
|
In general this method is only practical when you have some idea of how
big the image being tiled is. Also as clones are actually very fast and
efficent it is a fairly simple and fast tiling method, especially if you
use the results to further tile the larger image.
- Virtual Pixel Tiling
- In this method we use the "
-fx" operator to read a tile image that is 'virtually tiled'.
See Edge Effects and Virtual Pixels for
more details.
This however will junk the tile image and all the other images in memory,
unless you use parenthesis.
convert rose: tree.gif \
-channel RGBA -virtual-pixel tile -fx v \
tile_fx_2.gif
| |
|
Note however that using "-fx" to tile images will be a lot slower compared to the
previous methods, though it is probably a little simpler.
You can also use "-distort" to tile images. The size of the final image however
needs to be specified using a special "viewport" setting.
convert tree.gif -set option:distort:viewport 100x100+0+0 \
-virtual-pixel tile -distort SRT 0 \
tile_distort.gif
| |
|
By using the General Distortion
Operator in this way, you also have the added bonus of distorting the
tiled image in some very complex ways. For example...
convert tree.gif -set option:distort:viewport 100x100-50-50 \
-virtual-pixel tile -distort Arc '45 0 50' \
tile_distort_polar.gif
| |
|
You can also use the 'mirror'
setting to get the same 'flip-flop' effect of the cloning technique.
Offset Tiling Canvases
Sometimes you need a little more control over the exact positioning of a
background texture, either for aligning a tile pattern with some other image,
or to avoid a bad correlation with some other part of the final image. For
many of the standard tiling methods this can be achieved using the "
-tile-offset" setting.
For example. Here I roll the tile image being used to directly create a tiled
canvas image using "
tile:" or "
pattern:".
convert -size 80x80 -tile-offset +30+30 tile:rose: offset_tile.gif
convert -size 80x80 -tile-offset +20+20 \
pattern:checkerboard offset_pattern.gif
|
  |
Tile Offset setting was broken before IM
version 6.3.9-9 in that the 'X' offset was being used for both 'X' and 'Y'
offset values (the given 'Y' value was ignored). This means that while the
above examples would have worked (both X and Y offsets are the same) you may
not get the expected results when the two values differ.
|
This also works for the "montage" background
"-texture"
setting.
montage tree.gif -geometry +24+24 \
-tile-offset +30+30 -texture rose: offset_texture.gif
| |
|
You can also use the setting by defining it before the "-tile" or "-fill" setting. For example...
convert -tile-offset +30+30 -tile rose: \
-size 80x80 xc: -draw 'color 30,20 reset' offset_tile_fill.gif
| |
|
However there is one major problem with offset tiling.
The problem is that due to the use of
Legacy
Command Line Style, the above will fail when using builtin
"
pattern:" tiles. For example here I tried the same thing as the
above using a '
checkerboard' tile pattern.
convert -tile-offset +20+20 -tile pattern:checkerboard \
-size 80x80 xc: -draw 'color 30,20 reset' offset_pattern_fail.gif
| |
|
What is happening is that the first real image processing 'operator' in the
above is '
xc:' and because of this
Legacy Command Line Style reads in all the 'settings' and just applies
them before actually processing the command line in the correct order.
Because of this 'legacy problem' the "
-size" setting gets set BEFORE
the "
-tile" setting
applies the "
pattern:" operator. As a consequence a 80 by 80
pixel 'tile' was generated BEFORE being rolled by the "
-tile-offset" option.
That is turn means the defined "
-tile" setting is a 80x80 pixel tile that will not actually 'tile'
properly. This is because while "
-tile" is regarded a pure setting, internally it calls a image
operator to read the tile, which can make use of the legacy setting handling.
This is probably one of the few examples where this legacy handling is
determental to normal IM 'do it as you see it' option handling by IM commands.
The solution to all this is to ensure that the "
-size" setting is reset before
defining the "
-tile-offset", but after an image has been read in, and this
satisfying IM legacy option handling.
convert -size 80x80 xc: \
-tile-offset +20+20 +size -tile pattern:checkerboard \
-draw 'color 30,20 reset' offset_pattern_good.gif
| |
|
In any case fact it is probably best to define the tile offset and tile image
just before its first use, which has the same result as the above solution.
Modifying Built-in IM Patterns/Tiles
See the full list of
ImageMagick Built In Images and Patterns. There are a lot of such
patterns, but I'll only look at one or two here.
Now the built-in patterns are generally very very small images, which can tile
to cover large areas. However on their own they are very plain looking, and
rather useless. For example, here is one of the larger more interesting
patterns that is provided...
convert pattern:checkerboard pattern_default.gif
| |
|
Pattern images are usually tiled over an larger areas, either as part of canvas
creation, by setting a "
-size", or as a fill tile (see
Tiled Canvases
above).
Now you will probably notice that all the patterns currently provided by IM
are all pure black and white, with the single exception of the
'
checkerboard' pattern I used in the last example.
Here is one pattern I particularly like to use as a tile pattern...
convert -size 60x60 pattern:hexagons pattern_hexagons.gif
| |
|
If you are not happy with these colors you can replace them using the
"
-opaque" image
operator.
convert -size 60x60 pattern:hexagons \
-fill blue -opaque black -fill skyblue -opaque white \
pattern_colored.gif
| |
|
If you want color the "
checkerboard" pattern, that is best done
by first using "
-normalize" to map the the two greys to black and white, before
substituting those two colors.
convert -size 60x60 pattern:checkerboard -normalize \
-fill red -opaque black -fill blue -opaque white \
pattern_color_checks.gif
| |
|
You can also use "
-floodfill" operator to color the pattern. However for this to
work properly you need to do this,
before you tile the modified
pattern. In this case I also need to expand the tile three times to color it
properly.
It is all very tricky, requiring knowledge of the IM pattern to do it
correctly.
convert -size 30x54 pattern:hexagons \
-fill tomato -opaque white \
-fill dodgerblue -draw 'color 10,10 floodfill' \
-fill limegreen -draw 'color 10,25 floodfill' \
-roll +15+27 \
-fill dodgerblue -draw 'color 10,10 floodfill' \
-fill limegreen -draw 'color 10,25 floodfill' miff:- |\
convert -size 100x100 tile:- pattern_color_hexagons.gif
| |
|
I used a pipeline of two commands above to separate the colored pattern
creation, from its actual usage. If you like to do this with a single command
see
Tiling an Image In Memory above.
Modifying Tile Images
The biggest problem people face with modifying tiles, whether it's an existing
tile, or one of the built in patterns, is that many image operations destroy
the 'tilability' of the image.
For example, here I have taken the built-in '
hexagon' pattern, and
tried to modify it to produce a shaded gray-scale pattern of wide hexagonal
lines.
convert pattern:hexagons -rotate 90 \
-blur 0x1 -edge 1 -negate -shade 120x45 \
miff:- |\
convert -size 100x100 tile:- tile_mod_failure.jpg
|
|
|
As you can see the resulting tile image does NOT tile properly, with
artificial edge distortions clearly visible in the tiled image. Basically we
lost the uniformity of the original tile, along the edges of the image.
One solution is to use a special setting ("
-virtual-pixel") which tells
IM operators to look at the image as a image tile, and wrap the edges around
the image when handling edge colors.
convert pattern:hexagons -rotate 90 -virtual-pixel tile \
-blur 0x1 -edge 1 -negate -shade 120x45 \
miff:- |\
convert -size 100x100 tile:- tile_mod_vpixels.jpg
|
|
|
See
Virtual Pixels, Colors beyond the Image
Bounds for more detail of this setting.
This works for most image operators, especially those using a graphical
technique called
Image Convolving, or color
lookups using the DIY operator "
-fx". Though it does not work for all operators.
For example here we join two related tile patterns together, and use various
effects to create unusual brick wall tile.
convert pattern:leftshingle pattern:rightshingle +append \
-virtual-pixel tile -blur 0x.6 -resize 150% -shade 100x45 \
-fill Peru -tint 100% miff:- |\
convert -size 100x100 tile:- tile_slanted_bricks.jpg
|
|
|
Alternative
There is an alternative to relying on "
-virtual-pixel". This is
especially useful for IM users, using very old versions pre-dating the
addition of this setting.
Basically we provide the 'virtual edge pixels' ourselves, before operating
on the image, so as to avoid any edge effects that may be present. And that
is done by tiling the image over a slightly larger area first. After
modifying the image, we can re-extract the tile, avoiding the edge distortions
that were introduced.
It does not have to be lot bigger, depending on the extent of the image
operations being performed. I have found 15 to 40 pixels should stop all edge
effects in the final result.
To re-extract the image we can either "
-shave" off the extra pixels, or "
-crop" the original tile size from the
middle of the processed image.
For example here I create a 3d "
-shade" effect using the builtin '
hexagons' pattern.
convert -size 60x60 tile:pattern:hexagons -rotate 90 \
-blur 0x1 -edge 1 -negate -shade 120x45 \
-gravity center -crop 18x30+0+0 +repage miff:- |\
convert -size 100x100 tile:- tile_mod_success.jpg
|
|
|
Note the exact position of the extracted tile does not matter. A tilable
image can be cut anywhere from the tiled image, as long as it is away from the
distorted edges, and use the same original size of the tile.
Here instead of tiling the image over a larger area, we use a 'double clone'
technique to double the area the tile covers. When finished we then just
center crop 50% of the image to recover our modified tile. This means we have
no need to know the exact size of the tile you are processing.
convert pattern:circles \( +clone \) +append \( +clone \) -append \
-fill grey -opaque black -blur 0x0.5 -shade 120x45 \
-gravity center -crop 50% +repage miff:- |\
convert -size 100x100 tile:- tile_circles.jpg
|
|
|
Generating Tile Images
The biggest problem you face when generating images which can tile together is
trying to match the edges and corners of the image so that they can fit
together seamlessly. If this is not done then all you get is a set of square
boxes each wit