ImageMagick and bash: Batch Power!

Ok, here is another topic on which I had planned to blog for quite some time, but I wanted to have the end result available on my gallery website before blogging about the technicalities…

An area where Linux shines

We have touched the subject of using bash scripts to quickly convert RAW files into JPEG with default settings. For that we used Ufraw (from the command line) and a bash script. Bash scripting (web, wiki) is actually one area where Linux (and Unix-like systems) shines since this has been an important part of the operating system since its inception. Basically, Linux is a kernel that you can interact with through a command line language (Bash is one of them). And you can write these commands to a file for ease of (re)use.

Now the command lines also allows you to interact with most Linux programs, as we have seen in the Ufraw example.

The power of ImageMagick

For image manipulation, Linux offers the hell of a powerful tool called ImageMagick (web, wiki). This library offers a lot of operations which you can do on images from the command line (and from a bash script):

  • scale, crop or rotate an image
  • change the image format
  • convert from one to another ICC editing profile (or remove any ICC profile information)
  • add text somewhere in an image
  • sharpen the image
  • add a border to the image
  • … (see ImageMagick web page for all the possibilities)

A step by step example: resizing images

Take me, for example🙂 I like to watch slideshows on my laptop, but this poor lappie doesn’t have enough horse power to cope with 6MP files. So wrote a little bash / ImageMagick file that resizes the original files to 800×700 pixels. I just run the file in the folder containing the original pictures, copy the screen_images folder to my laptop and enjoy a screen-optimized slideshow.

#!/bin/bash

if [ ! -d ./screen_images ]; then mkdir ./screen_images; fi;

# creates the screen image
for f in *.jpg;
do
    echo "Processing $f"
    convert -strip  -modulate 105,110,100  -resize "800x700"  -unsharp 0,1.5,0.05  \
        $f ./screen_images/$f
done

if ls | grep tif; then for g in *.tif;
    do
        echo "Processing $g"
        convert -strip -resize "800x700" -unsharp 0,1.5,0.05  \
            $g ./screen_images/${g/.tif}.jpg
    done
fi

cd ./screen_images

# change the image names
for i in *.jpg;
do
    mv "$i" "${i/.jpg}"_s.jpg;
done

Actually it does a little more than that, lets to through it step by step, as an introduction to bash and ImageMagick.

The script first checks whether the directory “processed_images” exists and if not, it creates it (this is a pure bash command)

for f in *.jpg; creates a list of all the jpg files in the folder for further processing (again, a bash command)

convert invokes ImageMagick command to transfer and convert each of the jpg files ($f) to the subfolder processed_image (still as a jpg file). While converting, it applies the following operations to the file:

-strip asks to remove any reference to ICC Editing Profile (AdobeRGB in our case)
-modulate 105,110,100 boosts a bit the brightness (105, 5%) and saturation (110, 10%) while leaving the hue at the default level – my camera is set up to produce rather soft images that support more post-processing so this little boost is required.
-resize 800x700 resizes (indeed) the image so that its biggest dimension fits in 800×700 while keeping the image ratio
-unsharp 0,1.5,0.05 applies an unsharp mask to the image

The script then goes on to converting any tiff image in the folder to a resized jpeg – except that it doesn’t modulate (brightness and saturation) since a tiff image at that stage has been already processed and doesn’t need the boost.

Eventually, it goes into the processed_images folder and renames all the files to *_s.jpg (to signify that they are screen size) – again, this is pure bash.

Taking that to the next level

What I did for my website was take that to the next level. My script takes high-quality (and big dimensions) tiff files and spits out an image optimized for the web. It also builds a basic xml file which I use to display the image titles (in French and English) and order the images.

Basically, the script resizes the image to 450 x 650 (max height, max width, keeping the image ratio) and applies an unsharp mask (the bigger the original image size, the stronger the USM). It then puts the image in the center of a 480 x 680 white canvas and draws the drop shadows. It saves the whole as a jpg file.

