ImageMagick v6 Examples --
Future Development

Index
ImageMagick Examples Preface and Index
Known and Fixed Bugs Index
This page known problems in areas of IM currently under development, so are not true bugs, but works in progress. Also listed below are new enhancements and suggested development within ImageMagick itself.

Current Development

MVG expansion to allow full use of SVG gradients

SVG gradients which are overlaid as a 'fill tile', can be defined using multiple colors (not just two), linearly from one point to another (any angle), radially, or using path shapes. The how range is defined in the SVG -- Scalable Vector Graphics manual.

Currently IM only supports vertical linear gadients across the whole canvas of the image.

This lack is becoming important as just about every SVG image I have looked at relies of gradients of various forms for shading images. Without it the SVG image conversion are basically yuck!.

An expandsion of the "gradient:" syntax to provide extra options would also be good. For example (posibility only)
  gradient:'red=.1-green=.3-blue=.9, 1,1, 50,90'

Future Development Proposals

These are suggestions for the future development for IM. They are currently not being developed but have been requested my myself and other users on the IM mail lists and web forum.

Some of these may never be developed, others may not be provided until a new major version number release of IM. Some may appear next week!

If you feel you can help, you can attempt to program these into IM and send the patches to Crisy. I am sure he wold welcome them.


Scripted form of Convert Command

What is really needed is for the command line API to be re-written in such as way as to allow...

This re-write may require some re-coding of mogrify which current does some very weird argument handling to seperate the list of images to process, from the operations and settings needed to process them. For example some settings need to be pre-set before reading the first image!

Actually is a "loop over image list" type construct is implemented, then it may be posible to make 'morgify' a special case of convert, just as 'montage' is a special convert with post processing of the final image list in memory.

This new command line API could in fact be done as a separate command to convert, but will need someone to get the ball rolling and keep it moving. One previous attempt that failed (probably was done before IM was ready for it) was "conjure". the new version would have to be BOTH command line and script capable, and do what convert does to properly replace convert.


Contrast, Auto-levels, Auto-Gamma, De-normalizing problem

A IM Forum Discussion has resulted in a request for a "-histogram-stretch" operator which normalizes the image so that the given percentage of the brightest and darkest pixels are pegged to black and white. That is a single odd white or black pixel will not majorly effect the overall result.

A "-linear-stretch" operator was also added recently.


Another IM mail list discussion between Jason Lamey and Ed Halley, talked about a posible gamma level auto adjusting operator.

Fit a gaussian peak to a histogram. This will give you a peak position, and a width for the peak (two half-widths, actually). Then choose a gamma value that will realign the distribution to be more centered and appropriately wide.

Redistributing the Histogram based on 'equalizing' the colors to fit a gaussian peak was also suggested by a image expert Fred Weinhaus. The overall brightness and contrast of an image can then be controled by two simple arameters (mean and std).

 A simpler and linear transformation can be effective if one computes the
linear transformation from a formula that uses desired mean and standard
deviations along with the image's actual mean and standard deviation. That was
why I was asking if you have a function that can extract the images mean and
standard deviation (as well as the min and max values). Something like
"-identify or info:" but more of an image statistics function that would report
these values per channel.  This could be very useful.  
I have yet to find a real-world use for "-equalize"


The current "-contrast-stretch" operator normalizes images using the peak color values in the image, then moving those points inward by the percentages given. This provides a more controled normalize.

However at this thime there is no easy 'controled de-normalize' either using specific colors, negative arguments for "-levels", or negitive arguments for "-contrast-stretch" arguments. Only a "+sigmodial-contrast" provides any sort of controled de-contrast function. The current "-contrast" function which has no control argument should be just scrapped.

The lack of a standard simple de-normalize is a real problem that should be looking at. About half of the current Color Modifications section is devoted to given ways to implement a simple linear histogram adjustment.

Recommended Solution...

This whole situation is bad, and something needs to be done. Preferably with a common 'core' function that all the other functions can be defined against. Prehaps as a multi-channel color-color mapping to color-color.


Equalized Sub-division of an image into tiles

It is currently not posible to sub-divide an image directly into a specified number of tiles.

You could do the maths and work out the tile size for the above Tile Cropping, but that will only work correctly for images that sub-divide exactly by the number of tiles wanted. If it does not then you will be left with a set of small 'reminder' tiles along the bottom and right edges.

