Hører egentlig med til r2727.
[gpstools.git] / gpst-pic
blob0715f1bd7111be50b7191f162a06f5d638423eec
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 # Version information {{{
135 # Without version field (same as version 1):
136 # date \t
137 # "(lat,lon)"-coordinates \t
138 # description \t
139 # filename \t
140 # author \t
141 # Version 1:
142 # "1" \t
143 # date \t
144 # "(lat,lon)"-coordinates \t
145 # description \t
146 # filename \t
147 # author \n
148 # }}}
149 $Output = join("\t",
150 1, # Version number
151 postgresql_copy_safe($date),
152 length($coor)
153 ? postgresql_copy_safe($coor)
154 : $NA,
155 length($Opt{'description'})
156 ? postgresql_copy_safe($Opt{'description'})
157 : $NA,
158 length($filename)
159 ? postgresql_copy_safe($filename)
160 : $NA,
161 length($Opt{'author'})
162 ? postgresql_copy_safe($Opt{'author'})
163 : $NA
164 ) . "\n";
165 } else {
166 die("$progname: $Opt{'output-format'}: Unknown output format\n");
168 print($Output);
169 $Opt{'verbose'} && print(STDERR $Output);
170 } else {
171 if (length($date)) {
172 warn("$filename: $date: Invalid date format");
173 $Retval = 2;
176 } else {
177 warn("$filename: Cannot open exifprobe(1) pipe: $!");
178 $Retval = 1;
180 return($Retval);
181 # }}}
182 } # print_entry()
184 sub print_version {
185 # Print program version {{{
186 for (@main::version_array) {
187 print("$_\n");
189 # }}}
190 } # print_version()
192 sub usage {
193 # Send the help message to stdout {{{
194 my $Retval = shift;
196 if ($Opt{'verbose'}) {
197 print("\n");
198 print_version();
200 print(<<END);
202 Usage: $progname [options] [file [files [...]]]
204 Extract EXIF info from pictures for use with PostgreSQL's COPY command.
205 If no filenames are specified on the command line, file names are read
206 from stdin.
208 Options:
210 -a, --author x
211 Specify author of picture.
212 -d, --description x
213 Specify description for picture.
214 -h, --help
215 Show this help.
216 -v, --verbose
217 Increase level of verbosity. Can be repeated.
218 -o x, --output-format x
219 Create output of type x:
221 pgtab
222 Default: "$Std{'output-format'}".
223 --version
224 Print version information.
225 --debug
226 Print debugging messages.
229 exit($Retval);
230 # }}}
231 } # usage()
233 sub msg {
234 # Print a status message to stderr based on verbosity level {{{
235 my ($verbose_level, $Txt) = @_;
237 if ($Opt{'verbose'} >= $verbose_level) {
238 print(STDERR "$progname: $Txt\n");
240 # }}}
241 } # msg()
243 sub D {
244 # Print a debugging message {{{
245 $Debug || return;
246 my @call_info = caller;
247 chomp(my $Txt = shift);
248 my $File = $call_info[1];
249 $File =~ s#\\#/#g;
250 $File =~ s#^.*/(.*?)$#$1#;
251 print(STDERR "$File:$call_info[2] $$ $Txt\n");
252 return("");
253 # }}}
254 } # D()
256 __END__
258 # Plain Old Documentation (POD) {{{
260 =pod
262 =head1 NAME
266 =head1 REVISION
268 $Id$
270 =head1 SYNOPSIS
272 [options] [file [files [...]]]
274 =head1 DESCRIPTION
278 =head1 OPTIONS
280 =over 4
282 =item B<-h>, B<--help>
284 Print a brief help summary.
286 =item B<-v>, B<--verbose>
288 Increase level of verbosity. Can be repeated.
290 =item B<--version>
292 Print version information.
294 =item B<--debug>
296 Print debugging messages.
298 =back
300 =head1 BUGS
304 =head1 AUTHOR
306 Made by Øyvind A. Holm S<E<lt>sunny@sunbase.orgE<gt>>.
308 =head1 COPYRIGHT
310 Copyleft © Øyvind A. Holm E<lt>sunny@sunbase.orgE<gt>
311 This is free software; see the file F<COPYING> for legalese stuff.
313 =head1 LICENCE
315 This program is free software; you can redistribute it and/or modify it
316 under the terms of the GNU General Public License as published by the
317 Free Software Foundation; either version 2 of the License, or (at your
318 option) any later version.
320 This program is distributed in the hope that it will be useful, but
321 WITHOUT ANY WARRANTY; without even the implied warranty of
322 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
323 See the GNU General Public License for more details.
325 You should have received a copy of the GNU General Public License along
326 with this program; if not, write to the Free Software Foundation, Inc.,
327 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
329 =head1 SEE ALSO
331 =cut
333 # }}}
335 # vim: set fenc=UTF-8 ft=perl fdm=marker ts=4 sw=4 sts=4 et fo+=w :
336 # End of file $Id$