5 Mar 2007

Sort pictures based on Exif date

Recently, I bumped into a problem: I had received pictures from the same event from three different sources (cameras). How could I sort these based on when the pictures were taken?

A small Perl script are born to the rescue. The program "jhead" dumps Exif data contained in JPEG images. Running jhead on a image without options gives:

jhead IMG_1195.JPG
File name : IMG_1195.JPG
File size : 2988387 bytes
File date : 2007:03:04 15:37:34
Camera make : Canon
Camera model : Canon DIGITAL IXUS 800 IS
Date/Time : 2007:02:22 19:17:14
Resolution : 2816 x 2112
Flash used : Yes (auto)
Focal length : 5.8mm (35mm equivalent: 37mm)
CCD width : 5.72mm
Exposure time: 0.017 s (1/60)
Aperture : f/2.8
Whitebalance : Auto
Metering Mode: matrix

The "Date/Time" header gives the time stamp. Renaming the file to the date, would make it easy to sort the pictures in time based on filename:

IMG_1195.JPG --> 20070222_191714.jpg

Instead of manually renaming a couple of hundred images, Perl can do the job:

#!/usr/bin/perl -w
# filename: exif_date_sort.pl
# Small utility that renames pictures based on the Exif date.
# Date: Sun Mar 4 19:13:42 CET 2007
# Lars Strand

use strict;
use File::Glob qw(:globally :nocase);
use File::Copy;

die "Usage: $0 PATH" if $#ARGV < 0; 

while (@ARGV) { 
   my @filelist = glob($ARGV[0]."*.jpg"); 
   foreach my $file (@filelist) { 
       for my $line (`jhead "$file"`) { 
           if ($line =~ /^Date\/Time\s*:\s*(\d+):(\d+):(\d+)\s*(\d+):(\d+):(\d+)/) { 
              print "$file --> $1$2$3_$4$5$6.jpg\n";
              copy("$file", "$1$2$3_$4$5$6.jpg") or die "Error: Copy failed: $!";
  shift @ARGV;

The script takes one or more directories as argument. Every JPG file that has a Exif date header, are copied to a new "date-filename".

Running it gives the following output:

~/exif_date_sort.pl 200702-Veggli/
200702-Veggli/IMG_1196.JPG --> 20070222_194000.jpg
200702-Veggli/IMG_1197.JPG --> 20070222_194007.jpg
200702-Veggli/IMG_1198.JPG --> 20070222_194012.jpg
200702-Veggli/IMG_1200.JPG --> 20070222_194437.jpg
200702-Veggli/IMG_1201.JPG --> 20070222_194443.jpg
200702-Veggli/IMG_1202.JPG --> 20070222_194643.jpg
200702-Veggli/IMG_1203.JPG --> 20070222_194844.jpg

.. or, as I'll learned later, you can just alias jhead to:

jhead-iso is aliased to `jhead -n%Y-%m-%d_%H:%M:%S'

No comments: