3 #=======================================================================
5 # Extract EXIF data from pictures for use with COPY in Postgres
8 # ©opyleft 2008– Øyvind A. Holm <sunny@sunbase.org>
9 # License: GNU General Public License version 2 or later, see end of
10 # file for legal stuff.
11 #=======================================================================
21 push(@INC, "$ENV{'HOME'}/bin/src/gpstools");
34 'output-format' => 'pgtab',
44 'output-format' => $Std{'output-format'},
45 'strip-whitespace' => 0,
46 'timezone' => $Std{'timezone'},
53 $progname =~ s/^.*\/(.*?)$/$1/;
56 my $id_date = $rcs_id;
57 $id_date =~ s/^.*?\d+ (\d\d\d\d-.*?\d\d:\d\d:\d\d\S+).*/$1/;
59 push(@main::version_array
, $rcs_id);
61 Getopt
::Long
::Configure
("bundling");
64 "author|a=s" => \
$Opt{'author'},
65 "debug" => \
$Opt{'debug'},
66 "description|d=s" => \
$Opt{'description'},
67 "help|h" => \
$Opt{'help'},
68 "output-format|o=s" => \
$Opt{'output-format'},
69 "strip-whitespace|w" => \
$Opt{'strip-whitespace'},
70 "timezone|T=s" => \
$Opt{'timezone'},
71 "verbose|v+" => \
$Opt{'verbose'},
72 "version" => \
$Opt{'version'},
74 ) || die("$progname: Option error. Use -h for help.\n");
76 $Opt{'debug'} && ($Debug = 1);
77 $Opt{'help'} && usage
(0);
78 if ($Opt{'version'}) {
83 $GPST::Spc
= $Opt{'strip-whitespace'} ?
"" : " ";
84 my $Spc = $GPST::Spc
; # FIXME
86 if (length($Opt{'timezone'})) {
87 if ($Opt{'timezone'} =~ /^[\+\-][0-2][0-9]{3}$/) {
88 $tz_str = $Opt{'timezone'};
89 } elsif ($Opt{'timezone'} =~ /^z$/i) {
90 $tz_str = $Opt{'timezone'};
91 } elsif ($Opt{'timezone'} =~ /^[a-z]+$/i) {
92 $tz_str = " $Opt{'timezone'}";
94 die("$progname: $Opt{'timezone'}: Invalid time zone\n");
98 if ($Opt{'output-format'} eq "xml") {
99 print("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<gpstpic>\n");
108 for my $fname (@ARGV) {
113 if ($Opt{'output-format'} eq "xml") {
114 print("</gpstpic>\n");
119 my $filename = shift;
125 D
("filename = '$filename'");
126 if (open(PicFP
, "exifprobe -L \"$filename\" |")) { # FIXME: Quick & Dirty™
131 $date =~ s/^(\d\d\d\d)(.)(\d\d)(.)(\d\d)(.)(\d\d:\d\d:\d\d)(.*)/$1-$3-${5}T$7$8/;
137 @Dates = reverse sort @Dates;
139 defined($date) || ($date = '');
140 D
("final date = '$date'");
141 if ($date =~ /^\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d$/) {
142 $filename =~ s/^.*\/(.*?)$/$1/;
144 if ($Opt{'output-format'} eq "xml") {
145 if (length("$filename$date")) {
149 ?
sprintf("$Spc$Spc$Spc$Spc<filename>%s</filename>\n",
150 txt_to_xml
($filename))
153 ?
sprintf("$Spc$Spc$Spc$Spc<date>%s</date>\n",
159 } elsif ($Opt{'output-format'} eq "pgtab") {
160 # Version information {{{
161 # Without version field (same as version 1):
163 # "(lat,lon)"-coordinates \t
170 # "(lat,lon)"-coordinates \t
175 $Output = pgtab_entry
(
184 die("$progname: $Opt{'output-format'}: Unknown output format\n");
187 $Opt{'verbose'} && print(STDERR
$Output);
190 warn("$filename: $date: Invalid date format");
195 warn("$filename: Cannot open exifprobe(1) pipe: $!");
204 my ($Version, $Date, $Coor, $Descr, $Filename, $Author) = @_;
205 defined($Date) || ($Date = $NA);
206 defined($Coor) || ($Coor = $NA);
207 defined($Descr) || ($Descr = $NA);
208 defined($Filename) || ($Filename = $NA);
209 defined($Author) || ($Author = $NA);
214 postgresql_copy_safe
($Date) . $tz_str,
216 ? postgresql_copy_safe
($Coor)
218 length($Opt{'description'})
219 ? postgresql_copy_safe
($Opt{'description'})
222 ? postgresql_copy_safe
($Filename)
224 length($Opt{'author'})
225 ? postgresql_copy_safe
($Opt{'author'})
234 # Print program version {{{
235 for (@main::version_array
) {
242 # Send the help message to stdout {{{
245 if ($Opt{'verbose'}) {
251 Usage: $progname [options] [file [files [...]]]
253 Extract EXIF info from pictures for use with PostgreSQL's COPY command.
254 If no filenames are specified on the command line, file names are read
260 Specify author of picture.
262 Specify description for picture.
266 Increase level of verbosity. Can be repeated.
267 -o x, --output-format x
268 Create output of type x:
271 Default: "$Std{'output-format'}".
273 Prepend X as timezone to the date. Valid formats:
275 A '+' or '-' followed by a four-digit number (HHMM) which
276 indicates the offset relative to UTC. Examples:
280 Time zone abbreviation. Examples:
284 -w, --strip-whitespace
285 Strip all unnecessary whitespace.
287 Print version information.
289 Print debugging messages.
297 # Print a status message to stderr based on verbosity level {{{
298 my ($verbose_level, $Txt) = @_;
300 if ($Opt{'verbose'} >= $verbose_level) {
301 print(STDERR
"$progname: $Txt\n");
307 # Print a debugging message {{{
309 my @call_info = caller;
310 chomp(my $Txt = shift);
311 my $File = $call_info[1];
313 $File =~ s
#^.*/(.*?)$#$1#;
314 print(STDERR
"$File:$call_info[2] $$ $Txt\n");
321 # Plain Old Documentation (POD) {{{
335 [options] [file [files [...]]]
345 =item B<-h>, B<--help>
347 Print a brief help summary.
349 =item B<-v>, B<--verbose>
351 Increase level of verbosity. Can be repeated.
355 Print version information.
359 Print debugging messages.
369 Made by Øyvind A. Holm S<E<lt>sunny@sunbase.orgE<gt>>.
373 Copyleft © Øyvind A. Holm E<lt>sunny@sunbase.orgE<gt>
374 This is free software; see the file F<COPYING> for legalese stuff.
378 This program is free software; you can redistribute it and/or modify it
379 under the terms of the GNU General Public License as published by the
380 Free Software Foundation; either version 2 of the License, or (at your
381 option) any later version.
383 This program is distributed in the hope that it will be useful, but
384 WITHOUT ANY WARRANTY; without even the implied warranty of
385 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
386 See the GNU General Public License for more details.
388 You should have received a copy of the GNU General Public License along
389 with this program; if not, write to the Free Software Foundation, Inc.,
390 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
398 # vim: set fenc=UTF-8 ft=perl fdm=marker ts=4 sw=4 sts=4 et fo+=w :