More photo stuff
August 18th, 2005 at 12:14 am by Dr. Drang
To continue on from my last
post,
the other program in my photo organization scheme is a program that
takes the photo files, which have names like DSCnnnn.JPG, and gives
them new names based on the day they were taken. The format for the
names is yymmddnn.jpg, where
yy is the last 2 digits of the year. I didn’t get a digital camera until after the year 2000, and I’m not too concerned about the Y2.1k problem.
mm is the two-digit month. January through September have a leading zero: 01-09.
dd is the two-digit day of the month.
nn is the two-digit number of the photograph taken on that day. I’m screwed if I take more than ninety-nine photos on any given day, but for personal photos I’ve never even come close.
I kept the name to the old DOS “8.3” format because I read somewhere that the ISO 9660 standard for CDROMs requires it. And although there are (obviously) extensions to that standard that allow longer names, the short naming system didn’t seem like too much of a burden.
The name of the program is canonize, a mild pun: the file name is being put in canonical form, and our camera is made by Canon.
Here’s the program.
#!/usr/bin/perl
use Image::Info qw(image_info);
use Getopt::Std;
$help = <<HELP;
canonize: rename photos to reflect the date on which they were taken.
Use the date embedded in the EXIF file. The format for the
file name is yymmddnn.jpg, where yy is the year, mm is
the month, dd is the day, and nnn is the photo number for
that day. This is specialized for the EXIF format of our
Canon PowerShot S30.
usage:
canonize [options] file-list
option:
-s num: the starting number for the photos (default: 1)
-p: print the new photo names, but don't rename the files
-h: display this help message
HELP
getopts('hps:');
$number = $opt_s || 1; # default starting number is 1
if ($opt_h || !@ARGV) { die $usage; }
#initialize count and date string
$i = 1;
$olddatestring = "1989:03:25"; # can be any date that will certainly
# be before the date the photo was taken
while ($oldname = shift) {
my $info = image_info($oldname);
$datestring = $info->{DateTimeOriginal};
if ($datestring =~ /^\d\d(\d\d):(\d\d):(\d\d)/) {
$datestring = substr($datestring,0,10);
if ($datestring ne $olddatestring) {
$olddatestring = $datestring;
$i = $number;
} else {
$i++;
}
$newname = sprintf("%02d%02d%02d%02d.jpg", $1,$2,$3,$i);
}
if ($opt_p) {
print "$oldname -> $newname\n";
} else {
rename ($oldname, $newname) or print "Couldn't change $oldname to $newname\n";
}
}
The program uses the Image::Info module from CPAN to extract the date and time of the photo from the file. (Although we call our photo files “JPEGs,” JPEG is actually a compression method, not a file format. Digital cameras save their images in EXIF files which use JPEG compression for the image data and also holds a bunch of other info, like the aperture setting, shutter speed, focal length. And date and time.)
As I’m trying to do in all my utility programs, canonize has a usage string near the top that I can print as a help message from the command line and which I see immediately upon opening the file for editing or study.
The -s option lets you start your photo numbering at something other
than 01. This may seem weird, but I thought it might be needed in case I
downloaded part of a day’s photos and renamed them before downloading
the rest. So far, I haven’t used that option. I used the -p option
(which prints out the old and new file names, but doesn’t actually
change the name) a lot during debugging and decided to leave it in the
final code (is any program really final?). It turns out I have used it a
few times to make sure things were going to go the way I thought they
should.
The program doesn’t actually sort the files in date order. The intention
is to invoke the program as canonize *.JPG, so it receives the file
names in alphabetical order from the shell. Because of the way the
camera names the files, alphabetical order is also chronological order.
This is potential flaw, and I suppose I should suck in all the file
names and sort them by date before assigning new names to them. But it
works with my personal camera (the Canon) and with the cameras I use a
work (three different models of Nikon), so I’m not inclined to dig in
and change it.
You’ll notice a date of 1989:03:25 embedded in the code. The logic of the program needed a date that was always going to be earlier than the earliest photo being renamed. Any date before I bought the camera would have been fine; March 25, 1989 is my daughter’s birth date.




