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. ------------------------------------------------------------------------------- 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 ------------------------------------------------------------------------------- Image Formats Notes... Builtin Constant Images logo: ImageMagick Logo Image rose: A rose image netscape: The netscape colormap granite: a classic tile pattern pattern:name Use a builtin tile pattern. See bottom of http://www.imagemagick.org/www/formats.html if -size is given acts like tile:pattern:name Builtin Image Generators label:string Generate image of string in current font null: Single white pixel null:color Single pixel of color specified xc: White canvas of size given xc:color Solid color image (white if no color specified) gradient: Vertical gradent (white to black) gradient:color Vertical gradent (color to white/black) gradient:color1-color2 Vertical gradent (color1 to color2) ASIDE: colors are stuffed in v5.4.9 plasma: Plasma gradient (same colors as gradient:) plasma:color plasma:color1-color2 plasma:fractal randomised without a gradient tile:tile_image_file fill image with given tile image pattern 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 Memory store mpr:{id} save an image into a "Magick Persistant Registry" IE: named images in memory. convert logo: -write mpr:abc +delete \ mpr:abc test.miff Image format Notes: GIF: Moved to ImageMagick Examples Page on "Image Formats - GIF" JPG: Moved to ImageMagick Examples "Image Formats - JPEG" Testing by some imagemagick users declare the new jpeg 2000 format is the smallest posible lossless format available. However you need the Jasper delegate. Jasper is included in the Mac OS X binary distribution. Download from here... http://ftp.imagemagick.org/pub/ImageMagick/binaries PNG: This is one of the newest and most modern image formats, supporting 32 bit colors including alpha channel transparency, but can also be optimised to a GIF like 8bit index color scheme. As such it makes a excellent intermedite format for image processing without loss of image information. To force the use of a indexed color tables in PNG use... convert -type Palette HPIM1391.JPG hp.png PNG8: The PNG equivelent to GIF, including boolean transparency and limited color table. To force the writing of 8bit PNG files use: "png8:file.png" SVG: Change the -density setting to increase or decrease the size of the input vector graphics file. Just like you do for Postscript. If you like to draw the SVG data on a transparent background use.. convert -background none file.svg file.png MVG: The intenal intermediate format of ImageMagick for SVG images The results look like the commands that 'draw' would normally use. convert image.svg image.mvg ASIDE: -render render vector operations Use +render to turn off rendering vector operations. This is useful when saving the result to vector formats such as MVG or SVG. PS: Postscript Vector Description Lauguage (a full computer language) Change -density setting to increase or decrease the size, however it is processed by the external delegate "ghostscript" TIFF: Error: "JPEG compression support not configured" This message comes from the TIFF library. You need to enable JPEG support when you build/install the TIFF library. You can get around this problem my using a different compression algorithm: convert image.jpg -compress zlib image.tif convert image.jpg -compress lzw image.tif convert image.jpg +compress image.tif MPEG: Some reports that unless the images are the righ aspect ratio is correct this will fail on older mpeg players, use the MPEG II extension (m2v:) instead. M2V: MPEG2 Video streams (not .MNG, Multi PNG-files) Instead of "convert *.miff sequence.m2v" use.. png2yuv -j file%08d.png -I p -f 25 -b 1 | \ mpeg2enc -f 3 -q 3 -b 5000 -o out.m2v See mjpeg.sf.net 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... ------------------------------------------------------------------------------- Histogram or Gray-Scale Adjustments This has been moved to my new ImageMagcik Examples Page.... http://www.cit.gu.edu.au/~anthony/graphics/imagick/basics/#greyscale ------------------------------------------------------------------------------- Color Reduction If you are color reducing an image, say for example from JPEG to GIF, you may find reds/greens/blue showing up in areas of mostly uniform grays. To stop this, use the YUV colorspace: convert -colorspace YUV -colors 256 image.jpg image.gif -- MattWalsh - 28 Dec 2001 You can specify exactly which colors you want using a colormap image with the -map option. When reducing colors make sure you decide if you want dither or not. By default it is on, +dither will turn it off. Reducing to minimal number of colors... convert -colorspace YUV +dither original.tif \ -treedepth 8 -colors 16 test16.tif A new option to IM v6 that does this is -posterize. This reduces the color set to a minimal set for creating advertizing posters. convert +dither original.tif -posterize 6 test6.tif ------------------------------------------------------------------------------- Color Replacements To replace one color use convert -fill new_color -opaque old_color input.png output.png WARNING: JPEG images generally modify colors slightly accross the image to aid in its compression algorthim. As such a small -fuzz factor is recomended, to also modify nearby colors. convert -fill new_color -fuzz 1% -opaque old_color input.png output.png WARNING: most images have some form of 'anti-alising' being used. as such replacing colors like this on a real image often leaves horrible edge pixels, and using a higher fuzz factor just results in an image losing its anti-aliasing, though that may be a good thing for outputing to GIF format. For more info see... ImageMagick Anti_Aliasing Examples http://www.cit.gu.edu.au/~anthony/graphics/imagick/antialiasing/ Change a whole color palette. This is not posible with IM at this time, but the simplist solution is to save the image in the text XPM format, and edit the color table with your favorite editor. Set background color on existing images, transparent Assuming the top left pixel is the color to be made transparent use.. convert -draw 'matte 0,0 replace' input.img output.img This will also set any 'holes' in the image of the background color as also being transparent. If you only want the outside of the image leaving any 'holes' of the same colour alone use convert -draw 'matte 0,0 floodfill' input.img output.img You may like to set a "-fuzz" factor to also convert colors close to the background color, especially for 'JPEG' format images where colors can be slightly off color. To set certain specific colors as transparent use... # tc = transparent color c1 c2 c3 = colors to make transparent convert in.gif -matte -fill tc -opaque c1 -opaque c2 -opaque c3 \ -transparent tc out.gif Note that when creating images (using -draw, or compositing parts of other images) it is better to start with a transparent canvas, rather than converting the colors afterward. The result will be much better. ------------------------------------------------------------------------------- Making a blank canvas in various colors from an existing image This has been moved to my Web Examples page... http://www.cit.gu.edu.au/~anthony/graphics/imagick/basics/ ------------------------------------------------------------------------------- Thumbnail Generation (for web pages) This has been moved to my web examples page... http://www.cit.gu.edu.au/~anthony/graphics/imagick6/thumbnails/ ------------------------------------------------------------------------------- Extracting and Applying a Transparency Mask See "Matte and Masks" Examples Page http://www.cit.gu.edu.au/~anthony/graphics/imagick/masks/ for the details... ------------------------------------------------------------------------------- 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 ------------------------------------------------------------------------------- Dithering (including transparency dithering). Dithering the Transparency into on/off values See "AntiAliasing, GIF for non-specific backgrounds" http://www.cit.gu.edu.au/~anthony/graphics/imagick/antialiasing/ for the details... ------------------------------------------------------------------------------- Concatanation of images (See also "Multiple Image Mosaics" below) This has been moved to My ImageMagisk Examples Page http://www.cit.gu.edu.au/~anthony/graphics/imagick/mosaics/#append ------------------------------------------------------------------------------- Composite Image Techniques These are being moved to my ImageMagick Examples Pages http://www.cit.gu.edu.au/~anthony/graphics/imagick/annotating/#overlay Add a pagecurl image to lower-right corner... NOTE: The pagecurl image was created via gimp's pagecurl filter, on a small transparent image. The outside was then manually filled with black. An extra mask can also be applied later to re-add transparency in the corner. composite -gravity SouthEast pagecurl.png mermaid.jpg miff:- | display Watermarking moved to http://www.cit.gu.edu.au/~anthony/graphics/imagick/annotating/ ------------------------------------------------------------------------------- Complex draw commands. For example given the Draw file font Candice font-size 72 gravity center fill white stroke black text 0,0 "Candice" you can now label with convert -size 400x100 xc:lightblue \ -draw @draw_file \ -trim +repage result.gif Also available in draw is... font-family font-size font-stretch font-style font-weight This is especially usful for UTF-8 unicode characters. EG: in the file put... encoding 'UTF-8' text 10,90 ' unicode UTF-8 characters' ------------------------------------------------------------------------------- Multi-Image Mosaics (using Convert) This has been moved to My ImageMagisk Examples Page http://www.cit.gu.edu.au/~anthony/graphics/imagick/mosaics/ ------------------------------------------------------------------------------- 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/ Draw Text on an Image The problem with writing text directly on a picture is that you can't be sure the text will be readable in the color you have chosen. The image being drawn onto could be black, white or a rainbow of colors. This has been moved to my web examples page... http://www.cit.gu.edu.au/~anthony/graphics/imagick/annotating/#label Here is a shell script example I wrote for someone, who wanted the size of the text to be image dependant. image="logo:" output="x:" copyright="Copyright (c) 2003 David" height=`identify -format %h "$image"` pointsize=`echo $height / 25 | bc` echo "height = $height pointsize = $pointsize" convert -background '#00000080' -fill white -font Courier \ -pointsize $pointsize label:"$copyright" miff:- |\ composite -gravity south -geometry +0+2 -type truecolormatte miff:- "$image" "$output" NOTES: Dividing by 25 is for produce font 4% of the image height. Color '#00000080' is a half-transparent black. label: will automatically size the semi-transparent box to the text. Best color to use for text. Crop the area of the image the font will appear in, Average the color (-resize 1x1) negate and monochrome it convert rose: -resize 1x1 -negate -monochrome txt:- # ImageMagick pixel enumeration: 1,1,255,RGB 0,0: (255,255,255) white convert logo: -resize 1x1 -negate -monochrome txt:- # ImageMagick pixel enumeration: 1,1,255,RGB 0,0: ( 0, 0, 0) black Patterns and Text.. This has been moved to my web examples page... http://www.cit.gu.edu.au/~anthony/graphics/imagick/fonts/#fun Drawing Text in various places... This has been moved to my web examples page... http://www.cit.gu.edu.au/~anthony/graphics/imagick/annotating/#gravity Attaching a Text Label below an image... The following has been moved to http://www.cit.gu.edu.au/~anthony/graphics/imagick/annotation/#labeling 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. ------------------------------------------------------------------------------- Crop to specific reference points. "bertelli" wrote | | Begin with scanning an old map which is divided in sections: | +-------------------+ | | +---------------+ | | | | drawing | | | | | inside the | | | | | internal | | | | | frame | | | | +---------------+ | | +-------------------+ | Only internal frames are really carrying information and should be tiled to | make out the whole map. | But, to be fast, we estimated the four corners and put the reference points | (which are not supposed to be seen on the final picture. The label in this | table is just for reference, in a database for later goereferencing. | We cannot alter the measures of the images, as all the work is related to | this. | Now consider the example image. The size is 8537 by 5336 pixels. | The reference header says: | | geographical x image y Point | coordinates coordinates reference | -----------------+----------+------------- | (1479210,4919510) (8277,336) Label "Pt 1", | (1477210,4918310) (414,5064) Label "Pt 2", | (1477210,4919510) (377,355) Label "Pt 3", | (1479210,4918310) (8281,5049) Label "Pt 4" | | +-------------------+ | | 3 1+ | | | + drawing | | | inside the | | | internal | | | frame 4+ | | | +2 | | +-------------------+ | As you can see, the internal frame is not straight, but I have the | coordinates that could lead me to erase the borders (choosing the appropriate | number if I add a straight white border) or doing something more elaborate to | draw a white mask around the internal frame. | I think you would provide the right idea for it with this more extensive | description of the problem. | Carlo | Hmmm. I gather the x,y coordinates are in the scanned image coordinate system and you want them to define the edges of the final image. OK what I would do is 1/ Create a working image the same size as the scanned image You could read in the image and clear is as per "canvas" examples. 2/ draw a single pixel at the x,y coordinates you specify, onto this blank canvas in any other color. 3/ Use -trim to crop the working image so those four points are on the image edges. 4/ Run trim on the blank image than pipe the image into "identify" (See exampe on the "size" example pages under crop for identify) The result from identify will be something like... (this is only a rough guess, not exact for the above) map_blank.gif 7900x4536 8537x5336+377+336 GIF PsuedoColor... The first numbers are the croped size, the next two is the original size (though currently that may not be right, so just ignore) The last to is the offset to the top left corner of the crop. Using these figures you can now crop your actual map using the first two figures, at the offset given. EG: 7900x4536+377+336 (then do a +repage after the -crop) After cropping the original scanned image, the reference points on the new map will be on the edge of the image at the same location MINUS the offset you specified for the crop. Thus you will still know where they are on the cropped image. If you want some extra space around the referenc points adjust the size and offset you feed to the -crop for the real map image EG: add 40 pixels to size and subtract 20 pixels from the offset so reference points are just inside the new images edges. Now if you are wanting to 'slew' the image so your reference points are squared into the corners, that is a trickier problem and may require a use of a affine matrix. I have not dealt with that problem as yet, so don't have notes on doing this as yet. ------------------------------------------------------------------------------- Affine Matrix convert -affine sx,rx,ry,sy,tx,ty -draw 'text 100,100 "text message"' \ input.jpg output.jpg The 's' parameters control scaling, the 'r' parameters control translation, and the 't' parameters control coordinate translation. The matrix is the same one used by Postscript and PDF. Also called a 2x3 matrix. Grab a copy of the Postscript or PDF reference - it's well documented in there. It's also used by many other graphics libraries. For a null affine matrix use 1.0 for scale, 0.0 for translate & rotate Note ther may be easier ways... convert -draw 'rotate 20 text 100,100 "text message"' input.jpg output.jpg ------------------------------------------------------------------------------- Draw Primative Notes Both "text" and "image" (as of IM v6 beta) placement are positioned relative to gravity. Other operators are NOT currently gravity effected. Arc and Path... -draw "arc x0,y0 x1,y1 a0,a1" Arc is a legacy primitive and has since been replaces by PATH. An example: convert -draw "path M500,500 arc 50,50 0 25,25 100,100" \ logo: miff:- | display - (Result was not an arc...) convert -draw "path M170,70 v-30 a30,30 0 0,0 -30,30 z" \ logo: miff:- | display - (No output!) This is also crazy... convert -size 50x50 xc:white -fill green -stroke black \ -draw 'path "moveto 10 10 lineto 40 10 lineto 40 40 lineto 10 40 closepath"'\ x: Answer: ImageMagick uses the language specification from the SVG standard. Use that specification and you should get a path rendered. The option -tile causes -draw to use the image given as a color source rather than the -fill setting. ------------------------------------------------------------------------------- Merging two seperate GIF animations... Notes and ideas for stacking two seperate animations on top of each other. Its posible but very difficult, and requires a lot of processing outside IM. Especially for animations that have non-simple delays EG delays between frames are not constant, or even the same between the two animations. First of all, the animatioan will need to be converted to simple overlay animations otherwise it will be practically imposible. Most animations are of this type anyway as it is easier to generate an process. Second you need to figure other how the frames of the animation should be interleaved, time-wise. That is the frames individual frames will need to be shuffled together so that the updates occur at the right moment. You may need to do two frame of animation B then 1 of animation A, then one of B, and two of A. It all depend on the delays set within the two original animations. For example: As the first (zeroth) frames of both animations (A and B) are at time index zero, animation A frame 0 would be drawn without any delay, then Animation B frame 0 would be drawn with the shorter original delay of the two. The next frame (frame 1) would then come from the faster of the two animations, after that the delay and the animation the next frame comes from starts getting complex. Lastly the output animation frame will have to be given a larger 'page size', and all the page offsets of second animation will need to be offset further so it is position below the first animation. All of this can be done but IM can't (at least not yet) do the calculations to interleave two seperate animation sequences. It is posible IM could be made to do this, thanks to the new parenthesis allowing you to hold two or more image sequenences in memory. But until the exact programming is worked out, it would be better for this to be done by a external program, probably in PerlMagick due to the mathematical complexity. PS: a program such as this could merge multiple simple animations on top of each other allowing you to build up some increadiabley complex animation sequences. ------------------------------------------------------------------------------- Common color map for GIF Animation It is easy to create a single global colormap for an image sequence with ImageMagick: convert *.gif -color 256 -adjoin animation.gif The local color tables are still included in the GIF, however it matches that of the global colormap. ImageMagick may be patched to not generate a local colormap if a single global colormap applies to all images in the sequence. Color map is also reduce to smallest map needed. ------------------------------------------------------------------------------- GIF LZW compression ImageMagick does not compress GIFs due to the patent on the GIF compression algorithm owned by Unisys. It is due to expire in 2003, but until then it is up to you to get the legal issues resolved. Re-build ImageMagick with the --enable-lzw option to configure to enable. Alturnative use the "gifsicle"... gifsicle --batch -i *.gif ------------------------------------------------------------------------------- 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<-------- ------------------------------------------------------------------------------- Extracting a color map using txt: format By deleting the pixel position and sort uniq, we get a color map. convert netscape: txt:- | sed "s/.*://" | sort -u Replace "sort -u" with "sort | uniq -c | sort -n" can get a color histogram. PS: you'd probably like to remove line containing ",RGB" in it as well. ------------------------------------------------------------------------------- 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. ------------------------------------------------------------------------------- Image Comments Remove profiles: mogrify +profile "*" image.jpg ------------------------------------------------------------------------------- Progressive JPEG This lets some browsers show a large jpeg image while it is being loaded. Of course you do get a quality loss from loading and saving the jpeg image again. convert infile.jpg -interlace Line outfile.jpg To do this without loss of quality use jpegtran jpegtran -progressive infile.jpg > outfile.jpg ------------------------------------------------------------------------------- JPeg2000 (jp2) This also has a lossless mode but may be some time before it become wide spread. It can handle 16-bit color, and (presumably includes an alpha channel). Unfortunatally jp2 compression is also slow. For example in IMv6 convert input.png -define jp2:rate=1.0 output.jp2 ------------------------------------------------------------------------------- TIFF file compression TIFF compression gets turned off by JPEG reading! To fix use. convert xxx.jpeg -compress LZW xxx.tiff OR convert xxx.jpeg -compress zip xxx.tiff OR convert xxx.jpeg -compress none xxx.tiff tiffcp -c LZW xxx.tiff yyy.tiff I think you have to reset the compression method *after* reading the JPEG because reading the JPEG resets it to "jpegcompression". Glenn Randers-Pehrson ------------------------------------------------------------------------------- TIFF CMYK notes... Image profiles are required to produce a proper CMYK to RGB translation. For example, a command line conversion it looks like this: convert cmyk.tif -profile USWebCoatedSWOP.icc -profile sRGB.icm im_rgb.tif You will need a LCMS delegate for color profiling images for the above to work. ------------------------------------------------------------------------------- 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. ------------------------------------------------------------------------------- Postscript to Images (anti-aliasing fonts) If you just convert a postscript file to an image directly (using ghostscript), you will get it at 72dpi resolution (yuck). A better idea is to do this at a larger resolution and then shrink it so that the edges are properly anti-aliased... Example: convert -density 288 -resize 25% foo.ps foo.jpg Convert is a ImageMagick command. It calls ghostscript to convert postscript to pbmplus format before converting (and shinking) to the final jpeg image. NOTE: Density 288 is 4 times the normal 72 dpi screen (and image) resolution. Also the bigger you render the images the more memory and CPU power you need ... 2x2 or 3x3 is probably good enough for web pages. ASIDE: If you need more antialiasing, you can blur the image a little bit before you reduce its size. ASIDE: if you want to resize the image, without the anti-alias color merging use -sample instead of -resize. The former simply copies the nearest pixel color into the new pixel. NOTE: "-filter point -resize WxH" and "-sample WxH" are equivilent. Richard Bollinger Notes... Running ghostscript directly is _much_ more efficient.. convert -density 300x300 -compress Group4 file.pdf file.tif required an 84mb temporary file, consumed 120 cpu seconds, paged like crazy and ran for 12 minutes on a two page pdf. gs -sDEVICE=tiffg4 -r300x300 -dNOPAUSE -sOutputFile=file.tif \ file.pdf 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 ------------------------------------------------------------------------------- Adaptive sharpening using FX From Kornelis Sietsma Basic tecnique from http://www.gimpguru.org/Tutorials/SmartSharpening2/ The basic original technique is : 1 - Create an edge mask by running an edge-detect on the image, converting to greyscale, blurring the results, and spreading the contrast out a bit. 2 - Split the image into HSV channels 3 - Strongly sharpen the V channel using unsharp mask 4 - Merge the sharpened V channel back with the H and S channels, using the edge mask as a mask. This means that areas near edges in the original image get sharpened quite strongly, while areas far from edges get left largely unprocessed. Due to a lack of HSV channel manipulation in ImageMagick I couldn't do this quite the same way - there is no way (that I could find) to do step 4 without resorting to some mathematics. But the rest of the steps were fairly easy: 1. With some fiddling of parameters, I make an edge mask with: convert orig.png -edge 3 -colorspace GRAY -level 20%,95% -gaussian 10 -level 10%,95% edgemask.png 2. I managed to extract just a brightness image with : convert orig.png -modulate 100,0 bchannel.png (This is close enough to the "V" channel for my purposes - I thought of using "intensity" but that was rather too slow for my liking) 3. Sharpening is simple, though again lots of fiddling of parameters can be done. Note this is stronger sharpening than you'd want to do normally! convert bchannel.png -unsharp 0x1+200+0 sharpened.png 4. Merging them back together is where 'fx' comes in: convert orig.png bchannel.png sharpened.png edgemask.png -fx "u[0]+(((u[2]+1)/(u[1]+1))-1)*u[0]*u[3]" output.png just to break that last mess down: u[0] is the original image u[1] is the brightness channel u[2] is the sharpened brightness channel u[3] is the edge mask ((u[2]+1)/(u[1]+1)) is the ratio of the sharpened brightness to the original - I had to use "((u[2]+1)/(u[1]+1))" instead of "(u[2]/u[1])" as the latter would cause divide-by-zero problems on black areas of the original image. (I'll call this "K" from here on for simplification.) The rest is to scale the amount of brightness change by the edge mask (u[3]): when u[3] is 0, the output is "u" when u[3] is 1, the output is "u + (K-1)*u" which equals "K * u" Finally, I string the whole thing together into a single command line: convert orig.png \ \( +clone -modulate 100,0 \) \ \( +clone -unsharp 0x1+200+0 \) \ \( -clone 0 -edge 3 -colorspace GRAY -level 20%,95% \ -gaussian 10 -level 10%,95% \) \ -colorspace RGB -fx "u + u*u[3]*(((u[2]+1)/(u[1]+1))-1)" \ output.png Note I had to put an extra "-colorspace RGB" in there to stop the output being greyscale. It's kind of slow on a big image, but it works! ------------------------------------------------------------------------------- Reading Linux Framebuffer with IM rgb: convert -depth 8 -size 800x600 rgb:/dev/fb/0[0] \ \( -clone 0 -channel B -separate \) \ \( -clone 0 -channel G -separate \) \ \( -clone 0 -channel R -separate \) \ -delete 0 -channel RGB -combine outfile.fmt in case you can't tell, what that does, is take a screenshot of whatever's currently displayed on your linux framebuffer (it works in console, too) this is for mine in particular, which is 800x600, 24bpp, BGR subpixels and located at /dev/fb/0 (as opposed to /dev/fb0) in accordance with the devfs structure... i put the [0] subscript on there to keep it loading just the first page of video memory, as there are two, for page-flipping and y-panning... if you can think of a faster method, i'd love to hear it... but in the mean time, you can look at this... for i in `seq 0 n`; do convert -depth 8 -size 800x600 rgb:/dev/fb/0[0] \ \( -clone 0 -channel B -separate \) \ \( -clone 0 -channel G -separate \) \ \( -clone 0 -channel R -separate \) \ -delete 0 -channel RGB -combine miff:- done | convert miff:- outfile.gif i used a two-pass, because i can't figure out a way to do images in series like that without unrolling the loop inside of the convert command line, and that quickly becomes insanity... of course it's better for capture framerate if you do something more along the lines of.... # capture for i in `seq 0 n`; do dd if=/dev/fb/0 of=outfile-`printf "%02d" $i`.rgb bs=1440000 count=1 done # process for i in `seq 0 n`; do convert -depth 8 -size 800x600 rgb:outfile-`printf "%02d" $i`.rgb \ \( -clone 0 -channel B -separate \) \ \( -clone 0 -channel G -separate \) \ \( -clone 0 -channel R -separate \) \ -delete 0 -channel RGB -combine miff:- done | convert miff:- outfile.gif # clean up rm *.rgb depending on what effect you're trying to get, capturing faster could be good or bad... i used both methods in capturing some framebuffer screensavers i wrote to gif format, which can be seen at... http://pegasus.pimpninjas.org/fire.gif - fast method http://pegasus.pimpninjas.org/tux.gif - slow method lemme know if you think this is worthy of inclusion on your page at all, and certainly at least let me know if you have a better method of swapping the red and blue bitplanes... oh, and if you happen to have a way to translate/modify 15 and 16bpp with imagemagick, that'd be very useful for me as well...i could write something to do it for me, but i'd much rather not have to rebuild something Pegasus ------------------------------------------------------------------------------- ImageMagick Limits The file limit is imposed by the shell, not ImageMagick. You could say '*.jpg' and ImageMagick will interpret the wildcard filename for you and it removes the filename limit imposed by the shell. --- When creating JPG thumbnails, within montage or elsewhere you can limit the amount of memory the read in by the jpeg library by setting the -size setting before reading. montage -size 100x100 -resize 100x100 ... This is passed to the JPEG library and which will return an image a little larger than this size (usally the next power of 2). To see what size is returned try convert -size 100x100 dragon_tatoo.jpg miff:- | identify dragon_tatoo.jpg - dragon_tatoo.jpg JPEG 398x431 DirectClass 40kb 0.000u 0:01 /tmp/magick-XXd3cJ6P[1] MIFF 199x216 DirectClass 126kb 0.000u 0:01 Note that while memory usage is reduced by this, the library will still need to process the whole file from the disk drive, so it can still be slow on very large images. --- Non IM cropping of large files Vips and nip, developed by the National Portrait Gallery in London, is designed to work on very large image files with low spec computers and should easily handle a 700MB TIFF file. Vips is the underlying engine and nip is the gui. Works on Linux, Windows and sometimes on Mac. http://www.vips.ecs.soton.ac.uk/index.php Jenny Drake < jennydrake @ lineone.net > --- ImageMagick, by default, grabs as much memory as needed to process a file, however, you can limit the memory to prevent this. convert -limit area 32 -crop 1000x1000+0+0 bigassimage.tif crop.tif If your version of ImageMagick does not support the area option, try convert -limit memory 32 -limit map 32 -crop 1000x1000+0+0 \ bigassimage.tif crop.tif This will force IM to use temporary disk swap files instead of real memory for processing images that will not fit into 32 Megabytes. From Manpage... Other limit setting and the current defaults are... File 768 files (number of open files) Memory 1024Mb (practically infinite on current desktop PC's) Map 4096Mb (disk swap memory mapping) Disk infinite (in Gb all others in Mb) Area infinite (pixels in memory) Environment variables and also be used to define these settings MAGICK_AREA_LIMIT, MAGICK_DISK_LIMIT, MAGICK_FILES_LIMIT, MAGICK_MEMORY_LIMIT, and MAGICK_MAP_LIMIT You can use -list to see current limits. -------------------------------------------------------------------------------