Friday 19 July 2019

ImageMagick Mogrify

Mogrify -- in-place batch processing

The "mogrify" command is in many ways like "convert" except it is designed to modify images in place. That is it's primary purpose is to read images (or animations), one file at a time, and modify them, before save the image back into the exact same filename the image was read from. Because of this...
Mogrify is dangerous, as it can easily destroy the original image!
As such, before you do anything final, test "mogrify" with a separate copy of your images. Do not do use it on an original image that has no backup.Now while "mogrify" normally saves a modified image into the same filename, it has two special options which allows it to save images into a different file.The "mogrify" specific setting "-format", defines a different format and suffix to use when saving files.As such a command like...

  mogrify    -format jpg   *.png
Will allow you to convert, or batch modify images, without destroying the original image. In this case converting all PNG files into JPEG files with that same filename but a different suffix. However be warned that if there is an existing file with the same name, it will be over-written.So let me re-iterate...
Think and check before you Mogrify
or you may find you just overwrote something you wanted to keep. As of IM v6.2.0 you can also use a new "-path" option to specify a different directory in which to output the processed images. This makes it safer, however it will still overwrite any images of the same name that may already be in that directory. Also any old images that was left in that directory will not be removed.As such you can have IM save the results (say image thumbnails) into a existing sub-directory, using something like this...

  mogrify   -path thumbnail-directory   -thumbnail 100x100  *