The scripts also generates thumbnails (standard and on-mouse-over ones) and puts them in a subfolder.

Lastly, it builds a basic xml file framework that reads:

<picture>
    <file_name>picture_file_name.jpg</file_name>
    <french_title></french_title>
    <english_title></english_title>
</picture>

for each picture. I can then add the French / English titles and cut-paste the <picture> ... </picture> tags around to reorder the gallery – obviously, my site knows how to handle these. I have one directory per gallery, so running this batch file in each directory creates the gallery xml file, images and thumbnails.

The great thing about that is that I only keep and work on the high quality once-for-all processed version of my files and have the web images generated when I need them. So if I decide to change the file size, for example, I can regenerate my webfiles in 10 mins instead of starting to modify each file again.

You can get the command file script_neweb.odt for your pleasure and tweaking – WordPress would only allow me an ODF version of the file, so I hope you can do something with it. But beforehand please read carefully the next paragraph.

A final word of warning

So bash scripts and ImageMagic is really a powerful combination for pictures batch processing in Linux. However I find bash syntax to be terribly difficult and picky (check here for a bash beginner’s guide), so putting together a bash script always requires lots of time (at least for me).

Plus you need to be very careful about what you are doing since your script is (potentially) modifying files on your system. One scripting error and you may find yourself with a script navigating around and deleting (or renaming) files – that can be very damaging to your datas (trust me…). So be warned: with power comes responsibility!

Here is the script result on one image I like very much, one of the very first good ones I took after I bought my Pentax *istDS – check a bigger size version on my site, as always.

geneva_cityline.jpg

11 Responses to ImageMagick and bash: Batch Power!

  1. Yves says:

    I have been beta testing a program that does the same, but graphically and very intuitively: it is called Phatch and is developed by Stani, known from the Python IDE. Phatch can be found here: http://photobatch.stani.be/

  2. jcornuz says:

    Hi Yves,

    Good to read from you again. I have made a note to look into Phatch (I saw the development thread in unbuntuforms but haven’t had a chance yet). How usable is it?

    Thanks for passing by.

  3. Yves says:

    Hey there, I just started a new job so I am very busy; I try to check in here every now and then. I like the articles I read thus far, going well!

    Phatch is already very usable, I use it for all my batch image processing in Linux. In Windows I use Lightroom, but whenever I need to add a watermark, resize and compress for web, I do it in a few clicks with Phatch. Just make sure you have a backup copy of the files you edit when you run it, just in case. Or maybe it is just me playing safe🙂

    Take care!

  4. jcornuz says:

    OK, that real life thing again…

    I’ll have a try at Phatch when I get a chance. If you recommend it, then it must be serious🙂

    Take care.

  5. nam says:

    Actualy i had to tiny-modify your bash script, double-quoting the filenames to work with pictures containing spaces and special chars in filename (like this : Processing poze cu david,diverse 105.jpg) .

    Nice job !

  6. jcornuz says:

    Hi there,

    Typical bash🙂 Thanks for sharing !!

  7. Mayuresh says:

    Hello friends,

    Can any one tell me that how can i read pages from pdf file one by one.
    Actualy i want to convert pdf to jpeg, i have done it using imageMagick, but i want to convert pages one by one…
    Please help..

    Thanks,
    Mayuresh

  8. BobD says:

    You can open single pdf pages in gimp and then save as jpeg. Not very fast, but an option.

    Bob

  9. Buna. Interesant site ai .Ai fii interesat un linkexchange in blogroll cu siteul meu http://www.poze.haioase.org ? Trimite-mi te rog un email daca da, o zi faina Alina IS

  10. Mat says:

    Thanks, was getting sick of doing all the resizing manually in gimp.

  11. Ty says:

    Thanks, this was just what I was looking for. Beats batch processing in Gimp and Photoshop, in terms of speed and ease of use.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: