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");
99 if ($Opt{'output-format'} eq "xml") {
100 print("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<gpstpic>\n");
109 for my $fname (@ARGV) {
114 if ($Opt{'output-format'} eq "xml") {
115 print("</gpstpic>\n");
120 my $filename = shift;
126 D
("filename = '$filename'");
127 if (open(PicFP
, "exifprobe -L \"$filename\" |")) { # FIXME: Quick & Dirty™
132 $date =~ s/^(\d\d\d\d)(.)(\d\d)(.)(\d\d)(.)(\d\d:\d\d:\d\d)(.*)/$1-$3-${5}T$7$8/;
138 @Dates = reverse sort @Dates;
140 defined($date) || ($date = '');
141 D
("final date = '$date'");
142 if ($date =~ /^\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d$/) {
143 $filename =~ s/^.*\/(.*?)$/$1/;
145 if ($Opt{'output-format'} eq "xml") {
146 if (length("$filename$date")) {
150 ?
sprintf("$Spc$Spc$Spc$Spc<filename>%s</filename>\n",
151 txt_to_xml
($filename))
154 ?
sprintf("$Spc$Spc$Spc$Spc<date>%s</date>\n",
160 } elsif ($Opt{'output-format'} eq "pgtab") {
161 # Version information {{{
162 # Without version field (same as version 1):
164 # "(lat,lon)"-coordinates \t
171 # "(lat,lon)"-coordinates \t
176 $Output = pgtab_entry
(
185 die("$progname: $Opt{'output-format'}: Unknown output format\n");
188 $Opt{'verbose'} && print(STDERR
$Output);
191 warn("$filename: $date: Invalid date format");
196 warn("$filename: Cannot open exifprobe(1) pipe: $!");
205 my ($Version, $Date, $Coor, $Descr, $Filename, $Author) = @_;
206 defined($Date) || ($Date = $NA);
207 defined($Coor) || ($Coor = $NA);
208 defined($Descr) || ($Descr = $NA);
209 defined($Filename) || ($Filename = $NA);
210 defined($Author) || ($Author = $NA);
215 postgresql_copy_safe
($Date) . $tz_str,
217 ? postgresql_copy_safe
($Coor)
219 length($Opt{'description'})
220 ? postgresql_copy_safe
($Opt{'description'})
223 ? postgresql_copy_safe
($Filename)
225 length($Opt{'author'})
226 ? postgresql_copy_safe
($Opt{'author'})
235 # Print program version {{{
236 for (@main::version_array
) {
243 # Send the help message to stdout {{{
246 if ($Opt{'verbose'}) {
252 Usage: $progname [options] [file [files [...]]]
254 Extract EXIF info from pictures for use with PostgreSQL's COPY command.
255 If no filenames are specified on the command line, file names are read
261 Specify author of picture.
263 Specify description for picture.
267 Increase level of verbosity. Can be repeated.
268 -o x, --output-format x
269 Create output of type x:
272 Default: "$Std{'output-format'}".
274 Prepend X as timezone to the date. Valid formats:
276 A '+' or '-' followed by a four-digit number (HHMM) which
277 indicates the offset relative to UTC. Examples:
281 Time zone abbreviation. Examples:
285 -w, --strip-whitespace
286 Strip all unnecessary whitespace.
288 Print version information.
290 Print debugging messages.
298 # Print a status message to stderr based on verbosity level {{{
299 my ($verbose_level, $Txt) = @_;
301 if ($Opt{'verbose'} >= $verbose_level) {
302 print(STDERR
"$progname: $Txt\n");
308 # Print a debugging message {{{
310 my @call_info = caller;
311 chomp(my $Txt = shift);
312 my $File = $call_info[1];
314 $File =~ s
#^.*/(.*?)$#$1#;
315 print(STDERR
"$File:$call_info[2] $$ $Txt\n");
322 # Plain Old Documentation (POD) {{{
336 [options] [file [files [...]]]
346 =item B<-h>, B<--help>
348 Print a brief help summary.
350 =item B<-v>, B<--verbose>
352 Increase level of verbosity. Can be repeated.
356 Print version information.
360 Print debugging messages.
370 Made by Øyvind A. Holm S<E<lt>sunny@sunbase.orgE<gt>>.
374 Copyleft © Øyvind A. Holm E<lt>sunny@sunbase.orgE<gt>
375 This is free software; see the file F<COPYING> for legalese stuff.
379 This program is free software; you can redistribute it and/or modify it
380 under the terms of the GNU General Public License as published by the
381 Free Software Foundation; either version 2 of the License, or (at your
382 option) any later version.
384 This program is distributed in the hope that it will be useful, but
385 WITHOUT ANY WARRANTY; without even the implied warranty of
386 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
387 See the GNU General Public License for more details.
389 You should have received a copy of the GNU General Public License along
390 with this program; if not, write to the Free Software Foundation, Inc.,
391 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
399 # vim: set fenc=UTF-8 ft=perl fdm=marker ts=4 sw=4 sts=4 et fo+=w :