texlive[72650] trunk: pdflatexpicscale (25oct24)

commits+karl at tug.org commits+karl at tug.org
Fri Oct 25 23:26:46 CEST 2024


Revision: 72650
          https://tug.org/svn/texlive?view=revision&revision=72650
Author:   karl
Date:     2024-10-25 23:26:46 +0200 (Fri, 25 Oct 2024)
Log Message:
-----------
pdflatexpicscale (25oct24)

Modified Paths:
--------------
    trunk/Build/source/texk/texlive/linked_scripts/pdflatexpicscale/pdflatexpicscale.pl
    trunk/Master/texmf-dist/doc/support/pdflatexpicscale/README
    trunk/Master/texmf-dist/doc/support/pdflatexpicscale/pdflatexpicscale.pdf
    trunk/Master/texmf-dist/doc/support/pdflatexpicscale/pdflatexpicscale.tex
    trunk/Master/texmf-dist/doc/support/pdflatexpicscale/testprinter.ps
    trunk/Master/texmf-dist/scripts/pdflatexpicscale/pdflatexpicscale.pl

Modified: trunk/Build/source/texk/texlive/linked_scripts/pdflatexpicscale/pdflatexpicscale.pl
===================================================================
--- trunk/Build/source/texk/texlive/linked_scripts/pdflatexpicscale/pdflatexpicscale.pl	2024-10-24 23:42:17 UTC (rev 72649)
+++ trunk/Build/source/texk/texlive/linked_scripts/pdflatexpicscale/pdflatexpicscale.pl	2024-10-25 21:26:46 UTC (rev 72650)
@@ -16,37 +16,71 @@
 #            with the documentation, even when the perl code does not change.
 # 2017-02-01 pdflatexpicscale did not work correct when log lines were 
 #            wrapped twice. This is fixed.
+# 2024-10-18 Replaced dependency of external ImageMagick software in favor
+#            of GD library.
 #
 use strict;
+
+use GD;
+use Image::ExifTool;
+
 use File::Basename;
 use File::Spec;
 use File::Copy;
+
 use Getopt::Long;
 
-my $version = '0.32';
-my $versiondate = '2018-02-12';           #version %version
+my $version = '0.50';
+my $versiondate = '2024-10-18';           #version %version
 my $showversion;
 
-my $verbose;
-my $help;
+# command line inouts
+my $verbose = 0;
+my $help = 0;
+my $draftoption = 0;
+my $finaloption = 0;
 my $TeXproject;
 
 # folders for scaled graphics, relative names
-my $printfolderprefix   = 'printimg';
-my $previewfolderprefix = 'previewimg';
-my $srcfolder           = '';
+my $outputfolderprefix = undef;
+my $srcfolder          = '';
 
-# final resolution. special b/w handling not implemented yet
-my $printdpi   = 300;
-my $printbwdpi = 4 * $printdpi;
-my $previewdpi = 72;
-my $tolerance  = 20;
+my %customsettings = (
+    'name' => 'from command line',
+    'outputdpi' => 300,
+    'outputfolder' => 'printimg',
+    'jpegquality' => 80,
+    'outputbwdpi' => 1200
+    );
 
-# file formats
+my %finalsettings = (
+    'name' => 'final',
+    'outputdpi' => 300,
+    'jpegquality' => 80,
+    'outputfolder' => 'finalimg',
+    'outputbwdpi' => 1200
+    );
+
+my %draftsettings = (
+    'name' => 'draft',
+    'outputdpi' => 96,
+    'jpegquality' => 50,
+    'outputfolder' => 'webimg',
+    'outputbwdpi' => 300
+    );
+
+my $outputdpi   = undef;     # final resolution. 
+my $outputbwdpi = undef;      # final resolution for pure b/w art
+my $tolerance  = 20;         # avoid resampling of almost fitting images
+my $jpegquality = undef;     # 50 is mostly acceptable, 80 is fine.
+
+# supported file formats (by extension)
 my %canhandle =
-( JPG => '1',
-  PNG => '1',
-);
+    (
+    'JPEG' => '1',
+     'JPG' => '1',
+     'PNG' => '1',
+    );
 
 # bookkeeping
 my %processedimages;
@@ -54,118 +88,276 @@
 my $scaled  = 0;
 my $skipped = 0;
 
-sub printInplaceError
+# the following is required by Image::ExifTool
+our $AUTOLOAD;
+sub AUTOLOAD
 {
+    Image::ExifTool::DoAutoLoad($AUTOLOAD, @_);
+}
+
+sub printError
+{
     my $filename = shift;
-    print "I will not do inplace modification of graphics:\n" .
-	"($filename) will not be processed. (Missing path?)\n";
+    my $kind = shift;
+    if ($kind eq 'i') {
+	print "I will not do inplace modification of graphics:\n" .
+	    "($filename) will not be processed. (Missing path?)\n";
+    } elsif ($kind eq 'm') {
+	print "I can't find ($filename). (What have you done?)\n";
+    } elsif ($kind eq 'f') {
+	print "File $filename has an unexpected or wrong format.\n";
+    } elsif ($kind eq 's') {
+	print "Trying to copy '$filename' leads to system error # $_.\n";
+    } elsif ($kind eq 'd') {
+	print "Directory '$filename' does not exist\n"
+	    . "in actual folder and I can't create it (sys error # $_).\n"
+	    . "Please check permissions. Aborting.\n";
+    } else {
+	print "I got trouble with '$filename'.\n";
+    }
 }
 
-sub printMissingError
+sub getDestFilename
 {
+    my @dstdirs;
     my $filename = shift;
-    print "I can not find ($filename). (What have you done?)\n";
+    my $dstfilename = undef;;
+    $dstdirs[0] = '.';
+    $dstdirs[1] = $outputfolderprefix;
+    $dstfilename = File::Spec->catfile(@dstdirs, basename($filename));
+    return $dstfilename;
 }
 
