#!/usr/local/bin/perl
# 
# pstogif.pl v1.0, July 1994, by Nikos Drakos <nikos@cbl.leeds.ac.uk>
# Computer Based Learning Unit, University of Leeds.
#
# Accompanies LaTeX2HTML Version 96.1
#
# Script to convert an arbitrary PostScript image to a cropped GIF image
# suitable for incorporation into HTML documents as inlined images to be
# viewed with WWW browsers.
#
# This is based on the pstoepsi script 
# by Doug Crabill dgc@cs.purdue.edu
#
# Please note the following:
# - The -density argument has no effect unless the 
#   color depth (set with the -depth argument) is equal to 1.
# - Valid arguments for -depth are 1,8, or 24.
#  
# This software is provided as is without any guarantee.
#
# Nikos Drakos (ND), nikos@cbl.leeds.ac.uk
# Computer Based Learning Unit, University of Leeds.
#
# 24 AUG 96 JCL - Print error message if translation fails.
#    - Allow any file name, assume it to be postscript, switch to
#      epsf mode if '%!' and 'EPSF' is found in the first line.
#    - Removed unused $PSTOPPM variable.
#    - Introduced global $BASE and $FILE variables.
#    - Ghostscript commands collected on a single line, space separated
#      and terminated by 'quit\n', to prevent multiple GS> prompts.
#
# 9 AUG 96 MEH  - If $DEBUG, it's more verbous and doesn't remove
#    intermediate files. -debug option introduced.
#    - Massive change to convert() to cope with EPS files and to speed
#      up conversion.
#
# 5 JUN 96 RRM  Allow Ghostscript 3.3+  to quit without a prompt.
#		Also, removed unused variable names.
# 
# 15 Jan 96 HS Call ppmquant only if needed.  Fixed bug relative to
#    V 95.3 .
#
# 15 Dec 95 HS (Herbert Swan <dprhws.edp.Arco.com> Added support for
#    the flip=option.  This allows images to be oriented differently
#    in the paper versus the electronic media
#
# 1 Nov 95 jmn - modified for use with gs ppm driver - from jhrg's patches
#    note that ppmtops.ps and ppmtops3.ps are no longer needed
#
# 20 JUL 94 ND Converted to Perl and made several changes eg it now accepts 
#    parameters from environment variables or from command line or will use 
#    default ones. 
#      
# 1  APR 94 ND Changed the suffixes of multi-page files from xbm to gif (oops!)
#

#####################################################################
$| =1;
&read_args;

### You may need to specify some pathnames here if you want to
### run the script without LaTeX2HTML

# Ghostscript
$GS= $ENV{'GS'} || 'gs';

# If available, you should really use pnmraw instead of ppmraw
$PNMDEVICE=$ENV{'PNMDEVICE'} || 'ppmraw' ;

# This allows Ghostscript to exit without displaying a prompt.
# --- applicable to versions 3.3+  (perhaps 3.0+ ?)
# $GSquit = '-c quit';
$GSquit = '';

# Available in the PBMPLUS libary	   
$PNMCROP=$ENV{'PNMCROP'} || 'pnmcrop' ;

# Also in PBMPLUS
$PNMFLIP=$ENV{'PNMFLIP'} || 'pnmflip' ;

# Also in PBMPPLUS	  
$PPMTOGIF=$ENV{'PPMTOGIF'} || 'ppmtogif' ;

# Also in PBMPPLUS	  
$REDUCE_COLOR=$ENV{'PPMQUANT'} || 'ppmquant 256' ;
 
$OUTFILE = $ENV{'OUTFILE'} || $out;
			
# Valid choices for $COLOR_DEPTH are 1, 8 or 24. 
$DEPTH = $ENV{'DEPTH'} || $depth || 24;

#Default density is 72
$DENSITY = $ENV{'DENSITY'} || $density || 72;
    
# Valid choices are any numbers greater than zero
# Useful choices are numbers between 0.1 - 5
# Large numbers may generate very large intermediate files
# and will take longer to process
$SCALE = $ENV{'SCALE'} || $scale; # No default value

$PAPERSIZE = $ENV{'PAPERSIZE'} || $papersize; # No default value;

$DEBUG = $ENV{'DEBUG'} || $DEBUG || 0;

$BASE = $FILE = undef;
######################################################################

&main;

sub read_args {
    local($_);
#    local($color);
    while ($ARGV[0] =~ /^-/) {
	$_ = shift @ARGV;
	if (/^-h(elp)?$/) {
	    &usage; exit}
        elsif (/^-out$/) {
            $out = shift @ARGV;
	}
        elsif (/^-debug$/) {
            $DEBUG = 1;
	}
	elsif (/^-(.*)$/) {
	    eval "\$$1 = shift \@ARGV"; # Create and set a flag $<name>
	    }
    }
}		 

