]> mj.ucw.cz Git - gallery.git/blob - gal-scan
bb74c06c5c5f77f5a3ac6f6e6f2deb34b7383ce5
[gallery.git] / gal-scan
1 #!/usr/bin/perl
2 # UCW Gallery: Scan images and generate image list
3 # (c) 2004--2015 Martin Mares <mj@ucw.cz>
4
5 use common::sense;
6
7 use UCW::Gallery;
8 use UCW::Gallery::Hashes;
9 use File::Spec;
10 use Image::EXIF;
11 use Getopt::Long;
12
13 if (@ARGV && $ARGV[0] eq '--help') {
14         die <<AMEN ;
15 Usage:  cat list | gal scan <options>
16    or:  gal scan <options> <files and directories>
17    or:  gal scan <options> --update
18
19 Options:
20 --add           Keep existing images and add new ones
21 AMEN
22 }
23
24 my $add;
25 my $update;
26 GetOptions(
27         'add!' => \$add,
28         'update!' => \$update,
29 ) or die "Try gal scan --help\n";
30
31 STDOUT->autoflush(1);
32 my $gal = UCW::Gallery->load_config;
33 my $orig_prefix = $gal->get('OrigDir');
34 $orig_prefix =~ m{/$} or $orig_prefix .= '/';
35
36 my @source = ();
37 if ($update) {
38         print "Loading previous gallery.list\n";
39         my $pg = $gal->read_list('gallery.list') or die "Unable to load gallery.list\n";
40         @source = @{$pg};
41 } elsif (@ARGV) {
42         for my $in (@ARGV) {
43                 if (-f $in) {
44                         push @source, { file => $in };
45                 } elsif (-d $in) {
46                         opendir D, $in or die "Cannot scan directory $in: $!\n";
47                         my @p = ();
48                         while (my $e = readdir D) {
49                                 my $f = File::Spec->canonpath(File::Spec->catfile($in, $e));
50                                 if ($f =~ m{\.(jpe?g|png)$}i) {
51                                         push @p, $f;
52                                 }
53                         }
54                         closedir D;
55                         push @source, map { { file => $_ } } sort @p;
56                 } else {
57                         die "$in is neither file nor directory\n";
58                 }
59         }
60 } else {
61         binmode STDIN, ':utf8';
62         @source = @{$gal->read_list_fh(\*STDIN)};
63 }
64
65 my $hashes = UCW::Gallery::Hashes->new($gal);
66
67 print "Scanning photos\n";
68 my @images = ();
69 foreach my $src (@source) {
70         my $name = $src->{file};
71         if ($name =~ m{^/}) {
72                 # Try to relativize to OrigDir
73                 if (substr($name, 0, length $orig_prefix) eq $orig_prefix) {
74                         $src->{file} = $name = substr($name, length $orig_prefix);
75                 }
76         }
77         print "\t$name:";
78
79         my $path = File::Spec->rel2abs($name, $gal->get('OrigDir'));
80         -f $path or die "Cannot find $path\n";
81
82         $src->{id} = $hashes->hash_image($path);
83         print " id=", $src->{id};
84
85         if (!defined $src->{orientation} || $src->{orientation} eq '-') {
86                 my $e = new Image::EXIF($path);
87                 my $i = $e->get_all_info();
88                 if ($e->error) {
89                         print "EXIF error: ", $e->error, "\n";
90                         $src->{orientation} = '.';
91                 } else {
92                         # print STDERR Dumper($i), "\n";
93                         my $o = $i->{'image'}->{'Image Orientation'} || "Top, Left-Hand";
94                         if ($o eq "Top, Left-Hand") { $o = "."; }
95                         elsif ($o eq "Right-Hand, Top") { $o = "r"; }
96                         elsif ($o eq "Left-Hand, Bottom") { $o = "l"; }
97                         elsif ($o eq "Bottom, Right-Hand") { $o = "u"; }
98                         else {
99                                 print "Unrecognized orientation: $o\n";
100                                 $o = ".";
101                         }
102                         $src->{orientation} = $o;
103                 }
104         }
105         print " ori=", $src->{orientation};
106
107         defined $src->{xf} or $src->{xf} = $gal->get('ScanDefaultTransform');
108         print " xfrm=", $src->{xf};
109
110         $src->{title} //= '';
111         push @images, $src;
112         print "\n";
113 }
114
115 if (!$update) {
116         my $old = $gal->read_list('gallery.list');
117         if ($old) {
118                 print "Updating gallery.list\n";
119                 my %new_by_id = map { $_->{id} => $_ } @images;
120                 my @result = ();
121                 for my $o (@$old) {
122                         my $id = $o->{id};
123                         my $i = $new_by_id{$id};
124                         if (!$i) {
125                                 if ($add) {
126                                         print "\t$id: kept\n";
127                                         push @result, $o;
128                                 } else {
129                                         print "\t$id: removed\n";
130                                 }
131                         } else {
132                                 print "\t$id: kept\n";
133                                 push @result, $o;
134                                 delete $new_by_id{$id};
135                         }
136                 }
137                 for my $i (@images) {
138                         my $id = $i->{id};
139                         $new_by_id{$id} or next;
140                         print "\t$id: new\n";
141                         push @result, $i;
142                 }
143                 @images = @result;
144         }
145 }
146
147 $gal->write_list('gallery.list', \@images);
148 print "Written gallery.list (", (scalar @images), " items)\n";
149 $hashes->write;