+sub getSourceFilename
+{
+    my @srcdirs;
+    my $filename = shift;
+    my $srcfilename = undef;
+    if (defined($srcfolder) and $srcfolder gt '') {
+	$srcdirs[0] = '$srcfolder';
+	$srcfilename = File::Spec->catfile(@srcdirs, basename($filename));
+	$filename = $srcfilename;
+    }
+    unless (-e $filename){
+	printError($filename, 'm');
+	return undef;
+    }
+    return $filename;
+}
+
+sub fileYounger
+{
+    my @filename = @_;
+    my ($mtime1, $mtime2, $size1, $size2, $idstring2, $existwidth);
+    my ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size,
+	$atime, $ctime, $blksize, $blocks);
+    ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size,
+     $atime, $mtime1, $ctime, $blksize, $blocks)
+	= stat($filename[0]);
+    ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size,
+     $atime, $mtime2, $ctime, $blksize, $blocks)
+	= stat($filename[1]);
+    if($mtime1 >= $mtime2) {
+	return 1;
+    }
+    return 0;
+    
+}
+
+sub numberInRange
+{
+    my $realwidth = shift;
+    my $wantedwidth = shift;
+    if (($realwidth >= $wantedwidth * 100 / (100 + $tolerance)) and
+	($realwidth <= $wantedwidth * (100 + $tolerance) / 100)) {
+	return 1;
+    } else {
+	return 0;
+    }
+}
+
+sub loadImage
+{
+    my %result = (
+	'filename' => undef,
+	'image' => undef, 'canhandle' => 0,
+	'format' => undef, 'width' => 0,
+	'height' => 0, 'monochrome' => 0,
+	'quality' => 50
+    );
+    $result{'filename'} = shift;
+    my $maketruecolor = shift || 0;
+    my $exifTool = Image::ExifTool->new;
+    my $imageinfo = $exifTool->ImageInfo($result{'filename'});
+#    foreach (sort keys %$imageinfo) {
+#	print "$_ => $$imageinfo{$_}\n";
+#    }
+    $result{'image'} = GD::Image->new($result{'filename'});
+    $result{'width'} = $$imageinfo{'ImageWidth'};
+    $result{'height'} = $$imageinfo{'ImageHeight'};
+    if ( ($$imageinfo{'FileType'} eq 'PNG') or
+	 ($$imageinfo{'FileType'} eq 'JPEG')) {
+	$result{'format'} = $$imageinfo{'FileType'};
+	$result{'canhandle'} = 1;
+    }
+    if (defined($$imageinfo{'BitDepth'}) and $$imageinfo{'BitDepth'} == 1) {
+	$result{'monochrome'} = 1;
+    } elsif (defined($result{'image'})) {
+	$result{'canhandle'} = 1;
+	if (defined ($result{'image'}->colorsTotal) and
+	    $result{'image'}->colorsTotal < 3) {
+	    $result{'monochrome'} = 1;
+	}
+	unless (defined($result{'width'})) {
+	    $result{'width'} = $result{'image'}->width;
+	}
+	unless (defined($result{'height'})) {
+	    $result{'height'} = $result{'image'}->height;
+	}
+    }
+    return %result;
+}
+
+sub writeImage
+{
+    my %dst = @_;
+    my $imagedata = undef;
+    my $realfilename = $dst{'filename'};
+    open(OUT, '>', $realfilename) or die;
+    binmode OUT;
+    if ($dst{'format'} eq 'PNG') {
+	$dst{'image'}->interlaced(undef); # else PFDTEX has to do it.
+	$imagedata = $dst{'image'}->png(9);
+    } elsif ($dst{'format'} eq 'JPEG') {
+	$imagedata = $dst{'image'}->jpeg($jpegquality);
+    }
+    print OUT $imagedata;
+    close(OUT);
+    return 1;
+}
+
+sub GDscale
+{
+    my $srcfilename = shift;
+    my $dstfilename = shift;
+    my $dstwidth = shift;
+    my $dstheight = shift;
+    # my $interpolationmethod = GD_BICUBIC;
+    # Unfortunately not exported by GD and item of an enum.
+    # So I guess:
+    my $interpolationmethod = 4;
+    my %src = loadImage($srcfilename, 0);
+    $src{'destwidth'} = $dstwidth;
+    $src{'destheight'} = $dstheight;
+    $src{'image'}->interpolationMethod($interpolationmethod);
+    # what I will not copy: image, width, height, filename 
+    my @properties = qw ( 
+	canhandle format monochrome
+	);
+    my %dstimage = ();
+    foreach (@properties) {
+	$dstimage{$_} = $src{$_};
+    }
+    $dstimage{'width'} = $src{'destwidth'};
+    $dstimage{'height'} = $src{'destheight'};
+    $dstimage{'filename'} = $dstfilename;
+    $dstimage{'image'} = $src{'image'}->copyScaleInterpolated(
+	$dstimage{'width'}, $dstimage{'height'});
+    writeImage(%dstimage);
+    return 1;
+}
+
 sub handleImage
 {
     my $filename  = shift;
     my $dstwidth  = shift;
     my $dstheight = shift;
-    my ($srcwidth, $srcheight, $srcdepth);
-    my $dstfilename;
-    my $xfilename;
-    my @xsrcdirs;
-    my @dstdirs;
+    my ($srcwidth, $srcheight, $srcdepth, $monochrome, $existwidth);
+    my ($dstfilename, $xfilename);
     my @convertargs;
-    my $idstring;
-    print "$filename\n";
-    $dstdirs[0] = '.';
-    $dstdirs[1] = $printfolderprefix;
-    $dstfilename = File::Spec->catfile(@dstdirs, basename($filename));
-    if($filename eq $dstfilename){
-	unless ($srcfolder gt ' ') {
-	    printInplaceError($filename);
-	    $skipped++;
-	    return;
-	}
-	$xsrcdirs[0] = $srcfolder;
-	$xfilename = File::Spec->catfile(@xsrcdirs, basename($filename));
-	unless (-e $xfilename){
-	    printMissingError($xfilename);
-	    $skipped++;
-	    return;
-	} 
+    my %srcimage = ();
+    my %dstimage = ();
+    print "$filename, " if $verbose;
+    $dstfilename = getDestFilename($filename);
+    $xfilename = getSourceFilename($filename);
+    if (defined($xfilename)) {
 	$filename = $xfilename;
+    } else {
+	printError($filename, 'm');
+	$skipped++;
+	return 0;
     }
+    if($filename eq $dstfilename) {
+	printError($filename, 'i');
+	$skipped++;
+	return 0;
+    }
     # check for image width and height
-    $idstring = `identify -format "%w x %h %[depth] " $filename`;
-    return unless $idstring =~ /(\d+) x (\d+) (\d+)/;
-    $srcwidth = $1; $srcheight = $2; $srcdepth = $3;
-    if($srcdepth == 1) { # hires for bw pix
-	$dstwidth  = int($dstwidth  * $printbwdpi / 72.27 + .5);
-	$dstheight = int($dstheight * $printbwdpi / 72.27 + .5);
+    %srcimage = loadImage($filename);
+    if ($srcimage{'canhandle'} == 0 or ! defined($srcimage{'image'})) {
+	# copy from source to dest.
+	print "I Can't deal with $filename, so I will just\n"
+	    . "copy it to $dstfilename\n" if $verbose;
+	copy($filename, $dstfilename);
+	$copied++;
+	return 1;
+    }
+    $srcwidth = $srcimage{'width'};
+    $srcheight = $srcimage{'height'};
+    $monochrome = $srcimage{'monochrome'};
+    if($monochrome == 1) { # hires for bw pix
+	$dstwidth  = int($dstwidth  * $outputbwdpi / 72.27 + .5);
+	$dstheight = int($dstheight * $outputbwdpi / 72.27 + .5);
     }else {              # moderate res for any other
-	$dstwidth  = int($dstwidth  * $printdpi / 72.27 + .5);
-	$dstheight = int($dstheight * $printdpi / 72.27 + .5);
+	$dstwidth  = int($dstwidth  * $outputdpi / 72.27 + .5);
+	$dstheight = int($dstheight * $outputdpi / 72.27 + .5);
     }
-    if(-e $dstfilename){
-	# if younger and requested size: skip
-	my ($mtime1, $mtime2, $size1, $size2, $idstring2, $existwidth);
-	my ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size,
-	    $atime, $ctime, $blksize, $blocks);
-	($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size,
-	    $atime, $mtime1, $ctime, $blksize, $blocks)
-           = stat($dstfilename);
-	($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size,
-        $atime, $mtime2, $ctime, $blksize, $blocks)
-           = stat($filename);
-	if($mtime1 >= $mtime2){
-	    $idstring2 = `identify -format "%w x %h %[depth] " $dstfilename`;
-	    if($idstring2 =~ /(\d+) x (\d+) (\d+)/){
-		$existwidth = $1; 
-		if($existwidth == $dstwidth){
-		    $processedimages{$filename} = $existwidth;
-		    $skipped++;
-		    return;
-		}
-	    }
+    if(-e $dstfilename and fileYounger($dstfilename, $filename)) {
+	# if requested size already processed: skip
+	if((defined $processedimages{$filename}) && 
+	   ($processedimages{$filename} >= $dstwidth)) {
+	    # if known, already processed and large enough: skip
+	    $skipped++;
+	    return 1;
 	}
+	%dstimage = loadImage($dstfilename);
+	$existwidth = $dstimage{'width'};
+	# if requested size already there: make known and skip
+	if(numberInRange($existwidth, $dstwidth)) {
+	    $processedimages{$filename} = $existwidth;
+	    $skipped++;
+	    return 1;
+	}
     }
-    if(($dstwidth >= $srcwidth) ||
-       ($dstwidth *(100 + $tolerance)/100 >= $srcwidth)) {
+    if (numberInRange($dstwidth, $srcwidth) or $dstwidth > $srcwidth) {
 	# we do no upscaling, but will probably copy the file.
-	if (defined $processedimages{$filename}){
-	    $skipped++;
-	}else {
-	    $processedimages{$filename} = $srcwidth;
-	    print "will copy $filename to $dstfilename\n" if $verbose;
-	    copy($filename, $dstfilename);
-	    $copied++;
-	    return;
-	}	    
+	$processedimages{$filename} = $srcwidth;
+	print "will copy $filename to $dstfilename\n" if $verbose;
+	copy($filename, $dstfilename);
+	$copied++;
+	return 1;
     }else {
-	if((defined $processedimages{$filename}) && 
-	   ($processedimages{$filename} >= $dstwidth)) {
-	    $skipped++;
-	    return;
-	}
-	# we do some downscaling
-	$processedimages{$filename} = $dstwidth;
-	$convertargs[0] = 'convert';
-	$convertargs[1] = ${filename};
-	$convertargs[2] = '-resize';
-#	$convertargs[3] = "${dstwidth}x${dstheight}!";
-	$convertargs[3] = "${dstwidth}x${dstheight}";
-	$convertargs[4] = "-density";
-	$convertargs[5] = $printdpi;
-	$convertargs[6] = ${dstfilename};
-	print "will @convertargs\n"  if $verbose;
-	system(@convertargs);
+	GDscale($xfilename, $dstfilename, $dstwidth, $dstheight);
 	$scaled++;
     }
+    return 1;
 }
 
+sub createOutputFolder
+{
+    my @dstdirs;
+    $dstdirs[0] = '.';
+    my $dstdirname = File::Spec->catfile(@dstdirs, $outputfolderprefix);
+    if (mkdir($dstdirname) == 0) {
+	printError($dstdirname, 'd');
+	return 0;
+    }
+    if ($verbose) {
+	print "Created directory $outputfolderprefix\n";
+    }
+    return 1;
+}
+
 sub readlog
 {
     my $logfilename = shift;
@@ -172,10 +364,18 @@
     $logfilename .= '.log';
     my ($picname, $picext, $picwidth, $picheight);
     my ($picextu, $state, $buffer);
-    open LOGFILE, "<$logfilename" or die "Cannot read $logfilename";
+    open LOGFILE, "<$logfilename" or die "Cannot read $logfilename.\n"
+	. 'Please run pdfLaTeX before pdflatexpicscale.';
     $state = 0;
+    unless (-d $outputfolderprefix) {
+	if (createOutputFolder() == 0) {
+	    close LOGFILE;
+	    return;
+	}
+    }
+    print "Processing " if $verbose;
     while (<LOGFILE>){
-	if (/^Package pdftex\.def\sInfo\:\s/){
+	if (/^Package\spdftex\.def\sInfo\:\s/){
 	    $buffer = $_;
 	    unless ($buffer =~ /\sused/){
 		chomp $buffer;
@@ -185,14 +385,16 @@
 		chomp $buffer;
 		$buffer .= <LOGFILE>;
 	    }
-	    if($buffer =~ /Info:\s(\S*)\.(\w+)\sused/){
+	    if($buffer =~ /Info:\s(\S*)\.(\w+)\s+used/){
 		$picname = $1;
 		$picext = $2;
 		($picextu = $picext) =~ tr/a-z/A-Z/;
 		if(defined $canhandle{$picextu}){
 		    $state = 1;
-		    next;
+		    next;  # width/height information will follow
 		}
+	    } else {
+		print  "Log file apparently damaged at line $.\n";
 	    }
 	}
 	next unless ($state == 1);
@@ -202,34 +404,84 @@
 	handleImage("$picname.$picext", $picwidth, $picheight);
 	$state = 0;
     }
+    close LOGFILE;
 }
 
+sub initializeGlobals
+{
+    my $settinghash = undef;
+    if($draftoption == 1) {
+	$settinghash = \%draftsettings;
+    } elsif ($finaloption == 1) {
+	$settinghash = \%finalsettings;
+    } else {
+	$settinghash = \%customsettings;
+    }
+    if ($verbose != 0) {
+	print 'Using settings: ' . $$settinghash{'name'} . "\n";
+    }
+    unless (defined ($outputdpi)) {
+	$outputdpi = $$settinghash{'outputdpi'} || 300;
+    }
+    unless (defined ($outputbwdpi)) {
+	$outputbwdpi = 4 * $outputdpi;
+    }
+    unless (defined ($outputfolderprefix)) {
+	$outputfolderprefix = $$settinghash{'outputfolder'} || 'printimg';
+    }
+    unless (defined ($jpegquality)) {
+	$jpegquality = $$settinghash{'jpegquality'} || 80;
+    }
+}
+
 sub usage
 {
-    print <<'_endusage';
+    print <<'_endusagehead';
 pdflatexpicscale will downscale large raster images for your TeX project
 to reasonable size. 
 Basic usage:
    pdflatexpicscale myarticle
 where your main LaTeX file is called 'myarticle.tex' and a log file exists.
-Fine tuning:
+General options:
+--help           (show this message)
+--usage          (show this message)
+--verbose        (let the script tell, what it attempts to do)
+--version        (show software version)
+If you are comfortable with defaults (see manual), you may use one of the
+following options:
+_endusagehead
+    my %optiondumper = (
+	'name' => 'Option name',
+	'outputfolder' => 'Output folder',
+	'outputdpi' => 'Output density',
+	'outputbwdpi' => 'same for B/W',
+	'jpegquality' => 'JPEG quality'
+);
+    print <<'_endusagefoot';
+Option name     --final          --draft
+Output folder   finalimg         webimg
+JPEG quality    80%              50%
+output density  300 dpi          96 dpi
+same for B/W    1200 dpi         300 dpi
+tolerance       20%              20%
+If not, you may do some fine tuning:
 --destdir=folder (relative path, must exist, 
                   defaults to 'printimg' subfolder of current folder)
 --srcdir=folder  (folder to find original images, if this software 
                   can't figure it out on it's own, because you already
-                  used the target directory.)
+                  named the target directory inside your LaTex document.)
 --printdpi=XXX   (default 300)
---tolerance=XX   (default 20 Percents over printdpi to ignore scaling)
---verbose        (if you want to know what the script attempts to do)
---version        (show software version)
-_endusage
+--tolerance=XX   (default 20 percent over printdpi to ignore scaling)
+_endusagefoot
 }
 
 GetOptions('verbose'       => \$verbose,
-	   'printdpi=i'    => \$printdpi,
-	   'destdir=s'     => \$printfolderprefix,
+	   'printdpi=i'    => \$outputdpi,
+	   'destdir=s'     => \$outputfolderprefix,
 	   'tolerance=i'   => \$tolerance,
            'srcdir=s'      => \$srcfolder,
+	   'draft'         => \$draftoption,
+	   'final'         => \$finaloption,
            'version'       => \$showversion,
 	   'help'          => \$help,
 	   'usage'         => \$help,
@@ -242,17 +494,23 @@
 
 if($help){
     usage();
+    exit(0);
 }
 
+my $settinghash = \%customsettings;
+
+initializeGlobals();
+
 $TeXproject = shift;
 
 if((defined $TeXproject) && ($TeXproject gt ' ')){
     readlog($TeXproject);
     if($verbose) {
-	print "pdflatexpicscale Version $version:\n"
+	print "\npdflatexpicscale Version $version:\n"
 	    . "$copied file(s) copied, $scaled file(s) converted " .
 	    "and $skipped occurence(s) skipped for:\n${TeXproject}.log.\n";
     }
 }else {    
     usage();
+    exit(1);
 }

Modified: trunk/Master/texmf-dist/doc/support/pdflatexpicscale/README
===================================================================
--- trunk/Master/texmf-dist/doc/support/pdflatexpicscale/README	2024-10-24 23:42:17 UTC (rev 72649)
+++ trunk/Master/texmf-dist/doc/support/pdflatexpicscale/README	2024-10-25 21:26:46 UTC (rev 72650)
@@ -3,11 +3,11 @@
 with PdfLaTeX.
 
 *Version*
-2018-02-12 (version of bundle)
+2024-10-18 (version of bundle)
 For version details check pdflatexpicscale.pdf.
 
 *Requirements*
-Perl and ImageMagick have to be installed.
+Perl and some Perl modules have to be installed - see pdflatexpicscale.pdf.
 
 *Basic usage*
 pdflatex article

Modified: trunk/Master/texmf-dist/doc/support/pdflatexpicscale/pdflatexpicscale.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/support/pdflatexpicscale/pdflatexpicscale.tex
===================================================================
--- trunk/Master/texmf-dist/doc/support/pdflatexpicscale/pdflatexpicscale.tex	2024-10-24 23:42:17 UTC (rev 72649)
+++ trunk/Master/texmf-dist/doc/support/pdflatexpicscale/pdflatexpicscale.tex	2024-10-25 21:26:46 UTC (rev 72650)
@@ -5,7 +5,7 @@
 \usepackage{url}
 \title{pdflatexpicscale}
 \author{Peter Willadt\footnote{willadt at t-online.de}}
-\date{2018-02-12} %version #version
+\date{2024-10-18} %version #version
 \begin{document}
 \maketitle
 
@@ -54,39 +54,50 @@
 
 \subsection{Prerequisites}
 
-You have to install ImageMagick and Perl. If you are using Linux, please use
-the tools of your distribution, if they are not already installed. As a
-windows user, you may probably use the official ImageMagick distribution at
-\url{http://www.imagemagick.org/script/download.php}. For Perl, you got more
-options. I have tested pdflatexpicscale with ActiveState ActivePerl, but other
-distributions should work too.
 
-You also need the following Perl modules:  \texttt{File::Basename}, 
-\texttt{File::Spec}, \texttt{File::Copy}, and \texttt{Getopt::Long}. There are
-several ways to get these modules, if you have not got them already:
+You \label{section:requisites} have to install Perl version~5, if it is not
+installed already. If you are using Linux, I recommend to use the tools of
+your distribution. As a windows user, you may probably use Strawberry Perl.
+You also need the following Perl modules:
+\begin{itemize}
+\item \texttt{GD} (at least version 2.2),
+\item \texttt{Image::ExifTool}, 
+\item \texttt{File::Basename}, 
+\item \texttt{File::Spec},
+\texttt{File::Copy}, and 
+\item \texttt{Getopt::Long}. 
+\end{itemize}
 
+There are no further requirements for the versions of the software to install,
+but it may be wise to use recent releases.
+There are several ways to get these modules, if you have not got them
+already. The most popular are probably:
+
 \begin{itemize}
 \item use your Linux distribution's software manager
 \item use the Perl CPAN module
-\item use ActiveState's \texttt{ppm} software, if you use ActivePerl.
+\item use ActiveState's \texttt{ppm} software, if you happen to use
+  ActivePerl.
 \end{itemize}
 
-Detailled description of these procedures is beyond the scope of this
-document. 
+Detailed description of these procedures is beyond the scope of this
+document.
 
-There are no special requirements for the versions of the software to install,
-but it may be wise to use recent versions, as there have been security flaws
-with ImageMagick. 
+As of 2024, no further external software is needed, in contrast to earlier
+versions. 
 
 \subsection{Installation}
 
-If the prerequisites have been fulfilled (which is perhaps standard for a
-Linux computer), it is sufficient to move the file
-\texttt{pdflatexpicscale.pl} to a place that is included in your PATH and to
-make it executable. Of course, there are alternatives. You may perhaps
-prefer to type\\
+If pdflatexpicscale.pl is part of your \TeX\ distribution,
+chances are good that you only have to install missing Perl modules, if
+any. Otherwise the following should apply:
+
+Having installed Perl and the required modules, it is sufficient to move
+the file \texttt{pdflatexpicscale.pl} to a place that is included in your PATH
+and to make it executable. Of course, there are alternatives. You may perhaps
+prefer to type the following instead:
+
 \texttt{perl /path/to/pdflatexpicscale.pl myarticle}\\
-instead.
 
 \section{Basic usage}
 
@@ -127,7 +138,8 @@
 
 You hopefully do not have distinct pictures with the same name in the listed
 folders. With \verb|\graphicspath| you have to use double braces, even if you
-use only one directory. 
+use only one directory. The best place for the \verb|\graphicspath| statement
+is probably near the beginning of your \LaTeX\ file.
 
 \subsection{Preparing your \LaTeX\ file, Part~2}
 
@@ -172,7 +184,7 @@
 \verb|\graphicspath|, haven't I?  If you still are curious, you can again
 check the size of \texttt{myarticle.pdf}.
 
-When it gets to preparing a print version, you create a directory for images
+When it is time to prepare a print version, you create a directory for images
 with more detail, say \texttt{printpix}. You reset the  \verb|\graphicspath|,
 run Pdf\LaTeX, issue\\
 \texttt{pdflatexpicscale --printdpi=300 --destdir=printpix myarticle}\\
@@ -180,11 +192,10 @@
 
 \section{Advanced usage}
 
-
 \subsection{Excluding files from scaling}
 
 You will probably exclude files from scaling when you think that scaling will
-do damage. You may achieve this by several means. Before you ask. Enumerating
+harm. You may achieve this by several means. Before you ask: Enumerating
 files to exclude is not really cool, so this is not supported.
 
 \begin{enumerate}
@@ -208,6 +219,19 @@
 and after pdflatexpicscale is through, you change it to\\
 \verb|\graphicspath{{hires/}{printimg/}}|
 
+\subsection{Monochrome Images}
+
+While \label{section:monochrome}Pdf\TeX\ supports JBIG2 files,
+pdflatexpicscale does not. Scaling JBIG2 files down looks like a bad idea,
+anyway.
+
+Scaling monochrome\footnote{\emph{Monochrome} in the technical sense of one
+  bit per pixel as opposed to grayscale or color images that use only one
+  color.}  images may lead to bad results. I recommend converting them to
+grayscale before scaling, as blurred details are perhaps better than missing
+details. pdflatexpicsacle will scale B/W images only if their resolution is at
+least two times higher as requested.
+
 \subsection{Gory details}
 
 pdflatexpicscale reads the log file, not the \LaTeX\ source. So you have to
@@ -256,12 +280,16 @@
 is 20, that means 20~percent. If target resolution is 300~dpi, files up to
 320~dpi get accepted too. Change to 0 if you want no tolerance.
 
+\paragraph{draft/final} Setting one of these options will use reasonable
+defaults, if you do not want to use any of the further options.
+Please call \texttt{pdflatexpicscale.pl --help} to see concrete values.
+
 \paragraph{verbose} entertains you by showing what the program is about to
 do. 
 
 \paragraph{version} shows the software version.
 
-Calling pdflatexpicscale without any options and without a project name will
+Calling pdflatexpicscale.pl without any options and without a project name will
 display a short usage text.
 
 \subsection{Printer testing}
@@ -335,5 +363,23 @@
 As the TUGboat article corresponding to pdflatexpicscale is freely available
 now, the link on page~\pageref{tugboatart} has been adjusted.
 
+\paragraph{2024-10-18}
+
+Added section~{section:monochrome} with hints for B/W images to
+documentation. Also did some minor edits, especially to accompany the
+following changes (see section~\ref{section:requisites}). 
+
+As there have been issues with ImagMagick, pdflatexpicscale no longer uses
+external software; Perl's GD and Image::ExifTool modules are used instead. 
+
+Added new shortcut options \texttt{--draft} and \texttt{--final}.
+
+Refactored pdflatexpicscale.pl, hopefully without bad side effects.
+
 % for file version please see line 8
 \end{document}
+
+%%% Local Variables:
+%%% mode: latex
+%%% TeX-master: t
+%%% End:

Modified: trunk/Master/texmf-dist/doc/support/pdflatexpicscale/testprinter.ps
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/scripts/pdflatexpicscale/pdflatexpicscale.pl
===================================================================
--- trunk/Master/texmf-dist/scripts/pdflatexpicscale/pdflatexpicscale.pl	2024-10-24 23:42:17 UTC (rev 72649)
+++ trunk/Master/texmf-dist/scripts/pdflatexpicscale/pdflatexpicscale.pl	2024-10-25 21:26:46 UTC (rev 72650)
@@ -16,37 +16,71 @@
 #            with the documentation, even when the perl code does not change.
 # 2017-02-01 pdflatexpicscale did not work correct when log lines were 
 #            wrapped twice. This is fixed.
+# 2024-10-18 Replaced dependency of external ImageMagick software in favor
+#            of GD library.
 #
 use strict;
+
+use GD;
+use Image::ExifTool;
+
 use File::Basename;
 use File::Spec;
 use File::Copy;
+
 use Getopt::Long;
 
-my $version = '0.32';
-my $versiondate = '2018-02-12';           #version %version
+my $version = '0.50';
+my $versiondate = '2024-10-18';           #version %version
 my $showversion;
 
-my $verbose;
-my $help;
+# command line inouts
+my $verbose = 0;
+my $help = 0;
+my $draftoption = 0;
+my $finaloption = 0;
 my $TeXproject;
 
 # folders for scaled graphics, relative names
-my $printfolderprefix   = 'printimg';
-my $previewfolderprefix = 'previewimg';
-my $srcfolder           = '';
+my $outputfolderprefix = undef;
+my $srcfolder          = '';
 
-# final resolution. special b/w handling not implemented yet
-my $printdpi   = 300;
-my $printbwdpi = 4 * $printdpi;
-my $previewdpi = 72;
-my $tolerance  = 20;
+my %customsettings = (
+    'name' => 'from command line',
+    'outputdpi' => 300,
+    'outputfolder' => 'printimg',
+    'jpegquality' => 80,
+    'outputbwdpi' => 1200
+    );
 
-# file formats
+my %finalsettings = (
+    'name' => 'final',
+    'outputdpi' => 300,
+    'jpegquality' => 80,
+    'outputfolder' => 'finalimg',
+    'outputbwdpi' => 1200
+    );
+
+my %draftsettings = (
+    'name' => 'draft',
+    'outputdpi' => 96,
+    'jpegquality' => 50,
+    'outputfolder' => 'webimg',
+    'outputbwdpi' => 300
+    );
+
+my $outputdpi   = undef;     # final resolution. 
+my $outputbwdpi = undef;      # final resolution for pure b/w art
+my $tolerance  = 20;         # avoid resampling of almost fitting images
+my $jpegquality = undef;     # 50 is mostly acceptable, 80 is fine.
+
+# supported file formats (by extension)
 my %canhandle =
-( JPG => '1',
-  PNG => '1',
-);
+    (
+    'JPEG' => '1',
+     'JPG' => '1',
+     'PNG' => '1',
+    );
 
 # bookkeeping
 my %processedimages;
@@ -54,118 +88,276 @@
 my $scaled  = 0;
 my $skipped = 0;
 
-sub printInplaceError
+# the following is required by Image::ExifTool
+our $AUTOLOAD;
+sub AUTOLOAD
 {
+    Image::ExifTool::DoAutoLoad($AUTOLOAD, @_);
+}
+
+sub printError
+{
     my $filename = shift;
-    print "I will not do inplace modification of graphics:\n" .
-	"($filename) will not be processed. (Missing path?)\n";
+    my $kind = shift;
+    if ($kind eq 'i') {
+	print "I will not do inplace modification of graphics:\n" .
+	    "($filename) will not be processed. (Missing path?)\n";
+    } elsif ($kind eq 'm') {
+	print "I can't find ($filename). (What have you done?)\n";
+    } elsif ($kind eq 'f') {
+	print "File $filename has an unexpected or wrong format.\n";
+    } elsif ($kind eq 's') {
+	print "Trying to copy '$filename' leads to system error # $_.\n";
+    } elsif ($kind eq 'd') {
+	print "Directory '$filename' does not exist\n"
+	    . "in actual folder and I can't create it (sys error # $_).\n"
+	    . "Please check permissions. Aborting.\n";
+    } else {
+	print "I got trouble with '$filename'.\n";
+    }
 }
 
-sub printMissingError
+sub getDestFilename
 {
+    my @dstdirs;
     my $filename = shift;
-    print "I can not find ($filename). (What have you done?)\n";
+    my $dstfilename = undef;;
+    $dstdirs[0] = '.';
+    $dstdirs[1] = $outputfolderprefix;
+    $dstfilename = File::Spec->catfile(@dstdirs, basename($filename));
+    return $dstfilename;
 }
 
+sub getSourceFilename
+{
+    my @srcdirs;
+    my $filename = shift;
+    my $srcfilename = undef;
+    if (defined($srcfolder) and $srcfolder gt '') {
+	$srcdirs[0] = '$srcfolder';
+	$srcfilename = File::Spec->catfile(@srcdirs, basename($filename));
+	$filename = $srcfilename;
+    }
+    unless (-e $filename){
+	printError($filename, 'm');
+	return undef;
+    }
+    return $filename;
+}
+
+sub fileYounger
+{
+    my @filename = @_;
+    my ($mtime1, $mtime2, $size1, $size2, $idstring2, $existwidth);
+    my ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size,
+	$atime, $ctime, $blksize, $blocks);
+    ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size,
+     $atime, $mtime1, $ctime, $blksize, $blocks)
+	= stat($filename[0]);
+    ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size,
+     $atime, $mtime2, $ctime, $blksize, $blocks)
+	= stat($filename[1]);
+    if($mtime1 >= $mtime2) {
+	return 1;
+    }
+    return 0;
+    
+}
+
+sub numberInRange
+{
+    my $realwidth = shift;
+    my $wantedwidth = shift;
+    if (($realwidth >= $wantedwidth * 100 / (100 + $tolerance)) and
+	($realwidth <= $wantedwidth * (100 + $tolerance) / 100)) {
+	return 1;
+    } else {
+	return 0;
+    }
+}
+
+sub loadImage
+{
+    my %result = (
+	'filename' => undef,
+	'image' => undef, 'canhandle' => 0,
+	'format' => undef, 'width' => 0,
+	'height' => 0, 'monochrome' => 0,
+	'quality' => 50
+    );
+    $result{'filename'} = shift;
+    my $maketruecolor = shift || 0;
+    my $exifTool = Image::ExifTool->new;
+    my $imageinfo = $exifTool->ImageInfo($result{'filename'});
+#    foreach (sort keys %$imageinfo) {
+#	print "$_ => $$imageinfo{$_}\n";
+#    }
+    $result{'image'} = GD::Image->new($result{'filename'});
+    $result{'width'} = $$imageinfo{'ImageWidth'};
+    $result{'height'} = $$imageinfo{'ImageHeight'};
+    if ( ($$imageinfo{'FileType'} eq 'PNG') or
+	 ($$imageinfo{'FileType'} eq 'JPEG')) {
+	$result{'format'} = $$imageinfo{'FileType'};
+	$result{'canhandle'} = 1;
+    }
+    if (defined($$imageinfo{'BitDepth'}) and $$imageinfo{'BitDepth'} == 1) {
+	$result{'monochrome'} = 1;
+    } elsif (defined($result{'image'})) {
+	$result{'canhandle'} = 1;
+	if (defined ($result{'image'}->colorsTotal) and
+	    $result{'image'}->colorsTotal < 3) {
+	    $result{'monochrome'} = 1;
+	}
+	unless (defined($result{'width'})) {
+	    $result{'width'} = $result{'image'}->width;
+	}
+	unless (defined($result{'height'})) {
+	    $result{'height'} = $result{'image'}->height;
+	}
+    }
+    return %result;
+}
+
+sub writeImage
+{
+    my %dst = @_;
+    my $imagedata = undef;
+    my $realfilename = $dst{'filename'};
+    open(OUT, '>', $realfilename) or die;
+    binmode OUT;
+    if ($dst{'format'} eq 'PNG') {
+	$dst{'image'}->interlaced(undef); # else PFDTEX has to do it.
+	$imagedata = $dst{'image'}->png(9);
+    } elsif ($dst{'format'} eq 'JPEG') {
+	$imagedata = $dst{'image'}->jpeg($jpegquality);
+    }
+    print OUT $imagedata;
+    close(OUT);
+    return 1;
+}
+
+sub GDscale
+{
+    my $srcfilename = shift;
+    my $dstfilename = shift;
+    my $dstwidth = shift;
+    my $dstheight = shift;
+    # my $interpolationmethod = GD_BICUBIC;
+    # Unfortunately not exported by GD and item of an enum.
+    # So I guess:
+    my $interpolationmethod = 4;
+    my %src = loadImage($srcfilename, 0);
+    $src{'destwidth'} = $dstwidth;
+    $src{'destheight'} = $dstheight;
+    $src{'image'}->interpolationMethod($interpolationmethod);
+    # what I will not copy: image, width, height, filename 
+    my @properties = qw ( 
+	canhandle format monochrome
+	);
+    my %dstimage = ();
+    foreach (@properties) {
+	$dstimage{$_} = $src{$_};
+    }
+    $dstimage{'width'} = $src{'destwidth'};
+    $dstimage{'height'} = $src{'destheight'};
+    $dstimage{'filename'} = $dstfilename;
+    $dstimage{'image'} = $src{'image'}->copyScaleInterpolated(
+	$dstimage{'width'}, $dstimage{'height'});
+    writeImage(%dstimage);
+    return 1;
+}
+
 sub handleImage
 {
     my $filename  = shift;
     my $dstwidth  = shift;
     my $dstheight = shift;
-    my ($srcwidth, $srcheight, $srcdepth);
-    my $dstfilename;
-    my $xfilename;
-    my @xsrcdirs;
-    my @dstdirs;
+    my ($srcwidth, $srcheight, $srcdepth, $monochrome, $existwidth);
+    my ($dstfilename, $xfilename);
     my @convertargs;
-    my $idstring;
-    print "$filename\n";
-    $dstdirs[0] = '.';
-    $dstdirs[1] = $printfolderprefix;
-    $dstfilename = File::Spec->catfile(@dstdirs, basename($filename));
-    if($filename eq $dstfilename){
-	unless ($srcfolder gt ' ') {
-	    printInplaceError($filename);
-	    $skipped++;
-	    return;
-	}
-	$xsrcdirs[0] = $srcfolder;
-	$xfilename = File::Spec->catfile(@xsrcdirs, basename($filename));
-	unless (-e $xfilename){
-	    printMissingError($xfilename);
-	    $skipped++;
-	    return;
-	} 
+    my %srcimage = ();
+    my %dstimage = ();
+    print "$filename, " if $verbose;
+    $dstfilename = getDestFilename($filename);
+    $xfilename = getSourceFilename($filename);
+    if (defined($xfilename)) {
 	$filename = $xfilename;
+    } else {
+	printError($filename, 'm');
+	$skipped++;
+	return 0;
     }
+    if($filename eq $dstfilename) {
+	printError($filename, 'i');
+	$skipped++;
+	return 0;
+    }
     # check for image width and height
-    $idstring = `identify -format "%w x %h %[depth] " $filename`;
-    return unless $idstring =~ /(\d+) x (\d+) (\d+)/;
-    $srcwidth = $1; $srcheight = $2; $srcdepth = $3;
-    if($srcdepth == 1) { # hires for bw pix
-	$dstwidth  = int($dstwidth  * $printbwdpi / 72.27 + .5);
-	$dstheight = int($dstheight * $printbwdpi / 72.27 + .5);
+    %srcimage = loadImage($filename);
+    if ($srcimage{'canhandle'} == 0 or ! defined($srcimage{'image'})) {
+	# copy from source to dest.
+	print "I Can't deal with $filename, so I will just\n"
+	    . "copy it to $dstfilename\n" if $verbose;
+	copy($filename, $dstfilename);
+	$copied++;
+	return 1;
+    }
+    $srcwidth = $srcimage{'width'};
+    $srcheight = $srcimage{'height'};
+    $monochrome = $srcimage{'monochrome'};
+    if($monochrome == 1) { # hires for bw pix
+	$dstwidth  = int($dstwidth  * $outputbwdpi / 72.27 + .5);
+	$dstheight = int($dstheight * $outputbwdpi / 72.27 + .5);
     }else {              # moderate res for any other
-	$dstwidth  = int($dstwidth  * $printdpi / 72.27 + .5);
-	$dstheight = int($dstheight * $printdpi / 72.27 + .5);
+	$dstwidth  = int($dstwidth  * $outputdpi / 72.27 + .5);
+	$dstheight = int($dstheight * $outputdpi / 72.27 + .5);
     }
-    if(-e $dstfilename){
-	# if younger and requested size: skip
-	my ($mtime1, $mtime2, $size1, $size2, $idstring2, $existwidth);
-	my ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size,
-	    $atime, $ctime, $blksize, $blocks);
-	($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size,
-	    $atime, $mtime1, $ctime, $blksize, $blocks)
-           = stat($dstfilename);
-	($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size,
-        $atime, $mtime2, $ctime, $blksize, $blocks)
-           = stat($filename);
-	if($mtime1 >= $mtime2){
-	    $idstring2 = `identify -format "%w x %h %[depth] " $dstfilename`;
-	    if($idstring2 =~ /(\d+) x (\d+) (\d+)/){
-		$existwidth = $1; 
-		if($existwidth == $dstwidth){
-		    $processedimages{$filename} = $existwidth;
-		    $skipped++;
-		    return;
-		}
-	    }
+    if(-e $dstfilename and fileYounger($dstfilename, $filename)) {
+	# if requested size already processed: skip
+	if((defined $processedimages{$filename}) && 
+	   ($processedimages{$filename} >= $dstwidth)) {
+	    # if known, already processed and large enough: skip
+	    $skipped++;
+	    return 1;
 	}
+	%dstimage = loadImage($dstfilename);
+	$existwidth = $dstimage{'width'};
+	# if requested size already there: make known and skip
+	if(numberInRange($existwidth, $dstwidth)) {
+	    $processedimages{$filename} = $existwidth;
+	    $skipped++;
+	    return 1;
+	}
     }
-    if(($dstwidth >= $srcwidth) ||
-       ($dstwidth *(100 + $tolerance)/100 >= $srcwidth)) {
+    if (numberInRange($dstwidth, $srcwidth) or $dstwidth > $srcwidth) {
 	# we do no upscaling, but will probably copy the file.
-	if (defined $processedimages{$filename}){
-	    $skipped++;
-	}else {
-	    $processedimages{$filename} = $srcwidth;
-	    print "will copy $filename to $dstfilename\n" if $verbose;
-	    copy($filename, $dstfilename);
-	    $copied++;
-	    return;
-	}	    
+	$processedimages{$filename} = $srcwidth;
+	print "will copy $filename to $dstfilename\n" if $verbose;
+	copy($filename, $dstfilename);
+	$copied++;
+	return 1;
     }else {
-	if((defined $processedimages{$filename}) && 
-	   ($processedimages{$filename} >= $dstwidth)) {
-	    $skipped++;
-	    return;
-	}
-	# we do some downscaling
-	$processedimages{$filename} = $dstwidth;
-	$convertargs[0] = 'convert';
-	$convertargs[1] = ${filename};
-	$convertargs[2] = '-resize';
-#	$convertargs[3] = "${dstwidth}x${dstheight}!";
-	$convertargs[3] = "${dstwidth}x${dstheight}";
-	$convertargs[4] = "-density";
-	$convertargs[5] = $printdpi;
-	$convertargs[6] = ${dstfilename};
-	print "will @convertargs\n"  if $verbose;
-	system(@convertargs);
+	GDscale($xfilename, $dstfilename, $dstwidth, $dstheight);
 	$scaled++;
     }
+    return 1;
 }
 
+sub createOutputFolder
+{
+    my @dstdirs;
+    $dstdirs[0] = '.';
+    my $dstdirname = File::Spec->catfile(@dstdirs, $outputfolderprefix);
+    if (mkdir($dstdirname) == 0) {
+	printError($dstdirname, 'd');
+	return 0;
+    }
+    if ($verbose) {
+	print "Created directory $outputfolderprefix\n";
+    }
+    return 1;
+}
+
 sub readlog
 {
     my $logfilename = shift;
@@ -172,10 +364,18 @@
     $logfilename .= '.log';
     my ($picname, $picext, $picwidth, $picheight);
     my ($picextu, $state, $buffer);
-    open LOGFILE, "<$logfilename" or die "Cannot read $logfilename";
+    open LOGFILE, "<$logfilename" or die "Cannot read $logfilename.\n"
+	. 'Please run pdfLaTeX before pdflatexpicscale.';
     $state = 0;
+    unless (-d $outputfolderprefix) {
+	if (createOutputFolder() == 0) {
+	    close LOGFILE;
+	    return;
+	}
+    }
+    print "Processing " if $verbose;
     while (<LOGFILE>){
-	if (/^Package pdftex\.def\sInfo\:\s/){
+	if (/^Package\spdftex\.def\sInfo\:\s/){
 	    $buffer = $_;
 	    unless ($buffer =~ /\sused/){
 		chomp $buffer;
@@ -185,14 +385,16 @@
 		chomp $buffer;
 		$buffer .= <LOGFILE>;
 	    }
-	    if($buffer =~ /Info:\s(\S*)\.(\w+)\sused/){
+	    if($buffer =~ /Info:\s(\S*)\.(\w+)\s+used/){
 		$picname = $1;
 		$picext = $2;
 		($picextu = $picext) =~ tr/a-z/A-Z/;
 		if(defined $canhandle{$picextu}){
 		    $state = 1;
-		    next;
+		    next;  # width/height information will follow
 		}
+	    } else {
+		print  "Log file apparently damaged at line $.\n";
 	    }
 	}
 	next unless ($state == 1);
@@ -202,34 +404,84 @@
 	handleImage("$picname.$picext", $picwidth, $picheight);
 	$state = 0;
     }
+    close LOGFILE;
 }
 
+sub initializeGlobals
+{
+    my $settinghash = undef;
+    if($draftoption == 1) {
+	$settinghash = \%draftsettings;
+    } elsif ($finaloption == 1) {
+	$settinghash = \%finalsettings;
+    } else {
+	$settinghash = \%customsettings;
+    }
+    if ($verbose != 0) {
+	print 'Using settings: ' . $$settinghash{'name'} . "\n";
+    }
+    unless (defined ($outputdpi)) {
+	$outputdpi = $$settinghash{'outputdpi'} || 300;
+    }
+    unless (defined ($outputbwdpi)) {
+	$outputbwdpi = 4 * $outputdpi;
+    }
+    unless (defined ($outputfolderprefix)) {
+	$outputfolderprefix = $$settinghash{'outputfolder'} || 'printimg';
+    }
+    unless (defined ($jpegquality)) {
+	$jpegquality = $$settinghash{'jpegquality'} || 80;
+    }
+}
+
 sub usage
 {
-    print <<'_endusage';
+    print <<'_endusagehead';
 pdflatexpicscale will downscale large raster images for your TeX project
 to reasonable size. 
 Basic usage:
    pdflatexpicscale myarticle
 where your main LaTeX file is called 'myarticle.tex' and a log file exists.
-Fine tuning:
+General options:
+--help           (show this message)
+--usage          (show this message)
+--verbose        (let the script tell, what it attempts to do)
+--version        (show software version)
+If you are comfortable with defaults (see manual), you may use one of the
+following options:
+_endusagehead
+    my %optiondumper = (
+	'name' => 'Option name',
+	'outputfolder' => 'Output folder',
+	'outputdpi' => 'Output density',
+	'outputbwdpi' => 'same for B/W',
+	'jpegquality' => 'JPEG quality'
+);
+    print <<'_endusagefoot';
+Option name     --final          --draft
+Output folder   finalimg         webimg
+JPEG quality    80%              50%
+output density  300 dpi          96 dpi
+same for B/W    1200 dpi         300 dpi
+tolerance       20%              20%
+If not, you may do some fine tuning:
 --destdir=folder (relative path, must exist, 
                   defaults to 'printimg' subfolder of current folder)
 --srcdir=folder  (folder to find original images, if this software 
                   can't figure it out on it's own, because you already
-                  used the target directory.)
+                  named the target directory inside your LaTex document.)
 --printdpi=XXX   (default 300)
---tolerance=XX   (default 20 Percents over printdpi to ignore scaling)
---verbose        (if you want to know what the script attempts to do)
---version        (show software version)
-_endusage
+--tolerance=XX   (default 20 percent over printdpi to ignore scaling)
+_endusagefoot
 }
 
 GetOptions('verbose'       => \$verbose,
-	   'printdpi=i'    => \$printdpi,
-	   'destdir=s'     => \$printfolderprefix,
+	   'printdpi=i'    => \$outputdpi,
+	   'destdir=s'     => \$outputfolderprefix,
 	   'tolerance=i'   => \$tolerance,
            'srcdir=s'      => \$srcfolder,
+	   'draft'         => \$draftoption,
+	   'final'         => \$finaloption,
            'version'       => \$showversion,
 	   'help'          => \$help,
 	   'usage'         => \$help,
@@ -242,17 +494,23 @@
 
 if($help){
     usage();
+    exit(0);
 }
 
+my $settinghash = \%customsettings;
+
+initializeGlobals();
+
 $TeXproject = shift;
 
 if((defined $TeXproject) && ($TeXproject gt ' ')){
     readlog($TeXproject);
     if($verbose) {
-	print "pdflatexpicscale Version $version:\n"
+	print "\npdflatexpicscale Version $version:\n"
 	    . "$copied file(s) copied, $scaled file(s) converted " .
 	    "and $skipped occurence(s) skipped for:\n${TeXproject}.log.\n";
     }
 }else {    
     usage();
+    exit(1);
 }



More information about the tex-live-commits mailing list.