about summary refs log tree commit diff
diff options
context:
space:
mode:
authorgiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2012-03-05 18:41:00 +0000
committergiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2012-03-05 18:41:00 +0000
commite5b924834c637e855c10eef3ce96f805b2949bad (patch)
tree4f39b705d990f4bfd1d66284715886d0e8e1aab0
parent2ae05f39e93bed9b39474bedf8ed97873ca7d746 (diff)
downloadnetpbm-mirror-e5b924834c637e855c10eef3ce96f805b2949bad.tar.gz
netpbm-mirror-e5b924834c637e855c10eef3ce96f805b2949bad.tar.xz
netpbm-mirror-e5b924834c637e855c10eef3ce96f805b2949bad.zip
Replace Bash Ppmquantall with Perl Pnmquantall
git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@1660 9d0c8265-081b-0410-96cb-a4ca84ce46f8
-rw-r--r--doc/HISTORY3
-rw-r--r--doc/USERDOC27
-rw-r--r--editor/Makefile8
-rwxr-xr-xeditor/pnmquantall184
-rwxr-xr-xeditor/ppmquantall96
-rw-r--r--editor/ppmquantall.csh57
6 files changed, 208 insertions, 167 deletions
diff --git a/doc/HISTORY b/doc/HISTORY
index 5db0ff29..c9d8d8fa 100644
--- a/doc/HISTORY
+++ b/doc/HISTORY
@@ -20,6 +20,9 @@ not yet  BJH  Release 10.58.00
               pm_make_tmpfile_fd: fix improper handling when unable to get
               memory to construct file name.
 
+              ppmquantall: replace with pnmquantall and change from Bash
+              to Perl.
+
               Windows/Mingw: fix bug: temporary file creation fails
               consistently.  Broken in 10.34.
 
diff --git a/doc/USERDOC b/doc/USERDOC
index 575f123d..e1589689 100644
--- a/doc/USERDOC
+++ b/doc/USERDOC
@@ -18,16 +18,12 @@ so you can use the current manual with old Netpbm code.
 INSTALLING A LOCAL COPY OF DOCUMENTATION
 ----------------------------------------
 
-If accessing the manual on the World Wide Web is not convenient for
-you (for example, if you want to access it from a computer that is not
-always connected to the Internet), just make a local copy of the web
-site files.  An obvious way to do that is just to copy the web site
-with GNU Wget:
+If accessing the manual on the World Wide Web is not convenient for you (for
+example, if you want to access it from a computer that is not always connected
+to the Internet), just make a local copy of the HTML files.
 
-  wget --recursive --relative http://netpbm.sourceforge.net/doc/
-
-However, a somewhat cleaner way is to get the files from the
-Subversion repository using the Subversion client program 'svn':
+You can get the files from the Subversion repository using the Subversion
+client program 'svn':
 
   URL=https://netpbm.svn.sourceforge.net/svnroot/netpbm/userguide
   svn export $URL
@@ -35,13 +31,20 @@ Subversion repository using the Subversion client program 'svn':
 This creates a directory "userguide" in your current directory containing
 all the same files that are on the web site.
 
-And a sometimes more convenient way to get those files from the
-Subversion repository is to get Sourceforge's Viewvc service to make a
-tarball of them:
+And a sometimes more convenient way to get those files from the Subversion
+repository is to get Sourceforge's Viewvc service to make a tarball of them:
 
   wget http://netpbm.svn.sourceforge.net/viewvc/netpbm/userguide.tar.gz?view=tar --output-document=/tmp/userguide.tgz
 
 
+An apparent alternative is just to copy the web site with something like GNU
+Wget.  However, the Sourceforge web server has limitations on how much you can
+download.  In a February 2012 experiment, Sourceforge started refusing HTTP
+requests (with an Internal Server Error indication and a message saying there
+had been too many requests) before all the files could be fetched.
+
+
+
 GETTING COMMAND HELP WITH A "MAN" COMMAND
 -----------------------------------------
 
diff --git a/editor/Makefile b/editor/Makefile
index b3d0e6b9..ec9305aa 100644
--- a/editor/Makefile
+++ b/editor/Makefile
@@ -44,8 +44,8 @@ NOMERGEBINARIES =
 MERGEBINARIES = $(PORTBINARIES)
 
 BINARIES = $(MERGEBINARIES) $(NOMERGEBINARIES)
