gpst-pic: Tidssona konverteres til upper case.
[gpstools.git] / gpst-pic
blob9fc412ec49ca27b9fbeaa4cb51bf5711c435b453
1 #!/usr/bin/perl -w
3 #=======================================================================
4 # $Id$
5 # File ID: 18245170-f924-11dd-93fc-0001805bf4b1
6 # Extract EXIF data from pictures for use with COPY in Postgres
8 # Character set: UTF-8
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 #=======================================================================
14 BEGIN {
15 our @version_array;
18 use strict;
19 use Getopt::Long;
21 BEGIN {
22 push(@INC, "$ENV{'HOME'}/bin/src/gpstools");
23 our @version_array;
26 use GPST;
27 use GPSTxml;
29 $| = 1;
31 our $Debug = 0;
32 our $NA = '\N';
33 our %Std = (
35 'output-format' => 'pgtab',
36 'timezone' => '',
39 our %Opt = (
41 'author' => '',
42 'debug' => 0,
43 'description' => '',
44 'help' => 0,
45 'output-format' => $Std{'output-format'},
46 'strip-whitespace' => 0,
47 'timezone' => $Std{'timezone'},
48 'verbose' => 0,
49 'version' => 0,
53 our $progname = $0;
54 $progname =~ s/^.*\/(.*?)$/$1/;
56 my $rcs_id = '$Id$';
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");
63 GetOptions(
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'}) {
80 print_version();
81 exit(0);
84 $GPST::Spc = $Opt{'strip-whitespace'} ? "" : " ";
85 my $Spc = $GPST::Spc; # FIXME
86 my $tz_str = "";
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'}";
94 } else {
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");
104 if ($#ARGV < 0) {
105 while (<>) {
106 chomp();
107 print_entry($_);
109 } else {
110 for my $fname (@ARGV) {
111 print_entry($fname);
115 if ($Opt{'output-format'} eq "xml") {
116 print("</gpstpic>\n");
119 sub print_entry {
120 # {{{
121 my $filename = shift;
122 my $Retval = 0;
123 my ($date, $coor) =
124 ( '', '');
125 my @Dates = ();
126 local *PicFP;
127 D("filename = '$filename'");
128 if (open(PicFP, "exifprobe -L \"$filename\" |")) { # FIXME: Quick & Dirty™
129 while (<PicFP>) {
130 if (/DateTime/) {
131 s/^.*'(.*?)'.*$/$1/;
132 chomp($date = $_);
133 $date =~ s/^(\d\d\d\d)(.)(\d\d)(.)(\d\d)(.)(\d\d:\d\d:\d\d)(.*)/$1-$3-${5}T$7$8/;
134 D("date = '$date'");
135 push(@Dates, $date);
138 close(PicFP);
139 @Dates = reverse sort @Dates;
140 $date = $Dates[0];
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/;
145 my $Output = "";
146 if ($Opt{'output-format'} eq "xml") {
147 if (length("$filename$date")) {
148 $Output = join("",
149 "$Spc$Spc<img>\n",
150 length($filename)
151 ? sprintf("$Spc$Spc$Spc$Spc<filename>%s</filename>\n",
152 txt_to_xml($filename))
153 : "",
154 length($date)
155 ? sprintf("$Spc$Spc$Spc$Spc<date>%s</date>\n",
156 txt_to_xml($date))
157 : "",
158 "$Spc$Spc</img>\n",
161 } elsif ($Opt{'output-format'} eq "pgtab") {
162 # Version information {{{
163 # Without version field (same as version 1):
164 # date \t
165 # "(lat,lon)"-coordinates \t
166 # description \t
167 # filename \t
168 # author \t
169 # Version 1:
170 # "1" \t
171 # date \t
172 # "(lat,lon)"-coordinates \t
173 # description \t
174 # filename \t
175 # author \n
176 # }}}
177 $Output = pgtab_entry(
178 1, # Version number
179 $date,
180 $coor,
181 $Opt{'description'},
182 $filename,
183 $Opt{'author'}
185 } else {
186 die("$progname: $Opt{'output-format'}: Unknown output format\n");
188 print($Output);
189 $Opt{'verbose'} && print(STDERR $Output);
190 } else {
191 if (length($date)) {
192 warn("$filename: $date: Invalid date format");
193 $Retval = 2;
196 } else {
197 warn("$filename: Cannot open exifprobe(1) pipe: $!");
198 $Retval = 1;
200 return($Retval);
201 # }}}
202 } # print_entry()
204 sub pgtab_entry {
205 # {{{
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);
212 my $Retval = "";
213 if ($Version == 1) {
214 $Retval = join("\t",
215 1, # Version number
216 postgresql_copy_safe($Date) . $tz_str,
217 length($Coor)
218 ? postgresql_copy_safe($Coor)
219 : $NA,
220 length($Opt{'description'})
221 ? postgresql_copy_safe($Opt{'description'})
222 : $NA,
223 length($Filename)
224 ? postgresql_copy_safe($Filename)
225 : $NA,
226 length($Opt{'author'})
227 ? postgresql_copy_safe($Opt{'author'})
228 : $NA
229 ) . "\n";
231 return($Retval);
232 # }}}
233 } # pgtab_entry()
235 sub print_version {
236 # Print program version {{{
237 for (@main::version_array) {
238 print("$_\n");
240 # }}}
241 } # print_version()
243 sub usage {
244 # Send the help message to stdout {{{
245 my $Retval = shift;
247 if ($Opt{'verbose'}) {
248 print("\n");
249 print_version();
251 print(<<END);
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
257 from stdin.
259 Options:
261 -a, --author x
262 Specify author of picture.
263 -d, --description x
264 Specify description for picture.
265 -h, --help
266 Show this help.
267 -v, --verbose
268 Increase level of verbosity. Can be repeated.
269 -o x, --output-format x
270 Create output of type x:
272 pgtab
273 Default: "$Std{'output-format'}".
274 -T X, --timezone X
275 Prepend X as timezone to the date. Valid formats:
276 UTC offset
277 A '+' or '-' followed by a four-digit number (HHMM) which
278 indicates the offset relative to UTC. Examples:
279 +0000
280 -1600
281 +0630
282 Time zone abbreviation. Examples:
286 -w, --strip-whitespace
287 Strip all unnecessary whitespace.
288 --version
289 Print version information.
290 --debug
291 Print debugging messages.
294 exit($Retval);
295 # }}}
296 } # usage()
298 sub msg {
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");
305 # }}}
306 } # msg()
308 sub D {
309 # Print a debugging message {{{
310 $Debug || return;
311 my @call_info = caller;
312 chomp(my $Txt = shift);
313 my $File = $call_info[1];
314 $File =~ s#\\#/#g;
315 $File =~ s#^.*/(.*?)$#$1#;
316 print(STDERR "$File:$call_info[2] $$ $Txt\n");
317 return("");
318 # }}}
319 } # D()
321 __END__
323 # Plain Old Documentation (POD) {{{
325 =pod
327 =head1 NAME
331 =head1 REVISION
333 $Id$
335 =head1 SYNOPSIS
337 [options] [file [files [...]]]
339 =head1 DESCRIPTION
343 =head1 OPTIONS
345 =over 4
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.
355 =item B<--version>
357 Print version information.
359 =item B<--debug>
361 Print debugging messages.
363 =back
365 =head1 BUGS
369 =head1 AUTHOR
371 Made by Øyvind A. Holm S<E<lt>sunny@sunbase.orgE<gt>>.
373 =head1 COPYRIGHT
375 Copyleft © Øyvind A. Holm E<lt>sunny@sunbase.orgE<gt>
376 This is free software; see the file F<COPYING> for legalese stuff.
378 =head1 LICENCE
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
394 =head1 SEE ALSO
396 =cut
398 # }}}
400 # vim: set fenc=UTF-8 ft=perl fdm=marker ts=4 sw=4 sts=4 et fo+=w :
401 # End of file $Id$