source: trunk/gsdl/perllib/plugins/ImagePlug.pm@ 3137

Last change on this file since 3137 was 3137, checked in by paynter, 22 years ago

Changed the way Width, Height, Size and Type metadata is calculated.
Previously, we trapped the STDERR output of convert, which included
this stuff, and parsed it with a complex regexp. The problem is the
format of this output keeps changing. This version stops trying to do
that, and uses the ImageMajick "identify" program instead. It's
slower but more reliable. (That said, I've not tested it on non-Linux
platforms.)

  • Property svn:keywords set to Author Date Id Revision
File size: 11.3 KB
Line 
1###########################################################################
2#
3# ImagePlug.pm -- simple text plugin
4# A component of the Greenstone digital library software
5# from the New Zealand Digital Library Project at the
6# University of Waikato, New Zealand.
7#
8# Copyright (C) 1999 New Zealand Digital Library Project
9#
10# This program is free software; you can redistribute it and/or modify
11# it under the terms of the GNU General Public License as published by
12# the Free Software Foundation; either version 2 of the License, or
13# (at your option) any later version.
14#
15# This program is distributed in the hope that it will be useful,
16# but WITHOUT ANY WARRANTY; without even the implied warranty of
17# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18# GNU General Public License for more details.
19#
20# You should have received a copy of the GNU General Public License
21# along with this program; if not, write to the Free Software
22# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23#
24###########################################################################
25
26package ImagePlug;
27
28use BasPlug;
29
30sub BEGIN {
31 @ISA = ('BasPlug');
32}
33
34
35sub print_usage {
36 my ($plugin_name) = @_;
37
38 print STDERR "
39 usage: plugin ImagePlug [options]
40
41 -noscaleup Don't scale up small images when making thumbnails
42
43 -thumbnailsize n Make thumbnails of size nxn
44
45 -thumbnailtype s Make thumbnails in format 's'
46
47 -screenviewsize n If set, makes an image of size n for screen display
48 and sets Screen, ScreenSize, ScrrenWidth and Screeneight
49 metadata. By default it is not set.
50
51 -screenviewtype s If -screenviewsize is set, this sets the screen display
52 image type. Defaults to jpg.
53
54 -convertto s Convert main inage to (gif|png|jpg)
55
56 -minimumsize n Ignore images smaller than n bytes
57
58"
59}
60
61
62sub new {
63 my ($class) = @_;
64 my $plugin_name = shift (@_);
65 my $self = new BasPlug ("ImagePlug", @_);
66
67 if (!parsargv::parse(\@_,
68 q^noscaleup^, \$self->{'noscaleup'},
69 q^converttotype/.*/^, \$self->{'converttotype'},
70 q^minimumsize/[0-9]*/100^, \$self->{'minimumsize'},
71
72 q^thumbnailsize/[0-9]*/100^, \$self->{'thumbnailsize'},
73 q^thumbnailtype/.*/gif^, \$self->{'thumbnailtype'},
74 q^screenviewsize/[0-9]*/0^, \$self->{'screenviewsize'},
75 q^screenviewtype/.*/jpg^, \$self->{'screenviewtype'},
76 "allow_extra_options")) {
77
78 print STDERR "\nImagePlug uses an incorrect option.\n";
79 print STDERR "Check your collect.cfg configuration file.\n";
80 &print_usage($plugin_name);
81 die "\n";
82 }
83
84 return bless $self, $class;
85}
86
87
88sub get_default_process_exp {
89 my $self = shift (@_);
90
91 return q^(?i)(\.jpe?g|\.gif|\.png|\.bmp|\.xbm|\.tif?f)$^;
92}
93
94
95# Create the thumbnail and screenview images, and discover the Image's
96# size, width, and height using the convert utility.
97
98sub run_convert {
99 my $self = shift (@_);
100 my $filename = shift (@_); # filename with full path
101 my $file = shift (@_); # filename without path
102 my $doc_obj = shift (@_);
103 my $section = $doc_obj->get_top_section();
104
105 my $verbosity = $self->{'verbosity'};
106 my $outhandle = $self->{'outhandle'};
107
108 # check the filename is okay
109 return 0 if ($file eq "" || $filename eq "");
110
111 if ($filename =~ m/ /) {
112 print $outhandle "ImagePlug: \"$filename\" contains a space. choking.\n";
113 return undef;
114 }
115
116 my $minimumsize = $self->{'minimumsize'};
117 if (defined $minimumsize && (-s $filename < $minimumsize)) {
118 print $outhandle "ImagePlug: \"$filename\" too small, skipping\n"
119 if ($verbosity > 1);
120 }
121
122 # Convert the image to a new type (if required).
123 my $converttotype = $self->{'converttotype'};
124 my $originalfilename = ""; # only set if we do a conversion
125 my $type = "unknown";
126
127 if ($converttotype ne "" && $filename =~ m/$converttotype$/) {
128
129 $originalfilename = $filename;
130 $filename = &util::get_tmp_filename() . ".$converttotype";
131 $self->{'tmp_filename'} = $filename;
132
133 my $command = "convert -verbose $originalfilename $filename";
134 print $outhandle "$command\n" if ($verbosity > 2);
135 my $result = '';
136 $result = `$command`;
137 print $outhandle "$result\n" if ($verbosity > 3);
138
139 $type = $converttotype;
140 }
141
142 # Add the image metadata
143 $doc_obj->add_metadata ($section, "Image", "$file");
144 my ($image_type, $image_width, $image_height, $image_size)
145 = &identify($filename, $outhandle, $verbosity);
146
147 $doc_obj->add_metadata ($section, "ImageType", $image_type);
148 $doc_obj->add_metadata ($section, "ImageWidth", $image_width);
149 $doc_obj->add_metadata ($section, "ImageHeight", $image_height);
150 $doc_obj->add_metadata ($section, "ImageSize", $image_size);
151
152 # Add the image as an associated file
153 $doc_obj->associate_file($filename,$file,"image/$type",$section);
154
155 # Make the thumbnail image
156 my $thumbnailsize = $self->{'thumbnailsize'} || 100;
157 my $thumbnailtype = $self->{'thumbnailtype'} || 'gif';
158 my $thumbnailfile = &util::get_tmp_filename() . ".$thumbnailtype";
159 $self->{'tmp_filename2'} = $thumbnailfile;
160
161 # Generate the thumbnail with convert
162 my $command = "convert -verbose -geometry $thumbnailsize"
163 . "x$thumbnailsize $filename $thumbnailfile";
164 print $outhandle "$command\n" if ($verbosity > 2);
165 my $result = '';
166 $result = `$command 2>&1` ;
167 print $outhandle "$result\n" if ($verbosity > 3);
168
169 # Add the thumbnail as an associated file ...
170 if (-e "$thumbnailfile") {
171 $doc_obj->associate_file("$thumbnailfile", "thumbnail.$thumbnailtype",
172 "image/$thumbnailtype",$section);
173 $doc_obj->add_metadata ($section, "ThumbType", $thumbnailtype);
174 $doc_obj->add_metadata ($section, "Thumb", "thumbnail.$thumbnailtype");
175 }
176
177 # Extract Thumnail metadata from convert output
178 if ($result =~ m/[0-9]+x[0-9]+=>([0-9]+)x([0-9]+)/) {
179 $doc_obj->add_metadata ($section, "ThumbWidth", $1);
180 $doc_obj->add_metadata ($section, "ThumbHeight", $2);
181 }
182
183 # Make a screen-sized version of the picture if requested
184 if ($self->{'screenviewsize'}) {
185
186 # To do: if the actual image smaller than the screenview size,
187 # we should use the original !
188
189 my $screenviewsize = $self->{'screenviewsize'};
190 my $screenviewtype = $self->{'screenviewtype'} || 'jpeg';
191 my $screenviewfilename = &util::get_tmp_filename() . ".$screenviewtype";
192 $self->{'tmp_filename3'} = $screenviewfilename;
193
194 # make the screenview image
195 my $command = "convert -verbose -geometry $screenviewsize"
196 . "x$screenviewsize $filename $screenviewfilename";
197 print $outhandle "$command\n" if ($verbosity > 2);
198 my $result = "";
199 $result = `$command 2>&1` ;
200 print $outhandle "$result\n" if ($verbosity > 3);
201
202 # get screenview dimensions, size and type
203 if ($result =~ m/[0-9]+x[0-9]+=>([0-9]+)x([0-9]+)/) {
204 $doc_obj->add_metadata ($section, "ScreenWidth", $1);
205 $doc_obj->add_metadata ($section, "ScreenHeight", $2);
206 }
207
208 #add the screenview as an associated file ...
209 if (-e "$screenviewfilename") {
210 $doc_obj->associate_file("$screenviewfilename", "screenview.$screenviewtype",
211 "image/$screenviewtype",$section);
212 $doc_obj->add_metadata ($section, "ScreenType", $screenviewtype);
213 $doc_obj->add_metadata ($section, "Screen", "screenview.$screenviewtype");
214 } else {
215 print $outhandle "ImagePlug: couldn't find \"$screenviewfilename\"\n";
216 }
217 }
218
219 return $type;
220}
221
222
223# Discover the characteristics of an image file with the ImageMagick
224# "identify" command.
225
226sub identify {
227 my ($image, $outhandle, $verbosity) = @_;
228
229 # Use the ImageMagick "identify" command to get the file specs
230 my $command = "identify $image 2>&1";
231 print $outhandle "$command\n" if ($verbosity > 2);
232 my $result = '';
233 $result = `$command`;
234 print $outhandle "$result\n" if ($verbosity > 3);
235
236 # Read the type, width, and height
237 my $type = 'unknown';
238 my $width = 'unknown';
239 my $height = 'unknown';
240
241 if ($result =~ /^$image (\w+) (\d+)x(\d+)/) {
242 $type = $1;
243 $width = $2;
244 $height = $3;
245 }
246
247 # Read the size
248 my $size = "unknown";
249 if ($result =~ m/^.* ([0-9]+)b/) {
250 $size = $1;
251 } elsif ($result =~ m/^.* ([0-9]+)kb/) {
252 $size = 1024 * $1;
253 }
254
255 print $outhandle "file: $image:\t $type, $width, $height, $size\n"
256 if ($verbosity > 2);
257
258 # Return the specs
259 return ($type, $width, $height, $size);
260}
261
262
263# The ImagePlug read() function. This function does all the right things
264# to make general options work for a given plugin. It calls the process()
265# function which does all the work specific to a plugin (like the old
266# read functions used to do). Most plugins should define their own
267# process() function and let this read() function keep control.
268#
269# ImagePlug overrides read() because there is no need to read the actual
270# text of the file in, because the contents of the file is not text...
271#
272# Return number of files processed, undef if can't process
273# Note that $base_dir might be "" and that $file might
274# include directories
275
276sub read {
277 my $self = shift (@_);
278 my ($pluginfo, $base_dir, $file, $metadata, $processor, $maxdocs) = @_;
279
280 my $outhandle = $self->{'outhandle'};
281
282 my $filename = &util::filename_cat($base_dir, $file);
283 return 0 if $self->{'block_exp'} ne "" && $filename =~ /$self->{'block_exp'}/;
284 if ($filename !~ /$self->{'process_exp'}/ || !-f $filename) {
285 return undef;
286 }
287 print $outhandle "ImagePlug processing \"$filename\"\n"
288 if $self->{'verbosity'} > 1;
289
290 #if there's a leading directory name, eat it...
291 $file =~ s/^.*[\/\\]//;
292
293 # create a new document
294 my $doc_obj = new doc ($filename, "indexed_doc");
295 $doc_obj->set_OIDtype ($processor->{'OIDtype'});
296
297 #run convert to get the thumbnail and extract size and type info
298 my $result = run_convert($self, $filename, $file, $doc_obj);
299
300 if (!defined $result)
301 {
302 print "ImagePlug: couldn't process \"$filename\"\n";
303 return 0;
304 }
305
306 #create an empty text string so we don't break downstream plugins
307 my $text = "Dummy text to sidestep display bug.";
308
309 # include any metadata passed in from previous plugins
310 # note that this metadata is associated with the top level section
311 my $section = $doc_obj->get_top_section();
312 $self->extra_metadata ($doc_obj, $section, $metadata);
313
314 # do plugin specific processing of doc_obj
315 return undef unless defined ($self->process (\$text, $pluginfo, $base_dir,
316 $file, $metadata, $doc_obj));
317
318 # do any automatic metadata extraction
319 $self->auto_extract_metadata ($doc_obj);
320
321 # add an OID
322 $doc_obj->set_OID();
323 $doc_obj->add_text($section, $text);
324
325 # process the document
326 $processor->process($doc_obj);
327
328 # clean up temporary files - we do this here instead of in
329 # run_convert becuase associated files aren't actually copied
330 # until after process has been run.
331 if (defined $self->{'tmp_filename'} &&
332 -e $self->{'tmp_filename'}) {
333 &util::rm($self->{'tmp_filename'})
334 }
335 if (defined $self->{'tmp_filename2'} &&
336 -e $self->{'tmp_filename2'}) {
337 &util::rm($self->{'tmp_filename2'})
338 }
339 if (defined $self->{'tmp_filename3'} &&
340 -e $self->{'tmp_filename3'}) {
341 &util::rm($self->{'tmp_filename3'})
342 }
343
344 return 1;
345}
346
347# do plugin specific processing of doc_obj
348sub process {
349 my $self = shift (@_);
350 my ($textref, $pluginfo, $base_dir, $file, $metadata, $doc_obj) = @_;
351 my $outhandle = $self->{'outhandle'};
352
353 return 1;
354}
355
3561;
Note: See TracBrowser for help on using the repository browser.