-SCRIPTS = pnmflip ppmfade ppmquant ppmquantall ppmshadow \
-	  pamstretch-gen pnmmargin pnmquant 
+SCRIPTS = pnmflip ppmfade ppmquant ppmshadow \
+	  pamstretch-gen pnmmargin pnmquant pnmquantall 
 
 OBJECTS = $(BINARIES:%=%.o)
 
@@ -90,3 +90,7 @@ install.bin.local: $(PKGDIR)/bin
 	cd $(PKGDIR)/bin ; \
 	rm -f pnmscale ; \
 	$(SYMLINK) pamscale$(EXE) pnmscale
+# In March 2012, pnmquantall replaced ppmquantall
+	cd $(PKGDIR)/bin ; \
+	rm -f ppmquantall ; \
+	$(SYMLINK) pnmquantall$(EXE) ppmquantall
diff --git a/editor/pnmquantall b/editor/pnmquantall
new file mode 100755
index 00000000..b7bb03d7
--- /dev/null
+++ b/editor/pnmquantall
@@ -0,0 +1,184 @@
+#!/usr/bin/perl
+##############################################################################
+#                                  pnmquantall  
+##############################################################################
+#
+# HISTORY:
+#
+# This was in the original 1989 Pbmplus as a C shell program.  In Netpbm 9.13
+# (April 2001), it was converted to Bash.  (Actually, it was thought to be
+# Bourne shell, but it used arrays).  In Netpbm 10.58 (March 2012), it was
+# converted to Perl for better portability.
+#
+# The 2012 Perl conversion also changed the name from Ppmquantall to
+# Pnmquantall.  It had already handled non-PPM input files for many years.
+#
+# The original program was more complex:  Because in those days Pnmcolormap
+# and Pnmremap did not exist, Ppmquantall concatenated all the input images
+# together and ran Ppmquant (later Pnmquant) on the combination.  It then
+# split the combination image apart to make one output image per input image.
+# Today, Pnmquant is just a combination of Pnmcolormap and Pnmremap, and
+# we are able to use them better separately in Ppmquantall: We still make
+# the combination image, but use it only to compute the colormap with
+# Pnmcolormap.  We then apply that colormap separately to each input image
+# to produce an output image.
+#
+# Bryan Henderson wrote the current version from scratch in March 2012
+# and contributed it to the public domain.
+#
+##############################################################################
+
+use strict;
+use warnings;
+use English;
+use Fcntl;  # gets open flags
+
+my $TRUE=1; my $FALSE = 0;
+
+
+
+sub parseArgs($$$$) {
+    my ($argvR, $extR, $newColorCtR, $fileNamesR) = @_;
+
+    my @argv = @{$argvR};
+
+    my $firstArgPos;
+
+    if (@argv > 0 && $argv[0] eq "-ext") {
+        if (@argv < 2) {
+            print STDERR ("-ext requires a value\n");
+        exit(100);
+        } else {
+            $$extR = $argv[1];
+            $firstArgPos = 2;
+        }
+    } else {
+        $$extR = "";
+        $firstArgPos = 0;
+    }
+
+    if (@argv < $firstArgPos + 2) {
+        print STDERR ("Not enough arguments.  You need at least the number " .
+                      "of colors and one file name\n");
+        exit(100);
+    }
+    
+    $$newColorCtR = $argv[$firstArgPos];
+
+    @{$fileNamesR} = @argv[$firstArgPos + 1 .. @argv-1];
+}
+
+
+
+sub tempFile($) {
+
+    # We trust Perl's File::Temp to do a better job of creating the temp
+    # file, but it doesn't exist before Perl 5.6.1.
+
+    if (eval { require File::Temp; 1 }) {
+        return File::Temp::tempfile("pnmquant_XXXX", 
+                                    SUFFIX=>".pnm", 
+                                    DIR=>File::Spec->tmpdir(),
+                                    UNLINK=>$TRUE);
+    } else {
+        my ($suffix) = @_;
+        my $fileName;
+        local *file;  # For some inexplicable reason, must be local, not my
+        my $i;
+        $i = 0;
+        do {
+            $fileName = File::Spec->tmpdir() . "/pnmquant_" . $i++ . $suffix;
+        } until sysopen(*file, $fileName, O_RDWR|O_CREAT|O_EXCL);
+
+        return(*file, $fileName);
+    }
+}
+
+
+
+sub makeColorMap($$$$) {
+    my ($fileNamesR, $newColorCt, $colorMapFileName, $errorR) = @_;
+
+    my $pnmcatCmd = "pnmcat -topbottom -white -jleft @{$fileNamesR}";
+
+    my $pnmcolormapCmd = "pnmcolormap $newColorCt";
+
+    my $makeMapCmd = "$pnmcatCmd | $pnmcolormapCmd >$colorMapFileName";
+
+    my $termStatus = system($makeMapCmd);
+
+    if ($termStatus != 0) {
+        $$errorR =
+            "Shell command to create the color map failed:  '$makeMapCmd'.";
+    }
+}
+
+
+ 
+sub remapFiles($$$$) {
+    my ($fileNamesR, $colorMapFileName, $ext, $errorR) = @_;
+
+    my ($outputFh, $outputFileName) = tempFile("pnm");
+    if (!defined($outputFh)) {
+        $$errorR = "Unable to create temporary file.  Errno=$ERRNO";
+    } else {
+        for (my $i = 0; $i < @{$fileNamesR} && !$$errorR; ++$i) {
+            my $inFileName = $fileNamesR->[$i];
+
+            my $pnmremapCmd =
+                "pnmremap '$inFileName' -mapfile=$colorMapFileName " .
+                ">$outputFileName";
+
+            my $pnmremapTermStatus = system($pnmremapCmd);
+
+            if ($pnmremapTermStatus != 0) {
+                $errorR =
+                    "Shell command to quantize '$inFileName'  failed:  " .
+                    "'$pnmremapCmd'";
+            } else {
+                my $newFileName = $inFileName . $ext;
+
+                unlink($newFileName);
+                rename($outputFileName, $newFileName)
+                    or $errorR = "Rename to '$newFileName' failed.";
+            }
+        }
+        unlink($outputFileName);  # In case something failed
+    }
+}
+
+
+
+###############################################################################
+#                             MAINLINE
+###############################################################################
+
+my $progError;
+
+parseArgs(\@ARGV, \my $ext, \my $newColorCt, \my @fileNames);
+
+my ($colorMapFh, $colorMapFileName) = tempFile("pnm");
+if (!defined($colorMapFh)) {
+    $progError = "Unable to create temporary file.  Errno=$ERRNO";
+}
+
+if (!$progError) {
+    makeColorMap(\@fileNames, $newColorCt, $colorMapFileName, \$progError);
+}
+print ("got color map\n");
+if (!$progError) {
+    remapFiles(\@fileNames, $colorMapFileName, $ext, \$progError);
+}
+
+my $exitStatus;
+
+if ($progError) {
+    print STDERR ("Failed.  $progError\n");
+    $exitStatus = 1;
+} else {
+    $exitStatus = 0;
+}
+
+unlink($colorMapFileName);
+
+exit($exitStatus);
diff --git a/editor/ppmquantall b/editor/ppmquantall
deleted file mode 100755
index 4807de8c..00000000
--- a/editor/ppmquantall
+++ /dev/null
@@ -1,96 +0,0 @@
-#!/bin/sh
-#
-# ppmquantall - run ppmquant on a bunch of files all at once, so they share
-#               a common colormap
-#
-# WARNING: overwrites the source files with the results!!!
-#
-# Verbose explanation: Let's say you've got a dozen pixmaps that you want
-# to display on the screen all at the same time.  Your screen can only
-# display 256 different colors, but the pixmaps have a total of a thousand
-# or so different colors.  For a single pixmap you solve this problem with
-# pnmquant; this script solves it for multiple pixmaps.  All it does is
-# concatenate them together into one big pixmap, run pnmquant on that, and
-# then split it up into little pixmaps again.
-#
-# IMPLEMENTATION NOTE:  Now that Pnmcolormap can compute a single colormap
-# for a whole stream of images, this program could be implemented more
-# simply.  Today, it concatenates a bunch of images into one image, uses
-# Pnmquant to quantize that, then splits the result back into multiple
-# images.  It could instead just run Pnmcolormap over all the images,
-# then run Pnmremap on each input image using the one colormap for all.
-
-usage()
-{
-    echo "usage: $0 [-ext extension] <newcolors> <ppmfile> ..."
-    exit 1
-}
-
-ext=
-
-while :; do
-
-    case "$1" in
-    -ext*)
-        if [ $# -lt 2 ]; then
-            usage
-        fi
-        ext=".$2"
-        shift
-        shift
-    ;;
-
-    *)  
-        break
-    ;;
-
-    esac
-done
-
-if [ $# -lt 2 ]; then
-    usage
-fi
-
-newcolors=$1
-shift
-nfiles=$#
-files=($@)
-
-# Extract the width and height of each of the images.
-# Here, we make the assumption that the width and height are on the
-# second line, even though the PPM format doesn't require that.
-# To be robust, we need to use Pnmfile to get that information, or 
-# Put this program in C and use ppm_readppminit().
-
-widths=()
-heights=()
-
-for i in ${files[@]}; do
-    widths=(${widths[*]} `grep -v '^#' $i | sed '1d; s/ .*//; 2q'`)
-    heights=(${heights[*]} `grep -v '^#' $i | sed '1d; s/.* //; 2q'`)
-done
-
-tempdir="${TMPDIR-/tmp}/ppmquantall.$$"
-mkdir -m 0700 $tempdir || \
-  { echo "Could not create temporary file. Exiting."; exit 1;}
-trap 'rm -rf $tempdir' 0 1 3 15
-
-all=$tempdir/pqa.all.$$
-
-pnmcat -topbottom -jleft -white ${files[@]} | pnmquant $newcolors > $all
-if [ $? != 0 ]; then
-    exit $?
-fi
-
-y=0
-i=0
-
-while [ $i -lt $nfiles ]; do
-    pamcut -left 0 -top $y -width ${widths[$i]} -height ${heights[$i]} $all \
-        > ${files[$i]}$ext
-    if [ $? != 0 ]; then
-        exit $?
-    fi
-    y=$(($y + ${heights[$i]}))
-    i=$(($i + 1))
-done
diff --git a/editor/ppmquantall.csh b/editor/ppmquantall.csh
deleted file mode 100644
index 9a89bca0..00000000
--- a/editor/ppmquantall.csh
+++ /dev/null
@@ -1,57 +0,0 @@
-#!/bin/csh -f
-#
-# ppmquantall - run ppmquant on a bunch of files all at once, so they share
-#               a common colormap
-#
-# WARNING: overwrites the source files with the results!!!
-#
-# Verbose explanation: Let's say you've got a dozen pixmaps that you want
-# to display on the screen all at the same time.  Your screen can only
-# display 256 different colors, but the pixmaps have a total of a thousand
-# or so different colors.  For a single pixmap you solve this problem with
-# ppmquant; this script solves it for multiple pixmaps.  All it does is
-# concatenate them together into one big pixmap, run ppmquant on that, and
-# then split it up into little pixmaps again.
-
-if ( $#argv < 3 ) then
-    echo "usage:  ppmquantall <newcolors> <ppmfile> <ppmfile> ..."
-    exit 1
-endif
-
-set newcolors=$argv[1]
-set files=( $argv[2-] )
-
-# Extract the width and height of each of the images.
-# Here, we make the assumption that the width and height are on the
-# second line, even though the PPM format doesn't require that.
-# To be robust, we need to use Pnmfile to get that information, or 
-# Put this program in C and use ppm_readppminit().
-
-set widths=()
-set heights=()
-foreach i ( $files )
-    set widths=( $widths `sed '1d; s/ .*//; 2q' $i` )
-    set heights=( $heights `sed '1d; s/.* //; 2q' $i` )
-end
-
-set all=/tmp/pqa.all.$$
-rm -f $all
-pnmcat -topbottom -jleft -white $files | ppmquant -quiet $newcolors > $all
-if ( $status != 0 ) exit $status
-
-@ y = 0
-@ i = 1
-while ( $i <= $#files )
-    pnmcut -left 0 -top $y -width $widths[$i] -height $heights[$i] $all \
-       > $files[$i]
-    if ( $status != 0 ) exit $status
-    @ y = $y + $heights[$i]
-    @ i++
-end
-
-rm -f $all
-
-
-
-
-