* /branches/gpst.gpxfix/.
[gpstools.git] / gpst-pic
blobdf0ff335e788cf984fced79c752d5359751318c4
1 #!/usr/bin/perl -w
3 #=======================================================================
4 # $Id$
5 # Extract EXIF data from pictures for use with COPY in Postgres
7 # Character set: UTF-8
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 #=======================================================================
13 BEGIN {
14 our @version_array;
17 use strict;
18 use Getopt::Long;
20 BEGIN {
21 push(@INC, "$ENV{'HOME'}/bin/src/gpstools");
22 our @version_array;
25 use GPST;
26 use GPSTxml;
28 $| = 1;
30 our $Debug = 0;
31 our $NA = '\N';
32 our %Std = (
33 'output-format' => 'pgtab',
35 our %Opt = (
36 'author' => '',
37 'debug' => 0,
38 'description' => '',
39 'help' => 0,
40 'output-format' => $Std{'output-format'},
41 'verbose' => 0,
42 'version' => 0,
45 our $progname = $0;
46 $progname =~ s/^.*\/(.*?)$/$1/;
48 my $rcs_id = '$Id$';
49 my $id_date = $rcs_id;
50 $id_date =~ s/^.*?\d+ (\d\d\d\d-.*?\d\d:\d\d:\d\d\S+).*/$1/;
52 push(@main::version_array, $rcs_id);
54 Getopt::Long::Configure("bundling");
55 GetOptions(
56 "author|a=s" => \$Opt{'author'},
57 "debug" => \$Opt{'debug'},
58 "description|d=s" => \$Opt{'description'},
59 "help|h" => \$Opt{'help'},
60 "output-format|o=s" => \$Opt{'output-format'},
61 "verbose|v+" => \$Opt{'verbose'},
62 "version" => \$Opt{'version'},
63 ) || die("$progname: Option error. Use -h for help.\n");
65 $Opt{'debug'} && ($Debug = 1);
66 $Opt{'help'} && usage(0);
67 if ($Opt{'version'}) {
68 print_version();
69 exit(0);
72 if ($Opt{'output-format'} eq "xml") {
73 print("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<gpstpic>\n");
76 if ($#ARGV < 0) {
77 while (<>) {
78 chomp();
79 print_entry($_);
81 } else {
82 for my $fname (@ARGV) {
83 print_entry($fname);
87 if ($Opt{'output-format'} eq "xml") {
88 print("</gpstpic>\n");
91 sub print_entry {
92 # {{{
93 my $filename = shift;
94 my $Retval = 0;
95 my ($date, $coor) =
96 ( '', '');
97 my @Dates = ();
98 local *PicFP;
99 D("filename = '$filename'");
100 if (open(PicFP, "exifprobe -L \"$filename\" |")) { # FIXME: Quick & Dirty™
101 while (<PicFP>) {
102 if (/DateTime/) {
103 s/^.*'(.*?)'.*$/$1/;
104 chomp($date = $_);
105 $date =~ s/^(\d\d\d\d)(.)(\d\d)(.)(\d\d)(.)(\d\d:\d\d:\d\d)(.*)/$1-$3-${5}T$7$8/;
106 D("date = '$date'");
107 push(@Dates, $date);
110 close(PicFP);
111 @Dates = reverse sort @Dates;
112 $date = $Dates[0];
113 defined($date) || ($date = '');
114 D("final date = '$date'");
115 if ($date =~ /^\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d$/) {
116 $filename =~ s/^.*\/(.*?)$/$1/;
117 my $Output = "";
118 if ($Opt{'output-format'} eq "xml") {
119 if (length("$filename$date")) {
120 $Output = join("",
121 " <img>\n",
122 length($filename)
123 ? sprintf(" <filename>%s</filename>\n",
124 txt_to_xml($filename))
125 : "",
126 length($date)
127 ? sprintf(" <date>%s</date>\n",
128 txt_to_xml($date))
129 : "",
130 " </img>\n",
133 } elsif ($Opt{'output-format'} eq "pgtab") {
134 $Output = join("\t",
135 postgresql_copy_safe($date),
136 length($coor)
137 ? postgresql_copy_safe($coor)
138 : $NA,
139 length($Opt{'description'})
140 ? postgresql_copy_safe($Opt{'description'})
141 : $NA,
142 length($filename)
143 ? postgresql_copy_safe($filename)
144 : $NA,
145 length($Opt{'author'})
146 ? postgresql_copy_safe($Opt{'author'})
147 : $NA
148 ) . "\n";
149 } else {
150 die("$progname: $Opt{'output-format'}: Unknown output format\n");
152 print($Output);
153 $Opt{'verbose'} && print(STDERR $Output);
154 } else {
155 if (length($date)) {
156 warn("$filename: $date: Invalid date format");
157 $Retval = 2;
160 } else {
161 warn("$filename: Cannot open exifprobe(1) pipe: $!");
162 $Retval = 1;
164 return($Retval);
165 # }}}
166 } # print_entry()
168 sub print_version {
169 # Print program version {{{
170 for (@main::version_array) {
171 print("$_\n");
173 # }}}
174 } # print_version()
176 sub usage {
177 # Send the help message to stdout {{{
178 my $Retval = shift;
180 if ($Opt{'verbose'}) {
181 print("\n");
182 print_version();
184 print(<<END);
186 Usage: $progname [options] [file [files [...]]]
188 Extract EXIF info from pictures for use with PostgreSQL's COPY command.
189 If no filenames are specified on the command line, file names are read
190 from stdin.
192 Options:
194 -a, --author x
195 Specify author of picture.
196 -d, --description x
197 Specify description for picture.
198 -h, --help
199 Show this help.
200 -v, --verbose
201 Increase level of verbosity. Can be repeated.
202 -o x, --output-format x
203 Create output of type x:
205 pgtab
206 Default: "$Std{'output-format'}".
207 --version
208 Print version information.
209 --debug
210 Print debugging messages.
213 exit($Retval);
214 # }}}
215 } # usage()
217 sub msg {
218 # Print a status message to stderr based on verbosity level {{{
219 my ($verbose_level, $Txt) = @_;
221 if ($Opt{'verbose'} >= $verbose_level) {
222 print(STDERR "$progname: $Txt\n");
224 # }}}
225 } # msg()
227 sub D {
228 # Print a debugging message {{{
229 $Debug || return;
230 my @call_info = caller;
231 chomp(my $Txt = shift);
232 my $File = $call_info[1];
233 $File =~ s#\\#/#g;
234 $File =~ s#^.*/(.*?)$#$1#;
235 print(STDERR "$File:$call_info[2] $$ $Txt\n");
236 return("");
237 # }}}
238 } # D()
240 __END__
242 # Plain Old Documentation (POD) {{{
244 =pod
246 =head1 NAME
250 =head1 REVISION
252 $Id$
254 =head1 SYNOPSIS
256 [options] [file [files [...]]]
258 =head1 DESCRIPTION
262 =head1 OPTIONS
264 =over 4
266 =item B<-h>, B<--help>
268 Print a brief help summary.
270 =item B<-v>, B<--verbose>
272 Increase level of verbosity. Can be repeated.
274 =item B<--version>
276 Print version information.
278 =item B<--debug>
280 Print debugging messages.
282 =back
284 =head1 BUGS
288 =head1 AUTHOR
290 Made by Øyvind A. Holm S<E<lt>sunny@sunbase.orgE<gt>>.
292 =head1 COPYRIGHT
294 Copyleft © Øyvind A. Holm E<lt>sunny@sunbase.orgE<gt>
295 This is free software; see the file F<COPYING> for legalese stuff.
297 =head1 LICENCE
299 This program is free software; you can redistribute it and/or modify it
300 under the terms of the GNU General Public License as published by the
301 Free Software Foundation; either version 2 of the License, or (at your
302 option) any later version.
304 This program is distributed in the hope that it will be useful, but
305 WITHOUT ANY WARRANTY; without even the implied warranty of
306 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
307 See the GNU General Public License for more details.
309 You should have received a copy of the GNU General Public License along
310 with this program; if not, write to the Free Software Foundation, Inc.,
311 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
313 =head1 SEE ALSO
315 =cut
317 # }}}
319 # vim: set fenc=UTF-8 ft=perl fdm=marker ts=4 sw=4 sts=4 et fo+=w :
320 # End of file $Id$