#!/usr/bin/perl # UCW Gallery: Scan images and generate image list # (c) 2004--2015 Martin Mares use common::sense; use UCW::Gallery; use UCW::Gallery::Hashes; use Encode; use File::Spec; use Image::EXIF; use Getopt::Long; if (@ARGV && $ARGV[0] eq '--help') { die < or: gal scan or: gal scan --update Options: --add Keep existing images and add new ones AMEN } my $add; my $update; GetOptions( 'add!' => \$add, 'update!' => \$update, ) or die "Try gal scan --help\n"; STDOUT->autoflush(1); my $gal = UCW::Gallery->load_config; my $orig_prefix = $gal->get('OrigDir'); $orig_prefix =~ m{/$} or $orig_prefix .= '/'; my @source = (); if ($update) { print "Loading previous gallery.list\n"; my $pg = $gal->read_list('gallery.list') or die "Unable to load gallery.list\n"; @source = @{$pg}; } elsif (@ARGV) { for my $in (@ARGV) { if (-f $in) { push @source, { file => $in }; } elsif (-d $in) { opendir D, $in or die "Cannot scan directory $in: $!\n"; my @p = (); while (my $e = readdir D) { $e = Encode::decode('utf-8', $e); my $f = File::Spec->canonpath(File::Spec->catfile($in, $e)); if ($f =~ m{\.(jpe?g|png)$}i) { push @p, $f; } } closedir D; push @source, map { { file => $_ } } sort @p; } else { die "$in is neither file nor directory\n"; } } } else { binmode STDIN, ':utf8'; @source = @{$gal->read_list_fh(\*STDIN)}; } my $hashes = UCW::Gallery::Hashes->new($gal); print "Scanning photos\n"; my @images = (); foreach my $src (@source) { my $name = $src->{file}; if ($name =~ m{^/}) { # Try to relativize to OrigDir if (substr($name, 0, length $orig_prefix) eq $orig_prefix) { $src->{file} = $name = substr($name, length $orig_prefix); } } print "\t$name:"; my $path = File::Spec->rel2abs($name, $gal->get('OrigDir')); -f $path or die "Cannot find $path\n"; $src->{id} = $hashes->hash_image($path); print " id=", $src->{id}; if (!defined $src->{orientation} || $src->{orientation} eq '-') { my $e = new Image::EXIF($path); my $i = $e->get_all_info(); if ($e->error) { print "EXIF error: ", $e->error, "\n"; $src->{orientation} = '.'; } else { # print STDERR Dumper($i), "\n"; my $o = $i->{'image'}->{'Image Orientation'} || "Top, Left-Hand"; if ($o eq "Top, Left-Hand") { $o = "."; } elsif ($o eq "Right-Hand, Top") { $o = "r"; } elsif ($o eq "Left-Hand, Bottom") { $o = "l"; } elsif ($o eq "Bottom, Right-Hand") { $o = "u"; } else { print "Unrecognized orientation: $o\n"; $o = "."; } $src->{orientation} = $o; } } print " ori=", $src->{orientation}; if (!defined $src->{xf} || $src->{xf} eq '-') { $src->{xf} = $gal->get('ScanDefaultTransform'); } print " xfrm=", $src->{xf}; $src->{title} //= ''; push @images, $src; print "\n"; } if (!$update) { my $old = $gal->read_list('gallery.list'); if ($old) { print "Updating gallery.list\n"; my %new_by_id = map { $_->{id} => $_ } @images; my @result = (); for my $o (@$old) { my $id = $o->{id}; my $i = $new_by_id{$id}; if (!$i) { if ($add) { print "\t$id: kept\n"; push @result, $o; } else { print "\t$id: removed\n"; } } else { print "\t$id: kept\n"; push @result, $o; delete $new_by_id{$id}; } } for my $i (@images) { my $id = $i->{id}; $new_by_id{$id} or next; print "\t$id: new\n"; push @result, $i; } @images = @result; } } $gal->write_list('gallery.list', \@images); print "Written gallery.list (", (scalar @images), " items)\n"; $hashes->write;