Fixing EXIF date information

Back in February, some friends and I spent a week visiting Punta Cana. We made a lot of photos there but, when we came back, we realized that most of us (not all!) forgot to adjust our camera's date to the foreign timezone, which was 5 hours behind of ours. I imported all our photos in iPhoto but the difference in their timestamps made all images appear unsorted in the main view; this was very annoying. So I wondered if the EXIF information embedded in them could be easily fixed. It turns out it is possible, but the tools to do so — or at least the one I used — leave a lot to be desired: it was not exactly trivial to resolve the problem. In order to modify the EXIF information, I installed the free libexif library alongside a very simple frontend to it named exif, distributed from the same page. To painlessly get this in Mac OS X, just use the graphics/exif package in pkgsrc. Then I had to see which fields I wanted to modify in each photo. This can be accomplished with the exif --tag <photo-name.jpg> command, which shows all tags currently attached to the photo and their corresponding values. Skimming through the resulting list, it is easy to spot which fields correspond to date information. I specifically picked up 0x0132, 0x9003 and 0x9004, but some of them may not exist in your images. With this information at hand, I wrote a little script that looped over all affected photos and, for each tag, adjusted it to the new value. It goes as follows:#!/bin/sh while [ $# -gt 0 ]; do file=$1; shift for tag in 0x0132 0x9003 0x9004; do date=$(exif --tag=${tag} $file | grep Value | cut -d ' ' -f 4-) date=$(perl adjust.pl "${date}") exif --tag=${tag} --ifd=0 --set-value="${date}" ${file} mv ${file}.modified.jpeg ${file} done doneThe magic to subtract five hours to each date is hidden in the adjust.pl script, which looks like this:($date, $time) = split / /, $ARGV[0]; ($year, $month, $day) = split /:/, $date; ($hour, $min, $sec) = split /:/, $time; $amount = 5; if ($hour >= $amount) { $hour -= $amount; } else { $hour = $hour - $amount + 24; if ($day == 1) { $day = 31; $month -= 1; } else { $day -= 1; } } printf "%04d:%02d:%02d %02d:%02d:%02dn", $year, $month, $day, $hour, $min, $sec;I know the code is really crappy but it did the job just fine!

April 7, 2007 · Tags: <a href="/tags/exif">exif</a>, <a href="/tags/photos">photos</a>
Continue reading (about 2 minutes)