Tue, 03 Oct 2006

Uploading Photos

I still use Gallery to display my photos and have recently upgraded to version 2. The upgrade was generally smooth and I'm fairly happy with Gallery2. But for a while I've been unhappy with the software I use to take the photos from my camera and organise them prior to uploading them to gallery.

My requirements are fairly simple. I want to be able to take a bunch of photographs from somewhere, organise them into directories named after the date on which they were taken, and the photographs themselves to be named after the date and time they were taken. I also want the photographs to be automatically rotated as required, losslessly. Finally, I don't want any duplicates. In this form, I can easily upload the directories to gallery.

I was sure I would be able to find something to do that, but I couldn't. So I finally got fed up and wrote something myself. It's only a hundred lines or so, so I probably should have done it myself a long time ago.

Anyway, here it is. I'll use it for a while, iron out the kinks, and then, if it seems worthwhile, I'll package it up somehow.

Note that the error checking is minimal, so don't delete your originals until you are happy with the results. Oh, and you'll need certain programs to be installed. So it will probably only work on *nix. I have somewhat unimaginatively named the program autorotate.


use strict;
use warnings;

my $Rotated = <~/g/pics/sorted>;

mkdir $Rotated or die "Can't create $Rotated: $!"
    unless -d $Rotated;

my %Rot =
    2 => "-flip horizontal",
    3 => "-rotate 180",
    4 => "-flip vertical",
    5 => "-transpose",
    6 => "-rotate 90",
    7 => "-transverse",
    8 => "-rotate 270",

sub date_name
    my ($year, $month, $day, $hour, $min, $sec) = @_;
    my $datef = "%04d-%02d-%02d";
    my $namef = "%s %02d:%02d:%02d.jpg";

    my $date = sprintf $datef, $year, $month, $day;
    my $name = sprintf $namef, $date, $hour, $min, $sec;

    ($date, $name)

for my $pic (@ARGV)
    unless ($pic =~ /\.jpe?g$/i)
        print "ignoring $pic\n";

    my $exif = `exiftags -a '$pic'`;
    my ($date, $name, $tmp);

    for my $type (qw( Created Generated Digitized mtime ))
        next if $date;
        if ($type eq "mtime")
            my $mtime = (stat $pic)[9];
            my ($sec, $min, $hour, $day, $month, $year) = localtime $mtime;
            ($date, $name) =
                date_name $year + 1900, $month +1, $day, $hour, $min, $sec;
            next unless
             $exif =~ /Image $type: (\d{4}):(\d\d):(\d\d) (\d\d):(\d\d):(\d\d)/;
            ($date, $name) = date_name $1, $2, $3, $4, $5, $6;
        $date = "" if $name eq "2005-01-01 00:00:00.jpg" ||
                      $name eq "0000-00-00 00:00:00.jpg";

    my $newdir = "$Rotated/$date";
    mkdir $newdir or die "Can't create $newdir: $!"
        unless -d $newdir;

    my $rot = `jpegexiforient -n '$pic'`;
    my $trans = $Rot{$rot} || "";
    print(($trans ? "rotating" : " copying"), " $pic to $name",
          ($trans ? " [$trans]" : ""), " ");

    $tmp  = "$newdir/tmp_$name";
    $name = "$newdir/$name";

    if ($trans)
        my $command = "jpegtran -copy all $trans '$pic' > '$tmp'";
        system $command and die "Can't run: $command: $?";
        $command = "jpegexiforient -1 '$tmp' > /dev/null";
        system $command and die "Can't run: $command: $?";
        my $command = "cp -a '$pic' '$tmp'";
        system $command and die "Can't run: $command: $?";

    while (-e $name)
        system "cmp -s '$tmp' '$name'";
        if (!$?)
            print "- exists!\n";
            unlink $tmp;
            next FILE;
        no warnings "uninitialized";
        $name =~ s/(-\d+)?\.jpg$/$1 - 1 . ".jpg"/e;
        print "- trying version ", -($1 -1), " ";

    # print "- renaming => $name" if $name =~ /-\d+\.jpg$/;
    print "\n";
    rename $tmp => $name or die "Can't rename $tmp => $name: $!";
    chmod 0644, $name;

[/software/gallery] permanent link

November 2022
Sun Mon Tue Wed Thu Fri Sat