From 9a401744c05ea3ac39c8038ee0228a58494d8c46 Mon Sep 17 00:00:00 2001 From: giraffedata Date: Sat, 10 Mar 2012 20:14:15 +0000 Subject: Release 10.57.04 git-svn-id: http://svn.code.sf.net/p/netpbm/code/advanced@1664 9d0c8265-081b-0410-96cb-a4ca84ce46f8 --- editor/Makefile | 8 ++- editor/pnmquantall | 184 +++++++++++++++++++++++++++++++++++++++++++++++++ editor/ppmquantall | 96 -------------------------- editor/ppmquantall.csh | 57 --------------- 4 files changed, 190 insertions(+), 155 deletions(-) create mode 100755 editor/pnmquantall delete mode 100755 editor/ppmquantall delete mode 100644 editor/ppmquantall.csh (limited to 'editor') 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] ..." - 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 ..." - 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 - - - - - -- cgit 1.4.1