Hints and tips specific to Imagemagick NOTE: General hints which can be handled by both imagemagick and other filters can be found in "algorithms.hints" of this same directory. Many of the hints and tips that use to be found on this page has now moved to a HTML version of ImageMagick Example Pages... http://www.cit.gu.edu.au/~anthony/graphics/imagick/ Here you can not only see the examples but the results and a more detailed explaination of the IM operations and usage. Anthony Thyssen From an IM Developer... ImageMagick is a robust general solution to a number of image processing problems. We traded off speed for robustness and image quality. ------------------------------------------------------------------------------- Personal build ImageMagick has two types of installs: "installed" and "uninstalled". The default is installed and the ImageMagick paths are fixed relative to the install path, typically /usr/local, determined by the --prefix option of the configure script. Use the --disable-installed option to install ImageMagick anywhere on your system and have ImageMagick find its configuration files relative to the MAGICK_HOME environment variable. From Cristy ./configure --disable-installed make From a users ISP /configure --prefix=$HOME/apps \ --with-magick-plus-plus=no --with-perl=no \ --disable-static --with-modules \ ; ------------------------------------------------------------------------------- Configuration See http://www.imagemagick.org/script/resources.php The actual search path for configuration files (like "type.xml" or "delegate.xml") is... $MAGICK_CONFIGURE_PATH /lib/ImageMagick-/config /share/ImageMagick-/config /share/ImageMagick-/ $HOME/.magick/ /lib/ImageMagick-/ / Where is the compile time installation prefix. The precompiled binary distribution, or non system install using the --disable-installed prefix, replaces with the $MAGICK_HOME Under Windows $MAGICK_CONFIGURE_PATH /config Typically all the ".xml" files are read in the first time that specific resource is needed, in the above sequence. After that the first reference to the desired configuarion item is what is used. For fonts (the "type.xml") in the directory $MAGICK_FONT_PATH is also looked for AFTER the above search is complete. If a font is still not found a fontfile (EG: font.ttf) is searched in the currect directory and the $MAGICK_FONT_PATH directory. Other environment variable include MAGICK_TEMPDIR location of temporary files or -set registry:temporary-path /data/tmp In Windows, it is defined by the Registry entry HKEY_Current_User\Environment\TMP LD_LIBRARY_PATH DYLD_LIBRARY_PATH Library patchs (unix and mac respectivally) ------------------------------------------------------------------------------- What image formats does IM know.. convert -list This fails for version < 5.4.9 and only lists options (-type isn't listed!) However the font list option works! convert -list type ------------------------------------------------------------------------------- Basic Image information Basic summery identify test.png Lots more info identify -verbose test.png In version beta/5.5.2, even more... identify -debug coders -log %e test.png ------------------------------------------------------------------------------- Special Input Sources: text: Read and convert a text file to an image txt: Read the output text format of txt: x: import the user selected X window window x:id import the window from the X window ID given Special Output Destinations... x: Just feed the image to "display" txt: list each pixel in the image one by one convert -size 2x2 xc:pink txt:- print: If used at a final target, image will be sent to the printer ("lpr" command) as postscript. Eg: convert logo: print: h: or image.h Generate a C header with the image as a string Format is GIF for colormapped images and PNG for truecolor ASIDE: IM also understands wildcard patterns. As such if *.jpg overflows the shell command line buffer, (EG: "argument List too long"), you can quote the wildcard pattern, and let IM expand it instead. You can also use @file_list which will get IM to read the images from a pre-prepared file list. ------------------------------------------------------------------------------- The Source of the Image Magick Logo The logo: image is stored in a pix.c as a array of data. This array is a GIF image which was created from a GIF image ImageMagick-6.0.0/guide/images/logo.gif using convert logo.gif logo.h The GIF image itself was created from a eps file ImageMagick-6.0.0/guide/images/logo.eps Which was developed from... ------------------------------------------------------------------------------- Restricting a modification to a small region. "Jean Piquemal" on wrote... | I display an image, then select a circle with the mouse and I want to modify | the color of some pixels in this region. It is a tool to remove red eyes on | photos, that's why the region must not be a square. Modify the whole image with whatever you are doing, (or limit it with a square reagion. Then overlay the modified image over the original using a circle mask.. # Create a circle mask by making a black canvas of the original image # and drawing a white circle in area you are modifing. You can fuzz # the mask too a bit with gaussian for a smoother boundary. # # circle of 8 pixels centered at 50,50 and a fuzzing of the border # by two # convert -threshold 100% original.png \ -fill white -draw 'circle 50,50 50,58' \ -gaussian 0x2 +matte circle_mask.png # do your stuff to the original image.... convert original.png {...do modifications here...} modified.png # now just overlay the area definied my the circle mask back onto # your original image... composite modified.png original.png circle_mask.png result.png Lars Ruben Skyum wrote... Or just use the mask while doing your modifications with convert: convert in.png -mask circle_mask.png <... modifications ...> out.png I didn't test it with the 5.5.8 beta, but my example shows how the mask option is used. EG fill with red... convert -threshold 100% test.png -fill white \ -draw "circle 80,80 150,150" -gaussian 0x2 +matte mask.png convert test.png -mask mask.png -fill red -colorize 20 result.png ------------------------------------------------------------------------------- Default Font in IM ImageMagick selects a font in the following order: 1. if a font is specified by -font from the command line or draw_info->font from the api and the font exists and is supported (TrueType fonts requires Freetype, use it, otherwise 2. find a font in type.mgk that closely matches the default family, style, stretch, and weight. if found, use it, otherwise 3. find a font in type.mgk that closely matches the Arial family and the default style, stretch, and weight. if found, use it otherwise 4. use the specified Psotscript font if the gs executable is installed and the ghostscript fonts are available. if found, use it, otherwise 5. use the default Ghostscript font if the gs executable is installed and the ghostscript fonts are available. if found, use it, otherwise 6. rendering text fails ------------------------------------------------------------------------------- Font Handling... See the preface of my IM Examples pages.. http://www.cit.gu.edu.au/~anthony/graphics/imagick/ Stroke and Stroke Width This has been moved to the Online examples page... http://www.cit.gu.edu.au/~anthony/graphics/imagick/options/#stroke Composite Fonts... This has been moved to my web examples page... http://www.cit.gu.edu.au/~anthony/graphics/imagick/fonts/ Fill a outlined font... It is actually a lot easier to fake an outline font from a solid font, than to use a real outline font (see above). The solution is a complex multi-step process to "mask" out a background image before drawing the outline font on that masked area. It does NOT work for a outline font that also has "holes" in it, such as in the middle of a "o" or a "p", Otherwise it works fairly well. Get the outline font to draw, convert convert -background transparent \ -font DoorJamb -pointsize 72 label:Test font.miff First we need to remove the alpha channel, pick one of the following... Directly convert -font DoorJamb -pointsize 72 label:Test mask.miff or indirectly (for images) by creating a white image and drawing on it composite -size 1000x1000 xc:white -compose copy font.miff mask.miff composite font.miff -compose atop mask.miff mask.miff Now make all the outside parts transparent (two methods) Note the extreme use of "-fuzz" to make the anti-aliased border blue for the mask. Watch out for fill "leaks". Either by making outside transparent... convert mask.miff -fill transparent -fuzz 80% \ -draw 'color 0,0 floodfill' mask.miff Or, just leave the insides of the font white.... convert mask.miff -fill black -fuzz 80% -draw 'color 0,0 floodfill' \ -fill blue -fuzz 0% -draw 'color 0,0 floodfill' \ -transparent blue mask.miff NOTE: The first method above is almost a correct solution in itself, but it loses any and all anti-alising at the boundaries, the second trys to only white out the parts that need it (inside the font). Create the final white-out mask. (all colors white, except transparency) composite -size 1000x1000 xc:white -compose atop mask.miff mask.miff Now stack and flatten the background image, white-out mask, and font image. A geometry argument positions the mask and font images. convert -size 370x80 tile:$HOME/icons/desc/gr-bgnd/curves.xpm \ -page +50+10 mask.miff font.miff -flatten \ result.jpg Display a directory of fonts (with labels)... montage -tile 1x15 -geometry +0+1 -pointsize 36 \ `sh -c 'for i in *.ttf; do \\ echo -label $i -font $i label:ABC-xyz-0123; done'` \ -font Arial -pointsize 12 miff:- | display - & This has been programmed into a script, which you can download from... http://www.cit.gu.edu.au/~anthony/software/show_fonts.sh Note on internal workings... The "-label" is associated with the NEXT input filename. On the other hand, it is only "drawn" after all the images have been read, fonts drawn, and labels assigned. As such the font used for the label is the one in effect when the actual output is produced Eg labels in the above are 12 point Arial. Because of the way ImageMagick works we could in fact to this as two seperate step, reading and assigning labels using convert, then montaging the result. This method however, is much slower... convert -pointsize 24 `sh -c 'for i in *.ttf; do \\ echo -label $i -font $i label:ABC-xyz-0123; \\ done'` miff:- | \ montage -tile 1x15 -geometry +0+1 - -font Arial -pointsize 10 miff:- | \ display - & NOTE: montage's frame color is picked up from a source image. Set it with -background if it isn't correct. ------------------------------------------------------------------------------- Tracking a point while image processing. Process your original image as normal, but also generate a second image the same size. say pure white. On this second image plot the point you are interested in, in black. Now process the second image in the same way. At the end of processing, -trim the secondary image. Hopefilly the trim wil reduce the image to a single point (or a very smallish area). You can then use identify (or the new info: output format) to return the size and location of that point on the processed secondary image. For example assuming the original image is 300x300 and the point you want to track is 125, 24 convert -size 300x300 xc:white -fill black -draw 'point 125,24' \ .... process image ... -trim -format '%wx%h %g' info:- for a -rotate 90 processing the result of the above will be... 1x1 300x300+275+125 so your tracked point is 275, 125 And that is where your point was tracked. If you are carful you can track multiple points, each ploted in a different color, (Especially the colors: red, green, and blue) though sorting out their new locations at the end could be trickier, and may not work for all processing. ------------------------------------------------------------------------------- Filtering Images though script and C programs. For shell/perl scripts you can read and write the txt: image file format which will allow you re read or write the image one pixel at a time. A simular format that is also very easy to parse is the PNM format =======8<-------- magic number (P7 for RGB compact) # optional comment Max value per channel (typically 255) # optional comment width height # optional comment Image data, in RGB format, one byte ber channel, for width * height * 3 bytes. =======8<-------- This format is excellent for C programming, as the size of the image is also included in the image format. A RAW image format is exactly the same as PNM, just without the headers. As such you will need some other way to determine the image input size. Filter that "raw image with a C program... =======8<-------- { ... fdi = fopen("old.raw","r"); fdo = fopen("new.raw","w"); for(y=0; yGet("pixel[$w,$h]"); #$s is a list, 4 numbers for r,g,b,i $image->Set("pixel[$w,$h]"=>"#0000ff"); } #set requires #rrggbb or color name } } =======8<-------- ------------------------------------------------------------------------------- WMF Scaling The math in the WMF renderer is correct to render the WMF at the effective "typeset" size specified in the metafile header. While the meaning of the metafile header is subject to interpretation, a fair amount of time was spent ensuring that it was right. ImageMagick and Adobe Illustrator appear to agree on the rendered size. The viewer provided with Windows XP appears to ignore the units from the metafile header, and uses 1:1 scaling, so WMFs are often claimed to be huge. The WMF header includes units which should be used to obtain the width and height of the image in inches. It is odd to claim this, but I think that ImageMagick is more correct than Windows itself at calculating the WMF size. Of course the metafile header was invented by Aldus, not Microsoft. This is the math used: image_width_inch = (double) wmf_width / units_per_inch; image_height_inch = (double) wmf_height / units_per_inch; image_width = image_width_inch * resolution_x; image_height = image_height_inch * resolution_y; where wmf_width and wmf_height specify the span of the vector data in width and height, and units_per_inch (obtained from the metafile header) specifies the number of WMF units per inch. The resolution_x & resolution_y parameters are from ImageMagick's density setting. The scaling applied to WMF files is based on 72 DPI when using convert, or uses the resolution specified by the X11 server when the 'display' program is used to display WMF on the screen. In order to create a larger rendering, you can use -density to specify a larger value. For example '-density 144' produces an image which is twice as large in each dimension. If you know the units per inch value from the metafile header, then you could apply a -density value which reverses the units_per_inch division. ------------------------------------------------------------------------------- Output older BMP format As was mentiond previously on the list, ImageMagick 5.4.9 supports writing BMP versions up to version 4, which supports application profiles. It chooses the lowest BMP version that supports the features required not to loose information. Maybe these applications make assumptions about the format, ignoring offset information, and don't deal with the profiles correctly. The PNG file contains a gAMA and cHRM chunk (gamma and chromaticity information) either of which forces "convert" to write a BMP-4. To get a BMP3 you need to get rid of that information. convert button.png PPM:- | convert PPM:- button.bmp will get rid of profiles, chromaticity, gamma, and transparency, title, copyright info, and should produce a BMP3 instead of a BMP4. ------------------------------------------------------------------------------- Display constantly says "not support an image matte (PsuedoColor)" You can get rid of the message by using the +matte option I.E. display +matte file.gif You don't need to worry about this on 24 bit color terminals Same goes to remove this message for the Animate program. ------------------------------------------------------------------------------- Convert postscript to PDF WORK IN PROGRESS Convert pages to grayscale images (anti-aliased) mogrify -colorspace gray -density 288 -resize 25% *.ps *.png then convert images to a PDF convert -sample 50% *.png newsletter.pdf ---- From Bruce LaZerte bdl at fwr.on.ca on the magick-users maillist... convert -adjoin -page letter scan*.tiff big.ps followed by, convert big.ps big.pdf gives big.pdf with size: 268,115 Whereas, convert -adjoin -page letter scan*.tiff big.pdf gives big.pdf with size: 2,151,932 That's an almost 10x difference in size. Also when converting directly to pdf, the "-page letter" stretches the tiff files over both axes, whereas if I convert first to PS then to pdf, the transformation maintains the aspect ratio. ---- A non-IM solution would be to convert to postscript (using convert or a image viewer, and printing to a file), then use ghostscript to convert that to PDF. EG: "ps2pdf" script. ------------------------------------------------------------------------------- IM Speed > Converting a 14Mb 9400x9400 truecolor jpg to 1024x1024 truecolor png > ... > Why is ImageMagick 35x slower than GDI+API? Sounds like you should use GDI+API. ImageMagick is a robust general solution to a number of image processing problems. We traded off speed for robustness and image quality. Image reduction, for example, defaults to the Lanczos finite impulse response filter which is much more computationally expensive than the bicubic filter GDI uses. You can reduce the ImageMagick memory requirements by setting the cache threshold to a very low value and make IM a bit faster by selecting a faster algorithm. convert -cache 1 -filter blackman -geometry 1024x1024 image.jpg image.png ------------------------------------------------------------------------------- Using IM and direct calls. I use a language that lets me use DLLs. I can use any DLL function that is available in the exported table, and up to 9 parameters (integer, float, string). I can also return 1 parameter. --- You might be able to use the MagickWand "wrapper". Start by trying a simple program which just initializes IM and then closes it. Something like this: LOAD DLL "CORE_RL_wand_.dll" CALL DLL "MagickWandGenesis" CALL DLL "MagickWandTerminus" I've assumed that you're using a static release version of ImageMagick that's in the current directory. If that doesn't work you're probably dead in the water. Next step would be to try to call one MagickWand function which returns a string and see if you can print out the string (I'm guessing at the syntax): LOAD DLL "CORE_RL_wand_.dll" CALL DLL "MagickWandGenesis" version = CALL DLL "MagickGetVersion" CALL DLL "MagickWandTerminus" print version$ If that works, you can try to read a builtin image file and write it out: LOAD DLL "CORE_RL_wand_.dll" CALL DLL "MagickWandGenesis" m_wand = CALL DLL "NewMagickWand" if m_wand$ = 0 then NewMagickWand failed err = CALL DLL "MagickReadImage",m_wand$,"logo:" if err$ = 0 then the read failed CALL DLL "MagickWriteImage",m_wand$,"logo_out.jpg" CALL DLL "MagickWandTerminus" If logo_out.jpg exists after all that then you should be able to use most of the MagickWand functions. Pete (el_supremo), Wed Jan 10, 2007 -------------------------------------------------------------------------------