- Index
- ImageMagick Examples Preface and Index
- API and other IM usage methods
- Security Issues
- Hints for Better ImageMagick Shell/PHP Scripts
- Why do you use multiple "convert" commands
- Making IM faster (in general)
- Creating linux RPMs from SRPMs
The Command Line Interface (CLI) of ImageMgaick which this examples deals with
is only one method by which you can use, modify and control images with the
core library of ImageMagick functions (MagickCore). It is basically the
'shell' API interface. There are lots of other Application Programming
Interfaces (API's) which you can use more directly from many programming
languages, see
ImageMagick APIs.
Here I look at ways of improving your IM scripting and programming,
differences between Windows and Unix scripting, and look at basics of using IM
from other API's and programming languages.
APIs and other IM usage methods
Windows DOS Batch Scripts
Window users should specifically note that...
- Backslashes '
\
' appearing on the end of the shown example
lines represents a 'line continuation' which appends the next line to the
same command line sequence.
Just append all the lines onto one line and remove those backshashes. OR
replace them with '^
' character to denote line continuation
in DOS scripts.
- Backslashes '
\
' are not needed to escape parenthesis
'()
' or exclamation marks '!
'.
- Double quotes '
"
' may need to be used (carefully) in place
of single quotes ''
' so that the command arguments remain
correct. Watch out for quotes within quotes such as in -draw commands.
You can use single quotes within a DOS double quoted argument as these are
passed to IM for handling, and not the DOS scripting language.
- The special character '
>
' (used for resize geometry)
needs to be escaped using '^
'. For example
"-resize 100x100^>
"
- Simularly the 'internal fit resize' flag '
^
' needs to be
doubled to become '^^
'.
- Also in DOS batch files any percent '
%
' characters may need
to be doubled '%%
' to work correctly. This is because in DOS
'%
' is used to prefix varible substitution. Unix scripts
use '$
' for variable substition.
- Comments in UNIX Shells start with an unquoted '
#
'.
In DOS they can only appear at the start of a line using
'@rem
' or '::
'
- Finally "
convert
" is a windows command in the "windows"
system directory. It is suggested you rename the IM convert command to
"imconvert.exe
" to distinguish the two commands. You can't
rename the system command, as a windows service pack would just restore
it, ignoring the renamed version.
For example... This command in IM Examples UNIX shell format...
convert -background none -fill red -gravity center \
-font Candice -size 140x92 caption:'A Rose by any Name' \
\( rose: -negate -resize 200% \) +swap -composite \
output.gif
|
Will become something like this in a Windows DOS script...
imconvert -background none -fill red -gravity center ^
-font "C:\path\to the\font\candice.ttf" ^
-size 140x92 caption:"A Rose by any Name" ^
( rose: -negate -resize 200%% ) +swap -composite ^
C:\where\to\save\output.gif
|
Perhaps someone would like to create rough a 'Linux Shell' to 'Window DOS'
IM command converter for the DOS users out there.
Thorsten Röllich pointed out that you can use a
FOR ... DO
sequence in a windows batch script to pass text output of one
"
convert
" command into the arguments of another (known as
command substitution). For Example...
FOR /F "tokens=*" %i IN ('imconvert ...') DO imconvert ... %i ...
|
Basically the output of the single quoted "
imconvert
" command
in parenthesis is saved into the special batch script "
%i
"
variable and substitued at the "
%i
" location in the second
"
imconvert
" command. Normally percent characters need to be
doubled in window batch scripts, this is the exception.
You can also use it to save the output of "
identify
" commands.
For example here is a dos script that reads the date of a photo, and writes
it into the top left corner of the image.
@ECHO OFF
:: Set some variables
SET INPUTFILE=%1
:: get the date the photo was taken
FOR /F %%x IN ('identify -format "%%[EXIF:DateTime]" %INPUTFILE%') ^
DO SET DateTime=%%x
:: Add the date photo taken to the image
imconvert %INPUTFILE% -pointsize 18 -fill black -gravity northwest ^
-annotate +0+0 "Date: %DateTime%" dated_%INPUTFILE%
|
|
Photos are typically saved using JPEG format. Reading and re-saving JPEG
images causes slight degrading of the image due to JPEG Lossy Compression and as such saving back
to JPEG is not recommended.
|
Note the doubled percent '
%
' and double quotes '
"
',
within the "
identify
" command for use in DOS batch scripting,
according to the rules above. However I do not claim to understand all the
rules concerning the use of percents in DOS scripting, expecially in
'
FOR
' loops, which seems to also allow some very fancy
substitution techniques.
Also remember that IM can be used for floating point mathematics, and can
add that maths to larger formated strings. There can be generated and saved
into variables to generate more complex "
convert
" commands
later in both DOS and shell scripts. See the first example in
FX Expressions which generated the valus
of PI, or in
Border with Rounded
Corner which uses it to directly generate a complex draw string based on
image width and height information.
Pete (
el_supremo on forum) noted that the DOS
percent ('
%
') variables do have some useful abilities.
This DOS script will do some integer maths to calcule a circle of a given
radius.
@rem Arguments: radius imagefile
@rem Draw a circle of given radius and color on given image
@rem compute the X coordinate of a point on the circumference of the circle
set /A rad=320+%1
set /A colour=255-%1
imconvert %2 -fill rgb(%colour%,255,127) -draw "circle 320,240 %rad%,240" %2
|
And this script will resize the single input argument and write it as a
png with "resized_" prepended to the name.
imconvert %1 -resize 50x50 "%~p1resized_%~n1.png"
|
'
%~p1
' is just the pathname part of the input '
%1
'
argument.
'
%~n1
' is just the filename part.
You must put quotes around the output filename because if it contains spaces
(e.g. "
C:\Program Files\test.jpg
") then DOS will parse it as two
(or more) separate arguments.
Unfortunatally there is no known tutorial which specifically cover using
ImageMagick commands in DOS batch files but the
PC-Ask.com web site
has a useful summary of DOS commands. The '
%~p1
' sort of syntax
is covered under the '
FOR
' command.
You may also like to look at '
Bonzo'
Batch Script
page.
PHP
(IM commands from "system()
" functions)
PHP users have three ways of using ImageMagick, The "
imagick
PECL interface, the "
MagicWand
" interface, and the much more
common method of useing "system()" to run "convert" as a shell command. As IM
Examples is mostly about using the command line, that is the form I will look
at here.
PHP using Shell Commands
The best source of information on using this technique is the IM forum user
'
Bonzo' and his web site
RubbleWebs.
The following is the recommend procedure for initial tests of an ISP command
line IM interface, assuming you do not have direct command line 'shell' access
on the remote system. That is you can only upload web files for execution.
So the first thing we need to do is try and find and run the 'convert' command.
to get information about the PHP web server you are using.
On a Linux Web Service Provider upload and access this PHP script from the
ISP's web server...
<?html
header('Content-Type: text/plain');
system("exec 2>&1; type convert");
system("exec 2>&1; locate */convert");
system("exec 2>&1; convert -version");
system("exec 2>&1; convert -list type"); <!-- before IM v6.3.5-7 -->
system("exec 2>&1; convert -list font");
?>
|
This will a number of commands to see what is present. The first
"
type
" command tells you if "
convert
" is available
on the command PATH, and if so where is it. The "
locate
" command
should find all convert commands that exists on the server, including those
that are NOT a ImageMagick "
convert
" command. You will need to
interpret the results.
The next three commands, assume "
convert
" is on the command PATH,
and asks it to report its version number, and what font does IM thing it has
access to.
If you only see errors, then the "
convert
" is not on the command
line path, and your ISP provider did NOT initialise the web server PATH
properly to include it.
If this is the case you will need to find out exactly where it is located and
use something like this for you PHP scripts, which makes your script less
portable.
For example supose the "
convert
" command is in
"
/opt/html5extras/ImageMagick/bin
", then you can set that in a
variable at the top (for quick changes for different ISP hosts), and directly
specify its location...
<?html
$im_path="/opt/html5extras/ImageMagick/bin"
header('Content-Type: text/plain');
system("exec 2>&1; $im_path/convert -version");
system("exec 2>&1; $im_path/convert -list type");
system("exec 2>&1; $im_path/convert -list font");
?>
|
If you get "
ldd
" library errors, the LD_LIBRARY_PATH is wrong,
and the ISP has definitely fallen down on the job during its installation, and
you need to report the error, and have them fix the web servers
LD_LIBRARY_PATH environment variable setting.
After that try some of the simpler examples from IM Examples and try to get
them working. EG: For example output the IM 'rose' image as a JPEG image
file back to the web user...
<?html
header( 'Content-Type: image/jpeg' );
system("convert rose: jpg:-");
?>
|
Or try one of the fonts listed from your PHP test scripts. On my Solaris
Server I noticed that the '
Utopia
' font set was available so I
was able to try to create a label with that font...
<?html
header('Content-Type: image/gif');
system("convert -pointsize 72 -font Utopia-Italic label:'Font Test' gif:-");
?>
|
Watch the extra quotes
Note that typically the IM commands in PHP are wrapped by an extra set of
quotes (usually double quotes), as such care must be taken to allow for the
use of these extra level of quoting.
For example, this command...
convert -background none -fill red -gravity center \
-font Candice -size 140x92 caption:"A Rose by any Name" \
\( rose: -negate -resize 200% \) +swap -composite output.gif
|
Will become something like this PHP equivalent...
<?html
header('Content-Type: image/gif');
$color="red";
$image="rose:";
$scale="200%";
$size="140x96";
$string="A Rose by any Name";
passthru("convert -background none -fill '$color' -gravity center" .
" -font Candice -size '$size' caption:'$string'" .
" \\( '$image' -negate -resize '$scale' \\) +swap -composite" .
" gif:-" );
?>
|
Note how I still split up the lines to make the image processing sequence
easier to follow, by using appended strings rather than a shell line
continuation.
Also note the extra space at the start of later lines. And doubling up the
other backslashes that was present in the original command. Alternatively you
can protect those options by using single quotes instead of backslashes.
I also used some PHP variables to allow easier adjusted of the PHP script
image generated, as well as to control the results, but insert those options
using single quotes to protect them from further modification by the shell.
Watchout for single quotes within those inserted strings.
You could make those options PHP arguments, so you can generate an image for
any input text, however I would be careful to throughly check ALL the PHP
input for correctness, and prevent anything unexpected. Otherwise it is very
easy to create a 'hole' in the web servers security.
You can perform multiple shell commands within the same system call string.
In fact a single system call can contain a complete shell script if you want!
So you can do shell loops and multiple commands (with cleanups) all in the one
system call. Something not may people realise.
Basically if you are careful, you can make good use of the mathematics
provided by PHP, and the scripting abilities of the shell. All at the same
time. Just watch the quotes.
I recomend you at least read the PHP manuals on
PHP exec(),
system(), and
passthru() and understand there
differences between them.
For various examples of calling ImageMagick commands from PHP see
Rubble
Web, Writing IM code in PHP which describes about four different
techniques.
The more secure method...
Also if you what to avoid the shell parsing the arguments and the need for
most of the quoting requirements, (you separate the arguments yourself), such
as for security reasions, or specific user input, then use the
pcntl_exec() PHP function.
This basically avoids all the quoting or other shell escaping, and is thus
much more secure that using a 'all in one string' type command. Note you will
also
However you will also have to fork a sub-process for the funtion to run in as
well, ir it replaces the PHP being executed. This can thus get fairly complex.
It is just a shame that PHP has not provided a simple 'shell-less' command
execution function, such as those provided in other languages like perl.
PHP PECL 'IMagick'
To test if the
PHP PECL
imagick module is actually working upload a simple test
"
image.jpg
" image and this PHP script to the same web assessable
directory.
<?html
$handle = imagick_readimage( getcwd() . "image.jpg" );
if ( imagick_iserror( $handle ) ) {
$reason = imagick_failedreason( $handle ) ;
$description = imagick_faileddescription( $handle ) ;
print "Handle Read failed!<BR>\n";
print "Reason: $reason<BR>\n";
print "Description: $description<BR>\n";
exit ;
}
header( "Content-type: " . imagick_getmimetype( $handle ) );
print imagick_image2blob( $handle );
?>
|
PHP 'MagickWand'
You can check if the
PHP
MagickWand module is part of the PHP installation (and switch to
command line or other fallbacks) using...
<?html
if (extension_loaded('magickwand')) {
echo "PHP MagickWand is available!";
}
?>
|
But to check that it is actually working properly, upload some test
"
image.png
" and this script...
<?html
$image = NewMagickWand();
if( MagickReadImage( $image, 'image.png' ) ) {
header( 'Content-Type: image/jpeg' );
MagickSetImageFormat( $image, 'JPEG' );
MagickEchoImageBlob( $image );
} else {
echo "Error in MagickReadImage()";
echo MagickGetExceptionString($image);
}
?>
|
No guarantees with the above, though more feedback welcome. I do not generally
program in PHP, but used the above for testing a SunONE-PHP5 test installation
(with all three methods: command-line, magick, MagickWand).
Complex PHP scripts...
If you need to generate and output both HTML and IMAGES, consider designing
your PHP script so that separate HTML requests or input options, generate the
various parts you need on your web document, from either the same, or
different PHP scripts.
That is a top level PHP script can output HTML with appropriate <IMG>
tags, that call itself (or another PHP script) with appropriate options, to
create or modify the images displayed on the first top level PHP script. This
is in what a lot of photo album, and graphing PHP scripts do. All controlled
by the GET, and PATH_INFO extensions to the URL calls. Note that you can not
use POST within an IMG tag.
By doing things in this way you should be able to completely avoid the need to
both generate, save, and clean-up, temporary images for PHP generated web
pages. A solution that is full of problems, such as resource limitations and
garbage collection, making it a very bad programming technique.
Security Warnings
When writing a script for public use, especially a web-based PHP script where
ANYONE in the world could be running it, it is vitally important to check
everything that could posibly have come from a unknown (or even a known) user.
And I mean
EVERYTHING, from arguments, filenames, URLs, and images too.
Until you verify some input argument, that argument it could contains letters,
numbers, spaces, punctuation, or even 'null' and control characters. Untill
you have throughly checked it, it should be treated as suspect and should not
be used.
It does not matter that you are using some web controlled input form. A
slightly knowledgeable person can easily call your PHP with his own arguments
without using that input form at all. An don't believe they won't do it,
robots are out there, reading input forms and creating there own 'hacked'
arguments to try an break into random scripts.
Meta-characters in file names
As a security issue, you should especially watch out for, are filenames that
contain spaces, quotes, punctuation, control-characters, or other
meta-characters as both IM and Shells may try to expand them.
The problem is that a file called '
*?@${&) .jpg
' is actually a
perfectly legal filename under UNIX, but a LOT of programs will have trouble
handling it if that program (like shell and IM) also do filename expansion.
Even when you quote the file name correctly some filenames can still break
your quoting, and IM itself does some filename expandsion.
As a security measure it is often a good idea to error and abort if a filename
has some unknown or unusual characters in it, anything that is say not a
letters, numbers, and the expected suffix. Before passing such a filename to
a shell command, or IM. It is better to be a LOT to restrictive and prevent
things, than be permissive and allowing something bad through.
Hints for Better ImageMagick Shell/PHP Scripts
These were some basic script programming points I made about a contributed
shell script that was sent to the IM mail list for others to use. I originally
sent these to the author privately (and who will remain anonymous), for which
he was grateful.
They are not all IM specific, but should be applied anyway, as standard
programming practice. Especially if you plan to have someone else, use, look
at, and/or bug fix your program or script. It will in turn make your script
more useful.
- Place the 'help' or 'doc' at the top of scripts and programs.
This makes it lot easier for other people to figure out what a particular
program does without needing to install or run the script. I myself will
often junk a program that has no such clear comment on what it is for
rather than try to compile or run such an unknown script.
In fact I have seen huge projects where the first README file does not
even say what the huge and complex project does! The programmer just
assumes that if you downloaded it you must know what it does!
Also make sure that a 'bad option' such as '-?' will print a synopsis of
not just the options, but also a quick summery of what the program does,
or where to find such help. Do not just point to a remote web site, that
may disappear 10 years down the track!
For an example of a script that prints its own 'opening comments' see the
"jigsaw" script in the IM scripts area.
Perl can use POD for self documentation (See the perl
"
Pod::Usage
" module). For example see the contributed dpx_timecode.pl script.
Having the help as a 'here file' in the first sub-routine is also
acceptable, and works for most languages. But have that subroutine AT THE
TOP, not at the bottom or middle of the script or program.
- Make sure you clean up your code, remove old obsolete code and comments,
making things as neat an tidy as you can. Be concise, with simply
commented stages (if possible).
Again see the "jigsaw" script.
- Make sure temporary files are cleaned up at the end.
Use a "trap" shell command to remove them on file exit or interrupt.
You can of course re-use a single temporary files multiple times, so you
don't need very many, especially with IM v6 convert commands.
Again see the "jigsaw" script, and search
for "trap".
- Also not everyone uses system X, though it may seem like that to you.
Don't refer to specific system requirements, or methods on rectifying the
problem. What works for you may be completely in-appropriate for their
system and setup. They may not even have Internet access!
Just say that the "
convert
" command from ImageMagick, was not
found.
If you want add installation requirements, or suggestions, add it as
part of separate more extensive documentation.
- Do check that the IM being used is a high enough version, or add backward
compatible changes. I purposefully give 'version warning' notes
throughout
IM examples as to when various special features were added for this
purpose. It makes it easier when creating scripts with a single minimal
version check.
Here is one simple way you can get a single version number for testing
purposes in a shell script. It extracts the 4 version numbers, and
inserts the right number of zeros to make each number 2 digits, producing
a simple 8 digit number.
IM_VERSION=`convert -list configure | \
sed '/^LIB_VERSION_NUMBER /!d;
s//,/; s/,/,0/g;
s/,0*\([0-9][0-9]\)/\1/g'`
|
For example IM v6.3.5-10 will generate "06030510
" while
the very next release IM v6.3.6.0 produces "06030600
".
A PHP version of the above is available from RubbleWeb, Font List examples page.
The resulting string can be tested, using either a simple numeric or
string test, to discover if the available ImageMagick version is modern
enough for what your script is trying to do. For example...
if [ "$IM_VERSION" -lt '06030600' ]; then
echo >&2 "The perspective distortion operator is not available."
echo >&2 "Sorry your installed ImageMagick is too old -- ABORTING"
exit 10
fi
|
Also note how I added an extra note, either as output to the user, or as a
programming comment, about what special feature(s) the version check was
for. Otherwise you may later forget why that specific version (or higher)
was needed.
You can also modify the behaviour of IM for specific versions.
For example say I want to get a list of available fonts. Before IM
version v6.3.5-7 the "-list
" setting "type
" returned the 'known font'
list. With later versions, you need to use "font
" setting
instead. So here I can do a version check to use the right setting to
get the information needed.
if [ "$IM_VERSION" -lt '06030507' ];
then font_list="type";
else font_list="font";
fi
avail_fonts=`convert -list $font_list | cut -d\ -f1 |\
egrep -v '^($|----|Path:|Name$)'`
|
WARNING: a string starting with '0' in PERL could be interpreted as being
an octal number!!! However comparing two octal numbers will still come
out correct, as long as the first digit remains '0'. Caution, and
checking of the version test is advised.
- You can also make use of the "
-list
" information output to check if some special feature
has been added to the currently installed ImageMagick.
convert -list distort | grep 'Arc' >/dev/null 2>&1
if [ "$?" -ne 0 ]; then
echo >&2 "Arc distortion method not available."
echo >&2 "Sorry your installed ImageMagick is too old -- ABORTING"
exit 10
fi
|
However be warned that often a new method, like "-distort Arc
" could appear
during IM development before it is properly ready for general use. As
such a version check may still be the better idea.
This is why in IM Examples I try to note (look for symbols) the IM version
when a new feature have become stable enough for general use.
- Don't use very very long single lines. Especially for complex 'convert'
commands. Split them up using line-continuation methods (shown above),
such as '
\
' in UNIX, '^
' in DOS, and
'.
' string concatenation in PHP.
However I do not mean placing each and EVERY setting and operation on a
seperate line. Do one major operation or stage per line, create new
image, modify image, merge with other images, etc. Place all operational
settings needed for a specific operator just before that operator. Think
of each line as single processing step.
Using extra parenthesis, indenting
the the lines over various stages, or even add empty lines between large
processing blocks, can make it to see the major stages of large and long
operation.
This lets you seperate the lines so as to allow for the easier reading,
and understanding of individual processing steps. The clearer the
separation of operators, the easier a complex image process is to follow.
I use these techniques all over IM examples, so as to make the examples
easier to follow and understand, so just look around!
Finally extra comments about what a specific command is doing can make a
big difference in someone else (or even yourself 2 months later) reading
and understanding your script.
- Try not to rely on too many external programs, or only use them only if
they are available (with possible alternatives). Other people probably
will not have that program, or prefer to use something else. If a program
use can be optional, make it optional, either under user control, or
automatic use if found. Do not make it a forced requirement, if at all
possible.
For example you could make use of "
pngcrush
",
"optipng
", "pngnq
" to compress PNG better than
IM would normally provide (IM is designed to be general not specific).
Also "gifsicle
", "intergif
", or other for LZW
compression optimizers for GIF animations, have good and bad points. Just
don't make it a definate requirement for a scripts working.
As a practical example, an older version of the "gif2anim" did not use the ImageMagick
"identify
" to look up GIF specific meta-data, but relied on a
patched version of "giftrans
". This requirement was later not needed due to
improvements in the ImageMagick "identify
", so I removed
that requirement to make the script more widely usable.
IM itself has a LOT of optional requirements, such as
"ghostscript
" for postscript and PDF document reading, or the
"librsvg
" for correct handling of SVG vector images. IM
itself is quite happy for them not to be available, and as such does
not make these a requirement, only an option. It only needs them to be
present if you want to process images of those formats.
- Taking the last point further. If you need floating point math in a shell
script that is using IM, you can use IM itself to do that math, rather
than relying on some difficult to use programs such as '
bc
',
that may not be available (especially under cygwin or windows).
For example here we get calculate the sin() of a specific angle given in
degrees...
angle=-20
sine=`convert xc: -format "%[fx:sin( $angle *pi/180)]" info:`
echo $sine
|
The above would output the value '-0.34202
', and was taking
from a AffineProjection
Distortion Example. Fred Weinhaus pioneered this usage of IM in his ImageMagick Shell
Scripts.
- Let the user decide on the input/output image formats to use.
ImageMagick is primarily a image converter and able to use lots of
different formats. It can output to the screen, postscript, printers, or
pipe the image into another command for further processing. Don't limit
the user to a specific format.
For example the "jigsaw" and "gif_anim_montage" scripts allow
the user to specify any input or output image. That way users can pipeline
images into or out of that script for further processing to other programs
and scripts.
For example, I often use a command like...
gif_anim_montage animation.miff show:
|
to display the result of the script on my display screen, rather than save
it to a file. I also did not limit it to input from a GIF animation file,
or limit output to a GIF, PNG, or JPEG image format.
In fact IM can read from either files, pipelines, the current display, or
even from the World Wide Web using a "URL:
" or
"HTTP:
" input format.
- Read input images, and output multiple-images, only ONCE!
If the user provides a pipeline file name or a URL, you do should not try
to read those images more than once, or things can go bad. Use a
temporary file, cloned images, or "
MPC:
" save a copy of the input image, when you need to refer
to that image multiple times. If you can handle a multiple image sequence
from the pipeline, even better.
Again see the "jigsaw" script, for an
example of saving input images into a temporary file, when you are forced
to process the input image multiple times, or in a different order than
what the program arguments imply.
These things basically gives the user using your program more freedom to do
what THEY want rather than what YOU want. Don't limit them or yourself by
making assumptions on what the script will be used for.
PS: One of my main expertise is in UNIX script writing, over lots of different
architectures and 'flavors' of UNIX, LINUX, and other UNIX-like systems, with
more than 15 years experience behind me. I should know what I am talking
about with regard to the above.
Why do you use multiple "convert" commands
- Willem on Wed, 25 Oct 2006 wrote...
-
I was wondering; sometimes I see in your examples you're invoking Convert
more then once to obtain the desired result. In general, I would expect
that invoking convert more then once isn't needed; it should all be
possible in 1 invocation (but the command would be more complex then). Do
you agree with this statement?
I agree totally. Though before IM version 6 that was actually imposible. You
should be able to do all your processing in one single step.
I use multiple commands for a number possible reasons. Typically in the
example pages, I do it so I can get and display the intermediate image result,
so as to better demonstrate the intermediate processing stages that are
involved. Often later in the same example area I repeat the process but using
a single command. As such in principle, yes a single command can do all image
processing.
The exception to this is in cases where I need to extract information and
later insert that info into another command. An example of this is the
Fuzzy Trim technique which requires you to
extract the results of a trim on a blurred copy of the image. This result is
then used to crop the original image. I also did this in the update to
Thumbnail Rounded Corners example, where I
used IM itself to generate a draw command using an images size for the next
command.
However there is a
proposal that will
allow options to be generated from image that have been previously read into
memory.
You are most welcome to combine the image processing techniques all into a
single command. I do this all the time myself.
In scripts, such as the '
jigsaw' script (see
Advanced Techniques,
Jigsaw Pieces) I
commonly end up using multiple commands for a different reason -- optional
processing. This allows various input options provided by the user to select
additional steps in the image processing sequence. So for optional processing
I also use a separate command for each stage of processing.
In such a case a temporary file is basically unavoidable. However I typically
only need at most one or two temporary images, and each step processes the
image back into the same temporary filename, for the next optional processing
step to continue with.
EG: convert /tmp/image1.png ..operations.. /tmp/image1.png
In this can a
MPC file can speed up the reading
of intermediate files to a near instant in the next processing step.
And finally you may need to change your processing style based on the results
of previous processing steps.
For example in image comparisons, I often need to change techniques based on
the type of images being compared. Comparing a diagram or cartoon can require
vary different techniques to say a photo image.
If multiple commands is becoming a problem, perhaps it is time to go to an
API interface such as
PerlMagick, where multiple image sequences can
all be held in memory so as to avoid unnecessary disk IO.
Making IM Faster (in general)
There are many ways of making IM work faster. Here are the most important
aspects to keep in mind. As you go down the list the speed up becomes
smaller, or requires more complex changes to the IM installation.
- IM Q8 (or 8 bits per color value, 3 to 4 bytes per pixel) is a lot faster
(3 to 4 times faster) than the IM Q16 default, with its higher color
resolution. If you don't need a Q16 for your images, perhaps you should
replace your IM with a Q8 version. Be warned however that only using 8 bit
internal quality can effect the overall image processing as intermediate
images loose information. See HDRI for the
opposite of this.
- Use a single "
convert
" command if possible, to so all the
processing required for a single image. This saves on initialization,
having to create temporary files, or pipelines between commands, and even
the encode/decode to image file formats for those pipelines and disk I/O.
Of course sometimes you still need to use multiple commands, to allow for
optional image processing steps, such a calculations involving image size,
colors or even optional processing steps.
- Shell scripts are inherently slow. It is interpreted, require multiple
steps and extra file handling to disk. This is of course better thanks
to the new IM v6 option handling, allowing you to do a large number of
image processing operations in a single command. Even so you can rarely
can do everything in a single "
convert
" command, so you often
have to use multiple commands to achieve what you want.
As such an API like perl, ruby, or a PHP magick module is faster as it
removes the all the interpretation aspects of both the shell, and the IM
command line API. It also reduces the initialization steps IM goes though
in reading fotn and color definations.
- An API also can hold hold all the images, or even multiple lists of images,
for the lifetime of the program (as long as you have enough memory for
it). This means you can chop and change what images are being worked on,
without the need to shuffle and juggle the images on the command line.
This is especially usful when you need to also do extra calculations
basied on previous image processing steps.
- Writing the GIF image file format is slow. IM has to work hard to color
reduce (quantize) the colors of an image to fit into the limited colors of
the file format. Even then you often need to do extra work to get it
right, especially for GIF animations. PNG and JPEG are faster but at a
cost of size for PNG, and loss of quality for JPEG.
- Pre-preparing and caching images such as backgrounds, overlays, frames,
masks, or pre-generating color look up tables, distortion maps, templates,
masks, etc. All these things can make large differences in your
processing time. Think about what can be done before hand. A large
library of pre-generated images can be a lot faster that trying to create
the images as needed.
See also the use of "MPC:" for intermediate
and cached images. These are memory mapped images on disk, and
essentially have zero read time, but are useless for anything else, or on
other machines. They should only be created at the start of a major image
handling process, and not preserved through any software or system
upgrade processure.
- Avoid using FX, The Special Effects Image
Operator, if you can use Alpha
Composition, or the simpler Evaluate, Simple Math Operations, or other techniques instead.
If you do need to use these, try restricting its use to the smallest image
posible, or to a single channel of the image (when handling grayscale).
- Avoid using large sized Image Blurs when
a few smaller ones may be faster. Do some timing tests to see whcih is
faster. The same goes for other Convolution
Operators such as Gaussian, and Shadow.
- Use smaller sub-images, or regions, for complex processing of small areas.
For example, find and extract the eyes of an person, before masking and
recoloring, can result in a huge speed increase than processing a large
image just to modify a small area of the image.
- When reading large or a large number of images, it is better to use a Read Modifier to resize, or crop
them, as it uses a smaller memory requirement.
This in turn prevents 'disk
thrashing' (which makes computers VERY slow), when lots of large
images are involved, such as when generating Montaged Directory Indexed, or other multi-image collages.
- For Really Massively Large Images that
have to be processed from disk, it may be better to process them in
smaller chunks.
- Also for large images... If you have a Window 64-bit OS, use the 64-bit
ImageMagick distribution. It uses a larger address space and can fit
larger images into memory than 32-bit Windows.
- IM by default uses multiple threads for image processing operations.
That means you can have the computer do two or more separate threads of
image processing, it will be faster than a single CPU machine.
- If you are doing small fast operations try not using any color names.
Specify colors using hash colors (such as "
#00AA99
" or rgb
numbers (such as "rgb(0,160,100)
" so as to stop IM from
having to load the color name tables (it is rather large!).
Also you can try removing or cutting back the system 'font' list
definition files (from "type.xml
". Or remove those files
completely and specify fonts directly by filename instead.
Basically reduce the loading of the extra configuration information, which
IM will read and initialise when first used for a specific image process.
So either don't use them or reduce the size and impact.
- Building ImageMagick as a shared library (the default) can greatly reduce
load time. libraries and coder modules are only loaded as they are needed
so a dynamic version of IM will not load anything that it doesn't need to
use during image processing.
- If you call ImageMagick as an Apache module it will also reduce startup
time, as parts will be loaded once and kept available for multiple use,
rather than needing re-loading over and over.
- For small images using the IM multi-thread capabilities will not give you
any advantage, though on a large busy server it could be detrimental.
But for large images the OpenMP multi-thread capabilities can produce
a definate speed advantage as it uses more CPU's to complete the image
processing operations.
Building ImageMagick RPMs for linux from SRPMs
You do NOT need root to actually build the RPM's though you do need root
to install the RPMs.
I use this for generating and installing IM under
Fedora Linux Systems,
but it has also been
reported to work
for
CentOS 5.2 (Enterprise Redhat) Linux Systems. If you have had
success or failes on other system, or know how to generate a DEB package
version, then please let me know, so I can include it here.
First get the latest source RPM release from
Linux Source
RPMs.
Create a working temporary directory in which to build IM
rpmdir=/tmp/imagemagick-rpmbuild
rm -rf $rpmdir; mkdir $rpmdir
mkdir $rpmdir/{BUILD,RPMS{,/i386},SOURCES,SPECS,SRPMS}
|
Now build the RPMs... All the defines in the command restrict the build to
just the top level of the temporary directory. If you remove all the defines
the RPMs will be built in the system /usr/src area which is usually root owned
though does not actually have to be.
nice rpmbuild --define="_topdir $rpmdir" \
--nodeps --rebuild ImageMagick*.src.rpm
|
Get the just built RPMs for the magick core and PerlMagick, you may like to
grab more than just two core RPMs, but that is up to you...
cp -p $rpmdir/RPMS/*/ImageMagick-[6p]*.i386.rpm
|
Clean up the build areas...
rm -rf $rpmdir /var/tmp/rpm-tmp.*
|
Now you can install the RPM packages you build specifically for your linux
system... You will need to be root for this, and only this, step...
rpm -ihv --force --nodeps ImageMagick-*.i386.rpm
|
To upgrade an existing installation I generally do this due to some unusal
dependancies that sometimes exists on Linux systems...
rpm -Uhv --force --nodeps ImageMagick-*.i386.rpm
|
To later remove IM, do this (again as root)...
rpm -e --force --nodeps ImageMagick\*
|
Sometimes I just want to completely clean and wipe out all traces of IM from
the system. To do this I first use the previous command to remove the actual
package from the system (a variation is shown below). I then run the
following remove commands.
NOTE I make no gurantees about this, and I would check the commands throughly
before hand to ensure they don't remove something that it shouldn't. If I
missed anything, or it removed something it shouldn't, then please let me know
so I can update it.
rpm -e --nodeps `rpm -q ImageMagick ImageMagick-perl`
rm -rf /usr/lib/ImageMagick-*
rm -rf /usr/lib/lib{Magick,Wand}*
rm -rf /usr/share/ImageMagick-*
rm -rf /usr/share/doc/ImageMagick-*
rm -rf /usr/include/{Magick++,magick,wand}
rm -rf /usr/lib/perl5/site_perl/*/i386-linux-thread-multi/Image/Magick*
rm -rf /usr/lib/perl5/site_perl/*/i386-linux-thread-multi/auto/Image/Magick*
rm -rf /usr/share/man/man?/*Magick*
|
Warning, other packages may need an IM installed, so if you remove it, I
suggest that you immediatally update your computer system, so as to install
the default version supplied by your linux system. This generally involves
using a 'GUI Software Update" package or "yum".
Enjoy.