For example try to sub-divide a 100x100 pixel image into 13x13 tiles will not work very well. Using "-crop" with 'best fit' '7x7' crop tile size, but that leaves a smller remainder image on the ends. Not want you wanted.

IM really needs an option to subdivide images, as equally as posible. Such an operator will produce some rows and column of tiles that are say one pixel smaller or larger than neighbouring rows and columns, but the tiles will be reasonably equal.

Does anyone have a script to do this?

Suggestions for a new option anyone?

What about making '@' the tile sub-division flag. That is something like "-crop 13x13@".


Divide an image into horizontal rows (or columns) of pixels

Given an image, divide the image into rows (or columns) basied on rows of pixels which are simular to each other (according to the fuzz factor).

One implementation would be to divide image into blank,non-blank... alturnating rows extracted from the image. An argument can used to place constraints on the minimum size for the separate blank and non-blank areas. A missed image at the start can denote if the first part was non-blank, something that is commonly just junked.

The offset positions can be kept or junked as per crop.

Two operators may be needed, -divide-vert and -divide-horiz.
EG: divide-horizontally +{bw}+{nbw}

Complementary operators such as -layers 'remove-blank' and -layers 'remove-null' may be needed to allow user to also delete 'blank' images if these are unwanted.

ADDUMDUM I wrote a script divide-vert whcih does basically what I am suggesting gets built into IM.

Another similar script is de-pixelate which removes 'doubled' rows and columns of pixels from an image.


Miscellanious functions to be added..

Other fuctions...

Add a -resize-fill operator

Rather than resizing an image to best fit into a box, create an operator "-resize-crop" which resizes the image so as to best fill a box box. The image is then automatically cut to fit using "-crop" with the same argument and the current "-gravity" setting.

See Resizing to Fill a Given Space for the current multi-resize work around.


Consolidation of Specialized Blur Options

Currently we have two specialised blur operations... "-radial-blur" and "-motion-blur" as generic blur operations.

First of all "-radial-blur" is miss-named, as it is really a rotational blur. A radial blur would blur out from the center point of the image or region, not in a circle around that point.

Secondally these speciallised blurs are only the start of a whole set of blur type operations that should be made available. And implementing as a single option per blur type woudl produce far too many options. It needs to be consolidated before new types of blurs are introduced.

I can see 7 types of special blurs...
Type Direction Description
linear one direction like -motion-blur
linear both directions like a 1d blur, but at any angle)
rotational one direction like a electron around an atom
rotational both directions like -radial-blur
radial out of small circles would look like
asteroids speeding from the center
radial into things heading toward the center
radial both in & out

I propose a single 2 argument operator for specialised blurs...
   -special-blur {type} {radius}x{sigma}+{dir}+{angle}
Where...

I do not want to seperate these into seperate settings as they are linked too closely to the specific operation being performed.

ADDITIONAL: A request has been made to provide a height variable blur. That is the blur starts with a sigma of 0 at y=0 and is at its maximum at the maximum height (bottom) of the image. Direction for this special blur could be limited to 90 degree angles as a simplification.

This will allow the generation of a more relistic shadow and mirror effects, especially if used with other distortions to add surface 'roughness' to the mirror image.

If you can think of other sorts of specialised blurs, mail them to me or the IM mail list or forum.


Adjust Color Quantization to understand 'Common Colors'

Currently Color Quantization is an all or nothing affair. Either you have it pick all the colors, or you pick none of the colors.

I would like to be able to give Color Quantization a user defined map of 'fixed colors', around which it can pick the other 'best' color selections posible.

---

Things in this regard has improved with some 'tweeking' of the complex quantization algorithm IM uses, so that colors which are common in the image do get picked.


Specify the exact depth for specific output formats

At this time depth is generally restricted to 8 or 16 depending on the compile time Q-level of your IM installation. That is setting of "-depth 4" only results in 8 bit images, not 4 bit images. Of course that is only valid if the image format and IM even allows the use of 'depths' for that image format. These depth/quantium restriction is becoming a problem for many image formats such as NetPBM, TXT (IM pixel enumeration), BMP, TIFF... etc..

