Index: /gsdl/trunk/perllib/plugins/ImageConverter.pm
===================================================================
--- /gsdl/trunk/perllib/plugins/ImageConverter.pm	(revision 15866)
+++ /gsdl/trunk/perllib/plugins/ImageConverter.pm	(revision 15866)
@@ -0,0 +1,382 @@
+package ImageConverter;
+
+use PrintInfo;
+
+use strict;
+
+BEGIN {
+    @ImageConverter::ISA = ('PrintInfo');
+}
+
+my $arguments = [
+      { 'name' => "create_thumbnail",
+	'desc' => "{ImageConverter.generatethumbnail}",
+	'type' => "bool",
+	'deft' => "true",
+	'reqd' => "no" },
+      { 'name' => "noscaleup",
+	'desc' => "{ImageConverter.noscaleup}",
+	'type' => "flag",
+	'reqd' => "no" },
+      { 'name' => "thumbnailsize",
+	'desc' => "{ImageConverter.thumbnailsize}",
+	'type' => "int",
+	'deft' => "100",
+	'range' => "1,",
+	'reqd' => "no" },
+      { 'name' => "thumbnailtype",
+	'desc' => "{ImageConverter.thumbnailtype}",
+	'type' => "string",
+	'deft' => "gif",
+	'reqd' => "no" },
+      { 'name' => "create_screenview",
+	'desc' => "{ImageConverter.generatescreenview}",
+	'type' => "bool",
+	'deft' => "true",
+	'reqd' => "no" },
+      { 'name' => "screenviewsize",
+	'desc' => "{ImageConverter.screenviewsize}",
+	'type' => "int",
+	'deft' => "500",
+	'range' => "1,",
+	'reqd' => "no" },
+      { 'name' => "screenviewtype",
+	'desc' => "{ImageConverter.screenviewtype}",
+	'type' => "string",
+	'deft' => "jpg",
+	'reqd' => "no" },
+      { 'name' => "converttotype",
+	'desc' => "{ImageConverter.converttotype}",
+	'type' => "string",
+	'deft' => "",
+	'reqd' => "no" },
+      { 'name' => "noscaleup",
+	'desc' => "{ImageConverter.noscaleup}",
+	'type' => "flag",
+	'reqd' => "no" },
+      { 'name' => "minimumsize",
+	'desc' => "{ImageConverter.minimumsize}",
+	'type' => "int",
+	'deft' => "100",
+	'range' => "1,",
+	'reqd' => "no" },
+      { 'name' => "cache_generated_images",
+	'desc' => "{ImageConverter.cache_generated_image}",
+	'type' => "flag",
+	'reqd' => "no" }
+		 ];
+
+my $options = { 'name' => "ImageConverter",
+		'desc' => "{ImageConverter.desc}",
+		'abstract' => "yes",
+		'inherits' => "yes",
+		'args' => $arguments };
+
+sub new {
+    my ($class) = shift (@_);
+    my ($pluginlist,$inputargs,$hashArgOptLists) = @_;
+    push(@$pluginlist, $class);
+
+    push(@{$hashArgOptLists->{"ArgList"}},@{$arguments});
+    push(@{$hashArgOptLists->{"OptList"}},$options);
+
+    my $self = new PrintInfo($pluginlist, $inputargs, $hashArgOptLists);
+
+    # Check that ImageMagick is installed and available on the path (except for Windows 95/98)
+    if (!($ENV{'GSDLOS'} eq "windows" && !Win32::IsWinNT())) {
+	my $result = `identify 2>&1`;
+	if ($? == -1 || $? == 256) {  # Linux and Windows return different values for "program not found"
+	    $self->{'imagemagick_not_installed'} = 1;
+	}
+    }
+    return bless $self, $class;
+
+}
+
+sub init {
+    my $self = shift(@_);
+
+    $self->{'tmp_file_paths'} = ();
+}
+	
+sub check_imagemagick {
+
+    my $self = shift (@_);
+    my ($gli) = @_;
+
+    my $outhandle = $self->{'outhandle'};
+    
+    my $image_magick_ok = 1;
+    # None of this works very well on Windows 95/98...
+    if ($ENV{'GSDLOS'} eq "windows" && !Win32::IsWinNT()) {
+	if ($gli) {
+	    #print STDERR "<ProcessingError n='$file' r='Windows 95/98 not supported'>\n";
+	    # have no file here. other kind of error? just want a warning really
+	}
+	print $outhandle "ImageConverter: Windows 95/98 not supported, no image processing available\n";
+	$image_magick_ok = 0;
+
+    } else {
+	# Check that ImageMagick is installed and available on the path 
+	my $result = `identify 2>&1`;
+	if ($? == -1 || $? == 256) {  # Linux and Windows return different values for "program not found"
+	    if ($gli) {
+		#print STDERR "<ProcessingError n='$file' r='ImageMagick not installed'>\n";
+	    }
+	    print $outhandle "ImageConverter: ImageMagick not installed, no image processing available\n";
+	    $image_magick_ok = 0;
+	}
+    }
+    return $image_magick_ok;
+    
+}
+
+# convert image to new type if converttotype is set
+# generate thumbnails if required
+# generate screenview if required
+# discover image metadata
+sub generate_images {
+    my $self = shift(@_);
+
+    my ($filename_full_path, $filename_no_path, $doc_obj, $section) = @_;
+
+    # check the filenames
+    return 0 if ($filename_no_path eq "" || !-f $filename_full_path);
+
+    my $verbosity = $self->{'verbosity'};
+    my $outhandle = $self->{'outhandle'};
+
+    # check the size of the image against minimum size if specified
+    my $minimumsize = $self->{'minimumsize'};
+    if (defined $minimumsize && (-s $filename_full_path < $minimumsize)) {
+        print $outhandle "ImageConverter: \"$filename_full_path\" too small, skipping\n"
+	    if ($verbosity > 1);
+	return 0; # or is there a better return value??
+    }
+    
+    my $filehead = $filename_no_path;
+    $filehead =~ s/\.([^\.]*)$//; # filename with no extension
+    my $assocfilemeta = "[assocfilepath]";
+    if ($section ne $doc_obj->get_top_section()) {
+	$assocfilemeta = "[parent(Top):assocfilepath]";
+    }
+
+    # Convert the image to a new type (if required).
+    my $converttotype = $self->{'converttotype'};
+    my $type = "unknown";
+
+    if ($converttotype ne "" && $filename_full_path !~ m/$converttotype$/) {
+	
+	my $result = $self->convert($filename_full_path, $converttotype, "", "");
+	($filename_full_path) = ($result =~ /=>(.*\.$converttotype)/);
+
+	$type = $converttotype;
+	$filename_no_path = "$filehead.$type";
+    }
+
+    # add Image metadata 
+    $doc_obj->add_metadata($section, "Image", $filename_no_path);
+
+    # Source and SourceUTF8 - should this be converted filename or original?
+    # here we overwrite the originals with converted ones
+    $self->set_Source_metadata($doc_obj, $filename_no_path);
+
+    # use identify to get info about the (possibly converted) image
+    my ($image_type, $image_width, $image_height, $image_size) 
+	= &identify($filename_full_path, $outhandle, $verbosity);
+
+    if ($image_type ne " ") {
+	$type = $image_type;
+    }
+
+    #overwrite the ones added in BasePlugin
+    $doc_obj->set_metadata_element ($section, "FileFormat", $type);
+    $doc_obj->set_metadata_element ($section, "FileSize",   $image_size);
+
+    $doc_obj->add_metadata ($section, "ImageType",   $image_type);
+    $doc_obj->add_metadata ($section, "ImageWidth",  $image_width);
+    $doc_obj->add_metadata ($section, "ImageHeight", $image_height);
+    $doc_obj->add_metadata ($section, "ImageSize",   $image_size);
+
+    $doc_obj->add_metadata ($section, "srclink", "<a href=\"_httpprefix_/collect/[collection]/index/assoc/$assocfilemeta/[Image]\">");
+    $doc_obj->add_metadata ($section, "/srclink", "</a>");
+    $doc_obj->add_metadata ($section, "srcicon", "<img src=\"_httpprefix_/collect/[collection]/index/assoc/$assocfilemeta/[Image]\" width=\"100\">");
+
+    # Add the image as an associated file
+    $doc_obj->associate_file($filename_full_path, $filename_no_path, "image/$type", $section);
+
+    if ($self->{'create_thumbnail'} eq "true") {
+	$self->create_thumbnail($filename_full_path, $filehead, $doc_obj, $section, $assocfilemeta);
+    }
+    if ($self->{'create_screenview'} eq "true") {
+	$self->create_screenview($filename_full_path, $filehead, $doc_obj, $section, $assocfilemeta);
+    }
+}
+
+sub create_thumbnail {
+    my $self = shift(@_);
+    my ($original_file, $filehead, $doc_obj, $section, $assocfilemeta) = @_;
+
+    my $thumbnailsize = $self->{'thumbnailsize'};
+    my $thumbnailtype = $self->{'thumbnailtype'};
+    
+    # Generate the thumbnail with convert
+    my $result = $self->convert($original_file, $thumbnailtype, "-geometry $thumbnailsize" . "x$thumbnailsize", "THUMB");
+    my ($thumbnailfile) = ($result =~ /=>(.*\.$thumbnailtype)/);
+    
+    # Add the thumbnail as an associated file ...
+    if (-e "$thumbnailfile") { 
+	$doc_obj->associate_file("$thumbnailfile", $filehead."_thumb.$thumbnailtype", 
+				 "image/$thumbnailtype",$section);
+	$doc_obj->add_metadata ($section, "ThumbType", $thumbnailtype);
+	$doc_obj->add_metadata ($section, "Thumb", $filehead."_thumb.$thumbnailtype");
+	
+	$doc_obj->add_metadata ($section, "thumbicon", "<img src=\"_httpprefix_/collect/[collection]/index/assoc/$assocfilemeta/[Thumb]\" width=[ThumbWidth] height=[ThumbHeight]>");
+    
+	
+	# Extract Thumbnail metadata from convert output
+	if ($result =~ m/[0-9]+x[0-9]+=>([0-9]+)x([0-9]+)/) {
+	    $doc_obj->add_metadata ($section, "ThumbWidth", $1);
+	    $doc_obj->add_metadata ($section, "ThumbHeight", $2);
+	}
+    } else {
+	my $outhandle = $self->{'outhandle'};
+	print $outhandle "Couldn't find thumbnail $thumbnailfile\n";
+
+    }
+}
+
+sub create_screenview {
+    
+    my $self = shift(@_);
+    my ($original_file, $filehead, $doc_obj, $section, $assocfilemeta) = @_;
+
+    # To do: if the actual image smaller than the screenview size,
+    # we should use the original !
+    
+    my $screenviewsize = $self->{'screenviewsize'};
+    my $screenviewtype = $self->{'screenviewtype'};
+    
+    # make the screenview image
+    my $result = $self->convert($original_file, $screenviewtype, "-geometry $screenviewsize" . "x$screenviewsize", "SCREEN");
+    my ($screenviewfilename) = ($result =~ /=>(.*\.$screenviewtype)/);
+    
+    
+    #add the screenview as an associated file ...
+    if (-e "$screenviewfilename") { 
+	$doc_obj->associate_file("$screenviewfilename", $filehead."_screen.$screenviewtype", "image/$screenviewtype",$section);
+	$doc_obj->add_metadata ($section, "ScreenType", $screenviewtype);
+	$doc_obj->add_metadata ($section, "Screen", $filehead."_screen.$screenviewtype");
+	
+	$doc_obj->add_metadata ($section, "screenicon", "<img src=\"_httpprefix_/collect/[collection]/index/assoc/$assocfilemeta/[Screen]\" width=[ScreenWidth] height=[ScreenHeight]>");
+
+	# get screenview dimensions, size and type
+	if ($result =~ m/[0-9]+x[0-9]+=>([0-9]+)x([0-9]+)/) {
+	    $doc_obj->add_metadata ($section, "ScreenWidth", $1);
+	    $doc_obj->add_metadata ($section, "ScreenHeight", $2);
+	} elsif ($result =~ m/([0-9]+)x([0-9]+)/) {
+	    #if the image hasn't changed size, the previous regex doesn't match
+	    $doc_obj->add_metadata ($section, "ScreenWidth", $1);
+	    $doc_obj->add_metadata ($section, "ScreenHeight", $2);
+	}
+    } else {
+	my $outhandle = $self->{'outhandle'};
+	print $outhandle "Couldn't find screenview file $screenviewfilename\n";
+
+    }
+
+}
+
+
+
+sub convert {
+    my $self = shift(@_);
+    my $source_file_path = shift(@_);
+    my $target_file_type = shift(@_);
+    my $convert_options = shift(@_) || "";
+    my $convert_type = shift(@_) || "";
+
+    my $outhandle = $self->{'outhandle'};
+    my $verbosity = $self->{'verbosity'};
+
+    # Determine the full name and path of the output file
+    my $filehead = &util::get_tmp_filename();
+    my $target_file_path = $filehead . "." . $target_file_type;
+    push(@{$self->{'tmp_file_paths'}}, $target_file_path);
+
+    # Generate and run the convert command
+    my $convert_command = "convert -interlace plane -verbose $convert_options \"$source_file_path\" \"$target_file_path\"";
+    print $outhandle "$convert_type $convert_command\n" if ($verbosity > 2);
+    my $result = `$convert_command 2>&1`;
+    print $outhandle "$convert_type RESULT = $result\n" if ($verbosity > 2);
+
+    return $result;
+}
+
+
+# Discover the characteristics of an image file with the ImageMagick
+# "identify" command.
+
+sub identify { 
+    my ($image, $outhandle, $verbosity) = @_;
+
+    # Use the ImageMagick "identify" command to get the file specs
+    my $command = "identify \"$image\" 2>&1";
+    print $outhandle "$command\n" if ($verbosity > 2);
+    my $result = '';
+    $result = `$command`;
+    print $outhandle "$result\n" if ($verbosity > 3);
+
+    # Read the type, width, and height
+    my $type =   'unknown';
+    my $width =  'unknown';
+    my $height = 'unknown';
+
+    my $image_safe = quotemeta $image;
+    if ($result =~ /^$image_safe (\w+) (\d+)x(\d+)/) {
+	$type = $1;
+	$width = $2;
+	$height = $3;
+    }
+
+    # Read the size
+    my $size = "unknown";
+    if ($result =~ m/^.* ([0-9]+)b/) {
+	$size = $1;
+    }
+    elsif ($result =~ m/^.* ([0-9]+)(\.([0-9]+))?kb?/) {
+	$size = 1024 * $1;
+	if (defined($2)) {
+	    $size = $size + (1024 * $2);
+	    # Truncate size (it isn't going to be very accurate anyway)
+	    $size = int($size);
+	}
+    }
+    elsif ($result =~ m/^.* (([0-9]+)(\.([0-9]+))?e\+([0-9]+))(kb|b)?/) {
+	# Deals with file sizes on Linux of type "3.4e+02kb" where e+02 is 1*10^2.
+	# 3.4e+02 therefore evaluates to 3.4 x 1 x 10^2 = 340kb.
+	# Programming languages including Perl know how that 3.4e+02 is a number,
+	# so we don't need to do any calculations.
+	$size = $1*1; # turn the string into a number by multiplying it by 1
+	       #if we did $size = $1; $size would be merely the string "3.4e+02"
+	$size = int($size); # truncate size
+    }
+    print $outhandle "file: $image:\t $type, $width, $height, $size\n" 
+	if ($verbosity > 2);
+
+    # Return the specs
+    return ($type, $width, $height, $size);
+}
+
+sub clean_up_temporary_files {
+    my $self = shift(@_);
+
+    foreach my $tmp_file_path (@{$self->{'tmp_file_paths'}}) {
+	if (-e $tmp_file_path) {
+	    &util::rm($tmp_file_path);
+	}
+    }
+   
+}
+
+1;	
