2 # UCW Gallery: Generate published photos
3 # (c) 2004--2015 Martin Mares <mj@ucw.cz>
17 my $gal = UCW::Gallery->load_config;
19 my $orig_list = $gal->read_list('gallery.list') or die "Cannot read gallery.list: $!\n";
21 my $photo_dir = $gal->get('PhotoDir');
23 print "Using existing output directory: $photo_dir\n";
25 print "Creating output directory: $photo_dir\n";
26 File::Path::mkpath($photo_dir) or die "Unable to create $photo_dir: $!\n";
29 my $photo_meta = $gal->photo_meta_name;
32 print "Reading old meta-data\n";
33 $old_meta = $gal->read_meta($photo_meta);
34 # use Data::Dumper; print "Read old meta: ", Dumper($old_meta), "\n";
36 my $meta = { 'photo' => {} };
38 sub get_meta_basic($$$) {
40 my $rotate = $f->{orientation};
42 my ($orig_w, $orig_h, $orig_size, $orig_format) = $p->PingImage($f->{orig}) or die "Error reading " . $f->{orig} . "\n";
43 print "${orig_w}x${orig_h} ";
45 my ($w0, $h0) = ($rotate eq "l" || $rotate eq "r") ? ($orig_h, $orig_w) : ($orig_w, $orig_h);
46 my ($w, $h) = ($w0, $h0);
47 if ($w > $gal->get('PhotoMaxWidth')) {
48 my $s = $gal->get('PhotoMaxWidth') / $w;
52 if ($h > $gal->get('PhotoMaxHeight')) {
53 my $s = $gal->get('PhotoMaxHeight') / $h;
61 for my $k (keys %UCW::Gallery::list_attrs) {
62 next if $UCW::Gallery::list_attrs{$k} < 2;
63 $m->{$k} = $f->{$k} if defined $f->{$k};
74 if ($g =~ m{^([NEWS]) (\d+)\xb0 ([0-9.]+)'$}) {
76 $g = -$g if $1 eq 'W' || $1 eq 'S';
77 } elsif ($g =~ m{^([NEWS]) (\d+)\xb0 (\d+)' ([0-9.]+)$}) {
78 $g = $2 + $3/60 + $4/3600;
79 $g = -$g if $1 eq 'W' || $1 eq 'S';
81 print "[EXIF: unable to parse coordinate $g] ";
84 return sprintf "%.6f", $g;
87 sub get_meta_exif($$) {
89 $gal->get('CacheExif') or return;
91 my $e = new Image::EXIF($f->{orig});
92 my $i = $e->get_all_info();
94 print "[EXIF error: ", $e->error, "] ";
97 # use Data::Dumper; print Dumper($i);
99 my $lat = parse_geo($i->{image}->{'Latitude'});
100 my $lon = parse_geo($i->{image}->{'Longitude'});
102 my $alt = $i->{image}->{'Altitude'};
104 if ($alt =~ m{^([0-9.]+) m$}) {
107 print "[EXIF: unable to parse altitude $alt] ";
112 # printf "[GEO: lat=%s lon=%s alt=%s] ", $lat // '?', $lon // '?', $alt // '?';
117 $m->{alt} //= $alt if $alt;
119 my $time = $i->{image}->{'Image Created'};
121 if ($time =~ m{^(\d{4}):(\d{2}):(\d{2}) (\d{2}:\d{2}:\d{2})$}) {
122 $m->{t} //= "$1-$2-$3 $4";
123 # print "[TIME: ", $m->{t}, "] ";
125 print "[EXIF: unable to parse time $time] ";
130 sub generate_photo($$$) {
131 my ($f, $m, $p) = @_;
134 $e = $p->Read($f->{orig}) and die "Error reading " . $f->{orig} . ": $e";
136 $p->SetAttribute(quality=>90);
144 print "-> equalize ";
148 print "-> normalize ";
152 my $rotate = $m->{o};
154 if ($rotate eq "l") { $rot = 270; }
155 elsif ($rotate eq "r") { $rot = 90; }
156 elsif ($rotate eq "u") { $rot = 180; }
158 print "-> rotate $rot ";
159 $p->Rotate(degrees=>$rot);
162 my ($w, $h) = ($m->{w}, $m->{h});
163 if ($w != $m->{w0} || $h != $m->{h0}) {
164 print "-> ${w}x${h} ";
165 $p->Resize(width=>$w, height=>$h);
168 my $photo = $gal->photo_name($m, $f->{id});
169 my $tmp = "$photo.new";
170 $e = $p->Write($tmp) and die "Unable to write $tmp: $e";
171 rename $tmp, $photo or die "Cannot rename $tmp to $photo: $!\n";
174 for my $f (@$orig_list) {
179 $meta->{photo}->{$id} = $m;
180 $f->{orig} = File::Spec->rel2abs($f->{file}, $gal->get('OrigDir'));
182 my $p = new Image::Magick;
183 get_meta_basic($f, $m, $p);
184 get_meta_exif($f, $m);
186 my $om = $old_meta->{photo}->{$id};
188 $om->{o} eq $m->{o} &&
189 $om->{xf} eq $m->{xf} &&
190 $om->{w} eq $m->{w} &&
191 $om->{h} eq $m->{h}) {
192 print "... uptodate\n";
196 generate_photo($f, $m, $p);
200 print "Cleaning up stale files\n";
201 for my $f (<$photo_dir/*.jpg>) {
202 my ($vv, $dd, $id) = File::Spec->splitpath($f);
204 unless (defined $meta->{photo}->{$id}) {
205 print "$id: removing\n";
210 print "Writing meta-data\n";
211 $gal->write_meta($photo_meta, $meta);