Perl programmer for hire: download my resume (PDF).
John Bokma MexIT
freelance Perl programmer

Getting the date and time of digital photos

Monday, July 10, 2006 | 4 comments

Since the number of photos I made with the Sony Cyber-Shot DSC-S600 I own is growing and growing I am looking for a way to organize it a bit better. I started with downloading pictures to a folder named after the year, month and day (i.e. yyyymmdd format). But when I ended up with several of such folders I had no idea which pictures were contained in which folder. So I decided to add a short description after the folder name, for example:

20060507-el-limon-totalco

Another problem was that I sometimes take just a handfull of digital photos over 3 days or so. When I download those photos from the camera, I just give the folder the date of the latest picture(s) taken. The last problem: a series can start at the end of a day, and end in the beginning of the next day. In the near future I want to automatically move photos to the right folder and I want to let, for example, a day start at 6 AM and end at 5:59 AM.

TextPad in hex mode with a Sony Cyber-shot photo file opened.
TextPad in hex mode with a Sony Cyber-shot photo file opened.

And when I say automatically I mean using a Perl program. I had already searched at CPAN for a module that can handle EXIF. But today I decided to have a peek at a photo using the TextPad editor in "hex" mode. And I noticed that the date and time are readable encoded as a string starting at offset 0xde (222 decimal) with a length of 19 bytes. This probably is only valid for this type of camera, the Sony Cyber-Shot DSC-S600, though. Anyway, the Perl function I wrote for extracting the date and time is given below:

sub get_date_time {

    my $filename = shift;

    open my $fh, $filename   or die "Can't open '$filename' for reading: $!";
    binmode $fh              or die "Can't set '$filename' to binary mode: $!";
    seek $fh, 0xde, 0        or die "Can't seek to position in '$filename': $!";
    my $date_time;
    read $fh, $date_time, 19 or die "Can't read date from '$filename': $!";
    close $fh                or die "Can't close '$filename' after reading: $!";

    return $date_time;
}

The above function opens the filename given as the first and only parameter and switches to binary mode. Next it moves to position 0xde and reads 19 bytes in the scalar $date_time. After reading the date and time the file is closed and the value read is returned. An example of a return value is:

2006:05:04 15:37:10

Notice that the date parts are also separated using a colon instead of a minus sign or slash character.

If you need a good example of how to open a file in binary mode in Perl, the above function is a very good start. Note how each call is followed by or die to handle errors, in this example by just reporting what went wrong using die. Also note that the actual error message stored in $! is included in the message. A common mistake is to not report the value of $!.

Again, this is a quick and dirty solution and has only been tested with digital photos downloaded from a Sony Cyber-Shot DSC-S600.

Please post a comment | read 4 comments, latest by John Bokma | RSS feed
Best site in bleep! >
< Cyclosternum fasciatum burrow