###########################################################################
#
# ImagePlug.pm -- simple text plugin
# A component of the Greenstone digital library software
# from the New Zealand Digital Library Project at the 
# University of Waikato, New Zealand.
#
# Copyright (C) 1999 New Zealand Digital Library Project
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
###########################################################################

package ImagePlug;

use BasPlug;

sub BEGIN {
    @ISA = ('BasPlug');
}


sub print_usage {
    my ($plugin_name) = @_;

    print STDERR "
  usage: plugin ImagePlug [options]

   -noscaleup         Don't scale up small images when making thumbnails

   -thumbnailsize n   Make thumbnails of size nxn

   -thumbnailtype s   Make thumbnails in format 's'

   -screenviewsize n  If set, makes an image of size n for screen display
                      and sets Screen, ScreenSize, ScrrenWidth and Screeneight
                      metadata.  By default it is not set.

   -screenviewtype s  If -screenviewsize is set, this sets the screen display
                      image type.  Defaults to jpg.

   -convertto s       Convert main inage to (gif|png|jpg)

   -minimumsize n     Ignore images smaller than n bytes

"
}

sub new {
    my ($class) = @_;
    my $plugin_name = shift (@_);
    my $self = new BasPlug ("ImagePlug", @_);

    if (!parsargv::parse(\@_,
			 q^noscaleup^, \$self->{'noscaleup'},
			 q^converttotype/.*/^, \$self->{'converttotype'},
			 q^minimumsize/[0-9]*/100^, \$self->{'minimumsize'},

			 q^thumbnailsize/[0-9]*/100^, \$self->{'thumbnailsize'},
			 q^thumbnailtype/.*/gif^, \$self->{'thumbnailtype'},
			 q^screenviewsize/[0-9]*/0^, \$self->{'screenviewsize'},
			 q^screenviewtype/.*/jpg^, \$self->{'screenviewtype'},
			 "allow_extra_options")) {
	
	print STDERR "\nImagePlug uses an incorrect option.\n";
	print STDERR "Check your collect.cfg configuration file.\n";
    	&print_usage($plugin_name);
	die "\n";
    }

    return bless $self, $class;
}

sub get_default_process_exp {
    my $self = shift (@_);

    return q^(?i)(\.jpe?g|\.gif|\.png|\.bmp|\.xbm|\.tif?f)$^; 
}


# Create the thumbnail and screenview images, and discover the Image's
# size, width, and height using the convert utility.

sub run_convert {
    my $self = shift (@_);
    my $filename = shift (@_);   # filename with full path
    my $file = shift (@_);       # filename without path
    my $doc_obj = shift (@_);
    my $section = $doc_obj->get_top_section();
    
    my $verbosity = $self->{'verbosity'};
    my $outhandle = $self->{'outhandle'};

    # check the filename is okay
    return 0 if ($file eq "" || $filename eq "");

    if ($filename =~ m/ /) {
	print $outhandle "ImagePlug: \"$filename\" contains a space. choking.\n";
	return undef;
    }

    my $minimumsize = $self->{'minimumsize'};
    if (defined $minimumsize && (-s $filename < $minimumsize)) {
        print $outhandle "ImagePlug: \"$filename\" too small, skipping\n"
	    if ($verbosity > 1);
    }


    # Convert the image to a new type (if required).
    my $converttotype = $self->{'converttotype'};
    my $originalfilename = "";  # only set if we do a conversion
    my $type = "unknown";

    if ($converttotype ne "" && $filename =~ m/$converttotype$/) {

	$originalfilename = $filename;
	$filename = &util::get_tmp_filename() . ".$converttotype";
	$self->{'tmp_filename'} = $filename;

	my $command = "convert -verbose $originalfilename $filename";
	print $outhandle "$command\n" if ($verbosity > 2);
	my $result = '';
	$result = `$command`;
	print $outhandle "$result\n" if ($verbosity > 3);

	$type = $converttotype;
    }
    

    # Make the thumbnail image
    my $thumbnailsize = $self->{'thumbnailsize'}  || 100;
    my $thumbnailtype = $self->{'thumbnailtype'} || 'gif';
	
    my $thumbnailfilename = &util::get_tmp_filename() . ".$thumbnailtype";
    $self->{'tmp_filename2'} = $thumbnailfilename;

    # Generate the thumbnail with convert
    my $command = "convert -verbose -geometry $thumbnailsize" 
	. "x$thumbnailsize $filename $thumbnailfilename";
    print $outhandle "$command\n" if ($verbosity > 2);
    my $result = '';
    $result = `$command` ;
    print $outhandle "$result\n" if ($verbosity > 3);

    # Add the thumbnail as an associated file ...
    if (-e "$thumbnailfilename") { 
	$doc_obj->associate_file("$thumbnailfilename", "thumbnail.$thumbnailtype", 
				 "image/$thumbnailtype",$section);
	$doc_obj->add_metadata ($section, "ThumbType", $thumbnailtype);
	$doc_obj->add_metadata ($section, "Thumb", "thumbnail.$thumbnailtype");
    }


    # Extract Image metadata from convert output
    if ($result =~ m/([0-9]+)x([0-9]+)=>([0-9]+)x([0-9]+)/) {
	$doc_obj->add_metadata ($section, "ImageWidth", $1);
	$doc_obj->add_metadata ($section, "ImageHeight", $2);
	$doc_obj->add_metadata ($section, "ThumbWidth", $3);
	$doc_obj->add_metadata ($section, "ThumbHeight", $4);
    }
    
    my $size = "unknown";
    if ($result =~ m/^[^\n]* ([0-9]+)b/) {
	$size = $1;
    } elsif ($result =~ m/^[^\n]* ([0-9]+)kb/) {
	$size = 1024 * $1;
    }
    
    if ($result =~ m/^[^\n]*JPE?G/i) {
	$type = "jpeg";
    } elsif ($result =~ m/^[^\n]*GIF/i) {
	$type = "gif";
    } elsif ($result =~ m/^[^\n]*PNG/i) {
	$type = "png";
    } elsif ($result =~ m/^[^\n]*TIF?F/i) {
	$type = "tiff";
    } elsif ($result =~ m/^[^\n]*BMP/i) {
	$type = "bmp";
    } elsif ($result =~ m/^[^\n]*XBM?F/i) {
	$type = "xbm";
    }

    $doc_obj->add_metadata ($section, "ImageType", $type);
    $doc_obj->add_metadata ($section, "Image", "$file");
    $doc_obj->add_metadata ($section, "ImageSize", $size);
    
    # Add the image as an associated file ...
    $doc_obj->associate_file($filename,$file,"image/$type",$section);
        

    # Make a screen-sized version of the picture if requested
    if ($self->{'screenviewsize'}) {

	my $screenviewsize = $self->{'screenviewsize'};
	my $screenviewtype = $self->{'screenviewtype'} || 'jpeg';
	my $screenviewfilename = &util::get_tmp_filename() . ".$screenviewtype";
	$self->{'tmp_filename3'} = $screenviewfilename;

	# make the screenview image
	my $command = "convert -verbose -geometry $screenviewsize" 
	    . "x$screenviewsize $filename $screenviewfilename";
	print $outhandle "$command\n" if ($verbosity > 2);
	my $result = "";
	$result = `$command` ;
	print $outhandle "$result\n" if ($verbosity > 3);

	# 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);
	}
    
	#add the screenview as an associated file ...
	if (-e "$screenviewfilename") { 
	    $doc_obj->associate_file("$screenviewfilename", "screenview.$screenviewtype",
				     "image/$screenviewtype",$section);
	    $doc_obj->add_metadata ($section, "ScreenType", $screenviewtype);
	    $doc_obj->add_metadata ($section, "Screen", "screenview.$screenviewtype");
	} else {
	    print $outhandle "ImagePlug: couldn't find \"$screenviewfilename\"\n";
	}
    }

    return $type;


}


