Batch-converting images for an HDTV

A couple of days ago, my parents bought their first HDTV. Since it has a USB port that can be used to show pictures stored on a flash drive, I found myself in the position of finally using an old 512 MB stick I had lying around.

I scouted my iPhoto Libraries for pictures, and simply dragged them into a folder I had created. I quickly stumbled across two problems:

  1. The Finder almost immediately reported that the drive was full, even when it still had over 350 MB available, or that one or more files couldn’t “be read or written”;
  2. 8-megapixel images are just too big for a Full HD screen, so you end up wasting a lot of space and possibly slowing down the TV.

Did I fix them? You bet I did. Read on to find how.

The first problem was the trickiest to solve. After trying to copy it directly using cp in a shell, and getting the same error, I decided to try copying the files without their resource forks. To do that, use the -X flag on cp. It magically worked, even though I’m not sure what the problem was, but using cp -X gives you the clean, data fork only images, and everything is merry again.

The second problem is more of an hassle, but going from 182 MiB to 63 MB (for 167 images) is certainly nice. After all, the output screen only has a resolution of 1920 x 1080 pixels, and it’s absolutely pointless to use it to display images sized up to 3456 x 2304 pixels.

So, how do you resize them in a pinch? Enter ImageMagick, an open-source image conversion suite. If you are on a Mac and you have MacPorts installed, you can simply run sudo port install ImageMagick and let it do all the work for you.

For the sake of the example, let’s suppose that the images are in a directory called stuff, and that they have the most random names; some of them have names ending in .JPG (capitalized), some of them end in .jpg (not capitalized). Isn’t that a nightmare? Not really.

Please note that this example implies that you use bash on any a Unix-like system. ImageMagick is available for many platform, including Windows, but you will need to find another way to run it on each file you need to resize. I personally use OS X.

Here is the sequence of steps we need to take to convert everything to HDTV size:
octavarium:~/stuff jollino$ mkdir _
octavarium:~/stuff jollino$ for f in *[Jj][Pp][Gg]; do convert $f -resize "1920x1080>" _/$f; echo Image $f converted successfully; done
Image 1b371a9f-a59c-4c5e-b9f2-9a8aa24c807e.original.jpg converted successfully
Image 2fb7c7da-999d-4744-b8e8-dffa5d466736.original.jpg converted successfully
Image 3a39767c-b830-4fb8-90ce-40d97e793c65.original.jpg converted successfully
Image IMG_0737.JPG converted successfully
Image IMG_0742.jpg converted successfully
Image IMG_0745.JPG converted successfully
Image IMG_0746.jpg converted successfully
Image IMG_0750.JPG converted successfully

The first command obviously creates a directory called _. You can name it any way you want, but I personally prefer very short names when dealing with batch processes, especially when there is little risk of confusion.

The second command is where the magic – no pun intended – happens. It can be read as folows:

  1. Iterate over each file in the current directory whose name ends in any case combination of ‘jpg’;
  2. In each cycle, call the name $f
  3. Run the command: convert $f resize "1920x1080>" _/$f
  4. Run the command: echo Image $f converted successfully
  5. Repeat for the next file

As can be easily inferred, the actual conversion takes place in step #3. If the file name is IMG_1891.jpg, for instance, the command is expanded as convert IMG_1891.jpg resize "1920x1080>" _/IMG_1891.jpg.

The > character in the output image size is not a mistake: it tells convert that we want it to be 1920 pixels wide and 1080 pixels high… but the aspect ratio is our main priority.
This means that images will not be smared to fill the 1920 x 1080 canvas; the output images will be at most 1920 pixels wide or 1080 pixels high, whichever can be optimized, and the other dimension will be changed accordingly. Okay, now that’s confusing. Let’s look at a few examples.

  • A 2816 x 2112 image (4:3 horizontal) will be resized to 1440 x 1080. If it had been resized to 1920 x 1440, it would have had to be cropped to fit on a 1920 x 1080 screen.
  • A 2112 x 2816 image (4:3 vertical) will be resized to 810 x 1080. That sure beats a 1920 x 2560 image (which would end up bigger than the original anyway!)
  • A 3456 x 2304 image (3:2 horizontal) will be resized to 1620 x 1080.
  • A 3456 x 1944 image (16:9 horizontal) will be resized to 1920 x 1080.
  • A 1048 x 699 image (3:2 horizontal) will not be resized and will stay at 1048 x 699.
  • A 2148 x 2148 image (1:1 square) will be resized to 1080 x 1080.

As you can see, most images will have a shorter horizontal side in order to accommodate for a as-tall-as-possible vertical side, as that is still shorter.

After doing all of this, make sure that the USB drive has a MBR rather than a GUID partition table and a FAT partition, and simply run:

octavarium:~/stuff jollino$ cp -Xv _/* /Volumes/nameofyourdrive/

Gracefully eject the drive, remove it, and enjoy your pictures!