diff options
-rw-r--r-- | doc/HISTORY | 3 | ||||
-rw-r--r-- | doc/USERDOC | 27 | ||||
-rw-r--r-- | editor/Makefile | 8 | ||||
-rwxr-xr-x | editor/pnmquantall | 184 | ||||
-rwxr-xr-x | editor/ppmquantall | 96 | ||||
-rw-r--r-- | editor/ppmquantall.csh | 57 |
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 - - - - - |