sub main {
    local($outfile, $i, $j, $done);
    &test_args; #sets $BASE and $FILE
    $outfile = $OUTFILE || "$BASE.gif";
    open(STDERR, ">/dev/null") unless $DEBUG;
    &convert;
    if (-f "$BASE.ppm") {
	&crop_scale_etc("$BASE.ppm", $outfile);
	++$done;
    }
    else {
	foreach $i (<$BASE.[1-9]*ppm>) {
	    $j = $i; 
	    $j =~ s/\.(.*)ppm/$1.gif/;
	    &crop_scale_etc($i, $j);
	    ++$done;
	}
    }
    print "Couldn't find ppm output of $FILE\n" unless $done;
    &cleanup($BASE);
}

sub crop_scale_etc {
    local($in, $out) = @_;
    local($tmp) = $in . ".tmp";
    open(STDERR, ">/dev/null") unless $DEBUG;

    if ($flip) {
	rename($tmp, $in) unless system("$PNMFLIP -$flip $in > $tmp");
	}
    system("$PNMCROP $in > $tmp");

    if (system("$PPMTOGIF $tmp > $out")) {
	print "Running ppmquant for $out\n";
	system("$REDUCE_COLOR < $tmp|$PPMTOGIF - > $out");
	}
    unlink $tmp unless $DEBUG;
    print "Writing $out\n";
}

sub test_args {
    $FILE = $ARGV[0];
    $BASE = $FILE;
    $BASE =~ s/\.[^.]*$//; #remove a trailing suffix the same way a shell would do it

    if (! ( -f "$FILE")) {
	print "Cannot find file $FILE\n.";
	exit}
    elsif (! ($DEPTH =~ /^(1|8|24)$/)) {
	print "The color depth must be 1 or 8 or 24. You specified $DEPTH\n";
	exit			
	}
    if (defined $SCALE) {
	if ($SCALE > 0) {
	    $DENSITY = int($SCALE * $DENSITY)}
	else {
	    print "Error: The scale must be greater than 0.\n" .
		"You specified $SCALE\n";
	    exit}
    }
}
   
sub convert {
    local($size) = "-sPAPERSIZE=$PAPERSIZE" if $PAPERSIZE;
    local($density) = "-r$DENSITY" if ($DENSITY != 72);
    local($bbx, $bby, $bbw, $bbh) = (0,0,0,0);
    local($max_lines) = 30;
    local($epsf) = 0;
    open (PS, "$FILE");
    $_ = <PS>;
    if ( /^%!.*EPSF/ ) {
	$epsf = 1;
	while (<PS>) {
	    if (/^%%BoundingBox:\s+(-?\d+)\s+(-?\d+)\s+(-?\d+)\s+(-?\d+)/) {
		$bbx = 0-$1;    $bby = 0-$2;
		$bbw = $3+$bbx;    $bbh = $4+$bby;
		if ( $DENSITY ) {
		    local($scale) = $DENSITY/72;
		    $bbw *= $scale;  $bbh *= $scale;
		}
		$size = "-g${bbw}x${bbh}";
		last;
	    }
	    if (/^%%EndComments/) { last; }
	    unless ( --$max_lines ) { last; }
	}
    }
    close PS;
    if ( $DEBUG ) {
	print "|$GS -q -dNOPAUSE -dNO_PAUSE -sDEVICE=$PNMDEVICE $size $density -sOutputFile=$BASE.ppm\n";
	print "$bbx $bby translate\n" if ($bbx != 0 || $bby != 0);
	print "($FILE) run\n";
	print "showpage\n" if ($epsf);
	print "quit\n";
    }
    open (GS, "|$GS -q -dNOPAUSE -dNO_PAUSE -sDEVICE=$PNMDEVICE $size $density -sOutputFile=$BASE.ppm");
    print GS "$bbx $bby translate " if ($bbx != 0 || $bby != 0);
    print GS "($FILE) run ";
    print GS "showpage " if ($epsf);
    print GS "quit\n";
    close GS;
}

sub cleanup {
    unlink <$BASE[0-9.]*ppm> unless $DEBUG;
}

sub usage {
    print "Usage: pstogif [-h(elp)] [-debug] [-out <output file>] [-depth <color depth 1, 8 or 24>]  [-flip <Flip_code>] [-density <pixel density>] <file>.ps\n\n";
}