Actually instead of "-depth", prehaps we can specify an exact "-quantum" for text image formats such as TXT: PGM: PPM: all of which should allow you to specify a different 'quantium' for its format.
   convert -size 1x1000 gradient:  -quantum  1000  t.pgm

    P2
    1 1000
    999
    999 998 997 ... 3 2 1 0
Where all image data values are in the 0 to 999 inclusive range.

If "-quantum" is unspecified (or reset using "+quantum"), it can fallback set to a default of 2^depth (if it ever allows depths other than 8 and 16!)


Justifications for Append

Addition of justification features to "-append". This first requires append allow left/right/center justification of images perpendicular to the direction of the append.

However this also can be expanded to allow the addition of spacing (with approriate justifications, between the images, when an appropriate a "-size" has been gievn.

Ascii art of justification styles (horizontal)
Left
|-||---||--|        
Center
    |-||---||--|    
Right
        |-||---||--|
Justify
  |-|  |---|  |--|  
Array
  |-|   |---|  |--| 

Note 'justify' just divides the extra space equally between each of the images and edges, while 'array' divides the whole space into equal sized areas (or tiles in "montage" terms) and centers each image into each of those areas.

Both of these specal settings should default to 'center' in the direction perpendicular from the append itself, unless separate X/Y justification settings are also provided by the user.

Future: a special 'Baseline' could use extra baseline info from images created as a single line text "label:", to line up mage along there baselines. For images, that baseline would me the center line of the image which lines things up properly.

Note that "justification" and "size" both have seperate horizontal and vertical settings, and the appropriate setting should be used for the appropriate direction being appended.

NOTES:
  1. "-append" will also need to report in meta-data the final size and offsets of the appended images that can be used for HTML image map generation. Do not 'guess' or try to work it out later! Use the real information.

  2. The "-gravity" setting probably should NOT be used for this. But a new "-justify" setting be used here, and then slowly spead this setting to its use in other operators as time goes by.


Text/Image Justification Setting (as distinct to gravity positioning)

Seperate the controls for text/image justification from the gravity position. and can also consist of a vertical and/or horizontal setting.

If the justification is unset use the gravity setting can be use to fill-in the justifications.
   gravity_setting            default justification setting
      undefined             Baseline        or  TopLeft (for images)
      North                 Top                 TopMiddle
      South                 Bottom          or  BottomMiddle
      East                  Right           or  MiddleRight
      West                  Left            or  MiddleLeft

      Center                Middle          or  MiddleMiddle

      SouthEast             BottomRight
and so on.

Note that justification can also have extra settings that are quite different to that supplied by gravity, specifically a vertical 'Baseline' justification. For images, this will fall back to 'Top' 'Center' Bottom as appropriate for the current "-gravity" setting.

Also there is a special 'Array' setting though this is only usful for the "-append" or montage like operations.


Montage abilities from convert

Addition of a "-layers" method 'montage' to take the image sequence list and generate a array of images in the same way the "montage" command does.

Also a 'montage_caption' method which given an output "-size" (width only) inserted images into lines in the same way "caption:" does for text. That is That is each line of images is filled to a given output width, before the next line starts.

As individual images are separate enitys, this caption-like operator could also conceivably also do vertical and horizontal centering, and even horozontal justification of images (under "-gravity" or a new "-justification" settings).

Other simular "-layers" options can also be provided.

Remember "-append", "-mosaic" and "-flatten" are really only image layer reduction operators.

This probably requies the Justifications for Append shown above to be implemented first.

Posible Meta-data needed to be saved with images...
"baseline" used from single line lables (reset when invalid)
"filename" used to generate this image, (hyperlinks)
This is already done for images made from one single image
"Area covered" by a particular "filename", Added by append
This may be extended to also be added by 'mosaics' and 'flatten'
Note that without size changes, areas remain the same, only offsets change.

Output size control for Montage

Often it is imposible for a user to know how big a "montage" will be, and it has, many times, been suggested that some sort of output size control added.

That is specify a final size and geometry size, and let montage work out the tiling, (and perhaps geometry spacing) to produce however many pages are nessary. Of course if the width of the individual tiles (as determined by -geometry is more that the final output size, then all bets are off, and a warning probably should be issued.

Or, specify the final size and number of tiles, then let montage work out the geometry needed. What algorithm should be used for figuring out tile size verses tile spacing is another matter, particularly when labels and framing also needs to taken into account.

It may be that in both cases some extra boarder space will be required to 'pad out' the image to the exact image size requested, as a variable geometry or tile setting may not generate an exact fit.

At the moment there is no defined method of setting a final output image size. Also what should "montage" do if all three (size, tile, geometry) is given.


One suggestion is to allow the use of a '!' flag to "-tile" as meaning a 'fit to this size if posible' setting. Of course the -tile setting (and extra boarder space) would then be the variable part of the montage generator.

EG: "-tile 800x600\!" would mean that montage will try to adjust the tile counts to form pages that fit into a final image of this size.

OR: "-tile 800x\!" will only adjust the number of columns to fit into 800 pixels, in a single page of appropriate length.

Some extra spacing may have to be added to the edges to handle any remaining space that can't be assorbed by the tile geometry size or spacing.


Shadow controls in Montage (interface change - require major release)

Add some control to shadows within "montage" to allow user defined hard or soft shadows in a simular way that the new "convert", "-shadow" operator does.

No suggestions as to implimentation, as "montage" "-shadow" setting should probably remain a boolean on/off operator, unless it is added as part of a major version number release.

Simularly add some extra framing controls, would be nice if more that a single number is given.


Simplified Trapaziodal Transform

This s a bit like "-shear", or "-wave". The bottom row remains unchanged (most common case requirement), but each side is slanted inward by the angles given, shinking the length of the top of the image. If only one angle is given the other is set to be the same value.
EG   -trapezoid 30   will turn

   +----------+                    +--+
   |          |                   /    \
   |          |     In to        /      \
   |          |                 /        \
   +----------+                +----------+

With a thin, and high image, or two high an angle you could
flip the image left to right at the top...

   -trapezoid 45

   +----+                +---+
   |    |                 \ /
   |    |     In to        X
   |    |                 / \
   +----+                +---+

This operator can of course do a x-shear if the
second angle is the negative of the first.
The image size of course should be adjsuted to suit.

   -trapezoid 30x-30

   +----+                 +---+
   |    |                /   /
   |    |     In to     /   /
   |    |              /   /
   +----+             +---+
Optional extra...
-trapezoid {angle}[x{angle}][+{row}]
if a row value is given, then that row of pixles will be the one unchanged. Default is the bottom row.
EG:   -trapezoid 30x30+30
with an image 60 pixels high...

   +------+                    +--+
   |      |                   /    \
   |      |     In to        /      \
   |      |                 /        \
   +------+                +----------+

The top will resize smaller, while the bottom resizes larger!

Or flip the transform to keep the top row unchanged.

EG:   -trapezoid -30x+0

   +----------+                +----------+
   |          |                 \        /
   |          |     In to        \      /
   |          |                   \    /
   +----------+                    +--+
For scaling in the vertical direction, a rotation will be required, just as it is needed for horizontal waves with the "-wave" transform.

NOTE: you can do this type of distortion (or any type of distortion) using Distortion Map, however that still leaves the problems of creating such a map.


Combine channel images from other color spaces

Using the builtin rose image....

   convert rose: -colorspace HSB -separate rose_HSB_%d.gif
   convert rose_HSB_?.gif -colorspace HSB -combine x:
   convert rose_HSB_?.gif  -combine x:

Neither of the combined images comes out correctly.

The problem here is that  -combine   only combines Red, Green, Blue
grey-scale channel images into a RGB image.

But if you use   -colorspace HSB  operator on the input images, then it
re-organizes the greyscale images into HSB grey-scale equivelents.
These naturally do not combine to produce the original RGB image!

This can be classed as a bug, and it is a consequence of how combine was
first developed.  That is -combine is  basied on this example channel
coping example...

    convert rose: -channel R -separate separate_red.gif
    convert rose: -channel G -separate separate_green.gif
    convert rose: -channel B -separate separate_blue.gif

    convert separate_red.gif  \
            separate_green.gif -compose CopyGreen -composite \
            separate_blue.gif  -compose CopyBlue  -composite \
            rose_composed.gif

This brings up the solution...

    convert rose: -colorspace HSB -separate rose_HSB_%d.gif

    convert separate_HSB_0.gif -colorspace HSB \
            separate_HSB_0.gif -compose CopyRed   -composite \
            separate_HSB_1.gif -compose CopyGreen -composite \
            separate_HSB_2.gif -compose CopyBlue  -composite \
            -colorspace RGB   rose_HSB_combined.gif

The first line just creates an image the right dimentions, though the
image should probably be cleared, incase not all the channels are being
copyed into it.  It then copes the RGB-grayscale channel images into
this correctly colorspaced image.

This example is

This WORKS.  But requires you to know the colorspace the greyscale
images represent, which requires some type of input from the user.
that is the color space, without it changing the input greyscale images.

EG something like

    convert rose_HSB_?.gif  +combine HSB  rose_HSB_combined.gif

The BETTER FIX, that does not require an interface change is to have -combine
the re-create the greyscale images as a single (or RGB) equivelent, then
re-build the image in the right color space as defined by the first greyscale
image.

That will then allow the original and logical method to work and does not
require greyscale images to be in RGB-greyscale format.

    convert rose_HSB_?.gif -colorspace HSB -combine rose_HSB_combined.gif

Setting arguments from in memory images and/or other settings

This is a suggestion that popped up from quite a large number of souces. in many different forms. Basically it is a way of retreving colors, and image widths and heights from images either in memory or on disk.

This is has now been particialy implemented, at least for "-format", "-label" and "-annotate". Basically in places where you can specify 'format escapes', and basically allows called to the 'fx expresion handler' to perform mathematical espressions.

For example, these can NOW be used...
Number of pixels in an image...
   convert rose: -format "pixels: %{fx:w*h}" info:
   pixels: 3220

Color of a specific pixel (this needs to be changed to return a color)
   fmt="color 12,36: rgb("
   fmt="$fmt%[fx:floor(p{12,36}.r*256)],"
   fmt="$fmt%[fx:floor(p{12,36}.g*256)],"
   fmt="$fmt%[fx:floor(p{12,36}.b*256)])"
   convert rose: -format "$fmt" info:

   color 12,36: rgb(115,112,105)

This is now implemented as
    convert rose: -format '%[pixel:p{12,36}]' info:
Whcih will use rgb() or color names as appropriate.

The FX expresion has also been augmented to include new shortcuts such as.
   s  = current image in sequence (for FX escapes, u otherwise)
   t  = index of current image (for FX escapes, 0 otherwise)
   u  = first image in sequence
   v  = second image in sequence
   n  = number of images in sequence
   i  = column offset of purrent pixel (for -fx operator, 0 otherwise)
   j  = row offset of purrent pixel (for -fx operator, 0 otherwise)

  with the default image now being 's' rather than 'u'. 

For more detail see FX Expressions as Format and Annotate Escapes.

As such some progress has even been made with this proposal, (see the rounded corners example) but is proving more difficult due to interfacing with the various API's (which has no concept of a 'current image sequence').

-----

Expand format escapes into geometry, and color arguments.

Example... set a background color to an average of an image
  convert rose: -resize 1x1 -background '%{fx:u}' +delete .... 
Example... Create a canvas the same size as the Fifth image in memory, using its center (posibly interpolated) color.
  convert ....  -size '%[fx:u[4].w]x%[fx:u[4].h]' \
                xc:'%[pixel: u[4].p{u[4].w/2,u[4].h/2} ]' ...  
----

Addendum: from cristy...
The operator xc:'p{30,40}' requires a prior image from the image stack.
Currently there is no method to access prior images from a coder module.  You
also need to keep in mind that APIs generally have no fixed 'current image
sequence' to refer to.  So how do we feed prior images so the fx expression
can get at the pixels (p{30,40}) when so specific image sequence is available?

Instead we may be able to say something like-

  convert rose: -define mypixel p{30,40} -size 100x100  xc:mypixel ...

Unfortunately the current color method signatures do not have access to
either the image or image_info structure and in many places where the color
methods are called they may not be available.  These are required to grab
image pixels, image attributes, or defines.  That means only the MPR is
available which could be ugly and slow. MPR is like a global variable for
images.

All-in-all this is a complex problem that is going to take some time to
implement properly if at all.

Created: 1 November 2005 from 'testing' page
Updated: 7 December 2006
Author: Anthony Thyssen, <A.Thyssen@griffith.edu.au>
Examples Generated with: [version image]
URL: http://www.imagemagick.org/Usage/bugs/future/