#!/usr/bin/perl -w use strict; use Getopt::Long; # Converts the image given in the first argument into # the format of the second argument. Decides how to do it # based on the filenames of the source and destination # my $usage = "Usage: image_convert.pl [--scale scale_filename] [--res resolution] source_file destination_file\n "; # A global hash to hold command-line arguments. my $cliArgs = {}; my $DEFAULT_SCALE = 0.75; my $DEFAULT_MAXX = 5; my $DEFAULT_MAXY = 8; my $DEFAULT_RESOLUTION = 72; sub max { return $_[0] > $_[1] ? $_[0] : $_[1]; } sub min { return $_[0] < $_[1] ? $_[0] : $_[1]; } sub getIMGdetails { # Takes the image filename as the only argument, returns the image # size in inches. # If the identify program is available: # Determine the current geometry and resolution of the image. # Return the image size in inches. # Otherwize return 0,0. my ($img) = shift; # # If the identify program is not available, bail. (`which identify 2>\&1` =~ /^which:/) and die "identify program (part of Imagemagick) not available -- aborting\n"; my $attrib = {}; # Determine the size of the existing image. my $response = `identify -verbose $img`; if ($response =~ /^identify: no decode delegate/ or !$response) { return 0; } ($attrib->{format}) = $response =~ /^\s*Format:\s+(\S*)\s+/m; ($attrib->{hdots},$attrib->{vdots}) = $response =~ /^\s*Geometry:\s*([\d\.]*)x([\d\.]*)/m; ($attrib->{hres},$attrib->{vres}) = $response =~ /^\s*Resolution:\s*([\d\.]*)x([\d\.]*)/m; $attrib->{hsize} = $attrib->{hdots} / $attrib->{hres}; $attrib->{vsize} = $attrib->{vdots} / $attrib->{vres}; return $attrib; } sub doConversion { my ($cli,$scales) = @_; my ($attrib,$ourScale,$newsizex,$newsizey); # Get the input file details. $attrib = getIMGdetails($cli->{infile}); if (ref($attrib) ne 'HASH') { # Identify failed. die "Failed to Identify Input Image File $cli->{infile}. Aborting\n"; } # If the scale factor is defined in the file of scale factors, # use that. Otherwise use the default scale provided on the command line, # If none was provided, use 0.75. if (defined($scales->{$cli->{infile}})) { $ourScale = $scales->{$cli->{infile}}; } else { if (defined $cli->{defaultscale}) { $ourScale = $cli->{defaultscale}; } else { $ourScale = $DEFAULT_SCALE; } # If after scaling the image is still too big, scale it to the max # size. Otherwise, scale it according to the scale factor. if ($attrib->{hsize} * $ourScale > $cli->{maxx} or $attrib->{vsize} * $ourScale > $cli->{maxy}) { $ourScale /= max($attrib->{hsize} * $ourScale / $cli->{maxx}, $attrib->{vsize} * $ourScale / $cli->{maxy}); } } $newsizex = $attrib->{hsize} * $ourScale; $newsizey = $attrib->{vsize} * $ourScale; # Get strings ready for the convert command. my $cdots = sprintf "%dx%d",$newsizex * $cli->{resolution}, $newsizey * $cli->{resolution}; my $cres = sprintf "%dx%d",$cli->{resolution},$cli->{resolution}; # Do the conversion... printf "Scaling by %.5f : %s -> %s\n",$ourScale,$cli->{infile},$cli->{outfile}; print STDERR `convert $cli->{infile} -resize $cdots -density $cres $cli->{outfile}`; # if ($cli->{infile} =~ /.*\.png$/ and $cli->{outfile} =~ /.*\.pdf$/) { # printf "Scaling %s to %s with scale %.3f\n",$cli->{infile},$cli->{outfile},$ourScale; # print STDERR `pngtopnm $cli->{infile} | pnmtops -scale=$ourScale -noturn -nosetpage | epstopdf --filter > $cli->{outfile}`; # pngtopnm $${i}.png | pnmtops -scale=0.85 --noturn -nosetpage | epstopdf --filter >$${i}.pdf ; # } elsif ($cli->{infile} =~ /.*\.png$/ and $cli->{outfile} =~ /.*\.eps$/) { # printf "Scaling %s to %s with scale %.3f\n",$cli->{infile},$cli->{outfile},$ourScale; # print STDERR `pngtopnm $cli->{infile} | pnmtops -scale=$ourScale -noturn -nosetpage > $cli->{outfile}`; # pngtopnm $${i}.png | pnmtops -scale=0.65 --noturn -nosetpage >$${i}.eps; # } elsif ($cli->{infile} =~ /.*\.jpg$/ and $cli->{outfile} =~ /.*\.png$/) { # printf "Converting %s to %s\n",$cli->{infile},$cli->{outfile}; # print STDERR `jpegtopnm $cli->{infile} | pnmtopng > $cli->{outfile}`; # jpegtopnm $${i}.jpg | pnmtopng >$${i}.png ; # } elsif ($cli->{infile} =~ /.*\.gif$/ and $cli->{outfile} =~ /.*\.png$/) { # printf "Converting %s to %s\n",$cli->{infile},$cli->{outfile}; # print STDERR `giftopnm $cli->{infile} | pnmtopng > $cli->{outfile}`; # giftopnm $${i}.gif | pnmtopng >$${i}.png ; # } else { # die "Unsupported Conversion: $cli->{infile} to $cli->{outfile}\n"; # } # Save the image scale for putting into the file of scales. $scales->{$cli->{infile}} = $ourScale; } sub loadImgScales { # Loads the image scales from the specified file into the # global hash %imgScales my $scaleFile = shift; my ($imagename,$scale,$cnt); my %imgScales; if (!open (IF,"<$scaleFile")) { warn "File of Image Scales not Found. Will create one when needed.\n"; } else { $cnt = 0; while () { $cnt++; chomp; my ($imagename,$scale) = split /\s+/; if (!defined $imagename or !defined $scale or $scale !~ /^[\-\+\d\.]+$/ or $scale < 0.01 or $scale > 100) { print STDERR "Invalid Image Scale Entry at line $cnt in $scaleFile\n"; } else { $imgScales{$imagename} = $scale; } } close IF; } return { %imgScales }; } sub writeImgScales { my ($fileName,$scales) = @_; open OF,">$fileName" or die "Cannot open scale file $fileName for output\n"; foreach (sort(keys(%{$scales}))) { printf OF "%s %.5f\n",$_,$scales->{$_}; } close OF; } sub getCliArgs { # Sets up the parameters and gets the command-line # options. $args is a pointer to a hash. my $args = shift; my ($infile,$outfile,@filenames); # Establish defaults: $args->{defaultscale} = $DEFAULT_SCALE; $args->{maxx} = $DEFAULT_MAXX; $args->{maxy} = $DEFAULT_MAXY; $args->{resolution} = $DEFAULT_RESOLUTION; GetOptions( "scalefile=s" => \$args->{scalefile}, "defaultscale=f" => \$args->{defaultscale}, "resolution=i" => \$args->{resolution}, "maxx=f" => \$args->{maxx}, "maxy=f" => \$args->{maxy}, ) or die $usage; # There should be just the input and output filenames and # nothing more in @filenames $args->{infile} = shift @ARGV; $args->{outfile} = shift @ARGV; if (!defined $args->{outfile}) { die $usage; } } ############################################### ############## MAIN ########################### ############################################### my ($scales); # Get the command-line arguments into the global hash. getCliArgs($cliArgs); #foreach (sort(keys(%$cliArgs))) { # print "$_ $cliArgs->{$_}\n"; #} if (! -e $cliArgs->{infile}) {die "Input File not Found: $cliArgs->{infile}\n";} # Load in the image conversion scales from the file of scale factors. if (defined $cliArgs->{scalefile}) { if (-e $cliArgs->{scalefile}) { $scales = loadImgScales($cliArgs->{scalefile}); } else { warn "File of Image Scales not Found. Will create one when needed.\n"; } } # Process the file. doConversion($cliArgs,$scales); # Write the file of scale factors. writeImgScales($cliArgs->{scalefile},$scales);