3 #=======================================================================
5 # File ID: 18245170-f924-11dd-93fc-0001805bf4b1
6 # Extract EXIF data from pictures for use with COPY in Postgres
9 # ©opyleft 2008– Øyvind A. Holm <sunny@sunbase.org>
10 # License: GNU General Public License version 2 or later, see end of
11 # file for legal stuff.
12 #=======================================================================
22 push(@INC, "$ENV{'HOME'}/bin/src/gpstools");
35 'output-format' => 'pgtab',
45 'output-format' => $Std{'output-format'},
46 'strip-whitespace' => 0,
47 'timezone' => $Std{'timezone'},
54 $progname =~ s/^.*\/(.*?)$/$1/;
57 my $id_date = $rcs_id;
58 $id_date =~ s/^.*?\d+ (\d\d\d\d-.*?\d\d:\d\d:\d\d\S+).*/$1/;
60 push(@main::version_array
, $rcs_id);
62 Getopt
::Long
::Configure
("bundling");
65 "author|a=s" => \
$Opt{'author'},
66 "debug" => \
$Opt{'debug'},
67 "description|d=s" => \
$Opt{'description'},
68 "help|h" => \
$Opt{'help'},
69 "output-format|o=s" => \
$Opt{'output-format'},
70 "strip-whitespace|w" => \
$Opt{'strip-whitespace'},
71 "timezone|T=s" => \
$Opt{'timezone'},
72 "verbose|v+" => \
$Opt{'verbose'},
73 "version" => \
$Opt{'version'},
75 ) || die("$progname: Option error. Use -h for help.\n");
77 $Opt{'debug'} && ($Debug = 1);
78 $Opt{'help'} && usage
(0);
79 if ($Opt{'version'}) {
84 $GPST::Spc
= $Opt{'strip-whitespace'} ?
"" : " ";
85 my $Spc = $GPST::Spc
; # FIXME
87 if (length($Opt{'timezone'})) {
88 if ($Opt{'timezone'} =~ /^[\+\-][0-2][0-9]{3}$/) {
89 $tz_str = $Opt{'timezone'};
90 } elsif ($Opt{'timezone'} =~ /^z$/i) {
91 $tz_str = $Opt{'timezone'};
92 } elsif ($Opt{'timezone'} =~ /^[a-z]+$/i) {
93 $tz_str = " $Opt{'timezone'}";
95 die("$progname: $Opt{'timezone'}: Invalid time zone\n");
97 $tz_str = uc($tz_str);
100 if ($Opt{'output-format'} eq "xml") {
101 print("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<gpstpic>\n");
110 for my $fname (@ARGV) {
115 if ($Opt{'output-format'} eq "xml") {
116 print("</gpstpic>\n");
121 my $filename = shift;
127 D
("filename = '$filename'");
128 if (open(PicFP
, "exifprobe -L \"$filename\" |")) { # FIXME: Quick & Dirty™
133 $date =~ s/^(\d\d\d\d)(.)(\d\d)(.)(\d\d)(.)(\d\d:\d\d:\d\d)(.*)/$1-$3-${5}T$7$8/;
139 @Dates = reverse sort @Dates;
141 defined($date) || ($date = '');
142 D
("final date = '$date'");
143 if ($date =~ /^\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d$/) {
144 $filename =~ s/^.*\/(.*?)$/$1/;
146 if ($Opt{'output-format'} eq "xml") {
147 if (length("$filename$date")) {
151 ?
sprintf("$Spc$Spc$Spc$Spc<filename>%s</filename>\n",
152 txt_to_xml
($filename))
155 ?
sprintf("$Spc$Spc$Spc$Spc<date>%s</date>\n",
161 } elsif ($Opt{'output-format'} eq "pgtab") {
162 # Version information {{{
163 # Without version field (same as version 1):
165 # "(lat,lon)"-coordinates \t
172 # "(lat,lon)"-coordinates \t
177 $Output = pgtab_entry
(
186 die("$progname: $Opt{'output-format'}: Unknown output format\n");
189 $Opt{'verbose'} && print(STDERR
$Output);
192 warn("$filename: $date: Invalid date format");
197 warn("$filename: Cannot open exifprobe(1) pipe: $!");
206 my ($Version, $Date, $Coor, $Descr, $Filename, $Author) = @_;
207 defined($Date) || ($Date = $NA);
208 defined($Coor) || ($Coor = $NA);
209 defined($Descr) || ($Descr = $NA);
210 defined($Filename) || ($Filename = $NA);
211 defined($Author) || ($Author = $NA);
216 postgresql_copy_safe
($Date) . $tz_str,
218 ? postgresql_copy_safe
($Coor)
220 length($Opt{'description'})
221 ? postgresql_copy_safe
($Opt{'description'})
224 ? postgresql_copy_safe
($Filename)
226 length($Opt{'author'})
227 ? postgresql_copy_safe
($Opt{'author'})
236 # Print program version {{{
237 for (@main::version_array
) {
244 # Send the help message to stdout {{{
247 if ($Opt{'verbose'}) {
253 Usage: $progname [options] [file [files [...]]]
255 Extract EXIF info from pictures for use with PostgreSQL's COPY command.
256 If no filenames are specified on the command line, file names are read
262 Specify author of picture.
264 Specify description for picture.
268 Increase level of verbosity. Can be repeated.
269 -o x, --output-format x
270 Create output of type x:
273 Default: "$Std{'output-format'}".
275 Prepend X as timezone to the date. Valid formats:
277 A '+' or '-' followed by a four-digit number (HHMM) which
278 indicates the offset relative to UTC. Examples:
282 Time zone abbreviation. Examples:
286 -w, --strip-whitespace
287 Strip all unnecessary whitespace.
289 Print version information.
291 Print debugging messages.
299 # Print a status message to stderr based on verbosity level {{{
300 my ($verbose_level, $Txt) = @_;
302 if ($Opt{'verbose'} >= $verbose_level) {
303 print(STDERR
"$progname: $Txt\n");
309 # Print a debugging message {{{
311 my @call_info = caller;
312 chomp(my $Txt = shift);
313 my $File = $call_info[1];
315 $File =~ s
#^.*/(.*?)$#$1#;
316 print(STDERR
"$File:$call_info[2] $$ $Txt\n");
323 # Plain Old Documentation (POD) {{{
337 [options] [file [files [...]]]
347 =item B<-h>, B<--help>
349 Print a brief help summary.
351 =item B<-v>, B<--verbose>
353 Increase level of verbosity. Can be repeated.
357 Print version information.
361 Print debugging messages.
371 Made by Øyvind A. Holm S<E<lt>sunny@sunbase.orgE<gt>>.
375 Copyleft © Øyvind A. Holm E<lt>sunny@sunbase.orgE<gt>
376 This is free software; see the file F<COPYING> for legalese stuff.
380 This program is free software; you can redistribute it and/or modify it
381 under the terms of the GNU General Public License as published by the
382 Free Software Foundation; either version 2 of the License, or (at your
383 option) any later version.
385 This program is distributed in the hope that it will be useful, but
386 WITHOUT ANY WARRANTY; without even the implied warranty of
387 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
388 See the GNU General Public License for more details.
390 You should have received a copy of the GNU General Public License along
391 with this program; if not, write to the Free Software Foundation, Inc.,
392 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
400 # vim: set fenc=UTF-8 ft=perl fdm=marker ts=4 sw=4 sts=4 et fo+=w :