ImageMagick Examples --
Canvas Creation
Index
You can even grab a single pixel from an existing image, and expand it to the canvas size you want. We use "
Note the use of the "
This was the recommended method in ImageMagick version 5.
The major complaint about all the above 'simple' methods is that none simply resets the image to the current "
The above as uses the '
This last method has the added advantage of also letting you slightly enlarge the image canvas, relative to the original images size.
All the above methods cannot 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 have a transparency channel before hand.
Also note that when using "
However this can be speed up by only selecting the pixel once. This can be done by using the fx formula as an argument for Sparse Color. It may seem less simple, but it is much faster.
Another more complex method is to crop out that one pixel and tile it across the image, using techniques described later in detail in Tiling with an Image already In Memory
-level" operator with the same argument for both 'black' and 'white' points will have the same effect.
-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 alpha channel to make it fully opaque.
-evaluate" version of this should be faster, particularly on larger images.
-gamma" operator to make an image all black.
Alpha Operator
-level" operator with same argument for both 'black' and 'white' points will have the same effect.
-fx" operator.
-evaluate" version of this should be faster, particularly on larger images.
Alpha Operator
However as this is a very recent addition it is probably not widely available yet.
Clear' alpha composition operator, with any overlay image (a single pixel "
-fill" color setting. In this case make it fully-transparent.
-fx" operator.
-evaluate" version of this should be faster, particularly on larger images.
-threshold" but again limiting its effects to just the transparency channel.
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 '
As mentioned before, and worth repeating, many of the above methods rely on an image already having an alpha channel. If it doesn't, add one using the "
As you can see by default "
Notice that when given a single color the second color will be either '
Note that the gradient is centered in the middle of the generated image, and has a diameter set to fit the larger of the X or Y size of the image. So if the size of the image isn't square you will get a 'clipped' radial gradient.
The colors of the gradient itself follow the same conventions as the much older linear "
This type of gradient is especially good for generating Overlapping Photos, as it removed the sharp gradient changes at the beginning of the overlapping region.
Or take it a step further and make a smooth parabolic peek in the center of the linear gradient.
Or band or a rippled pattern...
Both of these closely related operators allow you to modify images and gradients based on Sine Curves, Polynomials, Logarithmic and Power-of mathematical functions. See Evaluate Math Functions and Function, Multi-Argument Evaluate for more examples.
As of IM v6.3.5 you have a much faster and simpler way of generating a rotated gradient by using a SRT Distortion. For example, here is a 100 pixel gradient rotated 60 degrees, in a 100x100 pixel image.
This uses the default Virtual Pixel, Edge setting to ensure the whole image is covered by the requested gradient. You can also use the expert Distort Viewport setting, to map a gradient onto a larger image, such as for an use in Overlapping Photos.
Or wrap the gradient into an arcs and circles using the General Distortion Operator...
Though the new "
The '
The last two images may seem very similar, except for their size, but the handling of the center-most pixels is slightly different. If you look closely you will see that the last example has a perfect grey center pixel, where the previous example does not have a single center pixel, but four of them. The final size of the image was determined by the value '
The value '
Circular shapes and gradients can be warped to produce some interesting non-linear gradients. For example arcing it using a Wave Distortion can generate roughly triangular shaped gradient.
Or a very odd looking bird like shape, generated by polar distortion along the top edge of the circular shape.
And even do this diagonally.
Or by blending two plain color gradients using either Channel Copying, or Mathematical Blending composition methods, you can generate colorful 2 dimensional colormap gradients.
This first converts a highly saturated color ('
The result is actually exactly the same as the previous method, just a little more direct, in that we generate the right values for the desired colorspace, then set the colorspace those values belong to. Here we take the masked angular gradient (see above) and re-map it into the HSB color space to generate a circular hue of colors. Red (hue=0) is rotated toward to the right, where it is traditionally placed (polar coordinates angle 0).
A similar example to the above is Color Wheel, which is generated by Combining Channel Images with both a Hue and a Lightness gradient.
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. The actual function the gradient follows depends on (and is close to) the exact Resampling Filter that was used by resize.
As you can see this diagonal gradient is not very linear when compared to the Rotated Gradient above.
Here is rough "Rainbow Gradient" created using the 'resize' technique.
With this method you can use any color combination and order for the gradients generation. This makes it very well suited to generating Color Lookup Tables.
Here the lookup X position '
Using this method also allows you to generate multi-colored gradients.
The limitation however is that the colors can only be defined with equal spacing. You can not simply shift the position of the middle color, except by roughly modifying the input gradient to some non-linear form, so as to shift that center. For more than three color is situation becomes worse. The above is also a good technique for coloring greyscale images using Duotones, with a guarantee on exactly defining the mid-tone color (unlike using the Tint Operator).
Interpolated lookup gradients can also be expanded to 2 dimensions, and generate square linear gradients (Bilinear Interpolation), just as easily as purely one dimensions gradients.
Here is the same example but using Catrom Interpolation, and generating using the Distort Operator instead of the very slow FX operator.
The key point to understanding the above is that we are enlarging the small image based on the centers of its pixels. See Image Coordinates vs Pixel Coordinates for details. Note that most interpolation methods have equivalent Interpolated Resize Filters. But the use of the viewport and pixel coordinates removes the edge effects that is shown in the previous Resize Gradients caused by extreme upscaling of the very small image.
The Mesh Interpolation setting however is not available as a Resize Filter. It is a special 2 dimensional interpolation that divides the intra-pixel area into two flat linear triangles, hinged along the diagonal connecting the corners with the minimal color difference. So by making two colors the same color, and using "
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. If the two diagonal colors are not the same, you may get a different diagonal division.
You can even generate some neat non-linear gradients.
The value '
Note how I use some assignment expressions to simplify the calculation of the distance from center of the image, then magick it to a gradient. This feature was added in IM v6.3.0.
Note that the '
When going from two points to three points the ratio of how much color each 'control point' provides, is a bit more complex, and uses a technique called Inverse Distance Weighted (IDW) Interpolation. You can see more details math for this in Wikipedia, IDW Here is an inverse distance example for three points.
And here I use an inverse distance squared which is the more normal method used for an IDW interpolation. This is also known as Shepard's Interpolation method.
Note that the '
The problem with using either 'Inverse Distance' or 'Shepard's Method' (inverse squared distance) is that all the 'control points' has a global effect over the whole image. As a result you get a sort of underlying 'average color' in between the points, and especially at a large distance from all control points. This, in turn, produces 'spots' of color rather than a smooth gradient of color.
DIY Gradients and Hues
ASIDE: This was a sort of failed attempt to generate an interesting rainbow effect. It was a failure, but I learned a lot from that failure, which I present to you here. The above works well but I wanted to try and to do better. I thought perhaps I could generate a bright rainbow gradient of colors between the points, rather than generating spots that merges into an average color. So to generate a hue gradient, I tried to do the Inverse Distance Weighted Interpolation in HSB colorspace, though I switched the yellow to blue, to make the colors more equally spaced around the hue, and hopefully provide another way of generating a color wheel (see Gradients in Other Colorspaces above).
As you can see all the colors were nice an bright as we are only generating a hue gradient. However it also appears very strange, which is caused by the 'cyclic' nature of the 'Hue' color channel. As a consequence the area between the blue and the red goes the long way round though a green hue, rather than that the shorter 'modulus' path via a purple hue. After much research I finally discovered how to do the modulus mathematics needed to do the above correctly by using a Circular Mean for the weighted average of distances. This involves converting the Hue as a polar angle, into X and Y rectangular coordinates. That allows you to perform linear mathematics, letting us perform a linear weighting of the values, appropriately. The result is then then converting back into an angular Hue.
NOTE: The above only performed its operations on the hue channel only. For real image, we would still need to operate (as normal) on saturation and brilliance channels. As you can see we now get a correct gradient between the red and blue, though the method when applied to just primary colors that have a high angular separation, tends to generate very sudden gradient changes in the middle. That is, while the result is correct the angular hue variation is not linear for very large changes in hue effects. It would work well for averaging lots of near hues, but not for these widely spaced primaries. I even switched to using a stronger 'Inverse Weighting' rather than the more usual 'Inverse Squared' or 'Shepard's' method (see above) and while it improved things, the hue changes were still compressing in the center due to the non-linear effects. As the input colors are constant, pre-converting them into hue-x, and hue-y coordinates, doing the shepard's weighting on those channels, then converting back again would actually make the process even faster. That is, convert colors from a HSB colorspace to a Hx,Hy,S,B colorspace, to apply the technique. If this is done, then central point and even gradient between the points, would shade to white (the center point of a HSB colorspace). If this was performed in HSL colorspace that area would shade toward a mid-tone gray.
This conversion from a polar Hue to X-Y coordinates would in some ways be similar to just doing the calculations in a non-polar RGB space, which shows that same shade toward gray effects (see previous examples). So if by using a Circular Mean we are in fact simply converting a HSB colorspace into a highly distorted variant RGB, why not just do the task in a linear RGB colorspace, and saturate the colors, to generate the hue!
As you can see we get practically exactly the same result as before, but with all the complex 'modulus mathematics' removed. However I am still no closer to getting a more linear spread of hues between the starting points of color. The moral of all this is that working with Hues is hard, not only due to the 'red discontinuity', but also because of non-linear effects that happen when colors are very widely spaced. And in the end the result was the same as if I have done the task directly linear RGB space and saturating the colors. Essentially while HSB and HSL colorspaces are fun, they are not linear, realistic, or practical colorspaces to work with. This is also probably why very few operations actually work with hue directly.
This image creates a gradient that goes from an exact 'white' color along the very top row, to an exact 'black' color along the bottom most row. It is an 'idealized' gradient, and typically exactly what an user wants, as it actually contains the actual colors the user specified. However while this is what an user expects, it is not a mathematically correct gradient. As discussed in Image Coordinates vs Pixel Coordinates pixels actually have an area, and as such the white pixel at the top of the image represents the center of that pixel, while the black represents the center of he bottom most pixel. That is, not the edge of the image but 1/2 pixel away from the edge. Mathematically images start at the edge. As such to generate a perfect mathematical gradient, you need to specify the color locations at the edge of the image, in pixel coordinates. As such in image coordinates, the positions are displaced by 1/2 a pixel, and the image size is exactly the number of pixels in the image (a distance), rather than a location that is 1 pixel smaller that the images size. One way to generate a mathematically perfect gradient is to use Barycentric Sparse Color (looked at in detail in the next section) to generate a perfect edge-to-edge gradient...
Note that the coordinates used go from
The resulting gradient image can then be Rotated as needed, to then generate the required image for later image processing. However while this gradient will 'cycle' correctly, the actual position of the color is not exactly correct. But in many cases this is good enough. If you need a 'perfect gradient' I recommend you use a sparse color gradient. In Summery... A little thought about exactly what you want from your gradient can make a big difference in the accuracy of your final results. But if it does not matter, than don't worry about it, use whatever is simplest for the task at hand.
The rest of the pixels (limited according to the "
If four or more points are given a 'best fit' will be performed, over all the points given, and as a result the actual points may not get the exact color specified for those points. However be warned that the gradient does not just 'stop' but continues to change beyond those points. Traditionally a barycentric gradient will be limited to within the enveloping triangle of the points used to generate it. For example..
This is a faster version from Fred Weinhaus, that creates a triangle mask in the alpha channel, which by default, the Sparse Color Operator will not update (due to the default channel settings). All the colors including fully transparent pixels are however still filled with color, just alpha masked.
The '
Here is the same example but with one of the angle control points moved to show how it sets the gradient angle.
And to align with the other two corners...
These 'diagonal gradients' produce a natural looking gradient even with long images such as the above. Study the locations of the three color points, especially the two points of equal color that define the angle of the gradient between the two corners. Notice that in both cases one of the those points is not even located within the image itself! Also note the use of Percent Escapes to make the positions automatically adjust to the size of the images on which the gradient is being drawn.
Two point gradients however do not work very well when applied to the corners of very 'wide' or 'tall' images (high-aspect ratio). Basically the gradient is not diagonally aligned, unlike the three point gradients above. It is angled, just not angled enough to make it 'interesting'.
You can see this '4 point fit' by taking the above image and separating out the individual color channel gradients.
Note how the equation produces curves (quadratic curves actually). However if the 4 points form parallel lines, the gradient generated will become linear. This method is actually equivalent to the Bilinear Interpolation method (see Interpolated Lookup Gradients below), when the 4 points are aligned to a orthogonal (rectangular) grid. If less than 4 points are given the above function will be replaced by a 3 point '
As you can see no attempt is made to provide anti-aliasing of the colored 'cells' around each point. The edge of each cell actually falls exactly midway between each point's nearest neighbours. This can be used for example to generate masks to cut up the image in various ways. Just assign one point as white and all the rest as black to extract one single 'cell' from the image. If you want to smooth (anti-alias) the result you can either use some form of Super Sampling to smooth the image. For example generate one 4 times as big, and "
The simpler way (though not very nice) is to just simply blur the image very slightly...
By blurring generated image by a large amount you can set up some non-linear gradients between the 'cells' that was generated.
The larger the "
The unblurred output could also passed to various Edge Detection techniques to generate various bounded edges. You can remap the image via a Raster to Vector Convertor to generate vector lines. However I found the default '
By surrounding a specific area with a similar color you can generate a plateau of that specific color, though the boundaries between the edging points may 'leak', and the center of the 'plateau' may sag to form shallow bowl (depending on distance to other color points). This method is also what is used to generate a displacement field, such as what is used in Shepards Image Distortions. In that case X and Y displacement vectors is what is being mapped rather than color R,G,B values.
As you can see it generates sharp points of color, that quickly merges into the background 'average color'. In comparison to Shepards Method which generates rounded spots, with a 'flat' color around the color points. It does however work better when generating linear gradients where all the control points form a line. That is, for generating 1 dimensional gradients along a specific line in the image. However there is one more point to be made. The speed of how fast these points of color drops to a near 'average' level is controlled my how close they are. Placing two point sources close together, and they drop quickly, the further apart they are and the larger individual colors influence results.
Also if you 'double up' a specific point (exactly on, or just near each other) with the same or similar color, you will make that color point, twice as strong.
These effects also applies to '
As you can see the 'spots of color' expand from very sharp points, to rounded spots, and on to large areas of color. At very high power levels it will eventually reproduce the same pattern as a Voronoi Sparse Color Method. This -define not only effects Shepards Sparse Color, but also will have similar effects on Shepards Distortion Method which is based on calculated displacement maps generated by the sparse color method. However it does not effect the Inverse sparse color method, which always uses a power-level of 1.0.
And here is a summery of the various, 3 point methods.
At this time only '
As of IM v6.6.8-5 unmodified channels is preserved, as such you can now use Sparse Color with the "
Sparse Color also accepts normalized floating point values instead of a color name. Exactly how many values need to be provided to replace the color name depends on the current "
This may be easier to handle in programmed scripts, and in API's, which may not have access to the 'colorname' translator.
Now we can extract the few non-transparent pixels that are present in this image, then fill in all the other colors using the multi-point sparse color method, '
The "
Note that the resulting image is exactly the same as the input, but with the transparent background replaced with a distance blurred 'edge colors'. This is why the edges of the image have become in-distinct. This image was specifically developed to try and generate better 'edge feathering' techniques. See Blur Feathering and Distance Feathering for other feathering techniques.
A better method is to generate multiple layers of blurred images with progressively smaller 'sigma' values, and the original unblurred image on top.
This layered blurring technique is equivalent to the result of a '
This will work very fast with very large images without needing large 'sigma' values (and thus very slow) for each of the blurring steps. Essentially it is using a faster image resizing technique to generate the blurred layers of the previous example. It is not as exact, but will generate a good approximation of the correct result. However it works best for images which are a square, and a power of two in size, or it will be less accurate. The special operator "
This leakage of colors is the main problem with using Shepards Method for 'hole filling' especially when multiple holes are involved, as the colors involved with one hole, can and will leak into and effect the colors in a completely different hole. And visa-versa. It is an understanding of boundaries that forms the difference between Shepards Method, and another form of color 'hole-filling' known as 'Color Diffusion'. Basically with 'Color Diffusion', colors can not pass though a line of some other defined color. It is achieved by limiting the effect to only colors in 'line of sight', or to those that leak, around the outside of an edge. This requires using distance to the nearest colors to limit what colors influence a pixel. One major use of 'Color Diffusion' is presented on the Diffusion Curves web site. This not only makes heavy use of color diffusion, but also includes information on techniques for generating diffusions very quickly. I hope to implement this into ImageMagick at some point in the future.
You can also see that plasma images are also a type of randomized gradient of colors, and like "
You can also see that mid-tone colors like '
Again as you can see, mid-tone colors will generate more varieties of color in the resulting image, than an extreme color, like black, white, or yellow. The '
Compare this image with the 'fractal plasma' images below.
In fact this is very similar to the constant color plasma images we have already seen, and in fact these are generated in the same way but with more pronounced color changes.
I often find that plasma images are a little 'noisy'. As such they usually will benefit from a little smoothing using "
You'd probably think you would get a lot of light and shadow effects, but the raw plasma is so random, that "
If this is not quite bold enough, use the channel copy method of grey-scaling the plasma image.
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.
The above image will never change, so unless I change the "
As you can see the same pattern of colors is present in all the above images, though the underlying color base can highlight or obscure parts of the shared pattern. Just one final word of warning. Other IM operators can also use the random number generator, such as the "
The result may seem very random, but it will produce a more controlled range of colors, (or just color values).
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 ('
These types of images are directly usable to generate Glitter Animations. But 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. For examples see Star Generators.
Like Seeded Plasma Images you can also use the "
Note however without the Virtual Pixel Setting the "
The problem with the above is that the blur will tend to create spots of red-yellow (low values) and red-magenta (high values), with bands of green, cyan and blues, in between them. This is simply a consequence of the way the hue values were blurred and leveled. The ideal solution to this would be a type of modulus-blur, that would take into account the cyclic nature of the Hue values. However such an operator is not currently available, and perhaps never will.
For more methods of processing a random images, see Plasma Images above, as well as Generating Backgrounds. Blurred Random GraysAs you can see from the above you get an image with various blobs of primary colors. That is, because each channel is being processed completely separately to each other as gray-scale images. Lets extract one of the channels of each of the above image so you can see the structure of the blurred image...
The first thing that you should notice is that the image will generally (but not always) contain roughly equal amounts of both black and white areas. You can see this if we Threshold the random images at 50%
As you can see you get approximately 50% white and 50% black areas, separated by a curvy line. Also the curve of this line varies according to the 'sigma' value used for the blurring of the purely random image. From individual pixels generating a black and white 'snow' until you get a very uniform (though still random) separation of the image into two black and white areas. For more examples of using random images, see Background Images or to have a look at generating randomised canvases, see Random Spots of Solid Color.
The heavy use of the "
First I would like to point out how we get roughly equal amounts of light and dark areas within the image, but that those areas are interconnected by the grey 'middle' colors of the gradient that forms between the light and dark areas. Now the individual blobs or 'granules' varies from area to area across the image, but they all roughy average at about a diameter of about three to four times the value used to blur the initial random image. This blur value is known as the 'granularity' of the image is a very important value, as it basically represents the average size of the circular structures the random image produces. Some times it is called the 'curviness' of the image. The larger the value the larger and slower these curves are within the image. This is the most important factor describing a Blurred Random image, so lets make it very clear...
ASIDE: Actually the size of the actual 'granules' themselves can vary depending on the threshold factor used to generate them. What the factor really describes is the average distance between centers of the white and black areas. The larger the value the larger the distance, and the larger and more spread out the spots have to be to accomidate that increased distance. This becomes more obvious when we start looking at Random Ripples below.
You may also like to try using a 50% Solarize operation with some extra Level Adjustments to extract both the well separated black and white granules from the image.
Be warned that as the value gets larger, the time to generate the blurred random image also gets much much longer. Also when the value reaches about half that of the size of the smallest image dimension, the effect stops growing as the random image settles into a single white and black spot. Large values are not recommended. To finish with, to the left is shown a Patrol Cycle Animation resulting from varying the 'granularity' (random blurring) of a single random image. The animation was generated using the shell script "
Where '
And your one random image can now generates a whole sequence images forming a cycle. Note that the 'time' extraction has to happen before any other processing such as blurring, which is probably the slowest part of the whole generation process. The other thing to notice is that at phase '
Or generate changing electrical filaments that slowly flow over the image.
Note that due to fact that half the cycle is a negation of the first half and we use a Solarize to fold the white and black colors in half, the cycle is actually repeating twice over one animation cycle. It really needs a lot more frames to remove some of very fast changes that is taking place.
To make the motion less predictable for a longer cyclic sequence, you can also use some Gradient Math to combine multiple Sinusoidal Cycles, from multiple random images, or even just using the other color channels of the same random image.
As you can see the larger the 'Frequency' of the Sinusoid Function, the more ripples are being added into the gradient between the 'granules'. A 'Frequency' of '
Both methods have advantages and disadvantages, but in essence they will enlarge granules, though not the distance between the white and black sets of granules. The side effect of this is of course a compression the ripples between the two sets of granules.
The second value '
The color of the 'white' granule, will depend on both the 'Phase', and the fraction of the 'Frequency' that use applied. An integer 'Frequency' value will cause both white and black granules to vary in color together (according to the 'Phase'). as such with a pahse of '
Note for the 'gray' 'Phase angles, one of granules is surrounded by a white ring, while the other is surrounded by a black ring. If a 'Frequency' value with a '
As previously in Random Flux, you can modify the 'Phase' with time so as to generate an animation of the ripples moving from one set of granules to the other. This works particularly well without any contrast enhancement.
ASIDE: the technique used in the above is known as a "Pipelined MIFF:" and is possible as the MIFF:" file format can simply 'concatenate' images to generate a multiple image file. One point is that the animation seem to change much much slower than a Flux Animation we created above. That is, because over the one animation cycle a ripple will only travel a short distance, where in a 'flux' animation thge change will travel from the large scale white to black granules in just half the cycle and back again. Now you can combine the above ripple animation with an underlying 'flux' animation from the same random image source to generate a much more dynamic and flowing form, but be warned of that animation speed difference.
You can also animate the ripples within the animation. Though you may need to use a much larger 'phase cycle rate' (the 'j = 5 * i' expression) for the ripples themselves. Also as you are generating a cycle within a cycle, you will need to generate a much longer animation 60 frames in this case. However that has the benefit of slowing the larger 'flux' movements down too.
Note in the second image how ripples seem to first come out from one point, then later they start back going into the same point, though they never just simply reverse direction. A better multi-cycled flux cycle generator should remove this slight weirdness by removing the 'negative' effect in the flux underlying flux animation.
FUTURE: Use of Rippled Random Images for Dispersion Mapped Distortions.
Currently there are quite a number of way in which you can tile an image, over a large area. You can "
You can use this to generate a tiled image much larger than you need, then use "
By specify a tile as 'tile fill pattern' for the "
This only works for "
This is actually exactly the same method as used by some Solid Color Canvases methods using a Specific Color. Only here we used "
A more advanced method is to use a Distort Operator with a special Distort Viewport setting, that was set to the size of the original image (using a Defined Global Artifact and Percent Escapes). This basically maps the smaller tiles Virtual Pixels, that surrounds the small tile image, to generate the larger tiled canvas.
See Tiling via Distort (below) where we will look at this same technique to tile an image that is already in memory.
Make sure that the "
In any case 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.
This method of tiling has the advantage of allowing you to flip-tile (mirror tile) the image.
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 efficient it is a fairly simple and fast tiling method, especially if you use the results to further tile the larger image.
The name given after "
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. You can see examples of this in Distort Affine Tiling. As a more complex example, here I use an Arc Distortion to tile the tree around the origin which is centered in the viewport. The '
Pattern images are usually tiled over an larger areas, either as part of canvas creation, by setting a "
If you are not happy with these colors you can replace them using the "
If you want to color the "
You can also use "
I used a pipeline of two commands in the 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.
The first command generates the 'tile image' while the second actually tiles the image, so we can see how they all fit together. 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 Virtual Pixels setting, which is used to make operators think the image wraps around the edges, when looking up colors that are beyond the bounds of the actual image proper.
Here is another example where I join two related tile patterns together, and use various effects to create unusual brick wall tile.
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 you 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.
As you can see it is a lot simpler to create randomized tiles using the raw random noise image, and you will not have any edge distortions in the results. This particular image transformation is listed on the Background Images page and is titled "pits". See that page for lots of other image random image transformations, and examples of what they look like.
Note however that for this tile to look 'hexagonal' the tile cannot be a normal square, or even a doubled square. The final tile size needs to be a rectangle. The exact ratio for this rectangle actually involves irrational numbers, which is not very good for image work with a pixel array. However a good working ratio is 4:3, which is used by most computer and digital camera images.
If you look at the pattern the tile produces you will see that any specific feature, will have 6 copies of that same feature surrounding it in a circle. This is the 'hexagonal' pattern the tile produces, even though it is still tiled in the same 'square' pattern as all other tiling images. One variant of the above 'hextile' pattern is to double up the tile image vertically, rather than horizontally as we have done above. The result is that the hexagonal pattern will be rotated ninety degrees. It is however still the same type of pattern.
Future: Flip the extra image over to generate a larger tiling pattern (pmg tiling group). Future: how to cut out (mask) a hexagon from an image so it will tile perfectly, without gaps or overlaps.
The above however only works for tiling a small shape in the middle of the original image. It does not work well for a general image. For a general image hex tiling we also need to mask out an equilateral triangles. The pieces are then rotated so the equilateral trianlge edges are mirrored. This is not an easy task.
The diagonal mirror is generated by doing a Transpose and then using a mask generated using a Voronoi, Sparse Color. Note that this diagonal mirror automatically shares one line of pixels across the mirror in the same way, due to the pixel geometry of the square. I also remove one set of pixels along the edge before creating vertical and horizontal Flips and Flops. I also recommend the removal another row and column of pixels along the top and left edge, before using this image as a 'tile'. You don't need to do this, but I think it looks better. Without removing one row and column of edge pixels, you get ugly 'seams' of doubled pixels, where the images join together. An alternative is to tile the raw random image first, then do the Background Pattern conversion, you are less likely to get a 'clipped look' along the mirror lines, but a smoother transition.
The first part is the generation of the 'tiling of the random data' the second half I magick the random data into a 'hues' mapping. I also added the extra pixel to the initial image which will be later choped as appropiate to generate a tiling image.
For a more complete introduction into tiling images and the mathematics behind them, see Wikipedia: Wallpaper Group. What we have explored above is only a few of the many tiling patterns you can create.
The 'p4g' is almost exactly the same as the 'p4m' tiling above, but uses a 180 degree rotations of the mirrored squares, rather than using flips, to generate the full tiling image. However as the images are not joined by mirrors you can not use an existing image as the tile source as the edges will become disjoint and discontinuous. However you can tile the raw random data then process the resulting tile image, to produce a smooth result.
Note that due to the non-mirroring nature of the tiling, you do not need need to remove the duplicated row or column of pixels from the edges before you append. Though it does not hurt to do so, if you want to follow the same type of process for both cases.
Solid Color Canvases
Direct Generation
Generating a canvas of a specific color and size is very simple to do. You just specify "-size
" (defaulting to "1x1
" is no size given), and then use "canvas:
" to generate an canvas of the color given. If no color is specified a 'white
' canvas is generated.
For example... here I generate a 'khaki ' colors canvas.
|
Using some fancy Image Read Modifiers we can just specify a solid color canvas image as a single argument. This technique means you can specify a 'xc' canvas image of a specific size and color as a single 'input image' argument to many ImageMagick Scripts.
|
If you have already created a canvas, but need one in a different color you can replace that color using the "-opaque " operator.
|
-scale
" for a simple and fast resizing of the single pixel.
Here we grab a rose color from the built-in "rose: " image.
|
Create Image of same size
One most basic techniques, when using ImageMagick, is to generate a canvas of the same size as some existing image. This can be done by converting that existing image into the canvas needed, but preserving the image's original size. Generally it is not just the images size that needs to be preserved, but all the images meta-data as well. That in things such as labels, comments, color profiles, time delays, as well as the save compression and depth. This meta-data can be important if you want to annotate such information onto the newly blanked canvas, or you plan to overlay the original image onto the new canvas, and need to preserve that information. Naturally IM provides a large number of ways to do this, usually as a side-effect of using various image operations. Only a few are very obvious about there use in clearing an image to a solid color.To the left is 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
As of IM v6.4.2-1 you can use the "+level-colors " with a single color and no comma's, to set all the colors.
|
-alpha
" operator to set the transparency to something useful before (or after) the color has been added. Altrunativally you could use "-channel All
" to ensure the transparency channel is also set by the color resetting operation. Another older technique is to use "-colorize
" to overlay the fill color but with a fully opaque value. However before IM v6.7.9 it did not change the the original images alpha channel, so it is a good idea if to disable the alpha channel first, using "-alpha Off
", or make it opaque with "-alpha Opaque
" even though you would get the same result without it.
|
As of IM v6.4.3-0 you can use the "-sparse-color " operator to set some point to the color wanted, and have it spread to cover the whole image, using just about any coloring method it provides (see Sparse Points of Color below).
|
A more general way is to use "-draw " to directly reset all the colors in the current image to the current "-fill " color.
|
The major complaint about all the above 'simple' methods is that none simply resets the image to the current "
-background
" color. The next set methods make use of Alpha Composition to force various operators to replace the image with the desired color. These multi-image techniques work with operators that use "-compose
".
For example you can use the "-flatten " (See Flatten onto Background example), which creates a canvas using the "-background " color.
|
Dst
' compose method to only read the background canvas, and ignore the pixel colors of the original image.
If you are just wanting to grab the original images meta-data (such as the comment or label data), but replace the image itself with a specific color and size of canvas image, then "-extent " operator (See Extent, Direct Image Size Adjustment) may be the best solution. Again the Dst ' compose method is used to have it ignore the original image pixel data, so as to onlyuse the "-background " color.
|
Or you can use "-border " (See Adding a Border), using the "-bordercolor " as the color source.
|
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 surrounded by the border color. Not very useful. |
A more flexible (but very slow) method of canvas generation was provided by the "FX, DIY Operator " operator. You will also need to turn off the input image's transparency channel as by default "-fx " will not touch the transparency channel.
|
The "-fx " operator will even let you do a little color mathematics. For example how about a 70% darker gold color...
|
Here for example we create a canvas with a semi-transparent red. However when overlaid on the web pages 'bluish' background we get an off purple-pink color.
|
-fx
" operator with transparency, you will need to set "-channel
" to modify all four 'RGBA
' color channels.
Blanking Image with Picked Color
Blanking images using a color from the original image is also posible, though can be tricky. It is an useful technique when you want to use a specific pixel as a 'background color'. For example pixel 0,0 is a common choice. In the following examples I will select colors from various pixels from the built in rose image (shown left), as I blank the image. The most obvious (though slow) method is to simply use the "FX, DIY Operator
" to select the pixel to use color blanking.
|
|
|
|
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 what you are actually 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
-threshold", and then turn off the transparency channel.Traditionally you can create a black canvas by using " |
magick test.png -threshold 100% -alpha off black_threshold.png |
Providing the " |
magick test.png -level 100%,100% -alpha off black_level.png |
The " |
magick test.png -fx 0 -alpha off black_fx.png |
However the " |
magick test.png -evaluate set 0 -alpha off black_evaluate.png |
You can also mis-use the " |
magick test.png -gamma 0 -alpha off black_gamma.png |
A less obvious way is to 'posterize' the image with too few color levels, resulting in only one color being used, black.
|
You can ensure the image is fully transparent then 'extract ' the images mask, using the |
magick test.png -alpha transparent -alpha extract black_alpha.png |
White Canvas
-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.The traditional way is again using " |
magick test.png -threshold -1 -alpha off white_threshold.png |
Providing the " |
magick test.png -level -1,-1 -alpha off white_level.png |
You can of course set the pixel values directly using the " |
magick test.png -fx 1.0 -alpha off white_fx.png |
However the " |
magick test.png -evaluate set 100% -alpha off white_evaluate.png |
Or negate some other black canvas generation method.
|
You can ensure the image is fully opaque (no transparency) then 'extract ' the images mask, using the |
magick test.png -alpha opaque -alpha extract white_alpha.png |
Transparent Canvas
Probably the most important canvas you want to generate from an existing image is a transparent canvas. You can then draw and add things to this canvas, get it the way you want it, the overlay it onto the original image. -alphatransparent" operator (added IM v6.4.3-7).The fastest and easiest way is to just get IM to directly clear the image to transparency, using the " |
magick test.png -alpha transparent trans_alpha.png |
null:
" in this case) as it will be ignored.
We can make a fully-transparent 'black' canvas using the ' |
magick test.png null: -alpha set -compose Clear -composite -compose Over \ trans_compose.png |
Here we use the "-draw matte " operator to replace the matte (transparency) channel value with the transparency value of the current " |
magick test.png -alpha set -fill none -draw 'matte 0,0 reset' color_matte.png |
We can also do this more directly with the " |
magick test.png -alpha set -channel A -fx 0 +channel trans_fx.png |
Naturally the " |
magick test.png -alpha set -channel A -evaluate set 0 +channel \ trans_evaluate.png |
Another way to just make the image fully transparent is to use " |
magick test.png -channel A -threshold -1 +channel trans_threshold.png |
-1
' was used in the above, rather than something like 101%
'. In many of the above image results, the original RGB colors of the original 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.
|
-alpha On
", but in that case you may as well just use the "-alpha Transparent
" operator. See the examples on Controlling Image Transparency.
Miscellaneous Canvas Coloring
Other than using a specific color, only the "-gamma" operator is truly flexible enough to generate a canvas of any primary/secondary color. You basically use0
to zero out a channel, and -1
to maximize a channel values.
For example, here I generate a yellow canvas...
|
As of IM v6.4.2 you can also use the "+level " operator to set a specific grey level for all the color channels.
|
Gradients of Color
As you saw above you can create canvases of solid colors easy enough. But sometimes you want something more interesting.
One very useful image creation operators is "gradient: ". For example...
|
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.
magick -size 100x100 gradient:blue gradient_range1.jpg magick -size 100x100 gradient:yellow gradient_range2.jpg magick -size 100x100 gradient:green-yellow gradient_range3.jpg magick -size 100x100 gradient:red-blue gradient_range4.jpg magick -size 100x100 gradient:tomato-steelblue gradient_range5.jpg |
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. The 'red-blue
' gradient shows a much darker band of purple colors in the middle. This darkening is caused by the darker non-linear sRGB colorspace being used, especially with strong primary colors. See Processing Real Images for more details.
"gradient: " currently only understands sRGB Color Space color representations. As such you can not use it to generate a brighter more correct 'purple' gradient using 'red-blue ' colors in a linear LAB colorspace.It also means you can not generate multi-color 'rainbow' gradients using HSV colorspace. However you can 'fudge' such gradients relatively simply. See Gradients in other Colorspaces below. |
Gradients cannot 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. |
Some particularly nice gradients include...
|
As of IM v6.3.1 the algorithm used to generate gradients now produce a horizontally uniform colors, such that all the pixels of each row in an image being assigned the same color. That is, one color per row. 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.As a result the gradient was a predominately vertical gradient, just as it is now, but not a perfect one. Usually this fact was only important in special case such as test images, and for use in Image Mapping. |
Note, the behavior of gradients can be affected by these defines:
gradient:angle=angle (in degrees) | For a linear gradient, this specifies the direction of the gradient going from color1 to color2 in a clockwise positive manner relative to north (up). For a radial gradient, this specifies the rotation of the gradient in a clockwise positive manner from its normal X-Y orientation. Supported in Imagemagick 6.9.2-5. |
gradient:bounding-box=WxH+X+Y | Limit the gradient to a larger or smaller region than the image dimensions. If the region defined by the bounding box is smaller than the image, then color1 will be the color of the background. Supported in Imagemagick 6.9.2-5. |
gradient:center=x,y | Specify the coordinates of the center point for the radial gradient. The default is the center of the image. Supported in Imagemagick 6.9.2-5. |
gradient:direction=value | Specify the direction of the linear gradient towards the top/bottom/left/right or diagonal corners. The choices are: NorthWest, North, Northeast, West, East, SouthWest, South, SouthEast. Supported in Imagemagick 6.9.2-5. |
gradient:extent=value | Specify the shape of an image centered radial gradient. The choices are: Circle, Diagonal, Ellipse, Maximum, Minimum. Circle and Maximum draw a circular radial gradient even for rectangular shaped images of radius equal to the larger of the half-width and half-height of the image. The Circle and Maximum options are both equivalent to the default radial gradient. The Minimum option draws a circular radial gradient even for rectangular shaped images of radius equal to the smaller of the half-width and half-height of the image. The Diagonal option draws a circular radial gradient even for rectangular shaped images of radius equal to the half-diagonal of the image. The Ellipse options draws an elliptical radial gradient for rectangular shaped images of radii equal to half the width and half the height of the image. Supported in Imagemagick 6.9.2-5. |
gradient:radii=x,y | Specify the x and y radii of the gradient. If the x radius and the y radius are equal, the shape of the radial gradient will be a circle. If they differ, then the shape will be an ellipse. The default values are the maximum of the half width and half height of the image. Supported in Imagemagick 6.9.2-5. |
gradient:vector=x1,y1,x2,y2 | Specify the direction of the linear gradient going from vector1 (x1,y1) to vector2 (x2,y2). Color1 (fromColor) will be located at vector position x1,y1 and color2 (toColor) will be located at vector position x2,y2. Supported in Imagemagick 6.9.2-5. |
Radial Gradients
As of IM v6.4.4 you can also generate radial gradient images in a similar way.
|
|
This lets you easily generate a square radial gradient from the center to a corner by making one edge 1.42 (square root of 2) times larger, and crop it.
|
gradient:
" image generator.
magick -size 100x100 radial-gradient:blue rgradient_range1.jpg magick -size 100x100 radial-gradient:yellow rgradient_range2.jpg magick -size 100x100 radial-gradient:green-yellow rgradient_range3.jpg magick -size 100x100 radial-gradient:red-blue rgradient_range4.jpg magick -size 100x100 radial-gradient:tomato-steelblue rgradient_range5.jpg |
Gradients with Transparency
As of IM v6.2.9-8 the "gradient: " (and later "radial-gradient: ") image creation operator understands the use of transparent and semi-transparent colors.
|
Before ImageMagick 6.5.4-7 gradients involving a full transparency (such as the last example) would generally produce a black halo. What was happening is that the gradient generated was from the given color to the special color ' none ' or transparent-black. As a result colors would shade toward a semi-transparent black, before becoming fully-transparent.The solution to this problem was to generate a transparency gradient and then Colorize it with the desired color. |
|
Gradients by Histogram Adjustment
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.
|
Evaluate/Function Gradients
You can also use the Evaluate Operator and related Function Operator to modify a simple linear gradient.
|
|
|
Distorted Gradients
Rotated Gradient
While the Sparse Color method 'Barycentric
' (see below), provides a convenient way to generate gradients at any angle, if your IM is older than version 6.4.3-0 then you may need to use other methods to generate a diagonal or rotated gradient. For example, 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.
|
|
Warping Gradients
But you can use the same distortion methods to do a lot more than simple rotations.
The gradient can also be twisted up...
|
You can re-map the gradient into a trapezoidal shape.
|
|
|
radial-gradient:
" is probably the more simpler method for generating these gradients. A very useful but harder to generate gradient is a polar angle gradient. The exact form of this gradient depends on if the gradient should be centered on an even sized image, or an odd sized image. For example an Arc Distort can be used to generate images with an even number of pixel dimensions, 76 pixels in this case.
|
-90
' in the above sets the angle for the 'discontinuity' where 'zero' and 'maximum' wraps around to the same value. The value '50
' should be at more than 1/2 the size of the final cropped image. Note how I used a much longer gradient to generate the smaller image. This improves the overall correctness of the result, especially as the image gets larger The closely related Polar Distort can also generate such a gradient, but as it has a control over the exact position of the 'center' of the distortion you can ensure it correctly generates an odd pixel size polar gradient image. In this case a 75 pixel image (radius = '36.5
' )
|
36.5
' which is half of the '75
' pixels wanted. The '.5
' offsets is the important aspect for correct handling of the polar center. Note that by default the distortion places the discontinuity at the top of the image, as such the Transverse Warp corrects the angle and location of the discontinuity to match that produced by the Arc Distort. Here is a slightly different variant that generates an angular gradient but with a transparent circular mask.
|
49
' is the radius minus 1 as by default a distort adds a 1 pixel anti-aliasing buffer around the resulting image. As such final image is 100x100 pixels.Circular shapes and gradients can be warped to produce some interesting non-linear gradients. For example arcing it using a Wave Distortion can generate roughly triangular shaped gradient.
|
|
Gradients by Composition
You can also modify gradients by combining them using various composition methods. For example you can use the Modulus_Add compose method to produce Venetian blind types of gradients.
|
|
|
Gradients in other Colorspaces
While "gradient:
" generator currently cannot generate gradients directly in some another Color Spaces, (only non-linear sRGB gradient images are created) you can transfer gradients into a different color space to generate interesting effects. For example...
magick -size 30x600 xc:red -colorspace HSB \ gradient: -compose CopyRed -composite \ -colorspace RGB -rotate 90 gradient_rainbow.jpg |
red
') into HSL colorspace, any saturated color can be used. This correctly sets the images saturation and brightness channels to the appropriate values. After this a gradient is generated and copied into the 'Hue' (equivalent to the 'red') channel of this HSL colorspace image. And hey presto when we magick the HSL image back to RGB, we get a full rainbow gradient of fully-saturated colors. Another method is to generate a gradient of just the right values for one of these colorspaces, then change the images colorspace (using "-set
"). This changes the colorspace without changing the color values that we created in the image. Now when we magick back to RGB we get the same rainbow of values.
magick -size 30x600 gradient:'#FFF-#0FF' -rotate 90 \ -set colorspace HSB -colorspace RGB \ gradient_rainbow_2.jpg |
|
Resized Gradient
One trick that was brought up on the 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 tries 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.
|
Some shells like 'csh' and variants, cannot 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. |
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.
|
Of course you are not limited to just a single dimension, with this technique. Here I use a four pixel 'portable greymap' (or PGM image format) to generate a 2-dimensional gradient.
|
The Network Portable Bitmap image formats, are very versatile for generating images from scripts. It is a format that is well worth knowing as a means of generating or manipulating image data. |
If you look carefully you will also see that the gradient also starts from the center of the enlarged pixel, and does not cover the whole image from edge to edge. This becomes more clear if we use a Triangle Resize Filter.
|
The Resize Operator smoothes the color between these pixels according to the "Resampling Filter " setings. By adjusting the filter you can have the resize gradient generate a more edge to edge effect.
|
magick 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
For more information on the "-interpolate
" setting see Interpolation Setting. Another method of generating gradients is to use the special Interpolation Setting. This setting is used to determine the pixel color returned when the pixel lookup is not an integer, and thus does not exactly match a specific pixel. Interpolation then determines the color based on the pixels that surround the lookup point. The default setting of 'bilinear
' for example will linearly determine the color for a lookup that falls between two pixels.
magick -size 600x30 xc: \( +size xc:gold xc:firebrick +append \) \ -fx 'v.p{i/(w-1),0}' gradient_interpolated.jpg |
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, much like "gradient:
" does. The above is actually almost equivalent (see Perfect Gradients for difference) to using a Clut Recolored Images" to recolor a gradient image, using interpolated lookup of the two color image.
magick -size 30x600 gradient: -rotate 90 \ \( +size xc:gold xc:firebrick +append \) -clut \ gradient_clut_recolored.jpg |
magick -size 30x600 gradient: -rotate 90 -interpolate Bicubic \ \( +size xc:black xc:tomato xc:wheat +append \) -clut \ gradient_clut.jpg |
Interpolated lookup gradients can also be expanded to 2 dimensions, and generate square linear gradients (Bilinear Interpolation), just as easily as purely one dimensions gradients.
|
|
The Mesh Interpolation setting however is not available as a Resize Filter. It is a special 2 dimensional interpolation that divides the intra-pixel area into two flat linear triangles, hinged along the diagonal connecting the corners with the minimal color difference. So by making two colors the same color, and using "
-interpolate mesh
" you can generate a very different 2D gradient.
|
Roll your own gradient
The FX DIY 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.
|
When generating gray-scale gradients, you can make the -fx operator 3 times faster, simply by asking it to only generate one color channel only, such as the 'G ' or green channel in the above example. This channel can then be Separated to form the required gray-scale image. This can represent a very large speed boost, especially when using a very complex "-fx " formula. |
|
||
|
How about a 2-dimensional circular linear radial gradient (a cone).
|
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. |
1.42
' (or sqrt(2)
) in the above controls the overall size of the gradient relative to the images dimensions. In this way the radius of the gradient (how far black is from center) is 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.
|
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.
|
Here is an angular gradient, generated using direct mathematics.
|
atan2(y,x)
' function returns an 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 Distorting a Gradient.
More Complex DIY Gradients
ASIDE: This section was created before the addition of Sparse Points of Color, and the had a direct influence on its creation. Of course an FX function can generate color gradients. For example, here is a gradient based on distance ratios, using an extremely complex FX expression.
|
The image processing was performed in a linear color space (RGB) to avoid 'sRGB darken' during the blending of such strong primary colors. See Processing Real Images for more details. |
|
|
hypot()
' function was not used in the above as there is no need to generate a square root of the distance. The above has now been implemented using the Sparse Color methods 'Inverse
' and 'Shepard's
'. As such the above can now be done far more simply using...
magick -size 100x100 xc: -colorspace RGB \ -sparse-color Inverse '50,10 red 10,70 yellow 90,90 lime' \ -colorspace sRGB gradient_inverse_alt.gif magick -size 100x100 xc: -colorspace RGB \ -sparse-color Shepards '50,10 red 10,70 yellow 90,90 lime' \ -colorspace sRGB gradient_shepards_alt.gif |
DIY Gradients and Hues
-- (Hues are hard to deal with)
ASIDE: This was a sort of failed attempt to generate an interesting rainbow effect. It was a failure, but I learned a lot from that failure, which I present to you here. The above works well but I wanted to try and to do better. I thought perhaps I could generate a bright rainbow gradient of colors between the points, rather than generating spots that merges into an average color. So to generate a hue gradient, I tried to do the Inverse Distance Weighted Interpolation in HSB colorspace, though I switched the yellow to blue, to make the colors more equally spaced around the hue, and hopefully provide another way of generating a color wheel (see Gradients in Other Colorspaces above).
|
|
This conversion from a polar Hue to X-Y coordinates would in some ways be similar to just doing the calculations in a non-polar RGB space, which shows that same shade toward gray effects (see previous examples). So if by using a Circular Mean we are in fact simply converting a HSB colorspace into a highly distorted variant RGB, why not just do the task in a linear RGB colorspace, and saturate the colors, to generate the hue!
magick -size 100x100 xc: -colorspace RGB \ -sparse-color Inverse '50,10 red 10,70 blue 90,90 lime' \ -colorspace sRGB gradient_inverse_RGB.png magick gradient_inverse_RGB.png -colorspace HSB \ -channel GB -evaluate set 100% +channel \ -colorspace sRGB gradient_inverse_RGB_Hue.gif |
The image processing was performed in a linear color space (RGB) to avoid 'sRGB darken' during the blending of such strong primary colors. See Processing Real Images for more details. |
Generating the Perfect Gradient (mathematically)
Generating perfect mathematical gradient, such as for Fourier Transforms (which is cyclic), Image Mapping, or even Gradient Mathematics; requires special gradients that is different to the gradients we have so far looked at.
What do I mean by this? Well here is a small 1x5 pixel "gradient: " image, that I have Scaled so you can see the individual pixel colors.
|
|
-0.5
to the images height minus 0.5
, That the pixel coordinates of the actual edges of the image. And if you were to look closely at the results you will find that the top and bottom most pixels are not white or black in color. The pixel is the color of the gradient at the pixels center. Because this gradient is mathematically correct, this gradient will 'tile' correctly when used in special 'tiling' or 'cyclic' situations. The previous gradient image will not 'tile' correctly. You get a pure-white pixel, next to, the pure-black pixel, so as to generate an one pixel gap or 'disjunction' in the mathematical cycle, in situations where pure white and pure black are typically regarded as equivalent values. A simpler way is to generate a "gradient:
" image that is one pixel longer, and chop one pixel, from either end (according to the current "-gravity
" setting).
For example, here chopped the top-most white pixel, as having a black pixel (or zero value) is often more desirable in the final result.
|
Sparse Points of Color
The "-sparse-color
" operator was added to IM v6.4.3-0 will take an image and set the color given at each of the given floating point 'x,y
' coordinates. That is, of the form...
-sparse-color {method} 'x,y color x,y color x,y color ...'
-channel
" setting) will then be mapped according to there relation to these isolated points of color, so as to smooth out the colors between those points. The method defines what that relationship will be. Naturally there are lots of ways to define what the intervening color should be, and which method you choose really depends on what you are attempting to achieve. It can also actually be classed as a completely free-form version of 2-dimensional interpolation (See Interpolation, Wikipedia). Image enlargement, or Resize is actually a specialized sub-set of this, but one where you start with a complete fixed grid of pixels to be enlarged. Unfortunately few of the Resize Filters or Interpolate Methods that are specifically designed to dealing with a grid of points, will translate directly into a free form set of sparsely separated points of color. That is, to say resize involving incomplete grid just does not work. This is also related to "Geographical Information System (GIS)" methods where landscapes are measured using sparsely separated points of height (which are rarely in a strict grid), with the rest of the landscape being determined from those isolated points. In a similar situation meteorology often has isolated points of air pressure and temperature, which then needs to be interpolated. Typically after interpolation the maps are further processed to generate 'iso-lines' showing points of equal value (height, pressure, temperature), producing the various weather maps almost everyone are familiar with. In this case you would think of the generated image as being a simple gray-scale 'height map' of the input data, or perhaps even of all three variables simultaneously, each to a separate image 'channel'.
Barycentric (triangle gradient)
The "Barycentric
" method, will map three and only three points into a linear triangle of color. The colors outside this triangle continue as before. I have marked the input points with a small circle, so that the colors you see are all the interpolated values that were generated by the Sparse Color Operator.
|
The image processing was performed in a linear color space (RGB) to avoid 'sRGB darken' during the blending of such strong primary colors. See Processing Real Images for more details. |
|
|
The triangular masks used above are 1/2 pixel too big due to the way draw draws an extra line around its shapes. See Draw Fill Bounds for details. This could be a problem when generating a generating a triangular mesh of gradients. |
barycentric
' method is in reality a mapping of a linear affine equation to each of the three color channels separately. As such if I separate each of the color channels of the above three point example, you get three simple linear gradients in each color channel.
It is only because of the use of primary colors that the above gradients all were mapped parallel to one of the edges of the triangle. That is, not typically the case. But you will always get a simple linear gradient in each separate channel of the image, and a flat plane of values in 3D color space.
Barycentric and Two Color Gradients
This parallel effect of the triangular barycentric gradient is actually very useful. If two of the points were set to the same color, then those to points will define the 'angle' of the gradient between them and the other colored point. For example by making two of the points 'red
' the gradient will be made parallel to the two 'red
' points...
|
|
Diagonal Gradients
This provides a simple way of generating any linear diagonal gradient using just two colors. For example, here is a particularly nice way of creating a diagonal gradient, going from one corner to another corner, for ANY sized input image.
magick -size 600x60 xc: -colorspace RGB \ -sparse-color barycentric '0,0 skyblue -%w,%h skyblue %w,%h black' \ -colorspace sRGB diagonal_gradient.jpg |
magick -size 600x60 xc: -colorspace RGB \ -sparse-color barycentric '0,%h black -%w,0 black %w,0 skyblue' \ -colorspace sRGB diagonal_gradient_2.jpg |
Two Point Gradients
If only two color points are given, IM will generate the third point for you, so that the angle is perpendicular between the two original points. The result is a simple linear gradient over which you have a lot of control.
|
magick -size 600x60 xc: -colorspace RGB \ -sparse-color barycentric '0,0 skyblue %w,%h black' \ -colorspace sRGB sparse_bary_two_point_wide.jpg |
Bilinear (4 point gradient)
This method fits an equation to 4 points, over all three color channels to produce an uniform color gradient between the points, and beyond.
|
Barycentric
' method (see above). If more than four points are given it will do a best fit of all the points, and thus may not actually match the given color at the point specified. This is not recommended.
Voronoi (nearest color)
The "Voronoi
" method, just maps each pixel to the closest color point you have provided. This basically divides the image into a set of polygonal 'cells' around each point. For example..
|
-scale
" it back to the desired size.
|
All the image processing was performed in a linear color space (RGB) to avoid 'sRGB darken' during the blending of such strong primary colors. See Processing Real Images for more details. |
|
|
-blur
", the larger the gradient between the various 'cells'. However be warned that this may not preserve small colored cells, or ensure the original point remains the color that was given, if it is close to the edge (and another point) of a different color. By using a special 'linear blur' technique, developed by Fred Weinhaus, you can produce a fixed width linear gradient between the cells.
|
autotrace
' settings may need to be adjusted with "-corner-threshold 120
" so it will detect the corners better.
Shepards (spots of color)
The "Shepards
" method uses a ratio of the inverse squares of the distances to each of the given points to determine the color of the canvas at each point. See More Complex DIY Gradients above for examples of how the mathematics is performed. It is a bit like having spotlights of color at each point which interacts with each other, as the light spreads out to an uniform average of all the given colors at infinity.
|
The image processing was performed in a linear color space (RGB) to avoid 'sRGB darken' during the blending of such strong primary colors. See Processing Real Images for more details. |
Inverse (sharp points of color)
The "Inverse
" method is practically identical to "Shepards
", except that it uses a more direct inverse distance weighting of the points given. See More Complex DIY Gradients above for examples of how the mathematics is performed. This was a much later addition to ImageMagick version 6.6.9-7. For example...
|
magick -size 100x100 xc: -colorspace RGB \ -sparse-color Inverse '45,45 red 55,55 lime' \ -colorspace sRGB -fill white -stroke black \ -draw 'circle 45,45 45,47 circle 55,55 55,57' \ sparse_inverse_near.png magick -size 100x100 xc: -colorspace RGB \ -sparse-color Inverse '30,30 red 70,70 lime' \ -colorspace sRGB -fill white -stroke black \ -draw 'circle 30,30 30,32 circle 70,70 70,72' \ sparse_inverse_far.png |
|
Shepards
' method too!
Shepards Power Factor
Both the Shepards and Inverse sparse color methods are actually the same but with different 'power levels' applied to the inverse distance weights. (2.0 and 1.0 respectiavally). As of IM v6.8.0-10, you can set this power level using an operational define, 'shepards:power
', which will be used by the 'Shepards
' method. For example
magick -size 100x100 xc: -colorspace RGB -define shepards:power=0.5 \ -sparse-color Shepards '30,10 red 10,80 blue 70,60 lime 80,20 yellow' \ -colorspace sRGB -fill white -stroke black \ -draw 'circle 30,10 30,12 circle 10,80 10,82' \ -draw 'circle 70,60 70,62 circle 80,20 80,22' \ sparse_shepards_pow0.5.png magick -size 100x100 xc: -colorspace RGB -define shepards:power=1 \ -sparse-color Shepards '30,10 red 10,80 blue 70,60 lime 80,20 yellow' \ -colorspace sRGB -fill white -stroke black \ -draw 'circle 30,10 30,12 circle 10,80 10,82' \ -draw 'circle 70,60 70,62 circle 80,20 80,22' \ sparse_shepards_pow1.png magick -size 100x100 xc: -colorspace RGB -define shepards:power=2 \ -sparse-color Shepards '30,10 red 10,80 blue 70,60 lime 80,20 yellow' \ -colorspace sRGB -fill white -stroke black \ -draw 'circle 30,10 30,12 circle 10,80 10,82' \ -draw 'circle 70,60 70,62 circle 80,20 80,22' \ sparse_shepards_pow2.png magick -size 100x100 xc: -colorspace RGB -define shepards:power=3 \ -sparse-color Shepards '30,10 red 10,80 blue 70,60 lime 80,20 yellow' \ -colorspace sRGB -fill white -stroke black \ -draw 'circle 30,10 30,12 circle 10,80 10,82' \ -draw 'circle 70,60 70,62 circle 80,20 80,22' \ sparse_shepards_pow3.png magick -size 100x100 xc: -colorspace RGB -define shepards:power=8 \ -sparse-color Shepards '30,10 red 10,80 blue 70,60 lime 80,20 yellow' \ -colorspace sRGB -fill white -stroke black \ -draw 'circle 30,10 30,12 circle 10,80 10,82' \ -draw 'circle 70,60 70,62 circle 80,20 80,22' \ sparse_shepards_pow8.png |
power 0.5 |
power 1.0 (inverse) |
power 2.0 (shepards) |
power 3.0 |
power 8.0 |
Summery of Sparse Color Methods
Here is a repeat of the various, 4 point "-sparse-color
" images, for comparison.
Voronoi |
Voronoi (blurred) |
Shepards |
Inverse |
Bilinear |
Voronoi |
Voronoi (blurred) |
Shepards |
Inverse |
Barycentric |
Voronoi
', 'Shepards
' and 'Inverse
' methods are suitable for more than four points. More "-sparse-color
" methods are planned. If you have any ideas mail them to me.
Channel and Sparse Color
The "-sparse-color
" operator is effected by the "-channel
" setting which means you can use that setting to limit its effects to just a single channel, or expand it to the transparency channel. You can also use the "-channel
" setting to speed up processing of gray-scale images by only operating on one channel, then "-separate
" that channel (see Channel Handling for more detail). For example..
|
-channel
" setting to add a transparent gradient to any image, quickly and easily. For example, here I add a transparent Diagonal Gradient, that is aligned so that 50% transparency is along the diagonal of the built-in "rose:
image.
|
The color 'Opaque ' is just another name for 'Black '. Basically it is used when you are really only interested in specifying a fully-opaque color, but the actual color itself unimportant. Similarly with the color 'Transparent '. I could have just as easily used 'White ' and 'None ' respectively. |
Before IM v6.6.8-5 any channels not selected by the "-channel " setting was reset to zero (black) values. This severely limited its effective usefulness |
-channel
" setting, and whether that channel is 'active' in the image being processed. The easiest way is to limited the processing to a single channel. Also note that when using raw numbers, rather than color names, transparency values are 'matte' values (0=opaque) and not 'alpha' values (1=opaque) (for IMv7). As such in the above I could have used numbers instead of color names...
-channel A -sparse-color Bilinear '0,0 1.0 -%w,%h 1.0 %w,%h 0.0' |
Sparse Color as a Fill Operator
One of the original reasons for creating the Sparse Color Operator, was so that you could give an image containing just a small number of fixed points of color, and from this 'fill-in' the rest of the undefined colors. For example, here I have drawn a small number of pixels. The "+antialias
" setting was specifically turned off so no semi-transparent, or mixed colors have been drawn, as such the image only contains the four exact colors specified an no others.
|
Shepards
'.
|
sed
" command in the above takes the Enumerated Text File Format, deletes the first header line and any line containing transparency, before re-formatting it into a list of pixel coordinates and colors. That list is then 'pipelined' into the Sparse Color Operator using the special "@-
" argument. Yes the above is very tricky, but works. At least for a very small number of points. However the more points that are provided, the slower the operation becomes. This is because Sparse Color is 'point' orientated in its processing, rather than image or Morphology orientated. Eventually I hope to be able to provide a set of morphology orientated, 'hole-filling' methods, where you can just give the above image as-is and have it fill in the transparent areas automatically. This point-extraction technique can be combined with the EdgeIn Morphology Method to extract the pixels around the edges of objects or holes, so that you can then 'fill-in' the missing background or holes (as shown in Morphology and Channels). For example...
magick figure.gif -channel A -morphology EdgeIn Diamond shape_edge_pixels.gif magick shape_edge_pixels.gif txt:- |\ sed '1d; / 0) /d; s/:.* /,/;' | \ magick shape_edge_pixels.gif -alpha off \ -sparse-color shepards '@-' shape_edge_in_lights.png magick shape_edge_in_lights.png figure.gif -composite shape_in_lights.png |
Sparse Color Shepards, a Blur Alternative
One alternative to using "-sparse-color
" is to take the image of pixels on a transparent background, and Blur it. Afterward the transparency is junked.
The problem with this is that the original colors not preserved, and you also have the problem of exact what 'sigma' value should be used. Also it does not take into account just now 'near' each color is, as such two colored pixels close together (less than the 'sigma' value) will swamp each other, and become blurred together.A better method is to generate multiple layers of blurred images with progressively smaller 'sigma' values, and the original unblurred image on top.
|
Shepards
' method on the same image, though not as exact, it is very close. However it is likely to be much faster when a lot of input pixels are involved, as it is image (morphology) oriented, rather than calculating using individual points. An other layered blur method is to use Resize to generate a 'pyramid' of blurred images. This technique is detailed in Large Blurs using Resize.
|
-layers RemoveDups
" in the above will remove any extra 'single average pixel' images that was generated, by the multiple 'clone-resize' operations. The images are then resize back to the original size using a Gaussian Resize Filter (the equivalent to a blur). The image order is then reversed so as to place the original on top, and the more blurry layers underneath, before flattening together as before. It has the advantage of only needing to read the image once, doing all the work in a single command. It also works very quickly even for large images, especially as the resize only halves the image at each step, and thus avoids the slow blurring with a very large sigma. The only disadvantage with this method is that you will need to have a rough idea of the original size of the image to restore the 'blurred' images, and to get at least a rough idea of how many resized clones to generate (Log2 of the largest dimension, plus 1). However overdoing the resize clones is not a major performance hit as the resize simply becomes a 'no-op' when the input image has already been resized down to the minimal 1 pixel image. The extra and useless 'resized image layers' are then dealt with automatically using "-layers RemoveDups
".The only real problem is the possibility of the resized images becoming 'out of sync' when handling an image that is not a power-of-two in size. How severe this problem is is not known, but shouldn't be too great, as those images are also the most blurred. Of course it still has the 'leakage' problem of the 'Shepards
' method, so lets look at this problem in more detail.
Shepards Method 'Leaks'
The 'Shepards
' method does not have any understanding of 'boundaries', and as such colors on the far side of some 'line of color' will leak, or 'bleed thru' past that line. Eventually at a large distance you will get a pure average color of all the pixels. This is not always a desirable outcome (though is desirable in some cases). In this example, the closer the 'Red
' curve approaches the 'White
' line, the more the color will 'leak' though the two lines to the far side producing a pink color.
|
|
Plasma Images
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.
|
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.
|
tomato
' and 'steelblue
' tend to work better than pure colors like 'red
' and 'blue
'. By using the same color twice with plasma you can produce a background that is predominantly that color, but with random splotches of colors close to those of the original colors.
|
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.
|
Alternatively you can just spread the contrast of the colors to just make them bolder, but without going to extremes.
|
Fractal Plasma
The plasma generator also has a special fractal mode, which produces highly colorful effects. The colors generated are enhanced to produce more exaggerated color changes.
|
I often find that plasma images are a little 'noisy'. As such they usually will benefit from a little smoothing using "
-blur
".
Here I have have smoothed out the noise from the middle plasma image above.
|
You can use "-paint " to create random blotches of color.
|
Or make the colors more pronounced and circular using the "-emboss " image operator, after using "-blur " to remove the low level noise.
|
By using a "-blur " followed by a "-sharpen " you can produce a more pastel color pattern than we produced with "-emboss ".
|
I actually find generating a swirled plasma gradient to be particularly nice, as a background pattern.
|
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.
|
||
Another way is to copy one of the color channel over the other two, for a stronger, single layer, effect.
|
||
A final technique is to use "-shade " on the plasma.
|
-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.
|
|
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 an 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 simpler 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.
|
-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 similar in their internal pattern.
magick -size 100x100 -seed 4321 plasma:grey-grey plasma_rnd1.jpg magick -size 100x100 -seed 4321 plasma:white-blue plasma_rnd2.jpg magick -size 100x100 -seed 4321 plasma:green-yellow plasma_rnd3.jpg magick -size 100x100 -seed 4321 plasma:red-blue plasma_rnd4.jpg magick -size 100x100 -seed 4321 plasma:tomato-steelblue plasma_rnd5.jpg |
-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 immediately 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 this setting after your 'seeded plasma' will ensure that any later operators correctly generate a randomized result if desired. 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 that 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.
There is no simple solution to this, so unless this is what you are wanting, caution is advised. There is also a definite 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...
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 Images
Raw Random Noise
As of IM v6.3.5 you can generate a purely random image from an existing image using Noise Generator, "+noise " method 'Random '.
|
If your IM is older than this you can still generate a pure random noise image using the slower DIY FX Operator, "-fx ".
|
Or for speed you can use the "-spread " operator to randomize a gradient (separatally for the three color channels) or by using some other image.
|
Random Specks (pixel dust)
Generating images of scattered random pixels can also be very useful. . just remember that each of the three Color Channels of a random 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.
|
G
' or green channel) to select random values from another color channel channel ('R
' or red channel), by using various Image Composition methods.
magick random.png -channel G -threshold 5% -negate \ -channel RG -separate +channel \ -compose Multiply -composite random_black.png magick random.png -channel G -threshold 5% \ -channel RG -separate +channel \ -compose Screen -composite random_white.png magick random.png -channel G -threshold 5% -negate \ -channel RG -separate +channel \ -compose CopyOpacity -composite random_trans.png |
-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.
Blurred Random Images (random blobs)
Now while you can make direct use of random images to create speckled effects, purely random images are generally not very useful. But by Blurring a purely random image you will introduce some 'neighbourhood' order, such that nearby pixels become related. For example, here I blur just one random image, causing the random values to produce larger 'blobs' or mottled colors.
magick random.png -virtual-pixel tile -blur 0x1 -auto-level random_1.png magick random.png -virtual-pixel tile -blur 0x3 -auto-level random_3.png magick random.png -virtual-pixel tile -blur 0x5 -auto-level random_5.png magick random.png -virtual-pixel tile -blur 0x10 -auto-level random_10.png magick random.png -virtual-pixel tile -blur 0x20 -auto-level random_20.png |
-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 an inherent result of pure random images being so random to start with. Blurred Random Hues
One particular conversion of a blurred random noise image that I found particularly pleasing is to map the values into HSB color hues.
|
The best solution I know of is to simply add all three random channels in the image (using Modulus-Add Composition) so as to extend the range of values. This also have a side effect of making the blurred spots smaller, but at least you now get a more dynamic range rainbow colors. Anyone got a better idea?
|
magick random.png -channel G -separate random_0_gray.png magick random_1.png -channel G -separate random_1_gray.png magick random_3.png -channel G -separate random_3_gray.png magick random_5.png -channel G -separate random_5_gray.png magick random_10.png -channel G -separate random_10_gray.png magick random_20.png -channel G -separate random_20_gray.png |
magick random_0_gray.png -threshold 50% random_0_thres.png magick random_1_gray.png -threshold 50% random_1_thres.png magick random_3_gray.png -threshold 50% random_3_thres.png magick random_5_gray.png -threshold 50% random_5_thres.png magick random_10_gray.png -threshold 50% random_10_thres.png magick random_20_gray.png -threshold 50% random_20_thres.png |
Random Granularity (order in the chaos)
Now remember all the blurred random images were generated from the same initial random image, thus they are all related. But every new random image generated will have a completely different pattern, though the patterns will more or less look similar in structure.
But first lets give a full example of generating a 'blured random image' from scratch...
|
-channel
" setting to limit operations to the 'Green' channel of the image is important as it speeds up the overall generation of the image by a factor of 3. The Channel separate will then ensure we get a pure grayscale result. If you want you could leave out both "-channel
" settings, which will result in the generation of 3 completely separate and different 'Blurred Random Images'. The image has some important characteristics, which we can see more clearly if we divide the image up into three equal sets of colors (using a technique called Posterization), you can see that inside each of the black and white zones you get more circle blobs or 'granules'.
For example...
|
The 'Granularity' of a random image (or blur factor)
determines the size of the circular structures within
Of course the smaller the 'blur factor' or 'Granularity', the smaller or tighter the curves become, until you reach a value of 'determines the size of the circular structures within
0
', at which point, all the clumping or 'blobs' within the image vanishes, and you are least with a purely random 'noise', 'snow', or 'pixel dust' type of effect.ASIDE: Actually the size of the actual 'granules' themselves can vary depending on the threshold factor used to generate them. What the factor really describes is the average distance between centers of the white and black areas. The larger the value the larger the distance, and the larger and more spread out the spots have to be to accomidate that increased distance. This becomes more obvious when we start looking at Random Ripples below.
You may also like to try using a 50% Solarize operation with some extra Level Adjustments to extract both the well separated black and white granules from the image.
For example, here is a full example with a granularity of '8 ' and a blob threshold of '25% ' generating white spots from both black and white parts of the image.
|
animate_granularity
", which you can download, study and play with. Note that as the same random image is used as a source the 'granules' or spots do not really move, but just sort of grow together, or fade away, so as to produce larger 'granules' with increasing granularity. Also remember that while I have reduced the number of colors in the animation, the structure of the full random image is actually smooth gradient between two sets of white and black granules. This gradient is what makes the image useful in other techniques.
Random Flux (animation cycles)
Now as you saw above the granules or spots do not actually move all that much. But for animation effects you want a pattern that moves smoothly in time. Also you don't want that pattern to just simply move back and forth. And finally, you do not want that pattern of movements to suddenly jump or jerk as the animation loops. So what we need is some way to generate a smoothly repeating random pattern. A tall order. Also as you need it to be smooth, you will need to generate all the patterns from the same single random image. Here is an idea that allows you to generate such a random pattern. Rather than think of each random pixel value as being a random intensity, we instead think of that value being a 'time' value defining when that pixel is at its maximum or minimum intensity. That is, we magick that value into a position on a 'wave'. Thus each pixel represents some 'phase' of a sine curve. This sounds complicated, but in reality it isn't. We just use the Random Image as a source image for a Sinusoid Function. Now for each image in the time sequence we set the time 'phase' for that particular point in the time cycle.
magick random.png -function Sinusoid 1,{time} \ ... do granular blurring, and other processing ... |
{time}
' goes from '0
' to '360
' over the complete animation cycle. The result is that instead of each pixel having a 'static' random value, we now have one that cycles in a loop between black and white over a period of time. Each pixel will follow this same cycle, but as each pixel has a completely different 'phase', and will cycle independently of all the other pixels. That is, the image is still random, but smoothly changing with the provided 'time' value. For the scientifically minded this is a bit like looking at the 'quantum flux' that exists at sub-atomic level, where space is far from the 'static' state we see at normal scales. Hence the name 'Random Flux'. For example lets generate a time sequence of 12 images...
|
180
' (bottom right), you actually get the exact negative of the first image (top-left). That is 'white' granules has become 'black' granules, and visa-versa. In fact the whole second half of the animation is actually the negative of the first half. This can be used to cut down the generation time of a simple 'Random Flux' animation. Because the image is a negative at a 180 degree phase, you will find that each 'white' granule slowly moves so as to swap places with a neighbouring 'black' granule. But as the whole second half is a negative of the first the it can't just simply shuffle back-and-forth, but must continue move forward to return to the original image, or circle around in a loop, or simply fade and appear appropriatally. In other words the white and black granules move in far more complex cycle.
To the right is an animation of the above frames... The fluctuating pattern is completely random, but smoothly changing from frame to frame, and when the animation loops. You can see no beginning or end to the result. Sometimes you will get a swirling of movement, other times it looks like all the 'gas' like blobs are being sucked into a dark zone, or just appearing and fading away again. You also get periods of very fast movements, as well as very slow movements. It is totally random. In summary: The same properties present in Blurred Random Images are also present in this animation. The image remains a roughly equal division between white and black segments, and it forms blobs of about three times the size of the blur or Granularity of the image. But on top of this you are guarantied that all parts of the image will form some cycle between both lighter and darker colors, as half the cycle is the negative of the other half. One thing you may not have noticed is that due to the conversion of a random linear value into a sinusoid waveform, you will get a sharper white and black separation of colors (contrast). As such you may like to use the de-contrasting aspect of Sigmoidal Contrast operator to make the resulting image less 'blob' like, and enhance the gradient between the granules, rather than the granules themselves. Now this is only a starting point for what you can do with a cyclic random animation. Everything that you can do with a Random Image, such as described in Generating Backgrounds, can also be applied to 'Random Flux Animation'
For example, lets just show the movement of just the 'white' granules...
|
|
To make the motion less predictable for a longer cyclic sequence, you can also use some Gradient Math to combine multiple Sinusoidal Cycles, from multiple random images, or even just using the other color channels of the same random image.
FUTURE: Create even less predictable, long time 'harmonic' cycles.
Random Ripples
By adding another variation to a Blurred Random Image we can add another level of complexity that makes these images far more useful, and gives use another control variable beyond its Granularity. But first you need to remember that the random image does not consist of just bright and dark areas, but also contains a slope between those areas. Using that slope as into to the Sinusoid Function, you can generate ripples between the spots in the image. Note that key difference to this use of the Sinusoid Function to the previous Random Flux examples was that this time the function is being applied to the image AFTER it was smoothed using blur, instead of before. Also in this case it is the 'Frequency' value, and not the second 'Phase' value that is more important. For example...
magick random_10_gray.png -function Sinusoid 1,90 ripples_1.png magick random_10_gray.png -function Sinusoid 2,90 ripples_2.png magick random_10_gray.png -function Sinusoid 3,90 ripples_3.png magick random_10_gray.png -function Sinusoid 4,90 ripples_4.png |
1
' will basically magick both the Light and Dark 'blobs' in the source image to white, and leave a dark gap between them. A 'Frequency' of '2
' squeezes an extra 'ridge' or 'ripple' in that dark gap. As the frequency increases you get more and more 'ripples' between the lightest and darkest areas of the original image, making it more an more complex. As the number of ridges increases, you can lose sight of the original 'blobs' or 'granules' in the image. You can fix this by modifying the gradient before adding the ripples, either by 'clipping' the gradient using a Level Adjustment, or compress the midtones using Sigmoidal Contrast. This will give the 'granules' some mass or area, providing areas of 'calm' between the ripples.
magick random_10_gray.png -level 25% random_enhanced.png magick random_enhanced.png -function Sinusoid 4,90 ripples_4e.png magick random_10_gray.png -sigmoidal-contrast 10,50% random_sigmoidal.png magick random_sigmoidal.png -function Sinusoid 4,90 ripples_4s.png |
The second value '
90
' used above examples is the 'Phase' of the Sinusoid Function. It will determine the color that the 'black' granule in the source image will become in the 'rippled' image.
magick random_enhanced.png -function Sinusoid 3,0 ripples_3e000.png magick random_enhanced.png -function Sinusoid 3,90 ripples_3e090.png magick random_enhanced.png -function Sinusoid 3,180 ripples_3e180.png magick random_enhanced.png -function Sinusoid 3,270 ripples_3e270.png |
90
' both will be white.
However if you apply a fractional 'Frequency' value of say '0.5 ', the 'white source' granule, will be the negative of the 'black source' granule (as determined by the 'Phase').
|
0.5
' fraction is used, the first ripple around each spot will be all white or all black, depending on the 'Phase' used.
Other 'Frequencies' other than integers, or '0.5 ' are not recommended as the two sets of granules will not be synchronized in some way.Similarly Phases other multiple of 90 degrees are not recommended unless generating a 'ripple animation' (see below). A Phase value of ' 0 ' is recommended when generating a 'Dispersion Maps' (see below) as this will cause minimal distortions within the enhanced 'granule' areas. |
|
For example, here I just take the previous Flux Animation created above, and add ripples to it. The ripples will in this case move only because the gradient in the flux animation moves.
|
|
FUTURE: Use of Rippled Random Images for Dispersion Mapped Distortions.
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 |
rings.jpg |
tile_disks.jpg |
tile_weave.gif |
-tile
" any image so as to completely replace the original background image (using the "Copy
" compose operator). (For more details see Tile Compositing).
|
Another way is to read in the tile image using the "tile: " coder, and tile it to a specific size.
|
Note that the "tile: " coder will replace any transparency in the image with the current background color. That is, because internally it generates a canvas of the size requested and 'overlays' the tiling image onto that canvas.If you want to preserve transparency either set " -background none " or "-compose SRC " (see Src Compose Method for details). |
-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.
|
-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 of the "-fill
" color setting used by draw. See MVG Drawing Settings.
|
-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).
|
-tile
" instead of a "-fill
" color.A more advanced method is to use a Distort Operator with a special Distort Viewport setting, that was set to the size of the original image (using a Defined Global Artifact and Percent Escapes). This basically maps the smaller tiles Virtual Pixels, that surrounds the small tile image, to generate the larger tiled canvas.
|
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:
".
magick -size 80x80 -tile-offset +30+30 tile:rose: offset_tile.gif magick -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 "magick montage " background "-texture " setting.
|
You can also use the setting by defining it before the "-tile " or "-fill " setting. For example...
|
-size
" setting is reset before defining the "-tile
" image, but after any other image has been read in.
|
Tiling with an Image already In Memory
Tiling an image you have in memory (created or modified) is not straight forward, and only a few indirect methods are available.
Clone and Append the Tile Image
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.
|
|
Tile using MPR: (Memory Program Register)
A better method is to save 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...
|
Remember that the "tile: " coder will replace any transparency in the image with the current background color. (see above) |
Or tile over an existing image, by setting the "-tile " or "-fill " fill pattern, and using "-draw " to do a color reset (see Color Fill Primitives)...
|
If tiling with an image containing transparency, ensure the destination image also has transparency by using "-alpha set ". If you do not the resulting image will show the tiles 'hidden' transparency color. |
Or draw using some other Draw Primitive, such as a circle, using the fill pattern.
|
mpr:
" can be anything you like, it is only a label on 'mpr' register name used to store the image, (in memory). It can even be a label, number, color, or even a filename.
Tiling using Virtual Pixels via Distort
In this method we use the Virtual Pixel Setting to generate a large tiled canvas. This setting defines how the area surronding the actual image (outside the normal image bounds) should look. The easiest way to extract virtual pixels is to use the Distort Operator with a special Distort Viewport setting.
|
You also have access to other styles of virtual pixel tiling settings, such as 'Mirror ', or even 'CheckerTile ', and even good offset tiling control using the viewport setting.
|
45
' specifies the angle the width of the tree covers, while the '50
' defines the radius for the top edge of the tree tile. The rest just follows from this.
|
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...
|
-size
", or as a fill tile (see Tiled Canvases above). Without a size setting the default tile size of the pattern will be used, 30x30
pixels in this case. 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...
|
-opaque
" image operator.
|
checkerboard
" pattern, then that is best done by first using "-auto-level
" to map the two greys to black and white before substituting those two colors. Here instead of using "-opaque
" to replace the colors, I use a "+level-colors
" operator (add IM v6.2.4-1), which is a bit simpler to 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 with the regular pattern of colors I wanted.
|
You can also warp and distort a simple tiling pattern to produce an interesting variations. For example a 'wrinkling' effect (technique courtesy of the wrinkle IM effect from Font Image Generator) on a hexagon pattern I found particularly interesting
|
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.
|
|
|
Alternative
There is an alternative to relying on Virtual Pixels. 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 built-in 'hexagons
' pattern.
|
|
Generating Tile Images
The biggest problem you face when generating images that 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 with a repeated copy of the image. This is not an easy matter and can be a very frustrating and hair pulling experience. An object appearing in the tile on one edge must re-appear on the other side of the image in order to re-form the whole when the image is tiled. While you can do this fairly easily with computer generated images, it is next to impossible to produce a good tiling image featuring real-world photographs. The other major problem is trying to make the tile not look like it is repeating. The only true solution to this is to make your tile images large enough to contain enough very similar, but still different elements that it becomes difficult to see a repeated pattern. For this reason, generating small tiles that do not seem to repeat is especially difficult.FUTURE: Ideas and suggestions for generating tile patterns? Anyone? Or roll, add element, roll, add element, etc... Any and all suggestions and examples accepted. Suggestions for generating tile from real photos of repeating patterns, such as water, fallen leaves, clouds, stucco, brickwork, etc... Generating Escher-like tile patterns.
Random Noise Tile
Because a raw random noise canvas has no edges characteristics to begin with (every pixel color is completely independent of any of its neighbours), you can tile it without worry about edge distortions. Basically it is so extremely random at the pixel level, no edges match to begin with, so we don't lose anything, by tiling. Unfortunately very few situations would use a raw random noise image, as is, for any real purpose. It is just so horribly random that it is useless. However by modifying the image while preserving its inherent tilability, we can make just about any randomized tile pattern we want.
For example lets look at the a basic "-blur " of the original tile, using the same 'modifying a tile' technique we used in the last example.
|
|
Using this technique you can apply just about any transformation to a raw random noise image image. For example...
|
|
Hexagonal Tiling
Rather than tile in a square fashion, the 'random noise' image allows use to generate a very different sort of tile. By doubling the image dimensions and re-laying the tile in the extra space, but offset by half, we can generate a basic random noise hexagonal tile pattern.
This is the same sort of tiling effect we get when we tile the special "pattern:hexagons " built-in of ImageMagick.
|
|
Here we overlay the same 'random noise' image (a rectangle with a 2:3 ratio) two extra times to generate the basic hexagon pattern (in a 4:3 rectangle). The hex-tiled random noise tile is then transformed using the "paint_3s" transformation from the Background Images page, to generate a rather nice looking hexagonal tile pattern.
|
|
Mathematically the above is not generating a new Wallpaper Group form an existing tile. Both the original 'non-hexagonal' image and the final verson belong to the same 'p1' tiling group. What we are actually doing in the above is converting a rhombus 'prototile' tiling pattern into a larger rectangular orthogonally aligned 'fundamental domain' of the same tiling pattern. In this way you can then tile the image using a standard tiling method. |
Triple Hex Tiling
Like we did when coloring the the "hexagons
" built-in pattern (See Modifying Built-in IM Patterns/Tiles above), you can make three different variants of the initial tile, (with rotations for example) before re-mapping them to form the larger tile. Of course, just as I did when coloring the "hexagons
" pattern, the final tile image will need to be enlarged three times larger, so as to generate a repeating rectangular tile pattern. The variations between the three tiles generated must not be too different, and should survive any post-processing, otherwise you will not get the benefits of the technique. This means the initial tile must be reasonably large as well, so any distinct features present will be preserved. For example, here we take a very simple line drawing, and rotate it to produce 3 similar variations. These rotated images are then tiled seven times onto a larger canvas (6 times larger) to produce the triple image hex pattern.
|
|
Diagonal Mirror Tiling
Here is one way to take any square image and magick it into 8 mirrored images around a central point. Specifically we are generating a complex 'p4m' tiling pattern. I first generate Random Hue Image, and using the bottom-left half of the source image I mirror it diagonally, then horizontally and vertically.
|
|
|
For a more complete introduction into tiling images and the mathematics behind them, see Wikipedia: Wallpaper Group. What we have explored above is only a few of the many tiling patterns you can create.
The 'p4g' is almost exactly the same as the 'p4m' tiling above, but uses a 180 degree rotations of the mirrored squares, rather than using flips, to generate the full tiling image. However as the images are not joined by mirrors you can not use an existing image as the tile source as the edges will become disjoint and discontinuous. However you can tile the raw random data then process the resulting tile image, to produce a smooth result.
|