Before IM v6.3.4-3 the "-format" and "-path" settings were mutually exclusive. From that version you can change formats and output directory location.
Due to the multi-image processing capability the "mogrify" command can not use any of the Multi-Image List Operators or Image Stack Operators.That means you can not use image processing operators like "-fx", "+swap", "-composite", "-append", "-flatten", and "-layers" in a "mogrify" command.As some setting options are needed to be set before the first image is read in (for example (for example "-size", "-label" and "-density"), these options are processed and set before the first image is read in. After this each image is read in and the operators applied to them in command line order before the image is saved and the next image read in.It is important to keep this in mind as if you change one of these settings later in the sequence you can make IM forget a previous setting.For example..

  mogrify -format gif  -size 200x200  -pointsize 18 \
          -font Candice -gravity north  -annotate 0 "%f" \
          -font Ravie   -gravity Center -annotate 0 "%f" \
          -font Gecko   -gravity south  -annotate 0 "%f" \
          -size 100x64   xc:gold  xc:orange   xc:tomato
[IM Output] [IM Output] [IM Output]
As you can see the size of the above images generated was determined by the second "-size" input setting with the first larger setting being ignored completely. On the other hand the operational setting "-font" is set correctly for each of the individul "-annotate" operations.This added complexity means that it is probably a good idea to...
Mogrify images simply.
Do not attempt to do very long and complex "convert"-like operations in a batch operation using "mogrify", it will probably have 'setting' issues. If you are really wanting to do complex processing, write a shell/dos/perl script to use "convert" to process each image one at a time, or go to a ImageMagick API interface.For examples of modifying lots of images using a script see Advanced ImageMagick Examples.Just remember, "mogrify" is a dangerous command, and should always be thoroughly tested on backup images, before putting into production.Actually I also recommend that scripts include a quick 'tests' on things like "mogrify" to make sure the command does not break anything (due to version changes or differences in computer installations) before processing a very large collection of images. That is do a small 'test case' and abort if it fails to produce a correct, before proceeding.This is actually a good idea for any large scale image processing project, so as to protect users from unforeseen consequences. I do this myself in IM Examples, and it has saved me a lot of trouble.

Alpha Composition using "mogrify"

Because "mogrify" can not use Multi-Image List Operators it can not easily overlay thing like logos, or mask images using Alpha Composition.There is one exception to this, using "-draw" to perform image alpha composition. This allows you to specify the second image, as part of the operators arguments, outside of the current image list.For example, here I first make a copy of the original images I want to process using a special "cp_perl" script. I then create temporary circle 'mask' image, which I then use to cut out a circle shape from all those images, using "mogrify" with a 'Dst_In' alpha composition method.

  cp_perl  's/^/mogrify_/'  eye.gif news.gif storm.gif tree.gif
  convert  -size 32x32 xc:none -draw 'circle 15.5,15.5 15.5,0'  circle.gif
  mogrify  -alpha Set -draw 'image Dst_In 0,0 0,0 "circle.gif"'  mogrify_*.gif
[IM Output] [IM Output] [IM Output] [IM Output]  +  [IM Output] ==> [IM Output] [IM Output] [IM Output] [IM Output]
Note that any Alpha Composition method can be used in this way, but only with a constant 'source' or 'overlay' image being applied to all the images.Also as "mogrify" will be reading the 'source' image multiple times, I suggest you use the special IM specific "MPC:" file format to reduce the overhead of decoding the image when reading it over and over. This image file format does not need to be parsed by IM as it will be mapped directly from disk into memory (for the same machine it was created on). This saves a lot of processing time, especially in dealing with a large number of images.

Using Convert Instead of Morgify

Using a special technique to modify the output filename using Percent Escapes, (see Filename Percent Escapes), you can replace "mogrify" with a more versatile "convert" command.Not only that but it will provide you with a more control of the final destination name of the image. and let you better handle multi-image processing such as compositions and animations.For example here I create thumbnails of images in the current directory, inserting a "_tn" string into the input filename, to create the appropraite output image filename.

  convert *.jpg   -thumbnail 120x90 \
          -set filename:fname '%t_tn' +adjoin '%[filename:fname].gif'
Warning, do not include a different file suffix in the filename setting itself. IM will not see it when deciding on the image file format to use. Note that IM can't decide from the filename it will fall back to the original file format that was read in, so a clear suffix, or a coder prefix can be important, when using this technique.To get the exact original filename the source image came from use "%i", "%d/%f" or "%d/%t.%e". Of course these all have the filename suffix, in the filename setting, whch IM does not use, but that should be okay as it is the same image file format.The real problem with using "convert" instead of "mogrify" is that ALL the images are read into memory first! Mogrify takes great pains to only read/modify/write one file (though that file could contain multiple images) at a time. But "convert" does not. As such you can very easily exceed memory limits if you are not careful. Though there are ways around this. See examples in Read Modifiers and Thumbnails.Also as all the images are in memory as a single image list, you will need to be careful on how you process those images. For example you can not directly use Alpha Composition as you normally would, but may need to use the specialised Multi-Image List Composition to do the job.Of course just as with "mogrify" this method of using "convert" can be dangerous, as it could easily overwrite and destroy the original image files.

Batch Processing Alternatives

If batch processing images using "mogrify" is not practical, especially if you are copying the images rather than modifying them in place, then it may be better to use some other non-IM looping solutions. These include...

  # Use a simple shell loop, to process each of the images.
  mkdir thumbnails
  for f in *.jpg
  do   convert $f -thumbnail 200x90 thumbnails/$f.gif
  done

  # Use find to substitute filenames into a 'convert' command.
  # This also provides the ability to recurse though directories by removing
  # the -prune option, as well as doing other file checks (like image type,
  # or the disk space used by an image).
  find * -prune -name '*.jpg' \
         -exec  convert '{}' -thumbnail 200x90 thumbnails/'{}'.gif \;

  # Use xargs -- with a shell wrapper to put the argument into a variable
  # This can be combined with either "find" or "ls" to list filenames.
  ls *.jpg | xargs -n1 sh -c 'convert $0 -thumbnail 200x90 thumbnails/$0.gif'

  # An alternative method on linux (rather than plain unix)
  # This does not need a shell to handle the argument.
  ls *.jpg | xargs -r -I FILE   convert FILE -thumbnail 200x90 FILE_thumb.gif
And so on.I recommend the use of both "find" and "xargs" for doing recursive or even non-recursive file processing. Read their man pages. For a quick introduction see this IM Discussion Post, as well as the guide Xargs - Wikipedia which includes information on the dangers involved.If your commands start to get more complicated than this, it may be time to go to a shell script, or API program, to read in multiple images, gather information, calculate appropriate arguments, and process the images.I also recommend a good look at the "parallel" command (typically a drop in replacement for "xargs"). This can not only let you run multiple commands simultaneously, but can with a little work run each command on different computers, allowing you to do network distributed processing of a very large number of tasks.For Windows Users I refer you to the Windows Usage section, and in particular Windows, Batch Processing Several Files.
Remember "mogrify", and all other IM commands will also expand all filenames containing shell meta-characters such as '*' and '?'. This is done to allow the use of these meta-characters on the old DOS command line shell. However this could cause a bug, repeated mogrify execution, or possibly even a 'hack' from a some evil source that provided the filename to use. Caution and complete understanding of security issues is advised.

No comments:

Post a Comment

Note: only a member of this blog may post a comment.

Blog Archive