# The ImagePlug read() function. This function does all the right things
# to make general options work for a given plugin. It calls the process()
# function which does all the work specific to a plugin (like the old
# read functions used to do). Most plugins should define their own 
# process() function and let this read() function keep control.
#
# ImagePlug overrides read() because there is no need to read the actual 
# text of the file in, because the contents of the file is not text...
#
# Return number of files processed, undef if can't process
# Note that $base_dir might be "" and that $file might 
# include directories

sub read {
    my $self = shift (@_);
    my ($pluginfo, $base_dir, $file, $metadata, $processor, $maxdocs) = @_;

    my $outhandle = $self->{'outhandle'};

    my $filename = &util::filename_cat($base_dir, $file);
    return 0 if $self->{'block_exp'} ne "" && $filename =~ /$self->{'block_exp'}/;
    if ($filename !~ /$self->{'process_exp'}/ || !-f $filename) {
	return undef;
    }
    print $outhandle "ImagePlug processing \"$filename\"\n"
	    if $self->{'verbosity'} > 1;

    #if there's a leading directory name, eat it...
    $file =~ s/^.*[\/\\]//;
    
    # create a new document
    my $doc_obj = new doc ($filename, "indexed_doc");
    $doc_obj->set_OIDtype ($processor->{'OIDtype'});    

    #run convert to get the thumbnail and extract size and type info
    my $result = run_convert($self, $filename, $file, $doc_obj);
    
    if (!defined $result)
    {
	print "ImagePlug: couldn't process \"$filename\"\n";
	return 0;
    }

    #create an empty text string so we don't break downstream plugins 
    my $text = "Dummy text to sidestep display bug.";

    # include any metadata passed in from previous plugins 
    # note that this metadata is associated with the top level section
    my $section = $doc_obj->get_top_section();
    $self->extra_metadata ($doc_obj, $section, $metadata);

    # do plugin specific processing of doc_obj
    return undef unless defined ($self->process (\$text, $pluginfo, $base_dir, 
						 $file, $metadata, $doc_obj));

    # do any automatic metadata extraction
    $self->auto_extract_metadata ($doc_obj);

    # add an OID
    $doc_obj->set_OID();
    $doc_obj->add_text($section, $text);

    # process the document
    $processor->process($doc_obj);

    # clean up temporary files - we do this here instead of in  
    # run_convert becuase associated files aren't actually copied 
    # until after process has been run.
    if (defined $self->{'tmp_filename'} && 
	-e $self->{'tmp_filename'}) {
      &util::rm($self->{'tmp_filename'})
    }
    if (defined $self->{'tmp_filename2'} && 
	-e $self->{'tmp_filename2'}) {
      &util::rm($self->{'tmp_filename2'})
    }
    if (defined $self->{'tmp_filename3'} && 
	-e $self->{'tmp_filename3'}) {
      &util::rm($self->{'tmp_filename3'})
    }

    return 1;
}

# do plugin specific processing of doc_obj
sub process {
    my $self = shift (@_);
    my ($textref, $pluginfo, $base_dir, $file, $metadata, $doc_obj) = @_;
    my $outhandle = $self->{'outhandle'};
    
    return 1;
}

1;











