about summary refs log tree commit diff
diff options
context:
space:
mode:
authorgiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2015-06-28 15:34:21 +0000
committergiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2015-06-28 15:34:21 +0000
commit620ecbee2ed1cb478e0289722d86dd72717f1cb8 (patch)
tree7a427b24d86f6789706acee21a52dca15b88806b
parent8c2dab4922b514045cbae8e71ba93aaf8c0fff48 (diff)
downloadnetpbm-mirror-620ecbee2ed1cb478e0289722d86dd72717f1cb8.tar.gz
netpbm-mirror-620ecbee2ed1cb478e0289722d86dd72717f1cb8.tar.xz
netpbm-mirror-620ecbee2ed1cb478e0289722d86dd72717f1cb8.zip
Release 10.71.00
git-svn-id: http://svn.code.sf.net/p/netpbm/code/advanced@2588 9d0c8265-081b-0410-96cb-a4ca84ce46f8
-rw-r--r--GNUmakefile194
-rw-r--r--analyzer/pamfile.c2
-rw-r--r--analyzer/pnmpsnr.c417
-rw-r--r--buildtools/Makefile6
-rw-r--r--buildtools/README.pkg2
-rwxr-xr-xbuildtools/makeman5
-rw-r--r--common.mk6
-rw-r--r--config.mk.in4
-rw-r--r--converter/other/Makefile19
-rw-r--r--converter/other/bmptopnm.c11
-rw-r--r--converter/other/cameratopam/camera.c4
-rw-r--r--converter/other/cameratopam/ljpeg.c237
-rw-r--r--converter/other/cameratopam/ljpeg.h9
-rw-r--r--converter/other/pamrgbatopng.c136
-rw-r--r--converter/other/pamtopng.c771
-rw-r--r--converter/other/pamtosvg/pxl-outline.c1
-rw-r--r--converter/other/pngtxt.c4
-rw-r--r--converter/other/pngx.c47
-rw-r--r--converter/other/pngx.h16
-rw-r--r--converter/other/pnmtopng.c53
-rw-r--r--converter/other/pnmtops.c8
-rw-r--r--converter/other/pnmtoxwd.c20
-rw-r--r--converter/other/sgitopnm.c7
-rw-r--r--converter/pbm/atktopbm.c425
-rw-r--r--converter/pbm/brushtopbm.c6
-rw-r--r--converter/pbm/macp.h18
-rw-r--r--converter/pbm/macptopbm.c426
-rw-r--r--converter/pbm/pbmto10x.c113
-rw-r--r--converter/pbm/pbmtoatk.c69
-rw-r--r--converter/pbm/pbmtoepson.c59
-rw-r--r--converter/pbm/pbmtog3.c6
-rw-r--r--converter/pbm/pbmtomacp.c707
-rw-r--r--converter/pbm/pbmtomatrixorbital.c35
-rw-r--r--converter/pbm/pbmtomgr.c6
-rw-r--r--converter/pbm/pbmtopi3.c163
-rw-r--r--converter/pbm/pbmtopk.c30
-rw-r--r--converter/pbm/pbmtoptx.c135
-rw-r--r--converter/pbm/pbmtoxbm.c59
-rw-r--r--converter/pbm/pbmtoybm.c86
-rw-r--r--converter/pbm/pbmtozinc.c241
-rw-r--r--converter/pbm/pi3topbm.c224
-rw-r--r--converter/pbm/xbmtopbm.c8
-rw-r--r--converter/pbm/ybmtopbm.c63
-rw-r--r--converter/ppm/ppmtoarbtxt.c7
-rw-r--r--converter/ppm/ppmtobmp.c26
-rw-r--r--converter/ppm/ppmtoicr.c532
-rw-r--r--converter/ppm/ppmtompeg/Makefile3
-rw-r--r--converter/ppm/ppmtompeg/headers/all.h1
-rw-r--r--converter/ppm/ppmtompeg/headers/ansi.h76
-rw-r--r--converter/ppm/ppmtompeg/headers/bitio.h1
-rw-r--r--converter/ppm/ppmtompeg/headers/dct.h9
-rw-r--r--converter/ppm/ppmtompeg/headers/frame.h1
-rw-r--r--converter/ppm/ppmtompeg/headers/frames.h1
-rw-r--r--converter/ppm/ppmtompeg/headers/frametype.h2
-rw-r--r--converter/ppm/ppmtompeg/headers/jpeg.h1
-rw-r--r--converter/ppm/ppmtompeg/headers/mheaders.h23
-rw-r--r--converter/ppm/ppmtompeg/headers/motion_search.h1
-rw-r--r--converter/ppm/ppmtompeg/headers/mpeg.h5
-rw-r--r--converter/ppm/ppmtompeg/headers/mproto.h47
-rw-r--r--converter/ppm/ppmtompeg/headers/opts.h15
-rw-r--r--converter/ppm/ppmtompeg/headers/parallel.h1
-rw-r--r--converter/ppm/ppmtompeg/headers/param.h1
-rw-r--r--converter/ppm/ppmtompeg/headers/prototypes.h35
-rw-r--r--converter/ppm/ppmtompeg/headers/rate.h18
-rw-r--r--converter/ppm/ppmtompeg/headers/specifics.h9
-rw-r--r--converter/ppm/ppmtompeg/jrevdct.c7
-rw-r--r--converter/ppm/ppmtompeg/mpeg.c6
-rw-r--r--converter/ppm/ppmtompeg/opts.c2
-rw-r--r--converter/ppm/ppmtompeg/ppmtompeg.c4
-rw-r--r--converter/ppm/ppmtompeg/rate.c14
-rw-r--r--converter/ppm/ppmtompeg/readframe.c26
-rw-r--r--converter/ppm/ppmtompeg/specifics.c16
-rw-r--r--converter/ppm/ppmtopcx.c16
-rw-r--r--doc/CONTRIBUTORS37
-rw-r--r--doc/HISTORY275
-rw-r--r--doc/Netpbm.programming96
-rw-r--r--doc/TESTS186
-rw-r--r--doc/patent_summary4
-rw-r--r--editor/pamenlarge.c7
-rw-r--r--editor/pamscale.c18
-rw-r--r--editor/pbmclean.c12
-rw-r--r--editor/pbmpscale.c11
-rw-r--r--editor/pnminvert.c7
-rw-r--r--generator/pamstereogram.c281
-rw-r--r--generator/pbmmake.c21
-rw-r--r--icon/Makefile3
-rw-r--r--lib/Makefile5
-rw-r--r--lib/libpbm2.c85
-rw-r--r--lib/libpnm1.c9
-rw-r--r--lib/libppm1.c9
-rw-r--r--lib/pbm.h22
-rw-r--r--lib/pnm.h2
-rw-r--r--lib/ppm.h2
-rw-r--r--lib/util/Makefile1
-rw-r--r--lib/util/bitio.c (renamed from lib/bitio.c)0
-rw-r--r--lib/util/bitio.h (renamed from lib/bitio.h)0
-rw-r--r--lib/util/nstring.c62
-rwxr-xr-xtest/411toppm.test4
-rw-r--r--test/BLOCK4
-rwxr-xr-xtest/Execute-Tests243
-rw-r--r--test/Makefile8
-rw-r--r--test/Test-Order5
-rw-r--r--test/all-in-place.ok38
-rwxr-xr-xtest/all-in-place.test92
-rwxr-xr-xtest/atari-roundtrip.test14
-rwxr-xr-xtest/atk-roundtrip.test5
-rwxr-xr-xtest/avs-roundtrip.test4
-rwxr-xr-xtest/bmp-roundtrip.test5
-rwxr-xr-xtest/cis-roundtrip.test8
-rwxr-xr-xtest/cmuw-roundtrip.test5
-rwxr-xr-xtest/cut-paste-roundtrip.test5
-rwxr-xr-xtest/eyuvtoppm.test4
-rwxr-xr-xtest/facesaver-roundtrip.test5
-rwxr-xr-xtest/fits-roundtrip.test5
-rwxr-xr-xtest/g3-roundtrip.test4
-rwxr-xr-xtest/gem-roundtrip.test9
-rwxr-xr-xtest/gif-quant-roundtrip.test7
-rwxr-xr-xtest/gif-roundtrip.test11
-rwxr-xr-xtest/hdiff-roundtrip.test5
-rw-r--r--test/ilbm-roundtrip.ok1
-rwxr-xr-xtest/ilbm-roundtrip.test9
-rwxr-xr-xtest/jbig-roundtrip.test5
-rwxr-xr-xtest/leaf-roundtrip.test5
-rw-r--r--test/legacy-names.ok36
-rwxr-xr-xtest/legacy-names.test131
-rw-r--r--test/macp-roundtrip.ok5
-rwxr-xr-xtest/macp-roundtrip.test36
-rwxr-xr-xtest/mda-roundtrip.test8
-rwxr-xr-xtest/mgr-roundtrip.test5
-rwxr-xr-xtest/mrf-roundtrip.test5
-rwxr-xr-xtest/pad-crop-roundtrip.test3
-rwxr-xr-xtest/pambackground.test14
-rwxr-xr-xtest/pamchannel.test3
-rwxr-xr-xtest/pamcrater.test10
-rwxr-xr-xtest/pamcut.test10
-rwxr-xr-xtest/pamdepth-roundtrip.test5
-rwxr-xr-xtest/pamdice-roundtrip.test6
-rwxr-xr-xtest/pamditherbw.test4
-rwxr-xr-xtest/pamedge.test7
-rwxr-xr-xtest/pamenlarge.test5
-rwxr-xr-xtest/pamfile.test7
-rwxr-xr-xtest/pamflip-roundtrip.test4
-rwxr-xr-xtest/pamflip1.test6
-rwxr-xr-xtest/pamflip2.test4
-rwxr-xr-xtest/pamseq.test4
-rwxr-xr-xtest/pamslice-roundtrip.test35
-rwxr-xr-xtest/pamsumm.test4
-rwxr-xr-xtest/pamtopam.test4
-rwxr-xr-xtest/pbmclean.test5
-rwxr-xr-xtest/pbmmake.test5
-rwxr-xr-xtest/pbmminkowski.test4
-rwxr-xr-xtest/pbmpage.test6
-rwxr-xr-xtest/pbmpscale.test6
-rwxr-xr-xtest/pbmtext.test4
-rwxr-xr-xtest/pbmtog3.test3
-rwxr-xr-xtest/pbmupc.test4
-rwxr-xr-xtest/pcx-roundtrip.test6
-rwxr-xr-xtest/pfm-roundtrip.test4
-rwxr-xr-xtest/pgmbentley.test3
-rw-r--r--test/pgmcrater.ok1
-rwxr-xr-xtest/pgmcrater.test31
-rwxr-xr-xtest/pgmhist.test3
-rwxr-xr-xtest/pgmmake.test10
-rwxr-xr-xtest/pgmnoise.test4
-rwxr-xr-xtest/pgmramp.test7
-rwxr-xr-xtest/pgmtopgm.test4
-rwxr-xr-xtest/pgmtoppm.test7
-rwxr-xr-xtest/pi3-roundtrip.test10
-rwxr-xr-xtest/pict-roundtrip.test7
-rwxr-xr-xtest/png-roundtrip.test11
-rwxr-xr-xtest/pnm-pam-roundtrip.test6
-rwxr-xr-xtest/pnm-plain-roundtrip.test15
-rwxr-xr-xtest/pnmcat.test4
-rwxr-xr-xtest/pnminvert-roundtrip.test4
-rwxr-xr-xtest/pnminvert.test7
-rw-r--r--test/pnmpsnr.ok2
-rwxr-xr-xtest/pnmpsnr.test7
-rwxr-xr-xtest/pnmremap1.test11
-rwxr-xr-xtest/pnmremap2.test7
-rwxr-xr-xtest/pnmshear.test4
-rwxr-xr-xtest/pnmtile.test3
-rwxr-xr-xtest/pnmtopnm-plain.test15
-rwxr-xr-xtest/ppmbrighten.test4
-rwxr-xr-xtest/ppmchange-roundtrip.test5
-rwxr-xr-xtest/ppmchange.test12
-rwxr-xr-xtest/ppmcie.test8
-rwxr-xr-xtest/ppmdfont.test10
-rwxr-xr-xtest/ppmdim.test11
-rwxr-xr-xtest/ppmdither.test4
-rwxr-xr-xtest/ppmforge.test4
-rwxr-xr-xtest/ppmgauss.test4
-rwxr-xr-xtest/ppmhist.test4
-rwxr-xr-xtest/ppmmake.test9
-rwxr-xr-xtest/ppmmix.test13
-rwxr-xr-xtest/ppmpat.test4
-rwxr-xr-xtest/ppmrelief.test6
-rwxr-xr-xtest/ppmrough.test5
-rw-r--r--test/ppmtoarbtxt-roundtrip.ok2
-rwxr-xr-xtest/ppmtoarbtxt-roundtrip.test34
-rwxr-xr-xtest/ppmtopgm.test5
-rwxr-xr-xtest/ppmtoppm.test4
-rwxr-xr-xtest/ppmwheel.test8
-rwxr-xr-xtest/ps-alt-roundtrip.test17
-rwxr-xr-xtest/ps-roundtrip.test24
-rwxr-xr-xtest/rgb3-roundtrip.test6
-rwxr-xr-xtest/sbig-roundtrip.test5
-rwxr-xr-xtest/sgi-roundtrip.test4
-rwxr-xr-xtest/st4-roundtrip.test3
-rwxr-xr-xtest/sunrast-roundtrip.test7
-rwxr-xr-xtest/symmetry.test8
-rwxr-xr-xtest/targa-roundtrip.test6
-rw-r--r--test/testrandom.c3
-rwxr-xr-xtest/tiff-roundtrip.test9
-rwxr-xr-xtest/utahrle-roundtrip.test5
-rwxr-xr-xtest/wbmp-roundtrip.test5
-rwxr-xr-xtest/winicon-roundtrip.test13
-rwxr-xr-xtest/xbm-roundtrip.test5
-rwxr-xr-xtest/xpm-roundtrip.test5
-rw-r--r--test/xv-roundtrip.ok1
-rwxr-xr-xtest/xv-roundtrip.test7
-rwxr-xr-xtest/xwd-roundtrip.test6
-rwxr-xr-xtest/yuv-roundtrip.test4
-rw-r--r--version.mk4
223 files changed, 4941 insertions, 3382 deletions
diff --git a/GNUmakefile b/GNUmakefile
index 2e624aa0..caf8e37d 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -1,12 +1,24 @@
 # Makefile for Netpbm
- 
+
 # Configuration should normally be done in the included file config.mk.
 
 # Targets in this file:
 #
 #   nonmerge:     Build everything, in the source directory.
-#   merge:        Build everything as merged executables, in the source dir
-#   package:      Make a package of Netpbm files ready to install
+#   merge:        Build everything as merged executables, in the source dir.
+#   package:      Make a package of Netpbm files ready to install.
+#
+#   deb:          Make a .deb file in the current dir.
+#
+#   check-tree:     Conduct tests on Netpbm files in the source dir. 
+#   check-package:  Conduct tests on packaged Netpbm files.
+#   check-install:  Conduct tests on installed Netpbm files.
+#   check:          Default check.  Synonym for check-package.
+#
+#   clean:        Delete target executables and intermediate objects.
+#   distclean:    Delete configuration files in addition to the above.
+#
+#   tags:         Generate/update an Emacs tags file, named TAGS.
 #   
 #   The default target is either "merge" or "nonmerge", as determined by
 #   the DEFAULT_TARGET variable set by config.mk.
@@ -60,9 +72,9 @@ VPATH=.:$(SRCDIR)
 
 include $(BUILDDIR)/config.mk
 
-PROG_SUBDIRS = converter analyzer editor generator other test
+PROG_SUBDIRS = converter analyzer editor generator other
 PRODUCT_SUBDIRS = lib $(PROG_SUBDIRS)
-SUPPORT_SUBDIRS = urt buildtools
+SUPPORT_SUBDIRS = urt buildtools test
 
 SUBDIRS = $(PRODUCT_SUBDIRS) $(SUPPORT_SUBDIRS)
 
@@ -72,10 +84,6 @@ NOMERGEBINARIES = netpbm
 
 OBJECTS = netpbm.o
 
-PBM_TESTPREFIX ?= $(PKGDIR)/bin
-PBM_LIBRARY_PATH ?= $(PKGDIR)/lib
-RGBDEF ?= $(SRCDIR)/lib/rgb.txt
-
 default: $(DEFAULT_TARGET)
 	echo "EXISTENCE OF THIS FILE MEANS NETPBM HAS BEEN BUILT." \
 	  >build_complete
@@ -134,6 +142,14 @@ $(TYPEGEN) $(ENDIANGEN): $(BUILDDIR)/buildtools
 inttypes_netpbm.h: $(TYPEGEN)
 	$(TYPEGEN) >$@
 
+
+# testrandom is a utility program used by the make file below.
+TESTRANDOM = $(BUILDDIR)/test/testrandom
+
+$(TESTRANDOM): $(BUILDDIR)/test
+	$(MAKE) -C $(dir $@) -f $(SRCDIR)/test/Makefile \
+	    SRCDIR=$(SRCDIR) BUILDDIR=$(BUILDDIR) $(notdir $@) 
+
 # We run a couple of programs on the build machine in computing the
 # contents of pm_config.h.  We need to give the user a way not to do
 # that or to override the results, because it doesn't work if he's
@@ -233,7 +249,7 @@ init_package:
 	@if [ -d $(PKGDIR) ]; then \
 	  echo "Directory $(PKGDIR) already exists.  Please specify a "; \
 	  echo "directory that can be created fresh, like this: "; \
-	  echo "  make package PKGDIR=/tmp/newnetpbm "; \
+	  echo "  make package pkgdir=/tmp/newnetpbm "; \
 	  false; \
 	  fi
 	mkdir $(PKGDIR)
@@ -286,22 +302,30 @@ ifneq ($(LINUXSVGALIB),NONE)
   MERGELIBS += $(LINUXSVGALIB)
 endif
 
-ifeq ($(shell libpng$(PNGVER)-config --version),)
-  PNGLD = $(shell $(LIBOPT) $(LIBOPTR) $(PNGLIB) $(ZLIB))
+ifneq ($(shell pkg-config --modversion libpng$(PNGVER)),)
+  PNGLD = $(shell pkg-config --libs libpng$(PNGVER))
 else
-  PNGLD = $(shell libpng$(PNGVER)-config --ldflags)
+  ifneq ($(shell libpng$(PNGVER)-config --version),)
+    PNGLD = $(shell libpng$(PNGVER)-config --ldflags)
+  else
+    PNGLD = $(shell $(LIBOPT) $(LIBOPTR) $(PNGLIB) $(ZLIB))
+  endif
 endif
 
-ifeq ($(shell xml2-config --version),)
-  XML2LD=
+ifneq ($(shell pkg-config --modversion libxml-2.0),)
+  XML2LD=$(shell pkg-config --libs libxml-2.0)
 else
-  XML2LD=$(shell xml2-config --libs)
+  ifneq ($(shell xml2-config --version),)
+    XML2LD=$(shell xml2-config --libs)
+  else
+    XML2LD=
+  endif
 endif
 
-ifeq ($(shell pkg-config x11 --libs),)
-  X11LD = $(shell $(LIBOPT) $(LIBOPTR) $(X11LIB))
-else
+ifneq ($(shell pkg-config x11 --libs),)
   X11LD = $(shell pkg-config x11 --libs)
+else
+  X11LD = $(shell $(LIBOPT) $(LIBOPTR) $(X11LIB))
 endif
 
 
@@ -354,31 +378,14 @@ netpbm.o: mergetrylist
 install.merge: local.install.merge
 .PHONY: local.install.merge
 local.install.merge:
-	cd $(PKGDIR)/bin; $(SYMLINKEXE) netpbm bmptoppm
+	cd $(PKGDIR)/bin; $(SYMLINKEXE) netpbm pnmnoraw
 	cd $(PKGDIR)/bin; $(SYMLINKEXE) netpbm gemtopbm
-	cd $(PKGDIR)/bin; $(SYMLINKEXE) netpbm icontopbm
-	cd $(PKGDIR)/bin; $(SYMLINKEXE) netpbm pgmedge
-	cd $(PKGDIR)/bin; $(SYMLINKEXE) netpbm pgmnorm
-	cd $(PKGDIR)/bin; $(SYMLINKEXE) netpbm pgmoil
-	cd $(PKGDIR)/bin; $(SYMLINKEXE) netpbm pgmslice
-	cd $(PKGDIR)/bin; $(SYMLINKEXE) netpbm pngtopnm
-	cd $(PKGDIR)/bin; $(SYMLINKEXE) netpbm pnmarith
-	cd $(PKGDIR)/bin; $(SYMLINKEXE) netpbm pnmcomp
-	cd $(PKGDIR)/bin; $(SYMLINKEXE) netpbm pnmcut
-	cd $(PKGDIR)/bin; $(SYMLINKEXE) netpbm pnmdepth
-	cd $(PKGDIR)/bin; $(SYMLINKEXE) netpbm pnmenlarge
-	cd $(PKGDIR)/bin; $(SYMLINKEXE) netpbm pnmfile
 	cd $(PKGDIR)/bin; $(SYMLINKEXE) netpbm pnminterp
-	cd $(PKGDIR)/bin; $(SYMLINKEXE) netpbm pnmnoraw
-	cd $(PKGDIR)/bin; $(SYMLINKEXE) netpbm pnmscale
-	cd $(PKGDIR)/bin; $(SYMLINKEXE) netpbm pnmsplit
-	cd $(PKGDIR)/bin; $(SYMLINKEXE) netpbm pnmtofits
-	cd $(PKGDIR)/bin; $(SYMLINKEXE) netpbm pnmnoraw
-	cd $(PKGDIR)/bin; $(SYMLINKEXE) netpbm pnmtopnm
-	cd $(PKGDIR)/bin; $(SYMLINKEXE) netpbm ppmnorm
+	cd $(PKGDIR)/bin; $(SYMLINKEXE) netpbm pgmoil
 	cd $(PKGDIR)/bin; $(SYMLINKEXE) netpbm ppmtojpeg
-	cd $(PKGDIR)/bin; $(SYMLINKEXE) netpbm pnmtotga
-	cd $(PKGDIR)/bin; $(SYMLINKEXE) netpbm pnmtouil
+	cd $(PKGDIR)/bin; $(SYMLINKEXE) netpbm bmptoppm
+	cd $(PKGDIR)/bin; $(SYMLINKEXE) netpbm pgmnorm
+	cd $(PKGDIR)/bin; $(SYMLINKEXE) netpbm pnmfile
 
 ifneq ($(NETPBMLIBTYPE),unixstatic)
 install.lib: lib/install.lib
@@ -442,16 +449,111 @@ install.sharedlibstub:
 deb:
 	buildtools/debian/mkdeb --buildtools=buildtools --pkgdir=$(PKGDIR)
 
+
 .PHONY: check
-check:
-# This works on typical Linux systems
-	if [ ! -d $(RESULTDIR) ]; then mkdir -pv $(RESULTDIR); fi
+.PHONY: check-tree
+.PHONY: check-package
+.PHONY: check-install
+
+# Test files in source tree.
+# This does not work when Netpbm is compiled in a separate build dir.
+
+check-tree : SRCBINDIRS :=./analyzer \
+./converter/other \
+./converter/other/cameratopam \
+./converter/other/fiasco \
+./converter/other/jbig \
+./converter/other/jpeg2000 \
+./converter/other/pamtosvg \
+./converter/other/pnmtopalm \
+./converter/pbm \
+./converter/pbm/pbmtoppa \
+./converter/pgm \
+./converter/ppm \
+./converter/ppm/hpcdtoppm \
+./converter/ppm/ppmtompeg \
+./converter/ppm \
+./editor \
+./editor/pamflip \
+./editor/specialty \
+./generator \
+./other \
+./other/pamx \
+./
+
+# Create colon-separated PATH list from the above.
+# Use realpath function (appears in GNU Make v.3.81) if available.
+
+# Kludge to test whether realpath is available:
+ifeq ($(realpath $(CURDIR)/.),$(CURDIR))
+  check-tree : RBINDIRS :=\
+    $(foreach dir,$(SRCBINDIRS),$(realpath $(BUILDDIR)/$(dir)))
+else
+  check-tree : RBINDIRS :=$(foreach dir,$(SRCBINDIRS),$(BUILDDIR)/$(dir))  
+endif
+
+# Kludge to express characters given special meanings by GNU Make.
+# See GNU Make texinfo manual "Function Call Syntax".
+empty :=
+space := $(empty) $(empty)
+colon :=:
+
+check-tree : PBM_TEST_PATH := $(subst $(space),$(colon),$(RBINDIRS))
+check-tree : PBM_LIBRARY_PATH ?= $(BUILDDIR)/lib
+check-tree : RGBDEF ?= $(SRCDIR)/lib/rgb.txt
+
+
+# Create RESULTDIR.
+# If it already exists, rename and covert to an archive directory.
+# Use numbered backup.
+# TODO: Renaming fails with old versions of mv which do not support -T.  
+
+resultdir-backup: FORCE
+	if [ -d $(RESULTDIR) ]; \
+	   then mv -T --backup=numbered $(RESULTDIR) $(RESULTDIR).bak; \
+	fi; \
+	mkdir -p $(RESULTDIR); \
+
+
+check-tree: $(TESTRANDOM) resultdir-backup
 	cd $(RESULTDIR); \
-	  PBM_TESTPREFIX=$(PBM_TESTPREFIX) \
+	  CHECK_TYPE=tree \
+	  PBM_TEST_PATH=$(PBM_TEST_PATH) BUILDDIR=$(BUILDDIR) \
 	  LD_LIBRARY_PATH=$(PBM_LIBRARY_PATH):${LD_LIBRARY_PATH} \
 	  RGBDEF=$(RGBDEF) \
 	  $(SRCDIR)/test/Execute-Tests 2>&1
 
+# Execute-Tests needs to know BUILDDIR in order to locate testrandom.
+# This applies to all check varieties.
+
+# Check after the packaging stage
+# This works on typical Linux systems.
+# This is the default check.
+
+check-package : PBM_TEST_PATH := $(PKGDIR)/bin
+check-package : PBM_LIBRARY_PATH := $(PKGDIR)/lib
+check-package : RGBDEF ?= $(PKGDIR)/misc/rgb.txt
+check: check-package
+
+check-package: $(TESTRANDOM) resultdir-backup
+	cd $(RESULTDIR); \
+	  CHECK_TYPE=package \
+	  PBM_TEST_PATH=$(PBM_TEST_PATH) BUILDDIR=$(BUILDDIR) \
+	  LD_LIBRARY_PATH=$(PBM_LIBRARY_PATH):${LD_LIBRARY_PATH} \
+	  RGBDEF=$(RGBDEF) \
+	  $(SRCDIR)/test/Execute-Tests 2>&1
+
+
+# Check after install
+check-install: $(TESTRANDOM) resultdir-backup
+	cd $(RESULTDIR); \
+	  CHECK_TYPE=install \
+	  BUILDDIR=$(BUILDDIR) \
+	  RGBDEF=$(RGBDEF) \
+	  $(SRCDIR)/test/Execute-Tests 2>&1
+
+
+
 clean: localclean
 
 .PHONY: localclean
@@ -469,7 +571,7 @@ localdistclean: localclean
 	-rm -f TAGS
 	-rm -f config.mk
 
-# 'tags' generates/updates an Emacs tags file, anmed TAGS, in the current
+# 'tags' generates/updates an Emacs tags file, named TAGS, in the current
 # directory.  Use with Emacs command 'find-tag'.
 
 .PHONY: tags
diff --git a/analyzer/pamfile.c b/analyzer/pamfile.c
index bb55ecce..a7c3c5ac 100644
--- a/analyzer/pamfile.c
+++ b/analyzer/pamfile.c
@@ -59,6 +59,8 @@ parseCommandLine(int argc, const char ** argv,
 
     cmdlineP->inputFilespec = (const char **)&argv[1];
     cmdlineP->inputFileCount = argc - 1;
+
+    free(option_def);
 }
 
 
diff --git a/analyzer/pnmpsnr.c b/analyzer/pnmpsnr.c
index b04316cf..af74e8c8 100644
--- a/analyzer/pnmpsnr.c
+++ b/analyzer/pnmpsnr.c
@@ -8,13 +8,71 @@
  *  Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de>
  */
 
+#include <assert.h>
 #include <string.h>
 #include <stdio.h>
 #include <math.h>
 
 #include "pm_c_util.h"
+#include "mallocvar.h"
 #include "nstring.h"
 #include "pam.h"
+#include "shhopt.h"
+
+
+
+struct CmdlineInfo {
+    /* All the information the user supplied in the command line,
+       in a form easy for the program to use.
+    */
+    const char * inputFile1Name;  /* Name of first input file */
+    const char * inputFile2Name;  /* Name of second input file */
+    unsigned int rgb;
+};
+
+
+
+static void
+parseCommandLine(int argc, const char ** argv,
+                 struct CmdlineInfo * const cmdlineP) {
+/*----------------------------------------------------------------------------
+   Note that the file spec array we return is stored in the storage that
+   was passed to as as the argv array.
+-----------------------------------------------------------------------------*/
+    optEntry * option_def;
+        /* Instructions to pm_optParseOptions3 on how to parse our options.
+         */
+    optStruct3 opt;
+
+    unsigned int option_def_index;
+
+    MALLOCARRAY_NOFAIL(option_def, 100);
+    
+    option_def_index = 0;   /* incremented by OPTENT3 */
+    OPTENT3(0,   "rgb",      OPT_FLAG,  NULL, &cmdlineP->rgb,       0);
+
+    opt.opt_table     = option_def;
+    opt.short_allowed = FALSE; /* We have no short (old-fashioned) options */
+    opt.allowNegNum   = FALSE; /* We have no parms that are negative numbers */
+    
+    pm_optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0);
+        /* Uses and sets argc, argv, and some of *cmdlineP and others */
+
+    if (argc-1 < 2) 
+        pm_error("Takes two arguments:  names of the two files to compare");
+    else {
+        cmdlineP->inputFile1Name = argv[1];
+        cmdlineP->inputFile2Name = argv[2];
+
+        if (argc-1 > 2)
+            pm_error("Too many arguments (%u).  The only arguments are "
+                     "the names of the two files to compare", argc-1);
+    }
+
+    free(option_def);
+}
+
+
 
 static int
 udiff(unsigned int const subtrahend,
@@ -68,79 +126,266 @@ validateInput(struct pam const pam1,
 }
 
 
+enum ColorSpaceId {
+    COLORSPACE_GRAYSCALE,
+    COLORSPACE_YCBCR,
+    COLORSPACE_RGB
+};
 
-static void
-psnrColor(tuple    const tuple1,
-          tuple    const tuple2,
-          double * const ySqDiffP, 
-          double * const cbSqDiffP,
-          double * const crSqDiffP) {
+typedef struct {
+
+    enum ColorSpaceId id;
+
+    unsigned int componentCt;
+
+    const char * componentName[3];
+        /* Only first 'componentCt' elements are valid */
+
+} ColorSpace;
+
+
+struct SqDiff {
+/*----------------------------------------------------------------------------
+   The square-differences of the components of two pixels, for some
+   component set.
+-----------------------------------------------------------------------------*/
+    double sqDiff[3];
+};
+
+
+
+static struct SqDiff
+zeroSqDiff() {
+
+    struct SqDiff retval;
+    unsigned int i;
+
+    for (i = 0; i < 3; ++i)
+        retval.sqDiff[i] = 0.0;
+
+    return retval;
+}
+
+
+
+static struct SqDiff
+sqDiffSum(ColorSpace    const colorSpace,
+          struct SqDiff const addend,
+          struct SqDiff const adder) {
+
+    struct SqDiff retval;
+    unsigned int i;
+
+    for (i = 0; i < colorSpace.componentCt; ++i)
+        retval.sqDiff[i] = addend.sqDiff[i] + adder.sqDiff[i];
+
+    return retval;
+}
+
+
+
+#define Y_INDEX  0
+#define CB_INDEX 1
+#define CR_INDEX 2
+
+static ColorSpace
+yCbCrColorSpace() {
+
+    ColorSpace retval;
+
+    retval.id = COLORSPACE_YCBCR;
+
+    retval.componentCt = 3;
+
+    retval.componentName[Y_INDEX]  = "Y";
+    retval.componentName[CR_INDEX] = "CR";
+    retval.componentName[CB_INDEX] = "CB";
+
+    return retval;
+}
+
+
+
+static struct SqDiff
+sqDiffYCbCr(tuple    const tuple1,
+            tuple    const tuple2) {
+
+    struct SqDiff retval;
 
     double y1, y2, cb1, cb2, cr1, cr2;
     
     pnm_YCbCrtuple(tuple1, &y1, &cb1, &cr1);
     pnm_YCbCrtuple(tuple2, &y2, &cb2, &cr2);
     
-    *ySqDiffP  = square(y1  - y2);
-    *cbSqDiffP = square(cb1 - cb2);
-    *crSqDiffP = square(cr1 - cr2);
+    retval.sqDiff[Y_INDEX]  = square(y1  - y2);
+    retval.sqDiff[CB_INDEX] = square(cb1 - cb2);
+    retval.sqDiff[CR_INDEX] = square(cr1 - cr2);
+
+    return retval;
+}
+
+
+
+#define R_INDEX 0
+#define G_INDEX 1
+#define B_INDEX 2
+
+
+
+static ColorSpace
+rgbColorSpace() {
+
+    ColorSpace retval;
+
+    retval.id = COLORSPACE_RGB;
+
+    retval.componentCt = 3;
+
+    retval.componentName[R_INDEX] = "Red";
+    retval.componentName[G_INDEX] = "Green";
+    retval.componentName[B_INDEX] = "Blue";
+
+    return retval;
+}
+
+
+
+static struct SqDiff
+sqDiffRgb(tuple    const tuple1,
+          tuple    const tuple2) {
+
+    struct SqDiff retval;
+
+    retval.sqDiff[R_INDEX] =
+        square((int)tuple1[PAM_RED_PLANE]  - (int)tuple2[PAM_RED_PLANE]);
+    retval.sqDiff[G_INDEX] =
+        square((int)tuple1[PAM_GRN_PLANE]  - (int)tuple2[PAM_GRN_PLANE]);
+    retval.sqDiff[B_INDEX] =
+        square((int)tuple1[PAM_BLU_PLANE]  - (int)tuple2[PAM_BLU_PLANE]);
+
+    return retval;
+}
+
+
+
+static ColorSpace
+grayscaleColorSpace() {
+
+    ColorSpace retval;
+
+    retval.id = COLORSPACE_GRAYSCALE;
+
+    retval.componentCt = 1;
+
+    retval.componentName[Y_INDEX]  = "luminance";
+
+    return retval;
+}
+
+
+
+static struct SqDiff
+sqDiffGrayscale(tuple    const tuple1,
+                tuple    const tuple2) {
+
+    struct SqDiff sqDiff;
+
+    sqDiff.sqDiff[Y_INDEX] = square(udiff(tuple1[0], tuple2[0]));
+
+    return sqDiff;
+}
+
+
+
+static struct SqDiff
+sumSqDiffFromRaster(struct pam * const pam1P,
+                    struct pam * const pam2P,
+                    ColorSpace   const colorSpace) {
+
+    struct SqDiff sumSqDiff;
+    tuple *tuplerow1, *tuplerow2;  /* malloc'ed */
+    unsigned int row;
+
+    tuplerow1 = pnm_allocpamrow(pam1P);
+    tuplerow2 = pnm_allocpamrow(pam2P);
+    
+    sumSqDiff = zeroSqDiff();
+
+    for (row = 0; row < pam1P->height; ++row) {
+        unsigned int col;
+        
+        pnm_readpamrow(pam1P, tuplerow1);
+        pnm_readpamrow(pam2P, tuplerow2);
+
+        assert(pam1P->width == pam2P->width);
+
+        for (col = 0; col < pam1P->width; ++col) {
+            struct SqDiff sqDiff;
+
+            switch (colorSpace.id) {
+            case COLORSPACE_GRAYSCALE:
+                sqDiff = sqDiffGrayscale(tuplerow1[col], tuplerow2[col]);
+                break;
+            case COLORSPACE_YCBCR:
+                sqDiff = sqDiffYCbCr(tuplerow1[col], tuplerow2[col]);
+                break;
+            case COLORSPACE_RGB:
+                sqDiff = sqDiffRgb(tuplerow1[col], tuplerow2[col]);
+                break;
+            }
+            sumSqDiff = sqDiffSum(colorSpace, sumSqDiff, sqDiff);
+        }
+    }
+
+    pnm_freepamrow(tuplerow1);
+    pnm_freepamrow(tuplerow2);
+
+    return sumSqDiff;
 }
 
 
 
 static void
-reportPsnr(struct pam const pam,
-           double     const ySumSqDiff, 
-           double     const crSumSqDiff,
-           double     const cbSumSqDiff,
-           char       const filespec1[],
-           char       const filespec2[]) {
-
-    bool const color = streq(pam.tuple_type, PAM_PPM_TUPLETYPE);
-
-    /* Maximum possible sum square difference, i.e. the sum of the squares of
-       the sample differences between an entirely white image and entirely
-       black image of the given dimensions.
-    */
+reportPsnr(struct pam    const pam,
+           struct SqDiff const sumSqDiff,
+           ColorSpace    const colorSpace,
+           const char *  const fileName1,
+           const char *  const fileName2) {
+
     double const maxSumSqDiff = square(pam.maxval) * pam.width * pam.height;
+        /* Maximum possible sum square difference, i.e. the sum of the squares
+           of the sample differences between an entirely white image and
+           entirely black image of the given dimensions.
+        */
+
+    unsigned int i;
+
 
     /* The PSNR is the ratio of the maximum possible mean square difference
-       to the actual mean square difference.
+       to the actual mean square difference, which is also the ratio of
+       the maximum possible sum square difference to the actual sum square
+       difference.
    
        Note that in the important special case that the images are
        identical, the sum square differences are identically 0.0.
        No precision error; no rounding error.
     */
 
-    if (color) {
-        pm_message("PSNR between %s and %s:", filespec1, filespec2);
+    pm_message("PSNR between '%s' and '%s':", fileName1, fileName2);
 
-        if (ySumSqDiff > 0)
-            pm_message("Y  color component: %.2f dB",
-                       10 * log10(maxSumSqDiff/ySumSqDiff) );
-        else
-            pm_message("Y color component does not differ.");
+    for (i = 0; i < colorSpace.componentCt; ++i) {
+        const char * label;
 
-        if (cbSumSqDiff > 0)
-            pm_message("Cb color component: %.2f dB",
-                       10 * log10(maxSumSqDiff/cbSumSqDiff) );
-        else
-            pm_message("Cb color component does not differ.");
+        pm_asprintf(&label, "%s:", colorSpace.componentName[i]);
 
-        if (crSumSqDiff > 0)
-            pm_message("Cr color component: %.2f dB",
-                       10 * log10(maxSumSqDiff/crSumSqDiff) );
+        if (sumSqDiff.sqDiff[i] > 0)
+            pm_message("  %-6.6s %.2f dB",
+                       label,
+                       10 * log10(maxSumSqDiff/sumSqDiff.sqDiff[i]));
         else
-            pm_message("Cr color component does not differ.");
-
-    } else {
-        if (ySumSqDiff > 0) {
-            pm_message("PSNR between %s and %s: %.2f dB",
-                       filespec1, filespec2,
-                       10 * log10(maxSumSqDiff/ySumSqDiff) );
-        } else
-            pm_message("Images %s and %s don't differ.",
-                       filespec1, filespec2);
+            pm_message("  %-6.6s no difference", label);
+
+        pm_strfree(label);
     }
 }
 
@@ -148,78 +393,42 @@ reportPsnr(struct pam const pam,
 
 int
 main (int argc, const char **argv) {
-    const char * fileName1;  /* name of first file to compare */
-    const char * fileName2;  /* name of second file to compare */
     FILE * if1P;
     FILE * if2P;
     struct pam pam1, pam2;
-    bool color;
-        /* It's a color image */
-    double ySumSqDiff, crSumSqDiff, cbSumSqDiff;
-    tuple *tuplerow1, *tuplerow2;  /* malloc'ed */
-    int row;
+    ColorSpace colorSpace;
     
+    struct CmdlineInfo cmdline;
+
     pm_proginit(&argc, argv);
 
-    if (argc-1 < 2) 
-        pm_error("Takes two arguments:  names of the two files to compare");
-    else {
-        fileName1 = argv[1];
-        fileName2 = argv[2];
+    parseCommandLine(argc, argv, &cmdline);
 
-        if (argc-1 > 2)
-            pm_error("Too many arguments (%u).  The only arguments are "
-                     "the names of the two files to compare", argc-1);
-    }
-    
-    if1P = pm_openr(fileName1);
-    if2P = pm_openr(fileName2);
+    if1P = pm_openr(cmdline.inputFile1Name);
+    if2P = pm_openr(cmdline.inputFile2Name);
 
     pnm_readpaminit(if1P, &pam1, PAM_STRUCT_SIZE(tuple_type));
     pnm_readpaminit(if2P, &pam2, PAM_STRUCT_SIZE(tuple_type));
 
     validateInput(pam1, pam2);
 
-    if (streq(pam1.tuple_type, PAM_PPM_TUPLETYPE)) 
-        color = TRUE;
-    else
-        color = FALSE;
+    if (streq(pam1.tuple_type, PAM_PPM_TUPLETYPE)) {
+        if (cmdline.rgb)
+            colorSpace = rgbColorSpace();
+        else
+            colorSpace = yCbCrColorSpace();
+    } else
+        colorSpace = grayscaleColorSpace();
 
-    tuplerow1 = pnm_allocpamrow(&pam1);
-    tuplerow2 = pnm_allocpamrow(&pam2);
-    
-    ySumSqDiff  = 0.0;
-    cbSumSqDiff = 0.0;
-    crSumSqDiff = 0.0;
+    {
+        struct SqDiff const sumSqDiff =
+            sumSqDiffFromRaster(&pam1, &pam2, colorSpace);
 
-    for (row = 0; row < pam1.height; ++row) {
-        int col;
-        
-        pnm_readpamrow(&pam1, tuplerow1);
-        pnm_readpamrow(&pam2, tuplerow2);
-
-        for (col = 0; col < pam1.width; ++col) {
-            if (color) {
-                double ySqDiff, cbSqDiff, crSqDiff;
-                psnrColor(tuplerow1[col], tuplerow2[col], 
-                          &ySqDiff, &cbSqDiff, &crSqDiff);
-                ySumSqDiff  += ySqDiff;
-                cbSumSqDiff += cbSqDiff;
-                crSumSqDiff += crSqDiff;
-                
-            } else {
-                unsigned int const yDiffSq =
-                    square(udiff(tuplerow1[col][0], tuplerow2[col][0]));
-                ySumSqDiff += yDiffSq;
-            }
-        }
+        reportPsnr(pam1, sumSqDiff, colorSpace,
+                   cmdline.inputFile1Name, cmdline.inputFile2Name);
     }
-
-    reportPsnr(pam1, ySumSqDiff, crSumSqDiff, cbSumSqDiff,
-               fileName1, fileName2);
-
-    pnm_freepamrow(tuplerow1);
-    pnm_freepamrow(tuplerow2);
+    pm_close(if2P);
+    pm_close(if1P);
 
     return 0;
 }
diff --git a/buildtools/Makefile b/buildtools/Makefile
index 6a2e33da..8671c066 100644
--- a/buildtools/Makefile
+++ b/buildtools/Makefile
@@ -8,9 +8,9 @@ include $(BUILDDIR)/config.mk
 
 MERGE_OBJECTS =
 
-PROGS = libopt typegen endiangen
+BUILDPROGS = libopt typegen endiangen
 
-all: $(PROGS)
+all: $(BUILDPROGS)
 
 OMIT_BUILDTOOL_RULE = 1
 include $(SRCDIR)/common.mk
@@ -39,4 +39,4 @@ $(BUILDPROGS):%:%.o
 distclean clean: cleanlocal
 .PHONY: cleanlocal
 cleanlocal:
-	rm -f $(PROGS)
+	rm -f $(BUILDPROGS)
diff --git a/buildtools/README.pkg b/buildtools/README.pkg
index 6761ecf3..d642dee8 100644
--- a/buildtools/README.pkg
+++ b/buildtools/README.pkg
@@ -172,7 +172,7 @@ library might use netpbm-config to generate the necessary compiler and linker
 options to access that library.
 
 Using netpbm-config, it's possible to have a viable Netpbm installation where
-netpbm.config is the only file in any default search path.
+netpbm-config is the only file in any default search path.
 
 The xxx-config concept (in general, not just Netpbm) has largely been replaced
 by the pkg-config concept (see netpbm.pc above).
diff --git a/buildtools/makeman b/buildtools/makeman
index 100ad580..9b2653bf 100755
--- a/buildtools/makeman
+++ b/buildtools/makeman
@@ -51,9 +51,7 @@ def makeman(name, file, indoc):
     # Protect escapes before we try generating font changes.
     indoc = indoc.replace("\\", r"\e")
     # Header-bashing
-    indoc = indoc.replace('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "DTD/xhtml11.dtd">', "")
-    indoc = indoc.replace('<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "")
-    indoc = indoc.replace('<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">\n',"")
+    indoc = re.sub('(?i)<!DOCTYPE html[^>]*>', "", indoc)
     indoc = indoc.replace('<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">', "")
     indoc = indoc.replace('<meta http-equiv="Content-Type" content="text/html; charset=us-ascii"/>', "")
     indoc = indoc.replace('<?xml version="1.1" encoding="iso-8859-1" ?>\n',"")
@@ -210,6 +208,7 @@ def makeman(name, file, indoc):
     # Special characters
     indoc = indoc.replace("&quot;", "'")
     indoc = indoc.replace("&nbsp;", "\\ ")
+    indoc = indoc.replace("\", "\\\\")
     # Tables
     indoc = re.sub(' *<table[^>]*>.*', ".TS", indoc)
     indoc = re.sub(" *</table>.*", ".TE", indoc)
diff --git a/common.mk b/common.mk
index 97413530..a5431727 100644
--- a/common.mk
+++ b/common.mk
@@ -143,12 +143,12 @@ endif
 IMPORTINC_ROOT_HEADERS := pm_config.h inttypes_netpbm.h version.h
 
 IMPORTINC_LIB_HEADERS := \
-  pm.h pbm.h pgm.h ppm.h pnm.h pam.h bitio.h pbmfont.h ppmcmap.h \
+  pm.h pbm.h pgm.h ppm.h pnm.h pam.h pbmfont.h ppmcmap.h \
   pammap.h colorname.h ppmfloyd.h ppmdraw.h pm_system.h ppmdfont.h \
   pm_gamma.h lum.h dithers.h pamdraw.h
 
 IMPORTINC_LIB_UTIL_HEADERS := \
-  bitarith.h bitreverse.h filename.h intcode.h floatcode.h io.h \
+  bitarith.h bitio.h bitreverse.h filename.h intcode.h floatcode.h io.h \
   matrix.h mallocvar.h \
   nsleep.h nstring.h pm_c_util.h shhopt.h token.h \
   wordaccess.h  wordaccess_generic.h wordaccess_64_le.h \
@@ -389,7 +389,7 @@ LDFLAGS_ALL = $(WINICON_OBJECT) \
 
 $(PORTBINARIES) $(MATHBINARIES): %: %.o \
   $(NETPBMLIB) $(LIBOPT) $(WINICON_OBJECT)
-	$(LD) -o $@ $@.o $(ADDL_OBJECTS) $(LDFLAGS_ALL)
+	$(LD) -o $@$(EXE) $@.o $(ADDL_OBJECTS) $(LDFLAGS_ALL)
 
 
 # MERGE STUFF
diff --git a/config.mk.in b/config.mk.in
index a59006e7..0f2ccb6c 100644
--- a/config.mk.in
+++ b/config.mk.in
@@ -110,6 +110,10 @@ LD_FOR_BUILD = $(LD)
 CFLAGS_FOR_BUILD = $(CFLAGS_CONFIG)
 LDFLAGS_FOR_BUILD = $(LDFLAGS)
 
+# WINDRES is the program that creates a linkable object file from 
+# a Windows Icon (.ico) file.
+WINDRES = windres
+
 # MAKE is set automatically by Make to what was used to invoke Make.
 
 INSTALL = $(SRCDIR)/buildtools/install.sh
diff --git a/converter/other/Makefile b/converter/other/Makefile
index e76373ef..f51a780b 100644
--- a/converter/other/Makefile
+++ b/converter/other/Makefile
@@ -46,7 +46,7 @@ else
     HAVE_PNGLIB = Y
     EXTERN_INCLUDES += $(shell libpng$(PNGVER)-config --cflags)
   else
-    # System can't tell use where libpng is; use stuff from config.mk
+    # System can't tell us where libpng is; use stuff from config.mk
     ifneq ($(PNGLIB),NONE)
       HAVE_PNGLIB = Y
       ifneq ($(PNGHDR_DIR)x,x)
@@ -131,7 +131,7 @@ ifneq ($(DONT_HAVE_PROCESS_MGMT),Y)
 endif
 
 ifeq ($(HAVE_PNGLIB),Y)
-  PORTBINARIES += pnmtopng pngtopam pamrgbatopng
+  PORTBINARIES += pamtopng pnmtopng pngtopam
 endif
 ifneq ($(JPEGLIB),NONE)
   PORTBINARIES += jpegtopnm pnmtojpeg
@@ -207,14 +207,14 @@ pngtopam: pngx.o
 pngtopam: ADDL_OBJECTS = pngx.o
 pngtopam: LDFLAGS_TARGET = $(PNGLIB_LIBOPTS)
 
+pamtopng: pngx.o pngtxt.o
+pamtopng: ADDL_OBJECTS = pngx.o pngtxt.o
+pamtopng: LDFLAGS_TARGET = $(PNGLIB_LIBOPTS)
+
 pnmtopng: pngx.o pngtxt.o
 pnmtopng: ADDL_OBJECTS = pngx.o pngtxt.o
 pnmtopng: LDFLAGS_TARGET = $(PNGLIB_LIBOPTS)
 
-pamrgbatopng: pngx.o
-pamrgbatopng: ADDL_OBJECTS = pngx.o
-pamrgbatopng: LDFLAGS_TARGET = $(PNGLIB_LIBOPTS)
-
 jpegtopnm: jpegdatasource.o exif.o
 jpegtopnm: ADDL_OBJECTS = jpegdatasource.o exif.o
 jpegtopnm: LDFLAGS_TARGET = $(shell $(LIBOPT) $(LIBOPTR) $(JPEGLIB))
@@ -242,6 +242,8 @@ pnmtorast rasttopnm: ADDL_OBJECTS = rast.o
 pdbimgtopam pamtopdbimg: ipdb.o
 pdbimgtopam pamtopdbimg: ADDL_OBJECTS = ipdb.o
 
+# Declare dependencies on created header files (symbolic links, actually).
+
 bmptopnm.o bmptopnm.o2: bmp.h
 
 pamtotga.o pamtotga.o2: tga.h
@@ -289,3 +291,8 @@ endif
 # In December 2010, sunicontopnm replaced icontopbm
 	cd $(PKGDIR)/bin ; \
 	$(SYMLINK) sunicontopnm$(EXE) icontopbm$(EXE)
+ifeq ($(HAVE_PNGLIB),Y)
+# In June 2015, pamtopng replaced pamrgbapng
+	cd $(PKGDIR)/bin ; \
+	$(SYMLINK) pamtopng$(EXE) pamrgbatopng$(EXE)
+endif
diff --git a/converter/other/bmptopnm.c b/converter/other/bmptopnm.c
index 84d39989..a069092f 100644
--- a/converter/other/bmptopnm.c
+++ b/converter/other/bmptopnm.c
@@ -1442,8 +1442,6 @@ writeRasterPbm(unsigned char ** const bmpRaster,
   
   We destroy *bmpRaster as a side effect.
 -----------------------------------------------------------------------------*/
-    unsigned int const charBits = (sizeof(unsigned char) * 8);
-        /* Number of bits in a character */
     unsigned int const colChars = pbm_packed_bytes(cols);
     
     int row;
@@ -1463,13 +1461,8 @@ writeRasterPbm(unsigned char ** const bmpRaster,
             for (i = 0; i < colChars; ++i) 
                 bitrow[i] = ~bitrow[i]; /* flip all pixels */ 
         }   
-            
-        if (cols % 8 > 0) {
-            /* adjust final partial byte */
-            bitrow[colChars-1] >>= charBits - cols % charBits;
-            bitrow[colChars-1] <<= charBits - cols % charBits;
-        }
-        
+
+        pbm_cleanrowend_packed(bitrow, cols);
         pbm_writepbmrow_packed(stdout, bitrow, cols, FALSE);
     }
 }
diff --git a/converter/other/cameratopam/camera.c b/converter/other/cameratopam/camera.c
index d318e379..a1adba95 100644
--- a/converter/other/cameratopam/camera.c
+++ b/converter/other/cameratopam/camera.c
@@ -108,7 +108,7 @@ adobe_dng_load_raw_lj(Image const image) {
             twide = raw_width-tcol;
 
         for (jrow=0; jrow < jh.high; jrow++) {
-            ljpeg_row (&jh);
+            ljpeg_row(ifp, &jh);
             for (rp=jh.row, jcol=0; jcol < twide; jcol++)
                 adobeCopyPixel(image,
                                trow+jrow, tcol+jcol, &rp, use_secondary);
@@ -170,7 +170,7 @@ nikon_compressed_load_raw(Image const image) {
     for (row=0; row < height; row++)
         for (col=0; col < raw_width; col++)
         {
-            diff = ljpeg_diff (first_decode);
+            diff = ljpeg_diff (ifp, first_decode);
             if (col < 2) {
                 i = 2*(row & 1) + (col & 1);
                 vpred[i] += diff;
diff --git a/converter/other/cameratopam/ljpeg.c b/converter/other/cameratopam/ljpeg.c
index d5e21d3b..07791e25 100644
--- a/converter/other/cameratopam/ljpeg.c
+++ b/converter/other/cameratopam/ljpeg.c
@@ -20,128 +20,145 @@
  */
 
 int  
-ljpeg_start (FILE * ifp, struct jhead *jh)
-{
-  int i, tag, len;
-  unsigned char data[256], *dp;
-
-  init_decoder();
-  for (i=0; i < 4; i++)
-    jh->huff[i] = free_decode;
-  fread (data, 2, 1, ifp);
-  if (data[0] != 0xff || data[1] != 0xd8) return 0;
-  do {
-    fread (data, 2, 2, ifp);
-    tag =  data[0] << 8 | data[1];
-    len = (data[2] << 8 | data[3]);
-    if (len < 2)
-      pm_error("Length field is %u; must be at least 2", len);
-    else {
-      unsigned int const dataLen = len - 2;
-      if (tag <= 0xff00 || dataLen > 255) return 0;
-      fread (data, 1, dataLen, ifp);
-      switch (tag) {
-      case 0xffc3:
-        jh->bits = data[0];
-        jh->high = data[1] << 8 | data[2];
-        jh->wide = data[3] << 8 | data[4];
-        jh->clrs = data[5];
-        break;
-      case 0xffc4:
-        for (dp = data; dp < data+dataLen && *dp < 4; ) {
-          jh->huff[*dp] = free_decode;
-          dp = make_decoder (++dp, 0);
+ljpeg_start(FILE *         const ifP,
+            struct jhead * const jhP) {
+
+    int i, tag;
+    unsigned char data[256], *dp;
+
+    init_decoder();
+    for (i=0; i < 4; i++)
+        jhP->huff[i] = free_decode;
+    fread (data, 2, 1, ifP);
+    if (data[0] != 0xff || data[1] != 0xd8) return 0;
+    do {
+        unsigned int len;
+
+        fread (data, 2, 2, ifP);
+        tag =  data[0] << 8 | data[1];
+        len = data[2] << 8 | data[3];
+
+        if (len < 2)
+            pm_error("Length field is %u; must be at least 2", len);
+        else {
+            unsigned int const dataLen = len - 2;
+
+            if (tag <= 0xff00 || dataLen > 255) return 0;
+            fread (data, 1, dataLen, ifP);
+            switch (tag) {
+            case 0xffc3:
+                jhP->bits = data[0];
+                jhP->high = data[1] << 8 | data[2];
+                jhP->wide = data[3] << 8 | data[4];
+                jhP->clrs = data[5];
+                break;
+            case 0xffc4:
+                for (dp = data; dp < data + dataLen && *dp < 4; ) {
+                    jhP->huff[*dp] = free_decode;
+                    dp = make_decoder (++dp, 0);
+                }
+            }
         }
-      }
-    }
-  } while (tag != 0xffda);
-  jh->row = calloc (jh->wide*jh->clrs, 2);
-  if (jh->row == NULL)
-      pm_error("Out of memory in ljpeg_start()");
-  for (i=0; i < 4; i++)
-    jh->vpred[i] = 1 << (jh->bits-1);
-  zero_after_ff = 1;
-  getbits(ifp, -1);
-  return 1;
+    } while (tag != 0xffda);
+    jhP->row = calloc (jhP->wide*jhP->clrs, 2);
+    if (jhP->row == NULL)
+        pm_error("Out of memory in ljpeg_start()");
+    for (i=0; i < 4; i++)
+        jhP->vpred[i] = 1 << (jhP->bits-1);
+    zero_after_ff = 1;
+    getbits(ifP, -1);
+    return 1;
 }
 
+
+
 int 
-ljpeg_diff (struct decode *dindex)
-{
-  int len, diff;
-
-  while (dindex->branch[0])
-    dindex = dindex->branch[getbits(ifp, 1)];
-  diff = getbits(ifp, len = dindex->leaf);
-  if ((diff & (1 << (len-1))) == 0)
-    diff -= (1 << len) - 1;
-  return diff;
+ljpeg_diff(FILE *          const ifP,
+           struct decode * const dindexHeadP) {
+
+    int len;
+    int diff;
+    struct decode * dindexP;
+
+    for (dindexP = dindexHeadP; dindexP->branch[0]; )
+        dindexP = dindexP->branch[getbits(ifP, 1)];
+
+    diff = getbits(ifP, len = dindexP->leaf);
+
+    if ((diff & (1 << (len-1))) == 0)
+        diff -= (1 << len) - 1;
+
+    return diff;
 }
 
+
+
 void
-ljpeg_row (struct jhead *jh)
-{
-  int col, c, diff;
-  unsigned short *outp=jh->row;
-
-  for (col=0; col < jh->wide; col++)
-    for (c=0; c < jh->clrs; c++) {
-      diff = ljpeg_diff (jh->huff[c]);
-      *outp = col ? outp[-jh->clrs]+diff : (jh->vpred[c] += diff);
-      outp++;
-    }
+ljpeg_row(FILE *         const ifP,
+          struct jhead * const jhP) {
+
+    int col, c, diff;
+    unsigned short *outp=jhP->row;
+
+    for (col=0; col < jhP->wide; col++)
+        for (c=0; c < jhP->clrs; c++) {
+            diff = ljpeg_diff(ifP, jhP->huff[c]);
+            *outp = col ? outp[-jhP->clrs]+diff : (jhP->vpred[c] += diff);
+            outp++;
+        }
 }
 
 
+
 void  
-lossless_jpeg_load_raw(Image const image) {
-
-  int jwide, jrow, jcol, val, jidx, i, row, col;
-  struct jhead jh;
-  int min=INT_MAX;
-
-  if (!ljpeg_start (ifp, &jh)) return;
-  jwide = jh.wide * jh.clrs;
-
-  for (jrow=0; jrow < jh.high; jrow++) {
-    ljpeg_row (&jh);
-    for (jcol=0; jcol < jwide; jcol++) {
-      val = curve[jh.row[jcol]];
-      jidx = jrow*jwide + jcol;
-      if (raw_width == 5108) {
-    i = jidx / (1680*jh.high);
-    if (i < 2) {
-      row = jidx / 1680 % jh.high;
-      col = jidx % 1680 + i*1680;
-    } else {
-      jidx -= 2*1680*jh.high;
-      row = jidx / 1748;
-      col = jidx % 1748 + 2*1680;
-    }
-      } else if (raw_width == 3516) {
-    row = jidx / 1758;
-    col = jidx % 1758;
-    if (row >= raw_height) {
-      row -= raw_height;
-      col += 1758;
-    }
-      } else {
-    row = jidx / raw_width;
-    col = jidx % raw_width;
-      }
-      if ((unsigned) (row-top_margin) >= height) continue;
-      if ((unsigned) (col-left_margin) < width) {
-    BAYER(row-top_margin,col-left_margin) = val;
-    if (min > val) min = val;
-      } else
-    black += val;
+lossless_jpeg_load_raw(Image  const image) {
+
+    int jwide, jrow, jcol, val, jidx, i, row, col;
+    struct jhead jh;
+    int min=INT_MAX;
+
+    if (!ljpeg_start (ifp, &jh)) return;
+    jwide = jh.wide * jh.clrs;
+
+    for (jrow=0; jrow < jh.high; jrow++) {
+        ljpeg_row (ifp, &jh);
+        for (jcol=0; jcol < jwide; jcol++) {
+            val = curve[jh.row[jcol]];
+            jidx = jrow*jwide + jcol;
+            if (raw_width == 5108) {
+                i = jidx / (1680*jh.high);
+                if (i < 2) {
+                    row = jidx / 1680 % jh.high;
+                    col = jidx % 1680 + i*1680;
+                } else {
+                    jidx -= 2*1680*jh.high;
+                    row = jidx / 1748;
+                    col = jidx % 1748 + 2*1680;
+                }
+            } else if (raw_width == 3516) {
+                row = jidx / 1758;
+                col = jidx % 1758;
+                if (row >= raw_height) {
+                    row -= raw_height;
+                    col += 1758;
+                }
+            } else {
+                row = jidx / raw_width;
+                col = jidx % raw_width;
+            }
+            if ((unsigned) (row-top_margin) >= height) continue;
+            if ((unsigned) (col-left_margin) < width) {
+                BAYER(row-top_margin,col-left_margin) = val;
+                if (min > val) min = val;
+            } else
+                black += val;
+        }
     }
-  }
-  free (jh.row);
-  if (raw_width > width)
-    black /= (raw_width - width) * height;
-  if (!strcasecmp(make,"KODAK"))
-    black = min;
+    free (jh.row);
+    if (raw_width > width)
+        black /= (raw_width - width) * height;
+    if (!strcasecmp(make,"KODAK"))
+        black = min;
 }
 
 
diff --git a/converter/other/cameratopam/ljpeg.h b/converter/other/cameratopam/ljpeg.h
index cfd68eb4..9d9d8ee9 100644
--- a/converter/other/cameratopam/ljpeg.h
+++ b/converter/other/cameratopam/ljpeg.h
@@ -9,10 +9,13 @@ struct jhead {
 LoadRawFn lossless_jpeg_load_raw;
 
 int  
-ljpeg_start (FILE * ifp, struct jhead *jh);
+ljpeg_start (FILE *         const ifP,
+             struct jhead * const jhP);
 
 int 
-ljpeg_diff (struct decode *dindex);
+ljpeg_diff (FILE *          const ifP,
+            struct decode * const dindexP);
 
 void
-ljpeg_row (struct jhead *jh);
+ljpeg_row(FILE *         const ifP,
+          struct jhead * const jhP);
diff --git a/converter/other/pamrgbatopng.c b/converter/other/pamrgbatopng.c
deleted file mode 100644
index 07a5181b..00000000
--- a/converter/other/pamrgbatopng.c
+++ /dev/null
@@ -1,136 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-/* Because of poor design of libpng, you must not #include <setjmp.h> before
-<png.h>.  Compile failure results.
-*/
-#include <png.h>
-#include <setjmp.h>
-
-#include "pm_c_util.h"
-#include "mallocvar.h"
-#include "pam.h"
-#include "pngx.h"
-
-
-
-struct cmdlineInfo {
-    const char * inputFileName;
-};
-
-
-
-static void
-processCommandLine(int                  const argc,
-                   char *               const argv[],
-                   struct cmdlineInfo * const cmdlineP) {
-        
-    if (argc-1 < 1)
-        cmdlineP->inputFileName = "-";
-    else {
-        cmdlineP->inputFileName = argv[1];
-
-        if (argc-1 > 1)
-            pm_error("Too many arguments.  "
-                     "The only argument is the input file name.");
-    }
-}
-
-
-
-static void
-convertPamToPng(const struct pam * const pamP,
-                const tuple *      const tuplerow,
-                png_byte *         const pngRow) {
-    
-    unsigned int col;
-    
-    for (col = 0; col < pamP->width; ++col) {
-        unsigned int plane;
-        
-        for (plane = 0; plane < 4; ++plane)
-            pngRow[4 * col + plane] = tuplerow[col][plane];
-    }
-}
-
-
-
-static void
-writeRaster(const struct pam * const pamP,
-            struct pngx *      const pngxP) {
-    
-    tuple * tupleRow;
-    png_byte * pngRow;
-    
-    tupleRow = pnm_allocpamrow(pamP);
-    MALLOCARRAY(pngRow, pamP->width * 4);
-
-    if (pngRow == NULL)
-        pm_error("Unable to allocate space for PNG pixel row.");
-    else {
-        unsigned int row;
-        for (row = 0; row < pamP->height; ++row) {
-            pnm_readpamrow(pamP, tupleRow);
-            
-            convertPamToPng(pamP, tupleRow, pngRow);
-            
-            png_write_row(pngxP->png_ptr, pngRow);
-        }
-        free(pngRow);
-    }
-    pnm_freepamrow(tupleRow);
-}
-
-
-
-static void
-writePng(const struct pam * const pamP,
-         FILE *             const ofP) {
-
-    struct pngx * pngxP;
-
-    pngx_create(&pngxP, PNGX_WRITE, NULL);
-    
-    pngx_setIhdr(pngxP, pamP->width, pamP->height,
-                 8, PNG_COLOR_TYPE_RGB_ALPHA, 0, 0, 0);
-        
-    png_init_io(pngxP->png_ptr, ofP);
-
-    pngx_writeInfo(pngxP);
-        
-    writeRaster(pamP, pngxP);
-
-    pngx_writeEnd(pngxP);
-        
-    pngx_destroy(pngxP);
-}
-    
-
-
-int
-main(int argc, char * argv[]) {
-
-    FILE * ifP;
-    struct cmdlineInfo cmdline;
-    struct pam pam;
-
-    pnm_init(&argc, argv);
-
-    processCommandLine(argc, argv, &cmdline);
-
-    ifP = pm_openr(cmdline.inputFileName);
-
-    pnm_readpaminit(ifP, &pam, PAM_STRUCT_SIZE(tuple_type));
-    
-    if (pam.depth < 4)
-        pm_error("PAM must have depth at least 4 (red, green, blue, alpha).  "
-                 "This one has depth %u", pam.depth);
-        
-    if (pam.maxval != 255)
-        pm_error("PAM must have maxval 255.  This one has %lu", pam.maxval);
-
-    writePng(&pam, stdout);
-
-    pm_close(ifP);
-
-    return 0;
-}
diff --git a/converter/other/pamtopng.c b/converter/other/pamtopng.c
new file mode 100644
index 00000000..af284ac0
--- /dev/null
+++ b/converter/other/pamtopng.c
@@ -0,0 +1,771 @@
+/*
+** read a PNM/PAM image and produce a Portable Network Graphics (PNG) file
+**
+** derived from pnmtorast.c by Jef Poskanzer and pamrgbatopng.c by Bryan
+** Henderson <bryanh@giraffe-data.com> and probably some other sources
+**
+** Copyright (C) 1995-1998 by Alexander Lehmann <alex@hal.rhein-main.de>
+**                        and Willem van Schaik <willem@schaik.com>
+** Copyright (C) 1999,2001 by Greg Roelofs <newt@pobox.com>
+** Copyright (C) 2015 by Willem van Schaik <willem@schaik.com>
+**
+** Permission to use, copy, modify, and distribute this software and its
+** documentation for any purpose and without fee is hereby granted, provided
+** that the above copyright notice appear in all copies and that both that
+** copyright notice and this permission notice appear in supporting
+** documentation.  This software is provided "as is" without express or
+** implied warranty.
+*/
+
+/*
+  This Netpbm program pamtopng was derived in 2015 from the Netpbm program
+  Pnmtopng. This was a nearly complete rewrite with the following goals:
+
+  - Add ability to create a PNG alpha channel from the alpha channel in a
+    PAM (format P7) file.
+
+  - Simplify the 20 year old pnmtopng code. Because of the many, many features
+    that program implements and its need for backward compatibility, the code
+    had become rather complex.  This program is roughly 1/3 the size of
+    pnmtopng.c that it replaces.
+
+  - In 1995 bandwith was limited and therefore filesize had to be kept
+    small. The original program tried to optimize for that by applying
+    many "clever tricks". Today that isn't an issue anymore, so gone 
+    are filters, palettes, etc. Also, image conversions were removed,
+    because those should be done with other NetPBM tools.
+
+  - Add support for iTXt (international language) chunks.
+*/
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <png.h>
+/* setjmp.h needs to be included after png.h */
+#include <setjmp.h>
+
+#include "pm_c_util.h"
+#include "mallocvar.h"
+#include "nstring.h"
+#include "shhopt.h"
+#include "pam.h"
+#include "pngx.h"
+#include "pngtxt.h"
+
+
+/* global variable */
+static bool verbose;
+
+
+struct CmdlineInfo {
+    const char * inputFileName;
+    unsigned int verbose;
+    unsigned int transparencySpec;
+    const char * transparency;
+    unsigned int chromaSpec;
+    struct pngx_chroma chroma;
+    unsigned int gammaSpec;
+    float gamma;
+    unsigned int srgbintentSpec;
+    pngx_srgbIntent srgbintent;
+    unsigned int textSpec;
+    const char * text;
+    unsigned int ztxtSpec;
+    const char * ztxt;
+    unsigned int itxtSpec;
+    const char * itxt;
+    unsigned int backgroundSpec;
+    const char * background;
+    unsigned int timeSpec;
+    time_t time;
+};
+
+
+
+static void
+parseChromaOpt(const char *         const chromaOpt,
+               struct pngx_chroma * const chromaP) {
+
+    int count;
+    
+    count = sscanf(chromaOpt, "%f %f %f %f %f %f %f %f",
+                   &chromaP->wx, &chromaP->wy,
+                   &chromaP->rx, &chromaP->ry,
+                   &chromaP->gx, &chromaP->gy,
+                   &chromaP->bx, &chromaP->by);
+
+    if (count != 6)
+        pm_error("Invalid syntax for the -rgb option value '%s'.  "
+                 "Should be 6 floating point number: "
+                 "x and y for each of white, red, green, and blue",
+                 chromaOpt);
+}
+
+
+
+static void
+parseSrgbintentOpt(const char *      const srgbintentOpt,
+                   pngx_srgbIntent * const srgbintentP) {
+    
+    if (streq(srgbintentOpt, "perceptual"))
+        *srgbintentP = PNGX_PERCEPTUAL;
+    else if (streq(srgbintentOpt, "relativecolorimetric"))
+        *srgbintentP = PNGX_RELATIVE_COLORIMETRIC;
+    else if (streq(srgbintentOpt, "saturation"))
+        *srgbintentP = PNGX_SATURATION;
+    else if (streq(srgbintentOpt, "absolutecolorimetric"))
+        *srgbintentP = PNGX_ABSOLUTE_COLORIMETRIC;
+    else
+        pm_error("Unrecognized sRGB intent value '%s'.  We understand "
+                 "only 'perceptual', 'relativecolorimetric', "
+                 "'saturation', and 'absolutecolorimetric'",
+                 srgbintentOpt);
+}
+
+
+
+static void
+parseTimeOpt(const char * const timeOpt,
+             time_t *     const timeP) {
+
+    struct tm brokenTime;
+    int year;
+    int month;
+    int count;
+
+    count = sscanf(timeOpt, "%d-%d-%d %d:%d:%d",
+                   &year,
+                   &month,
+                   &brokenTime.tm_mday,
+                   &brokenTime.tm_hour,
+                   &brokenTime.tm_min,
+                   &brokenTime.tm_sec);
+
+    if (count != 6)
+        pm_error("Invalid value for -time '%s'.   It should have "
+                 "the form [yy]yy-mm-dd hh:mm:ss.", timeOpt);
+    
+    if (year < 0)
+        pm_error("Year is negative in -time value '%s'", timeOpt);
+    if (year > 9999)
+        pm_error("Year is more than 4 digits in -time value '%s'",
+                 timeOpt);
+    if (month < 0)
+        pm_error("Month is negative in -time value '%s'", timeOpt);
+    if (month > 12)
+        pm_error("Month is >12 in -time value '%s'", timeOpt);
+    if (brokenTime.tm_mday < 0)
+        pm_error("Day of month is negative in -time value '%s'",
+                 timeOpt);
+    if (brokenTime.tm_mday > 31)
+        pm_error("Day of month is >31 in -time value '%s'", timeOpt);
+    if (brokenTime.tm_hour < 0)
+        pm_error("Hour is negative in -time value '%s'", timeOpt);
+    if (brokenTime.tm_hour > 23)
+        pm_error("Hour is >23 in -time value '%s'", timeOpt);
+    if (brokenTime.tm_min < 0)
+        pm_error("Minute is negative in -time value '%s'", timeOpt);
+    if (brokenTime.tm_min > 59)
+        pm_error("Minute is >59 in -time value '%s'", timeOpt);
+    if (brokenTime.tm_sec < 0)
+        pm_error("Second is negative in -time value '%s'", timeOpt);
+    if (brokenTime.tm_sec > 59)
+        pm_error("Second is >59 in -time value '%s'", timeOpt);
+
+    brokenTime.tm_mon = month - 1;
+    if (year >= 1900)
+        brokenTime.tm_year = year - 1900;
+    else
+        brokenTime.tm_year = year;
+
+    /* Note that mktime() considers brokeTime to be in local time.
+       This is what we want, since we got it from a user.  User should
+       set his local time zone to UTC if he wants absolute time.
+    */
+    *timeP = mktime(&brokenTime);
+}
+
+
+
+static void
+parseCommandLine (int                  argc,
+                  const char **        argv,
+                  struct CmdlineInfo * const cmdlineP) {
+    
+    optEntry * option_def;
+    optStruct3 opt;
+    unsigned int option_def_index = 0;  /* incremented by OPTENT3 */
+
+    const char * srgbintent;
+    const char * chroma;
+    const char * time;
+
+    MALLOCARRAY(option_def, 100);
+
+    OPTENT3(0,  "verbose",      OPT_FLAG,       NULL,
+            &cmdlineP->verbose,        0);
+    OPTENT3(0,  "transparency", OPT_STRING,     &cmdlineP->transparency,
+            &cmdlineP->transparencySpec, 0);
+    OPTENT3(0,  "chroma",       OPT_STRING,     &chroma,
+            &cmdlineP->chromaSpec,     0);
+    OPTENT3(0,  "gamma",        OPT_FLOAT,      &cmdlineP->gamma,
+            &cmdlineP->gammaSpec,      0);
+    OPTENT3(0,  "srgbintent",   OPT_STRING,     &srgbintent,
+            &cmdlineP->srgbintentSpec, 0);
+    OPTENT3(0,  "text",         OPT_STRING,     &cmdlineP->text,
+            &cmdlineP->textSpec,       0);
+    OPTENT3(0,  "ztxt",         OPT_STRING,     &cmdlineP->ztxt,
+            &cmdlineP->ztxtSpec,       0);
+    OPTENT3(0,  "itxt",         OPT_STRING,     &cmdlineP->itxt,
+            &cmdlineP->itxtSpec,       0);
+    OPTENT3(0,  "background",   OPT_STRING,     &cmdlineP->background,
+            &cmdlineP->backgroundSpec, 0);
+    OPTENT3(0,  "time",         OPT_STRING,        &time,
+            &cmdlineP->timeSpec,       0);
+
+    opt.opt_table = option_def;
+    opt.short_allowed = false;  /* we have no short (old-fashioned) options */
+    opt.allowNegNum = false;  /* we have no parms that are negative numbers */
+
+    /* uses and sets argc, argv, and some of *cmdlineP and others */
+    pm_optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0);
+
+    if (cmdlineP->chromaSpec)
+        parseChromaOpt(chroma, &cmdlineP->chroma);
+
+    if (cmdlineP->srgbintentSpec)
+        parseSrgbintentOpt(srgbintent, &cmdlineP->srgbintent);
+
+    if (cmdlineP->timeSpec)
+        parseTimeOpt(time, &cmdlineP->time);
+    
+    /* get the input-file or stdin pipe */
+    if (argc-1 < 1)
+        cmdlineP->inputFileName = "-";
+    else if (argc-1 == 1)
+        cmdlineP->inputFileName = argv[1];
+    else
+        pm_error("Program takes at most one argument: input file name.");
+
+    free(option_def);
+}
+
+
+
+static png_byte
+colorTypeFromInputType(const struct pam * const pamP) {
+/*----------------------------------------------------------------------------
+  Analyse the Netpbm image for color-type and bit-depth
+-----------------------------------------------------------------------------*/
+    png_byte retval;
+
+    if (pamP->depth < 1 && pamP->depth > 4)
+        pm_error ("Number of color planes must be between 1 and 4 inclusive");
+
+    if (pamP->maxval != 1 && pamP->maxval != 3 && pamP->maxval != 15 &&
+        pamP->maxval != 255 && pamP->maxval != 65535)
+        pm_error("The maxval of the input image is %u; "
+                 "it must be 1, 3, 15, 255 or 65535", (unsigned)pamP->maxval);
+
+    if (strneq(pamP->tuple_type, "RGB_ALPHA", 9)) {
+        if (pamP->depth == 4)
+            retval = PNG_COLOR_TYPE_RGB_ALPHA;
+        else
+            pm_error("Input tuple type is RGB_ALPHA, "
+                     "but number of planes is %u instead of 4",
+                pamP->depth);
+    } else if (strneq(pamP->tuple_type, "RGB", 3)) {
+        if (pamP->depth == 3)
+            retval = PNG_COLOR_TYPE_RGB;
+        else
+            pm_error("Input tuple type is RGB, "
+                     "but number of planes is %u instead of 3",
+                     pamP->depth);
+    } else if (strneq(pamP->tuple_type, "GRAYSCALE_ALPHA", 15)) {
+        if (pamP->depth == 2)
+            retval = PNG_COLOR_TYPE_GRAY_ALPHA;
+        else
+            pm_error("Input tupel type is GRAYSCALE_ALPHA, "
+                     "but number of planes is %u instread of 2",
+                     pamP->depth);
+    } else if (strneq(pamP->tuple_type, "GRAYSCALE", 9)) {
+        if (pamP->depth == 1)
+            retval = PNG_COLOR_TYPE_GRAY;
+        else
+            pm_error("Input tuple type is GRAYSCALE, "
+                     "but number of planes is %u instead of 1",
+                     pamP->depth);
+    } else if (strneq(pamP->tuple_type, "BLACKANDWHITE", 3)) {
+        if (pamP->depth != 1)
+            pm_error("Input tuple type is BLACKANDWHITE, "
+                     "but number of planes is %u instead of 1",
+                     pamP->depth);
+        if (pamP->maxval != 1)
+            pm_error("Input tuple type is BLACKANDWHITE, "
+                     "but maxval is %u instead of 1", (unsigned)pamP->maxval);
+
+        retval = PNG_COLOR_TYPE_GRAY;
+    } else
+        pm_error("Unrecognized tuple type: '%s'", pamP->tuple_type);
+
+    return retval;
+}
+
+
+
+/*****************************************************************************
+*  Subroutines that create all the (ancillary) chunks
+*****************************************************************************/
+
+
+
+static png_color_16
+parseAndScaleColor(const char * const colorString,
+                   xelval       const pngMaxval) {
+
+    png_color_16 pngColor;
+
+    if (colorString) {
+        xel const inputColor = ppm_parsecolor(colorString, PNM_OVERALLMAXVAL);
+
+        xel scaledColor;
+
+        /* Scale the color down to the PNG bit depth */
+        PPM_DEPTH(scaledColor, inputColor, PNM_OVERALLMAXVAL, pngMaxval);
+
+        pngColor.red   = PPM_GETR(scaledColor);
+        pngColor.green = PPM_GETG(scaledColor);
+        pngColor.blue  = PPM_GETB(scaledColor);
+        pngColor.gray  = PNM_GET1(scaledColor);
+    }
+
+    return pngColor;
+}
+
+
+
+static void
+doTrnsChunk(const struct pam * const pamP,
+            struct pngx *      const pngxP,
+            const char *       const trans) {
+
+    if (pngx_colorType(pngxP) == PNG_COLOR_TYPE_GRAY_ALPHA || 
+        pngx_colorType(pngxP) == PNG_COLOR_TYPE_RGB_ALPHA)
+        pm_error("Both alpha channel and transparency chunk not allowed.");
+    else {
+        xelval const pngMaxval = pm_bitstomaxval(pngx_bitDepth(pngxP));
+        png_color_16 const pngColor = parseAndScaleColor(trans, pngMaxval);
+            /* Transparency color from text format scaled from 16-bit to
+               maxval.
+            */
+
+        pngx_setTrnsValue(pngxP, pngColor);
+
+        if (verbose) {
+            if (pngx_colorType(pngxP) == PNG_COLOR_TYPE_GRAY) {
+                pm_message("writing tRNS chunk with color {gray} = {%u}",
+                           pngColor.gray );
+            } else if (pngx_colorType(pngxP) == PNG_COLOR_TYPE_RGB) {
+                pm_message("writing tRNS chunk with color "
+                           "{red, green, blue} = {%u, %u, %u}",
+                           pngColor.red, pngColor.green, pngColor.blue);
+            }
+        }
+    }
+}
+
+
+
+static void
+doChrmChunk(struct pngx *      const pngxP,
+            struct pngx_chroma const chroma) {
+    
+    pngx_setChrm(pngxP, chroma);
+
+    if (verbose) {
+        pm_message("writing cHRM chunk { wx, wy, rx, ry, gx, gy, bx, by } = "
+                   "{ %4.2f, %4.2f, %4.2f, %4.2f, "
+                   "%4.2f, %4.2f, %4.2f, %4.2f }", 
+                   chroma.wx, chroma.wy,
+                   chroma.rx, chroma.ry,
+                   chroma.gx, chroma.gy,
+                   chroma.bx, chroma.by);
+    }
+}
+
+
+
+static void 
+doGamaChunk(struct pngx *  const pngxP,
+            float          const gamma) {
+
+    pngx_setGama(pngxP, gamma);
+
+    if (verbose) {
+        pm_message("writing gAMA chunk with image gamma value %4.2f", gamma);
+    }
+}
+
+
+
+static void
+doSbitChunk(const struct pam * const pamP,
+            struct pngx *      const pngxP) {
+
+    unsigned int const pnmBitDepth = pm_maxvaltobits(pamP->maxval);
+
+    /* create SBIT chunk in case of 1,2,4 bit deep images stored in 8 bit
+       format PNG files 
+    */
+    if (pngx_colorType(pngxP) != PNG_COLOR_TYPE_GRAY && pnmBitDepth < 8) {
+        png_color_8 sBit;
+
+        if (pngx_colorType(pngxP) == PNG_COLOR_TYPE_RGB || 
+            pngx_colorType(pngxP) == PNG_COLOR_TYPE_RGB_ALPHA) {
+            sBit.red = sBit.green = sBit.blue = pnmBitDepth;
+        } else {
+            sBit.gray = pnmBitDepth;
+        }
+        if (pngx_colorType(pngxP) == PNG_COLOR_TYPE_RGB_ALPHA || 
+            pngx_colorType(pngxP) == PNG_COLOR_TYPE_GRAY_ALPHA) {
+            sBit.alpha = pnmBitDepth;
+        }
+        pngx_setSbit(pngxP, sBit);
+    }
+}
+
+
+
+static void
+doSrgbChunk(struct pngx *   const pngxP,
+            pngx_srgbIntent const srgbIntent) {
+
+    pngx_setSrgb(pngxP, srgbIntent);
+
+    if (verbose) {
+        pm_message("writing sRGB chunk with intent value %s",
+                   pngx_srgbIntentDesc(srgbIntent));
+    }
+}
+
+
+
+static void
+doTextChunk(struct pngx * const pngxP,
+            const char *  const textFileName) {
+
+    FILE * tfP;
+
+    tfP = pm_openr(textFileName);
+    
+    pngtxt_read(pngxP, tfP, false, verbose);
+    
+    if (verbose)
+        pm_message("writing tEXt chunk");
+
+    pm_close(tfP);
+}
+
+
+
+static void
+doZtxtChunk(struct pngx * const pngxP,
+            const char *  const textFileName) {
+
+    FILE * tfP;
+
+    tfP = pm_openr(textFileName);
+    
+    pngtxt_read(pngxP, tfP, true, verbose);
+    
+    if (verbose)
+        pm_message("writing zTXt chunk");
+
+    pm_close(tfP);
+    
+}
+
+
+
+
+static void
+doItxtChunk (struct pngx * const pngxP,
+             const char *  const textFileName) {
+
+    FILE * tfP;
+
+    tfP = pm_openr(textFileName);
+
+    pm_error("Code to handle an ITXT chunk has not been written yet");
+
+    /* pngtxt_read(pngxP, tfP, true, true, verbose); */
+
+    if (verbose)
+        pm_message("writing iTXt chunk");
+}
+
+
+
+static void
+doBkgdChunk (const struct pam * const pamP,
+             struct pngx *      const pngxP,
+             const char *       const colorName)
+{
+    xelval const pngMaxval = pm_bitstomaxval(pngx_bitDepth(pngxP));
+
+    png_color_16 const pngColor = parseAndScaleColor(colorName, pngMaxval);
+        /* Background color from text format, scaled from 16-bit to maxval */
+
+    pngx_setBkgdRgb(pngxP, pngColor);
+
+    if (verbose) {
+        if (pngx_colorType(pngxP) == PNG_COLOR_TYPE_GRAY || 
+            pngx_colorType(pngxP) == PNG_COLOR_TYPE_GRAY_ALPHA) {
+            pm_message("writing bKGD chunk with gray level = %u",
+                       pngColor.gray);
+        } else if (pngx_colorType(pngxP) == PNG_COLOR_TYPE_RGB || 
+                   pngx_colorType(pngxP) == PNG_COLOR_TYPE_RGB_ALPHA) {
+            pm_message("writing bKGD chunk with color {red, green, blue} = "
+                       "{%u, %u, %u}",
+                       pngColor.red, pngColor.green, pngColor.blue);
+        }
+    }
+}
+
+
+
+static void
+doTimeChunk(struct pngx * const pngxP,
+            time_t        const time) {
+
+    pngx_setTime(pngxP, time);
+
+    if (verbose) {
+        struct tm * const brokenTimeP = gmtime(&time);
+
+        char buffer[100];
+
+        strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", brokenTimeP);
+
+        pm_message("Writing tIME chunk specifying datetime %s", buffer);
+    }
+}
+
+
+
+static void
+convertRaster(const struct pam * const pamP,
+              const tuple *      const tuplerow,
+              png_byte *         const pngRow,
+              unsigned int       const bitDepth) {
+
+    unsigned int col;
+
+    /* An image row consists of columns x planes like gray or rgb(a) x 8 or 16
+       bits.
+    */
+    for (col = 0; col < pamP->width; ++col) {
+        unsigned int plane;
+        for (plane = 0; plane < pamP->depth; ++plane) {
+            if (bitDepth > 8) {
+                /* Copy 2 bytes = 16 bits for one pixel */
+                pngRow[2 * (pamP->depth * col + plane)] =
+                    (tuplerow[col][plane] >> 8) & 0xff ;
+                pngRow[2 * (pamP->depth * col + plane) + 1] =
+                    tuplerow[col][plane] & 0xff ;
+            } else {
+                /* Copy 1 byte for one pixel. Later, a packing of 2, 4 or 8
+                   pixels into a single byte can still happen.
+                */
+                pngRow[pamP->depth * col + plane] = tuplerow[col][plane];
+            }
+        }
+    }
+}
+
+
+
+static void
+writeRaster(const struct pam * const pamP,
+            struct pngx *      const pngxP,
+            int                const bitDepth) {
+
+    tuple * tupleRow;
+    png_byte * pngRow;
+    unsigned int row;
+
+    /* We process row-by-row and do not read the complete image into memory */
+
+    tupleRow = pnm_allocpamrow(pamP);
+
+    MALLOCARRAY(pngRow, pamP->width * 8);
+        /* sufficient to store a 16-bit RGB+A row */
+
+    if (pngRow == NULL)
+        pm_error("Unable to allocate space for PNG pixel row for "
+                 "%u columns", pamP->width);
+    else {
+        for (row = 0; row < pamP->height; ++row) {
+            pnm_readpamrow(pamP, tupleRow);
+
+            convertRaster(pamP, tupleRow, pngRow, bitDepth);
+
+            png_write_row(pngxP->png_ptr, pngRow);
+        }
+        free(pngRow);
+    }
+    pnm_freepamrow(tupleRow);
+}
+
+
+
+static void
+writePng(const struct pam * const pamP,
+         FILE *             const ofP,
+         struct CmdlineInfo const cmdline) {
+
+    unsigned int const pnmBitDepth = pm_maxvaltobits(pamP->maxval);
+    int const pngColorType = colorTypeFromInputType(pamP);
+
+    struct pngx * pngxP;
+    unsigned int pngBitDepth;
+    png_color_8 sBit;
+
+    pngx_create(&pngxP, PNGX_WRITE, NULL);
+
+
+
+    if ((pngColorType == PNG_COLOR_TYPE_RGB ||
+         pngColorType == PNG_COLOR_TYPE_RGB_ALPHA) &&
+        pnmBitDepth < 8) {
+
+        pngBitDepth = 8;
+    } else
+        pngBitDepth = pnmBitDepth;
+
+    png_init_io(pngxP->png_ptr, ofP);
+
+    pngx_setIhdr(pngxP, pamP->width, pamP->height,
+                 pngBitDepth, pngColorType,
+                 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
+                 PNG_FILTER_TYPE_BASE);
+
+    /* Where requested, add ancillary chunks */
+    if (cmdline.transparencySpec)
+        doTrnsChunk(pamP, pngxP,cmdline.transparency);
+
+    if (cmdline.chromaSpec)
+        doChrmChunk(pngxP, cmdline.chroma);
+
+    if (cmdline.gammaSpec)
+        doGamaChunk(pngxP, cmdline.gamma);
+
+    /* no iccp */
+
+    doSbitChunk(pamP, pngxP);
+
+    if (cmdline.srgbintentSpec)
+        doSrgbChunk(pngxP, cmdline.srgbintent);
+
+    if (cmdline.textSpec)
+        doTextChunk(pngxP, cmdline.text);
+
+    if (cmdline.ztxtSpec)
+        doZtxtChunk(pngxP, cmdline.ztxt);
+
+    if (cmdline.itxtSpec)
+        doItxtChunk(pngxP, cmdline.itxt);
+
+    if (cmdline.backgroundSpec)
+        doBkgdChunk(pamP, pngxP, cmdline.background);
+
+    /* no hist */
+
+    /* no phys */
+
+    /* no splt */
+
+    if (cmdline.timeSpec)
+        doTimeChunk(pngxP, cmdline.time);
+
+    /* Write the ancillary chunks to PNG file */
+    pngx_writeInfo(pngxP);
+
+    if (pngColorType != PNG_COLOR_TYPE_GRAY && pnmBitDepth < 8) {
+        /* Move the 1, 2, 4 bits to most significant bits */
+        pngx_setShift(pngxP, sBit);
+    }
+    if ((pngColorType == PNG_COLOR_TYPE_GRAY) && (pnmBitDepth < 8)) {
+        /* Pack multiple pixels in a byte */
+        pngx_setPacking(pngxP);
+    }
+
+    writeRaster(pamP, pngxP, pnmBitDepth);
+
+    pngx_writeEnd(pngxP);
+    pngx_destroy(pngxP);
+}
+
+
+
+
+static void
+reportInputFormat(const struct pam * const pamP) {
+
+    const char * formatDesc;
+
+    if (pamP->format == PBM_FORMAT || pamP->format == RPBM_FORMAT)
+        formatDesc = "PBM";
+    else if (pamP->format == PGM_FORMAT || pamP->format == RPGM_FORMAT)
+        formatDesc = "PGM";
+    else if (pamP->format == PPM_FORMAT || pamP->format == RPPM_FORMAT)
+        formatDesc = "PPM";
+    else if (pamP->format == PAM_FORMAT)
+        formatDesc = "PAM";
+    else
+        formatDesc = NULL;
+
+    if (formatDesc)
+        pm_message("Input format = %s", formatDesc);
+    else
+        pm_message("Unrecognized input format, format code = 0x%x",
+                   pamP->format);
+
+    pm_message("Input tuple type = '%s'", pamP->tuple_type);
+    pm_message("Input depth = %u", pamP->depth);
+    pm_message("Input maxval = %u", (unsigned int) pamP->maxval);
+}
+
+
+
+int
+main(int           argc,
+     const char ** argv) {
+
+    FILE * ifP;
+    struct CmdlineInfo cmdline;
+    struct pam pam;
+
+    pm_proginit(&argc, argv);
+
+    parseCommandLine(argc, argv, &cmdline);
+
+    verbose = cmdline.verbose;
+
+    ifP = pm_openr(cmdline.inputFileName);
+
+    pnm_readpaminit(ifP, &pam, PAM_STRUCT_SIZE(tuple_type));
+
+    if (verbose)
+        reportInputFormat(&pam);
+
+    writePng(&pam, stdout, cmdline);
+
+    pm_close(ifP);
+
+    return 0;
+}
+
+
+
diff --git a/converter/other/pamtosvg/pxl-outline.c b/converter/other/pamtosvg/pxl-outline.c
index a1fa5299..456f41e1 100644
--- a/converter/other/pamtosvg/pxl-outline.c
+++ b/converter/other/pamtosvg/pxl-outline.c
@@ -9,7 +9,6 @@
 
 #include "message.h"
 #include "bitmap.h"
-#include "bitmap.h"
 #include "logreport.h"
 #include "pxl-outline.h"
 
diff --git a/converter/other/pngtxt.c b/converter/other/pngtxt.c
index 853edf0a..bca06d73 100644
--- a/converter/other/pngtxt.c
+++ b/converter/other/pngtxt.c
@@ -242,7 +242,7 @@ handleArrayAllocation(png_text **    const arrayP,
 
 void 
 pngtxt_read(struct pngx * const pngxP,
-            FILE *        const tfp, 
+            FILE *        const fileP, 
             bool          const ztxt,
             bool          const verbose) {
 
@@ -266,7 +266,7 @@ pngtxt_read(struct pngx * const pngxP,
    
     eof = FALSE;
     while (!eof) {
-        getFileLine(tfp, &textline, &lineLength);
+        getFileLine(fileP, &textline, &lineLength);
         if (textline == NULL)
             eof = TRUE;
         else {
diff --git a/converter/other/pngx.c b/converter/other/pngx.c
index 8d7b7c70..c9f6c7e9 100644
--- a/converter/other/pngx.c
+++ b/converter/other/pngx.c
@@ -322,6 +322,45 @@ pngx_setChrm(struct pngx *      const pngxP,
 
 
 
+const char *
+pngx_srgbIntentDesc(pngx_srgbIntent const srgbIntent) {
+
+    switch (srgbIntent) {
+    case PNGX_PERCEPTUAL:            return "PERCEPTUAL";
+    case PNGX_RELATIVE_COLORIMETRIC: return "RELATIVE COLORIMETRIC";
+    case PNGX_SATURATION:            return "SATURATION";
+    case PNGX_ABSOLUTE_COLORIMETRIC: return "ABSOLUTE_COLORIMETRIC";
+    }
+    assert(false);
+}
+
+
+
+static int
+const libpngSrgbIntentCode(pngx_srgbIntent const srgbIntent) {
+
+    switch (srgbIntent) {
+    case PNGX_PERCEPTUAL:            return 0;
+    case PNGX_RELATIVE_COLORIMETRIC: return 1;
+    case PNGX_SATURATION:            return 2;
+    case PNGX_ABSOLUTE_COLORIMETRIC: return 3;
+    }
+
+    assert(false);  /* All cases above return */
+}
+
+
+
+void
+pngx_setSrgb(struct pngx *   const pngxP,
+             pngx_srgbIntent const srgbIntent) {
+
+    png_set_sRGB(pngxP->png_ptr, pngxP->info_ptr,
+                 libpngSrgbIntentCode(srgbIntent));
+}
+
+
+
 void
 pngx_setCompressionSize(struct pngx * const pngxP,
                         unsigned int  const bufferSize) {
@@ -476,13 +515,13 @@ pngx_setText(struct pngx * const pngxP,
 
 void
 pngx_setTime(struct pngx * const pngxP,
-             png_time      const timeArg) {
+             time_t        const timeArg) {
 
-    png_time time;
+    png_time pngTime;
 
-    time = timeArg;
+    png_convert_from_time_t(&pngTime, timeArg);
 
-    png_set_tIME(pngxP->png_ptr, pngxP->info_ptr, &time);
+    png_set_tIME(pngxP->png_ptr, pngxP->info_ptr, &pngTime);
 }
 
 
diff --git a/converter/other/pngx.h b/converter/other/pngx.h
index 10e8204d..1252e32a 100644
--- a/converter/other/pngx.h
+++ b/converter/other/pngx.h
@@ -128,6 +128,20 @@ void
 pngx_setChrm(struct pngx *      const pngxP,
              struct pngx_chroma const chroma);
 
+typedef enum {
+    PNGX_PERCEPTUAL,
+    PNGX_RELATIVE_COLORIMETRIC,
+    PNGX_SATURATION,
+    PNGX_ABSOLUTE_COLORIMETRIC
+} pngx_srgbIntent;
+
+const char *
+pngx_srgbIntentDesc(pngx_srgbIntent const srgbIntent);
+
+void
+pngx_setSrgb(struct pngx *   const pngxP,
+             pngx_srgbIntent const srgbIntent);
+
 void
 pngx_setCompressionSize(struct pngx * const pngxP,
                         unsigned int  const bufferSize);
@@ -196,7 +210,7 @@ pngx_setText(struct pngx * const pngxP,
 
 void
 pngx_setTime(struct pngx * const pngxP,
-             png_time      const time);
+             time_t        const timeArg);
 
 void
 pngx_setTrnsPalette(struct pngx *    const pngxP,
diff --git a/converter/other/pnmtopng.c b/converter/other/pnmtopng.c
index 154ca279..8cf9f92e 100644
--- a/converter/other/pnmtopng.c
+++ b/converter/other/pnmtopng.c
@@ -120,6 +120,8 @@ struct cmdlineInfo {
     struct pngx_chroma rgb;          /* Meaningless if !rgbSpec */
     unsigned int  sizeSpec;
     struct pngx_phys   size;         /* Meaningless if !sizeSpec */
+    unsigned int srgbintentSpec;
+    pngx_srgbIntent srgbintent;
     const char *  text;         /* NULL if none */
     const char *  ztxt;         /* NULL if none */
     unsigned int  modtimeSpec;
@@ -199,6 +201,27 @@ parseRgbOpt(const char *         const rgbOpt,
 
 
 static void
+parseSrgbintentOpt(const char *      const srgbintentOpt,
+                   pngx_srgbIntent * const srgbintentP) {
+    
+    if (streq(srgbintentOpt, "perceptual"))
+        *srgbintentP = PNGX_PERCEPTUAL;
+    else if (streq(srgbintentOpt, "relativecolorimetric"))
+        *srgbintentP = PNGX_RELATIVE_COLORIMETRIC;
+    else if (streq(srgbintentOpt, "saturation"))
+        *srgbintentP = PNGX_SATURATION;
+    else if (streq(srgbintentOpt, "absolutecolorimetric"))
+        *srgbintentP = PNGX_ABSOLUTE_COLORIMETRIC;
+    else
+        pm_error("Unrecognized sRGB intent value '%s'.  We understand "
+                 "only 'perceptual', 'relativecolorimetric', "
+                 "'saturation', and 'absolutecolorimetric'",
+                 srgbintentOpt);
+}
+
+
+
+static void
 parseModtimeOpt(const char * const modtimeOpt,
                 time_t *     const modtimeP) {
 
@@ -292,6 +315,7 @@ parseCommandLine(int argc, const char ** argv,
     const char * modtime;
     const char * compMethod;
     const char * compStrategy;
+    const char * srgbintent;
 
     MALLOCARRAY_NOFAIL(option_def, 100);
 
@@ -306,6 +330,8 @@ parseCommandLine(int argc, const char ** argv,
             &cmdlineP->rgbSpec,    0);
     OPTENT3(0, "size",             OPT_STRING,    &size,
             &cmdlineP->sizeSpec,   0);
+    OPTENT3(0,  "srgbintent",      OPT_STRING,    &srgbintent,
+            &cmdlineP->srgbintentSpec, 0);
     OPTENT3(0, "text",             OPT_STRING,    &cmdlineP->text,
             &textSpec,             0);
     OPTENT3(0, "ztxt",             OPT_STRING,    &cmdlineP->ztxt,
@@ -433,6 +459,9 @@ parseCommandLine(int argc, const char ** argv,
     if (cmdlineP->rgbSpec)
         parseRgbOpt(rgb, &cmdlineP->rgb);
     
+    if (cmdlineP->srgbintentSpec)
+        parseSrgbintentOpt(srgbintent, &cmdlineP->srgbintent);
+
     if (cmdlineP->modtimeSpec)
         parseModtimeOpt(modtime, &cmdlineP->modtime);
 
@@ -2460,11 +2489,8 @@ static void
 doTimeChunk(struct cmdlineInfo const cmdline,
             struct pngx *      const pngxP) {
 
-    if (cmdline.modtimeSpec) {
-        png_time pngTime;
-        png_convert_from_time_t(&pngTime, cmdline.modtime);
-        pngx_setTime(pngxP, pngTime);
-    }
+    if (cmdline.modtimeSpec)
+        pngx_setTime(pngxP, cmdline.modtime);
 }
 
 
@@ -2604,6 +2630,20 @@ doSbitChunk(struct pngx * const pngxP,
 
 
 
+static void
+addSrgbChunk(struct pngx *   const pngxP,
+             pngx_srgbIntent const srgbIntent) {
+
+    pngx_setSrgb(pngxP, srgbIntent);
+
+    if (verbose) {
+        pm_message("writing sRGB chunk with intent value %s",
+                   pngx_srgbIntentDesc(srgbIntent));
+    }
+}
+
+
+
 static void 
 convertpnm(struct cmdlineInfo const cmdline,
            FILE *             const ifP,
@@ -2813,6 +2853,9 @@ convertpnm(struct cmdlineInfo const cmdline,
 
     doSbitChunk(pngxP, pngMaxval, maxval, alpha, alphaMaxval);
 
+    if (cmdline.srgbintentSpec)
+        addSrgbChunk(pngxP, cmdline.srgbintent);
+
     /* tEXT and zTXT chunks */
     if (cmdline.text || cmdline.ztxt)
         pngtxt_read(pngxP, tfP, !!cmdline.ztxt, cmdline.verbose);
diff --git a/converter/other/pnmtops.c b/converter/other/pnmtops.c
index cf6b2873..6cd6be95 100644
--- a/converter/other/pnmtops.c
+++ b/converter/other/pnmtops.c
@@ -1853,18 +1853,14 @@ convertRowPbm(struct pam *     const pamP,
 ----------------------------------------------------------------------*/
     unsigned int colChar;
     unsigned int const colChars = pbm_packed_bytes(pamP->width);
-    unsigned int const padRight = (8 - pamP->width %8) %8;
 
     pbm_readpbmrow_packed(pamP->file, bitrow, pamP->width, pamP->format);
 
     for (colChar = 0; colChar < colChars; ++colChar)
         bitrow[colChar] =  ~ bitrow[colChar];
 
-    if (padRight > 0) {
-        bitrow[colChars-1] >>= padRight;  /* Zero clear padding beyond */
-        bitrow[colChars-1] <<= padRight;  /* right edge */
-    }
-
+    /* Zero clear padding beyond right edge */
+    pbm_cleanrowend_packed(bitrow, pamP->width);
     writeFile(bitrow, colChars, "PBM reader", fP);
 }
 
diff --git a/converter/other/pnmtoxwd.c b/converter/other/pnmtoxwd.c
index 8a001390..eda2ee8f 100644
--- a/converter/other/pnmtoxwd.c
+++ b/converter/other/pnmtoxwd.c
@@ -20,11 +20,11 @@
 #include "x11wd.h"
 
 
-struct cmdlineInfo {
+struct CmdlineInfo {
     /* All the information the user supplied in the command line,
        in a form easy for the program to use.
     */
-    const char *inputFilespec;  /* Filespecs of input file */
+    const char * inputFilename;  /* Filename of input file */
     unsigned int pseudodepth;
     unsigned int directcolor;
 };
@@ -34,7 +34,7 @@ struct cmdlineInfo {
 static void 
 parseCommandLine(int argc, 
                  char ** argv, 
-                 struct cmdlineInfo  * const cmdlineP) {
+                 struct CmdlineInfo  * const cmdlineP) {
 /* --------------------------------------------------------------------------
    Parse program command line described in Unix standard form by argc
    and argv.  Return the information in the options as *cmdlineP.  
@@ -78,12 +78,12 @@ parseCommandLine(int argc,
     }
 
     if (argc-1 == 0) 
-        cmdlineP->inputFilespec = "-";
+        cmdlineP->inputFilename = "-";
     else if (argc-1 != 1)
         pm_error("Program takes zero or one argument (filename).  You "
                  "specified %d", argc-1);
     else
-        cmdlineP->inputFilespec = argv[1];
+        cmdlineP->inputFilename = argv[1];
 }
 
 
@@ -410,7 +410,7 @@ writeRaster(FILE *           const ofP,
 int
 main(int argc, char * argv[]) {
 
-    struct cmdlineInfo cmdline;
+    struct CmdlineInfo cmdline;
     FILE* ifP;
     xel ** xels;
     int rows, cols, format, colors;
@@ -426,7 +426,7 @@ main(int argc, char * argv[]) {
 
     parseCommandLine(argc, argv, &cmdline);
 
-    ifP = pm_openr(cmdline.inputFilespec);
+    ifP = pm_openr(cmdline.inputFilename);
 
     xels = pnm_readpnm(ifP, &cols, &rows, &maxval, &format);
     xmaxval = (1 << cmdline.pseudodepth) - 1;
@@ -473,13 +473,13 @@ main(int argc, char * argv[]) {
         }
     }
 
-    if (streq(cmdline.inputFilespec, "-"))
+    if (streq(cmdline.inputFilename, "-"))
         dumpname = "stdin";
     else {
-        if (strlen(cmdline.inputFilespec) > XWDVAL_MAX - sizeof(h11) - 1)
+        if (strlen(cmdline.inputFilename) > XWDVAL_MAX - sizeof(h11) - 1)
             pm_error("Input file name is ridiculously long.");
         else
-            dumpname = cmdline.inputFilespec;
+            dumpname = cmdline.inputFilename;
     }
 
     setupX11Header(&h11, dumpname, cols, rows, format, 
diff --git a/converter/other/sgitopnm.c b/converter/other/sgitopnm.c
index 008d5376..6fd4efcf 100644
--- a/converter/other/sgitopnm.c
+++ b/converter/other/sgitopnm.c
@@ -28,6 +28,7 @@
 #include "pnm.h"
 #include "sgi.h"
 
+#define MAX_ZSIZE 256
 
 
 struct CmdlineInfo {
@@ -82,6 +83,10 @@ parseCommandLine(int argc, const char ** argv,
 
     free(option_def);
 
+    if (!cmdlineP->channelSpec)
+        cmdlineP->channel = MAX_ZSIZE + 1;
+            /* Invalid value; to suppress Valgrind error */
+
     if (argc-1 < 1)
         cmdlineP->inputFileName = "-";
     else if (argc-1 == 1)
@@ -212,7 +217,7 @@ readHeader(FILE *       const ifP,
     headP->xsize     = getBigShort(ifP);
     headP->ysize     = getBigShort(ifP);
     headP->zsize     = getBigShort(ifP);
-    if (headP->zsize > 256)
+    if (headP->zsize > MAX_ZSIZE)
         pm_error("Too many channels in input image: %u",
                  (unsigned int) headP->zsize );
     headP->pixmin    = getBigLong(ifP);
diff --git a/converter/pbm/atktopbm.c b/converter/pbm/atktopbm.c
index 62664999..807e4f4a 100644
--- a/converter/pbm/atktopbm.c
+++ b/converter/pbm/atktopbm.c
@@ -61,17 +61,24 @@
 */
 
 /* macros to generate case entries for switch statement */
-#define case1(v) case v
-#define case4(v) case v: case (v)+1: case (v)+2: case(v)+3
-#define case6(v) case4(v): case ((v)+4): case ((v)+5)
-#define case8(v) case4(v): case4((v)+4)
+#define CASE1(v) case v
+#define CASE4(v) case v: case (v)+1: case (v)+2: case(v)+3
+#define CASE6(v) CASE4(v): case ((v)+4): case ((v)+5)
+#define CASE8(v) CASE4(v): CASE4((v)+4)
+
+
 
 static long
-ReadRow(FILE * const file, unsigned char * const row, long const length) {
+ReadRow(FILE *          const file,
+        unsigned char * const row,
+        long            const length) {
 /*----------------------------------------------------------------------------
   'file' is where to get them from.
   'row' is where to put bytes.
   'length' is how many bytes in row must be filled.
+  
+  Return the delimiter that marks the end of the row, or EOF if EOF marks
+  the end of the row, or NUL in some cases.
 -----------------------------------------------------------------------------*/
     /* Each input character is processed by the central loop.  There are 
     ** some input codes which require two or three characters for
@@ -80,18 +87,23 @@ ReadRow(FILE * const file, unsigned char * const row, long const length) {
     ** to the Ready state whenever a character unacceptable to the
     ** current state is read.
     */
-    enum stateCode {
-        Ready,      /* any input code is allowed */
-        HexDigitPending,    /* have seen the first of a hex digit pair */
-        RepeatPending,  /* repeat code has been seen:
-                   must be followed by two hex digits */
-        RepeatAndDigit};    /* have seen repeat code and its first
-                   following digit */
-    enum stateCode InputState;  /* current state */
-    register int c;     /* the current input character */
-    register long repeatcount = 0;  /* current repeat value */
-    register long hexval;   /* current hex value */
-    long pendinghex = 0;    /* the first of a pair of hex characters */
+    enum StateCode {
+        Ready,
+            /* any input code is allowed */
+        HexDigitPending,
+            /* have seen the first of a hex digit pair */
+        RepeatPending,
+            /* repeat code has been seen: must be followed by two hex digits
+             */
+        RepeatAndDigit
+            /* have seen repeat code and its first following digit */
+    };
+    
+    enum StateCode InputState;  /* current state */
+    int c;     /* the current input character */
+    long repeatcount;  /* current repeat value */
+    long hexval;   /* current hex value */
+    long pendinghex;    /* the first of a pair of hex characters */
     int lengthRemaining;
     unsigned char * cursor;
     
@@ -101,262 +113,239 @@ ReadRow(FILE * const file, unsigned char * const row, long const length) {
     ** zero, we ungetc the byte.
     */
 
-    lengthRemaining = length;
-    cursor = row;
+    repeatcount = 0;  /* initial value */
+    pendinghex = 0;  /* initial value */
+
+    lengthRemaining = length;  /* initial value */
+    cursor = row;  /* initial value */
+    InputState = Ready;  /* initial value */
 
-    InputState = Ready;
     while ((c=getc(file)) != EOF) switch (c) {
 
-    case8(0x0):
-    case8(0x8):
-    case8(0x10):
-    case8(0x18):
-    case1(' '):
-        /* control characters and space are legal and ignored */
-        break;
-    case1(0x40):    /* '@' */
-    case1(0x5B):    /* '[' */
-    case4(0x5D):    /*  ']'  '^'  '_'  '`' */
-    case4(0x7D):    /* '}'  '~'  DEL  0x80 */
-    default:        /* all above 0x80 */
-        /* error code:  Ignored at present.  Reset InputState. */
-        InputState = Ready;
-        break;
-
-    case1(0x7B):    /* '{' */
-    case1(0x5C):    /* '\\' */
-        /* illegal end of line:  exit anyway */
-        ungetc(c, file);    /* retain terminator in stream */
-        /* DROP THROUGH */
-    case1(0x7C):    /* '|' */
-        /* legal end of row: may have to pad  */
-        while (lengthRemaining-- > 0)
-            *cursor++ = WHITEBYTE;
-        return c;
+        CASE8(0x0):
+        CASE8(0x8):
+        CASE8(0x10):
+        CASE8(0x18):
+        CASE1(' '):
+            /* control characters and space are legal and ignored */
+            break;
+        CASE1(0x40):    /* '@' */
+        CASE1(0x5B):    /* '[' */
+        CASE4(0x5D):    /*  ']'  '^'  '_'  '`' */
+        CASE4(0x7D):    /* '}'  '~'  DEL  0x80 */
+        default:        /* all above 0x80 */
+            /* error code:  Ignored at present.  Reset InputState. */
+            InputState = Ready;
+            break;
+
+        CASE1(0x7B):    /* '{' */
+        CASE1(0x5C):    /* '\\' */
+            /* illegal end of line:  exit anyway */
+            ungetc(c, file);    /* retain terminator in stream */
+            /* DROP THROUGH */
+        CASE1(0x7C):    /* '|' */
+            /* legal end of row: may have to pad  */
+            while (lengthRemaining-- > 0)
+                *cursor++ = WHITEBYTE;
+            return c;
     
-    case1(0x21):
-    case6(0x22):
-    case8(0x28):
-        /* punctuation characters: repeat byte given by two
-        ** succeeding hex chars
-        */
-        if (lengthRemaining <= 0) {
-            ungetc(c, file);
-            return('\0');
-        }
-        repeatcount = c - OTHERZERO;
-        InputState = RepeatPending;
-        break;
-
-    case8(0x30):
-    case8(0x38):
-        /* digit (or following punctuation)  -  hex digit */
-        hexval = c - 0x30;
-        goto hexdigit;
-    case6(0x41):
-        /* A ... F    -  hex digit */
-        hexval = c - (0x41 - 0xA);
-        goto hexdigit;
-    case6(0x61):
-        /* a ... f  - hex digit */
-        hexval = c - (0x61 - 0xA);
-        goto hexdigit;
-
-    case8(0x67):
-    case8(0x6F):
-    case4(0x77):
-        /* g ... z   -   multiple WHITE bytes */
-        if (lengthRemaining <= 0) {
-            ungetc(c, file);
-            return('\0');
-        }
-        repeatcount = c - WHITEZERO;
-        hexval = WHITEBYTE;
-        goto store;
-    case8(0x47):
-    case8(0x4F):
-    case4(0x57):
-        /* G ... Z   -   multiple BLACK bytes */
-        if (lengthRemaining <= 0) {
-            ungetc(c, file);
-            return('\0');
-        }
-        repeatcount = c - BLACKZERO;
-        hexval = BLACKBYTE;
-        goto store;
-
-hexdigit:
-        /* process a hex digit.  Use InputState to determine
-            what to do with it. */
-        if (lengthRemaining <= 0) {
-            ungetc(c, file);
-            return('\0');
-        }
-        switch(InputState) {
-        case Ready:
-            InputState = HexDigitPending;
-            pendinghex = hexval << 4;
+        CASE1(0x21):
+        CASE6(0x22):
+        CASE8(0x28):
+            /* punctuation characters: repeat byte given by two
+            ** succeeding hex chars
+            */
+            if (lengthRemaining <= 0) {
+                ungetc(c, file);
+                return('\0');
+            }
+            repeatcount = c - OTHERZERO;
+            InputState = RepeatPending;
             break;
-        case HexDigitPending:
-            hexval |= pendinghex;
-            repeatcount = 1;
+
+        CASE8(0x30):
+        CASE8(0x38):
+            /* digit (or following punctuation)  -  hex digit */
+            hexval = c - 0x30;
+            goto hexdigit;
+        CASE6(0x41):
+            /* A ... F    -  hex digit */
+            hexval = c - (0x41 - 0xA);
+            goto hexdigit;
+        CASE6(0x61):
+            /* a ... f  - hex digit */
+            hexval = c - (0x61 - 0xA);
+            goto hexdigit;
+
+        CASE8(0x67):
+        CASE8(0x6F):
+        CASE4(0x77):
+            /* g ... z   -   multiple WHITE bytes */
+            if (lengthRemaining <= 0) {
+                ungetc(c, file);
+                return('\0');
+            }
+            repeatcount = c - WHITEZERO;
+            hexval = WHITEBYTE;
             goto store;
-        case RepeatPending:
-            InputState = RepeatAndDigit;
-            pendinghex = hexval << 4;
-            break;
-        case RepeatAndDigit:
-            hexval |= pendinghex;
+        CASE8(0x47):
+        CASE8(0x4F):
+        CASE4(0x57):
+            /* G ... Z   -   multiple BLACK bytes */
+            if (lengthRemaining <= 0) {
+                ungetc(c, file);
+                return('\0');
+            }
+            repeatcount = c - BLACKZERO;
+            hexval = BLACKBYTE;
             goto store;
-        }
-        break;
-
-store:
-        /* generate byte(s) into the output row 
-            Use repeatcount, depending on state.  */
-        if (lengthRemaining < repeatcount) 
-            /* reduce repeat count if it would exceed
-                available space */
-            repeatcount = lengthRemaining;
-        lengthRemaining -= repeatcount;  /* do this before repeatcount-- */
-        while (repeatcount-- > 0)
+
+        hexdigit:
+            /* process a hex digit.  Use InputState to determine
+               what to do with it. */
+            if (lengthRemaining <= 0) {
+                ungetc(c, file);
+                return('\0');
+            }
+            switch(InputState) {
+            case Ready:
+                InputState = HexDigitPending;
+                pendinghex = hexval << 4;
+                break;
+            case HexDigitPending:
+                hexval |= pendinghex;
+                repeatcount = 1;
+                goto store;
+            case RepeatPending:
+                InputState = RepeatAndDigit;
+                pendinghex = hexval << 4;
+                break;
+            case RepeatAndDigit:
+                hexval |= pendinghex;
+                goto store;
+            }
+            break;
+
+        store:
+            /* generate byte(s) into the output row 
+               Use repeatcount, depending on state.  */
+            if (lengthRemaining < repeatcount) 
+                /* reduce repeat count if it would exceed
+                   available space */
+                repeatcount = lengthRemaining;
+            lengthRemaining -= repeatcount;  /* do this before repeatcount-- */
+            while (repeatcount-- > 0)
                 *cursor++ = hexval;
-        InputState = Ready;
-        break;
+            InputState = Ready;
+            break;
 
-    } /* end of while( - )switch( - ) */
+        } /* end of while( - )switch( - ) */
     return EOF;
 }
 
 
 
-#undef case1
-#undef case4
-#undef case6
-#undef case8
+#undef CASE1
+#undef CASE4
+#undef CASE6
+#undef CASE8
 
 
 
 static void
-ReadATKRaster(FILE * const file, 
-              int * const rwidth, 
-              int * const rheight, 
-              unsigned char ** const destaddrP) {
+ReadATKRaster(FILE * const ifP) {
 
-    int row, rowlen;  /* count rows;  byte length of row */
+    int row;  /* count rows;  byte length of row */
     int version;
     char keyword[6];
     int discardid;
     int objectid;     /* id read for the incoming pixel image */
     long tc;            /* temp */
     int width, height;      /* dimensions of image */
+    bit * bitrow;
 
-    if (fscanf(file, "\\begindata{raster,%d", &discardid) != 1
-                || getc(file) != '}' || getc(file) != '\n')
-      pm_error ("input file not Andrew raster object");
+    if (fscanf(ifP, "\\begindata{raster,%d", &discardid) != 1
+        || getc(ifP) != '}' || getc(ifP) != '\n')
+        pm_error ("input file not Andrew raster object");
 
-    fscanf(file, " %d ", &version);
+    fscanf(ifP, " %d ", &version);
     if (version < 2) 
-      pm_error ("version too old to parse");
+        pm_error ("version too old to parse");
 
     {
         unsigned int options;
         long xscale, yscale;
         long xoffset, yoffset, subwidth, subheight;
         /* ignore all these features: */
-        fscanf(file, " %u %ld %ld %ld %ld %ld %ld",  
+        fscanf(ifP, " %u %ld %ld %ld %ld %ld %ld",  
                &options, &xscale, &yscale, &xoffset, 
                &yoffset, &subwidth, &subheight);
     }
     /* scan to end of line in case this is actually something beyond V2 */
-    while (((tc=getc(file)) != '\n') && (tc != '\\') && (tc != EOF)) {}
+    while (((tc=getc(ifP)) != '\n') && (tc != '\\') && (tc != EOF)) {}
 
     /* read the keyword */
-    fscanf(file, " %5s", keyword);
+    fscanf(ifP, " %5s", keyword);
     if (!streq(keyword, "bits"))
-      pm_error ("keyword is not 'bits'!");
+        pm_error ("keyword is not 'bits'!");
 
-    fscanf(file, " %d %d %d ", &objectid, &width, &height);
+    fscanf(ifP, " %d %d %d ", &objectid, &width, &height);
 
     if (width < 1 || height < 1 || width > 1000000 || height > 1000000) 
-      pm_error ("bad width or height");
-
-    *rwidth = width;
-    *rheight = height;
-    rowlen = (width + 7) / 8;
-    MALLOCARRAY(*destaddrP, height * rowlen);
-    if (destaddrP == NULL)
-        pm_error("Unable to allocate %u bytes for the input image.",
-                 height * rowlen);
-    for (row = 0;   row < height;   row++)
-      {
-        long c;
-
-        c = ReadRow(file, *destaddrP + (row * rowlen), rowlen);
-        if (c != '|')
-          {
-        if (c == EOF)
-          pm_error ("premature EOF");
-        else
-          pm_error ("bad format");
-        break;
-          }
-      }
-    while (! feof(file) && getc(file) != '\\') {};  /* scan for \enddata */
-    if (fscanf(file, "enddata{raster,%d", &discardid) != 1
-        || getc(file) != '}' || getc(file) != '\n')
-      pm_error ("missing end-of-object marker");
-}
+        pm_error("bad width or height");
 
+    pbm_writepbminit(stdout, width, height, 0);
+    bitrow = pbm_allocrow_packed(width);
 
+    for (row = 0;   row < height; ++row) {
+        unsigned int const rowlen = (width + 7) / 8;
+        long const nextChar = ReadRow(ifP, bitrow, rowlen);
 
-int
-main(int argc, char **argv) {
+        switch (nextChar) {
+        case '|': 
+            pbm_writepbmrow_packed(stdout, bitrow, width, 0);
+            break;
+        case EOF:
+            pm_error("premature EOF");
+            break;
+        default:
+            pm_error("bad format");
+        }
+    }
 
-    FILE *ifp;
-    register bit *bitrow, *bP;
-    int rows, cols, row, col, charcount;
-    unsigned char *data, mask;
+    pbm_freerow_packed(bitrow);
 
+    while (! feof(ifP) && getc(ifP) != '\\') {};  /* scan for \enddata */
 
-    pbm_init ( &argc, argv );
+    if (fscanf(ifP, "enddata{raster,%d", &discardid) != 1
+        || getc(ifP) != '}' || getc(ifP) != '\n')
+        pm_error("missing end-of-object marker");
+}
 
-    if ( argc > 2 )
-        pm_usage( "[raster obj]" );
-    
-    if ( argc == 2 )
-        ifp = pm_openr( argv[1] );
-    else
-        ifp = stdin;
 
-    ReadATKRaster( ifp, &cols, &rows, &data );
 
-    pm_close( ifp );
+int
+main(int argc, const char ** argv) {
 
-    pbm_writepbminit( stdout, cols, rows, 0 );
-    bitrow = pbm_allocrow( cols );
+    FILE * ifP;
 
-    for ( row = 0; row < rows; ++row )
-    {
-        charcount = 0;
-        mask = 0x80;
-        for ( col = 0, bP = bitrow; col < cols; ++col, ++bP )
-        {
-            if ( charcount >= 8 )
-            {
-                ++data;
-                charcount = 0;
-                mask = 0x80;
-            }
-            *bP = ( *data & mask ) ? PBM_BLACK : PBM_WHITE;
-            ++charcount;
-            mask >>= 1;
-        }
-        ++data;
-        pbm_writepbmrow( stdout, bitrow, cols, 0 );
+    pm_proginit(&argc, argv);
+
+    if (argc-1 < 1)
+        ifP = stdin;
+    else {
+        ifP = pm_openr(argv[1]);
+
+        if (argc-1 > 1)
+            pm_error("Too many arguments.  The only possible argument is "
+                     "the input file name");
     }
 
-    pm_close( stdout );
-    exit( 0 );
-}
+    ReadATKRaster(ifP);
+
+    pm_close(ifP);
 
+    pm_close(stdout);
+
+    return 0;
+}
diff --git a/converter/pbm/brushtopbm.c b/converter/pbm/brushtopbm.c
index c50fe8a1..ebd817be 100644
--- a/converter/pbm/brushtopbm.c
+++ b/converter/pbm/brushtopbm.c
@@ -93,11 +93,7 @@ main(int argc, const char ** argv)  {
             bitrow[i] = ~bitrow[i];
 
         /* Clean off remainder of fractional last character */
-        if (cols % 8 > 0) {
-            unsigned int const colChars = pbm_packed_bytes(cols);
-            bitrow[colChars-1] >>= 8 - cols % 8;
-            bitrow[colChars-1] <<= 8 - cols % 8;
-        }
+        pbm_cleanrowend_packed(bitrow, cols);
 
         pbm_writepbmrow_packed(stdout, bitrow, cols, 0);
     }
diff --git a/converter/pbm/macp.h b/converter/pbm/macp.h
index 26a720a2..d00dc5c9 100644
--- a/converter/pbm/macp.h
+++ b/converter/pbm/macp.h
@@ -1,12 +1,16 @@
-/* macp.h - header file for MacPaint files
-*/
-
+/*=============================================================================
+                               macp.h
+===============================================================================
+  Information about MacPaint files
+=============================================================================*/
 #ifndef MACP_H_INCLUDED
 #define MACP_H_INCLUDED
 
-#define	HEADER_LENGTH	512
-#define	MAX_LINES	720
-#define	BYTES_WIDE	72
-#define MAX_COLS	576	/* = BYTES_WIDE * 8 */
+#define	MACBIN_HEAD_LEN	128
+#define	MACP_HEAD_LEN	512
+#define	MACP_ROWS	720
+#define	MACP_COLCHARS	72
+#define MACP_COLS	((MACP_COLCHARS) * 8)
+#define MACP_BYTES	((MACP_COLCHARS) * (MACP_ROWS))
 
 #endif
diff --git a/converter/pbm/macptopbm.c b/converter/pbm/macptopbm.c
index f4a341d3..db628b6c 100644
--- a/converter/pbm/macptopbm.c
+++ b/converter/pbm/macptopbm.c
@@ -1,6 +1,8 @@
 /* macptopbm.c - read a MacPaint file and produce a portable bitmap
 **
 ** Copyright (C) 1988 by Jef Poskanzer.
+** Some code of ReadMacPaintFile() is based on the work of
+** Patrick J. Naughton.  (C) 1987, All Rights Reserved.
 **
 ** Permission to use, copy, modify, and distribute this software and its
 ** documentation for any purpose and without fee is hereby granted, provided
@@ -8,133 +10,347 @@
 ** copyright notice and this permission notice appear in supporting
 ** documentation.  This software is provided "as is" without express or
 ** implied warranty.
+
+
+** Apr 2015 afu
+** Changed code style (ANSI-style function definitions, etc.)
+** Added automatic detection of MacBinary header.
+** Added diagnostics for corruptions.
+** Replaced byte-wise operations with bit-wise ones.
 */
 
 #include "pbm.h"
+#include "pm_c_util.h"
 #include "macp.h"
 
-static void ReadMacPaintFile ARGS(( FILE* file, int extraskip, int* scanLineP, unsigned char Pic[MAX_LINES][BYTES_WIDE] ));
 
-static unsigned char Pic[MAX_LINES][BYTES_WIDE];
+
+static bool
+validateMacPaintVersion( const unsigned char * const rBuff,
+                         const int offset ) {
+/*---------------------------------------------------------------------------
+  Macpaint (or PNTG) files have two headers.
+  The 512 byte MacPaint header is mandatory.
+  The newer 128 byte MacBinary header is optional.  If it exists, it comes
+  before the MacPaint header.
+
+  Here we examine the first four bytes of the MacPaint header to get
+  the version number.
+
+  Valid version numbers are 0, 2, 3.
+  We also allow 1.
+-----------------------------------------------------------------------------*/
+
+    bool retval;
+    const unsigned char * const vNum = rBuff + offset;
+
+   if ( ( ( vNum[0] | vNum[1] | vNum[2] ) != 0x00 ) || vNum[3] > 3 )
+        retval = FALSE;
+    else
+        retval = TRUE;
+
+    pm_message("MacPaint version (at offset %u): %02x %02x %02x %02x (%s)",
+               offset, vNum[0], vNum[1], vNum[2], vNum[3],
+               retval == TRUE ? "valid" : "not valid" );
+
+    return( retval );
+}
+
+
+
+static bool
+scanMacBinaryHeader( const unsigned char * rBuff ) {
+/*----------------------------------------------------------------------------
+  We check byte 0 and 1, and then the MacPaint header version assuming it
+  starts at offset 128.
+
+  Byte 0: must be 0x00.
+  Byte 1: (filename length) must be 1-63.
+
+  Other fields that may be of interest:
+
+  Bytes 2 through 63: (Internal Filename)
+    See Apple Charmap for valid characters.
+    Unlike US-Ascii, 8-bit characters (range 0x80 - 0xFF) are valid.
+    0x00-0x1F and 0x7F are control characters.  0x00 appears in some files.
+    Colon ':' (0x3a) should be avoided in Mac environments but in practice
+    does appear.
+
+  Bytes 65 through 68: (File Type)
+    Four Ascii characters.  Should be "PNTG".
+
+  Bytes 82 to 85: (SizeOfDataFork)
+    uint32 value.  It seems this is file size (in bytes) / 256 + N, N <= 4.
+
+  Bytes 100 through 124:
+    Should be all zero if the header is MacBinary I.
+    Defined and used in MacBinary II.
+
+  Bytes 124,125: CRC
+    (MacBinary II only) CRC value of bytes 0 through 123.
+
+  All multi-byte values are big-endian.
+
+  Reference:
+  http://www.fileformat.info/format/macpaint/egff.htm
+  Fully describes the fields.  However, the detection method described
+  does not work very well.
+
+  Also see:
+  http://fileformats.archiveteam.org/wiki/MacPaint
+-----------------------------------------------------------------------------*/
+    bool          foundMacBinaryHeader;
+
+    /* Examine byte 0.  It should be 0x00.  Note that the first
+       byte of a valid MacPaint header should also be 0x00.
+    */
+    if ( rBuff[0] != 0x00 ) {
+        foundMacBinaryHeader = FALSE;
+    }
+
+    /* Examine byte 1, the length of the filename.
+       It should be in the range 1 - 63.
+    */
+    else if( rBuff[1] == 0 || rBuff[1] > 63 ) {
+        foundMacBinaryHeader = FALSE;
+    }
+
+    /* Check the MacPaint header version starting at offset 128. */
+    else if ( validateMacPaintVersion ( rBuff, MACBIN_HEAD_LEN ) == FALSE) {
+        foundMacBinaryHeader = FALSE;
+    }
+    else
+        foundMacBinaryHeader = TRUE;
+
+    if( foundMacBinaryHeader == TRUE)
+      pm_message("Input file contains a MacBinary header "
+                   "followed by a MacPaint header.");
+    else
+      pm_message("Input file does not start with a MacBinary header.");
+
+    return ( foundMacBinaryHeader );
+}
+
+
+
+
+static void
+skipHeader( FILE * const ifP ) {
+/*--------------------------------------------------------------------------
+  Determine whether the MacBinary header exists.
+  If it does, read off the initial 640 (=128 + 512) bytes of the file.
+  If it doesn't, read off 512 bytes.
+
+  In the latter case we check the MacHeader version number, but just issue
+  a warning if the value is invalid.  This is for backward comaptibility.
+---------------------------------------------------------------------------*/
+    unsigned int re;
+    const unsigned int buffsize = MAX( MACBIN_HEAD_LEN, MACP_HEAD_LEN );
+    unsigned char * const rBuff = malloc(buffsize);
+
+    if( rBuff == NULL )
+        pm_error("Out of memory.");
+
+    /* Read 512 bytes.
+       See if MacBinary header exists in the first 128 bytes and
+       the next 4 bytes signal the start of a MacPaint header. */
+    re = fread ( rBuff, MACP_HEAD_LEN, 1, ifP);
+        if (re < 1)
+        pm_error("EOF/error while reading header.");
+
+    if ( scanMacBinaryHeader( rBuff ) == TRUE ) {
+    /* MacBinary header found.  Read another 128 bytes to complete the
+       MacPaint header, but don't conduct any further analysis. */
+        re = fread ( rBuff, MACBIN_HEAD_LEN, 1, ifP);
+            if (re < 1)
+            pm_error("EOF/error while reading MacPaint header.");
+
+    } else {
+    /* MacBinary header not found.  We assume file starts with
+       MacPaint header.   Check MacPaint version but dismiss error. */
+        if (validateMacPaintVersion( rBuff, 0 ) == TRUE)
+          pm_message("Input file starts with valid MacPaint header.");
+        else
+          pm_message("  - Ignoring invalid version number.");
+    }
+    free( rBuff );
+}
+
+
+
+static void
+skipExtraBytes( FILE * const ifP,
+                int    const extraskip) {
+/*--------------------------------------------------------------------------
+  This function exists for backward compatibility.  Its purpose is to
+  manually delete the MacBinary header.
+
+  We check the MacHeader version number, but just issue a warning if the
+  value is invalid.
+---------------------------------------------------------------------------*/
+    unsigned int re;
+    unsigned char * const rBuff = malloc(MAX (extraskip, MACP_HEAD_LEN));
+
+    if( rBuff == NULL )
+        pm_error("Out of memory.");
+
+    re = fread ( rBuff, 1, extraskip, ifP);
+        if (re < extraskip)
+        pm_error("EOF/error while reading off initial %u bytes"
+                     "specified by -extraskip.", extraskip);
+    re = fread ( rBuff, MACP_HEAD_LEN, 1, ifP);
+        if (re < 1)
+        pm_error("EOF/error while reading MacPaint header.");
+
+    /* Check the MacPaint version number.  Dismiss error. */
+    if (validateMacPaintVersion( rBuff, 0 ) == TRUE)
+        pm_message("Input file starts with valid MacPaint header.");
+    else
+        pm_message("  - Ignoring invalid version number.");
+
+    free( rBuff );
+}
+
+
+
+static unsigned char
+readChar( FILE * const ifP ) {
+
+    int const ch = getc( ifP );
+
+    if (ch ==EOF)
+        pm_error("EOF encountered while unpacking image data.");
+
+    /* else */
+        return ((unsigned char) ch);
+}
+
+
+
+
+static void
+ReadMacPaintFile( FILE *  const ifP,
+                  int  * outOfSyncP,
+                  int  * pixelCntP ) {
+/*---------------------------------------------------------------------------
+  Unpack image data.  Compression method is called "Packbits".
+  This run-length encoding scheme has also been adopted by
+  Postscript and TIFF.  See source: converter/other/pnmtops.c
+
+  Unpacked raster array is raw PBM.  No conversion is required.
+
+  One source says flag byte should not be 0xFF (255), but we don't reject
+  the value, for in practice, it is widely used.
+
+  Sequences should never cross row borders.
+  Violations of this rule are recorded in outOfSync.
+
+  Note that pixelCnt counts bytes, not bits, so it is the number of pixels
+  multiplied by 8.  This counter exists to detect corruptions.
+---------------------------------------------------------------------------*/
+    int           pixelCnt   = 0;   /* Initial value */
+    int           outOfSync  = 0;   /* Initial value */
+    unsigned int  flag;             /* Read from input */
+    unsigned int  i;
+    unsigned char * const bitrow = pbm_allocrow_packed(MACP_COLS);
+
+    while ( pixelCnt < MACP_BYTES ) {
+        flag = (unsigned int) readChar( ifP );    /* Flag (count) byte */
+        if ( flag < 0x80 ) {
+            /* Unpack next (flag + 1) chars as is */
+            for ( i = 0; i <= flag; i++ )
+                if( pixelCnt < MACP_BYTES) {
+                  int const colChar = pixelCnt % MACP_COLCHARS;
+                  pixelCnt++;
+                  bitrow[colChar] = readChar( ifP );
+                  if (colChar == MACP_COLCHARS-1)
+                      pbm_writepbmrow_packed( stdout, bitrow, MACP_COLS, 0 );
+                  if (colChar == 0 && i > 0 )
+                      outOfSync++;
+                }
+        }
+        else {
+          /* Repeat next char (2's complement of flagCnt) times */
+            unsigned int  const flagCnt = 256 - flag;
+            unsigned char const ch = readChar( ifP );
+            for ( i = 0; i <= flagCnt; i++ )
+                if( pixelCnt < MACP_BYTES) {
+                  int const colChar = pixelCnt % MACP_COLCHARS;
+                  pixelCnt++;
+                  bitrow[colChar] = ch;
+                  if (colChar == MACP_COLCHARS-1)
+                      pbm_writepbmrow_packed( stdout, bitrow, MACP_COLS, 0 );
+                  if (colChar == 0 && i > 0 )
+                      outOfSync++;
+                }
+        }
+    }
+    pbm_freerow_packed ( bitrow );
+    *outOfSyncP  = outOfSync;
+    *pixelCntP   = pixelCnt;
+}
+
 
 int
-main( argc, argv )
-    int argc;
-    char* argv[];
-    {
-    FILE* ifp;
-    bit* bitrow;
-    int argn, extraskip, scanLine, rows, cols, row, bcol, i;
-    const char* usage = "[-extraskip N] [macpfile]";
+main( int argc, char * argv[])  {
 
+    FILE * ifp;
+    int argn, extraskip;
+    const char * const usage = "[-extraskip N] [macpfile]";
+    int outOfSync;
+    int pixelCnt;
 
     pbm_init( &argc, argv );
 
-    argn = 1;
-    extraskip = 0;
+    argn = 1;      /* initial value */
+    extraskip = 0; /* initial value */
 
     /* Check for flags. */
-    if ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
-	{
-	if ( pm_keymatch( argv[argn], "-extraskip", 2 ) )
-	    {
-	    argn++;
-	    if ( argn == argc || sscanf( argv[argn], "%d", &extraskip ) != 1 )
-		pm_usage( usage );
-	    }
-	else
-	    pm_usage( usage );
-	argn++;
-	}
-
-    if ( argn < argc )
-	{
-	ifp = pm_openr( argv[argn] );
-	argn++;
-	}
+    if ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' ) {
+        if ( pm_keymatch( argv[argn], "-extraskip", 2 ) ) {
+            argn++;
+            if ( argn == argc || sscanf( argv[argn], "%d", &extraskip ) != 1 )
+                pm_usage( usage );
+        }
+        else
+            pm_usage( usage );
+        argn++;
+    }
+
+    if ( argn < argc ) {
+        ifp = pm_openr( argv[argn] );
+        argn++;
+        }
     else
-	ifp = stdin;
+        ifp = stdin;
 
     if ( argn != argc )
-	pm_usage( usage );
+        pm_usage( usage );
 
-    ReadMacPaintFile( ifp, extraskip, &scanLine, Pic );
+    if ( extraskip > 256 * 1024 )
+        pm_error("-extraskip value too large");
+    else if ( extraskip > 0 )
+        skipExtraBytes( ifp, extraskip);
+    else
+        skipHeader( ifp );
 
+    pbm_writepbminit( stdout, MACP_COLS, MACP_ROWS, 0 );
+
+    ReadMacPaintFile( ifp, &outOfSync, &pixelCnt );
+    /* We may not be at EOF.
+       Macpaint files often have extra bytes after image data. */
     pm_close( ifp );
 
-    cols = BYTES_WIDE * 8;
-    rows = scanLine;
-    pbm_writepbminit( stdout, cols, rows, 0 );
-    bitrow = pbm_allocrow( cols );
+    if ( pixelCnt == 0 )
+        pm_error("No image data.");
+
+    else if ( pixelCnt < MACP_BYTES )
+        pm_error("Compressed image data terminated prematurely.");
 
-    for ( row = 0; row < rows; row++ )
-	{
-	for ( bcol = 0; bcol < BYTES_WIDE; bcol++ )
-	    for ( i = 0; i < 8; i++ )
-		bitrow[bcol * 8 + i] =
-		    ( (Pic[row][bcol] >> (7 - i)) & 1 ) ? PBM_BLACK : PBM_WHITE;
-	pbm_writepbmrow( stdout, bitrow, cols, 0 );
-	}
+    else if ( outOfSync > 0 )
+        pm_message("Warning: Corrupt image data.  %d rows misaligned.",
+                   outOfSync);
 
     pm_close( stdout );
     exit( 0 );
-    }
-
-/*
-** Some of the following routine is:
-**
-**                Copyright 1987 by Patrick J. Naughton
-**                         All Rights Reserved
-** Permission to use, copy, modify, and distribute this software and its
-** documentation for any purpose and without fee is hereby granted,
-** provided that the above copyright notice appear in all copies and that
-** both that copyright notice and this permission notice appear in
-** supporting documentation.
-*/
-
-static void
-ReadMacPaintFile( file, extraskip, scanLineP, Pic )
-    FILE* file;
-    int extraskip;
-    int* scanLineP;
-    unsigned char Pic[MAX_LINES][BYTES_WIDE];
-    {
-    unsigned int i, j, k;
-    unsigned char ch;
-
-    /* Skip over the header. */
-    for ( i = 0; i < extraskip; i++ )
-	getc( file );
-    for ( i = 0; i < HEADER_LENGTH; i++ )
-	getc( file );
-
-    *scanLineP = 0;
-    k = 0;
-
-    while ( *scanLineP < MAX_LINES )
-	{
-	ch = (unsigned char) getc( file );	/* Count byte */
-	i = (unsigned int) ch;
-	if ( ch < 0x80 )
-	    {	/* Unpack next (I+1) chars as is */
-	    for ( j = 0; j <= i; j++ )
-		if ( *scanLineP < MAX_LINES )
-		    {
-		    Pic[*scanLineP][k++] = (unsigned char) getc( file );
-		    if ( ! (k %= BYTES_WIDE) )
-			*scanLineP += 1;
-		    }
-	    }
-	else
-	    {	/* Repeat next char (2's comp I) times */
-	    ch = getc( file );
-	    for ( j = 0; j <= 256 - i; j++ )
-		if ( *scanLineP < MAX_LINES )
-		    {
-		    Pic[*scanLineP][k++] = (unsigned char) ch;
-		    if ( ! (k %= BYTES_WIDE) )
-			*scanLineP += 1;
-		    }
-	    }
-	}
-    }
+}
diff --git a/converter/pbm/pbmto10x.c b/converter/pbm/pbmto10x.c
index 8a3edb36..d040b3ed 100644
--- a/converter/pbm/pbmto10x.c
+++ b/converter/pbm/pbmto10x.c
@@ -12,16 +12,14 @@
 ** Modified to shorten stripes and eliminate blank stripes. Dec 1994.
 */
 
+#include <stdbool.h>
+
 #include "pbm.h"
 #include "mallocvar.h"
 
 #define LOW_RES_ROWS    8       /* printed per pass */
 #define HIGH_RES_ROWS   16      /* printed per pass */
 
-static int  highres = 0;
-static FILE *ifp;
-static int  rows, cols, format;
-
 
 
 static void
@@ -29,8 +27,6 @@ outstripe(char * const stripe,
           char * const sP, 
           int    const reschar) {
 
-    int ncols;
-
     char * p;
 
     p = sP;  /* initial value */
@@ -41,10 +37,14 @@ outstripe(char * const stripe,
             ++p;
             break;
         }
-    ncols = p - stripe;
-    if (ncols > 0) {
-        printf("\033%c%c%c", reschar, ncols % 256, ncols / 256);
-        fwrite(stripe, sizeof(char), ncols, stdout);
+
+    {
+        unsigned int const ncols = p - stripe;
+
+        if (ncols > 0) {
+            printf("\033%c%c%c", reschar, ncols % 256, ncols / 256);
+            fwrite(stripe, sizeof(char), ncols, stdout);
+        }
     }
     putchar('\n');          /* flush buffer */
 }
@@ -52,26 +52,44 @@ outstripe(char * const stripe,
 
 
 static void
-res_60x72(void) {
-    int i, item, npins, row, col;
-    bit *bitrows[LOW_RES_ROWS], *bP[LOW_RES_ROWS];
-    char *stripe, *sP;
+res_60x72(FILE * const ifP,
+          int    const rows,
+          int    const cols,
+          int    const format) {
+
+    int row;
+    unsigned int i;
+    bit * bitrows[LOW_RES_ROWS];
+    char *stripe;
+    char *sP;
 
     MALLOCARRAY(stripe, cols);
     if (stripe == NULL)
         pm_error("Unable to allocate %u bytes for a stripe buffer.",
                  (unsigned)(cols * sizeof(stripe[0])));
+
     for (i = 0; i < LOW_RES_ROWS; ++i)
         bitrows[i] = pbm_allocrow(cols);
+
     printf("\033A\010");        /* '\n' = 8/72 */
+
     for (row = 0, sP = stripe; row < rows; row += LOW_RES_ROWS, sP = stripe) {
+        unsigned int col;
+        unsigned int i;
+        unsigned int npins;
+        bit * bP[LOW_RES_ROWS];
+
         if (row + LOW_RES_ROWS <= rows)
             npins = LOW_RES_ROWS;
         else
             npins = rows - row;
+
         for (i = 0; i < npins; ++i)
-            pbm_readpbmrow(ifp, bP[i] = bitrows[i], cols, format);
+            pbm_readpbmrow(ifP, bP[i] = bitrows[i], cols, format);
+
         for (col = 0; col < cols; ++col) {
+            unsigned int item;
+
             item = 0;
             for (i = 0; i < npins; ++i)
                 if (*(bP[i]++) == PBM_BLACK)
@@ -81,32 +99,52 @@ res_60x72(void) {
         outstripe(stripe, sP, 'K');
     }
     printf("\033@");
+
+    for (i = 0; i < LOW_RES_ROWS; ++i)
+        pbm_freerow(bitrows[i]);
+
     free(stripe);
 }
 
 
 
 static void
-res_120x144(void) {
-    int i, pin, item, npins, row, col;
-    bit *bitrows[HIGH_RES_ROWS], *bP[HIGH_RES_ROWS];
-    char *stripe, *sP;
+res_120x144(FILE * const ifP,
+            int    const rows,
+            int    const cols,
+            int    const format) {
+
+    unsigned int i;
+    int row;
+    char *stripe;
+    char * sP;
+    bit * bitrows[HIGH_RES_ROWS];
 
     MALLOCARRAY(stripe, cols);
     if (stripe == NULL)
         pm_error("Unable to allocate %u bytes for a stripe buffer.",
                  (unsigned)(cols * sizeof(stripe[0])));
+
     for (i = 0; i < HIGH_RES_ROWS; ++i)
         bitrows[i] = pbm_allocrow(cols);
+
     printf("\0333\001");            /* \n = 1/144" */
+
     for (row = 0, sP = stripe; row < rows; row += HIGH_RES_ROWS, sP = stripe) {
+        unsigned int i;
+        unsigned int col;
+        bit * bP[HIGH_RES_ROWS];
+        unsigned int npins;
+
         if (row + HIGH_RES_ROWS <= rows)
             npins = HIGH_RES_ROWS;
         else
             npins = rows - row;
         for (i = 0; i < npins; ++i)
-            pbm_readpbmrow(ifp, bP[i] = bitrows[i], cols, format);
+            pbm_readpbmrow(ifP, bP[i] = bitrows[i], cols, format);
         for (col = 0; col < cols; ++col) {
+            unsigned int pin;
+            unsigned int item;
             item = 0;
             /* even rows */
             for (pin = i = 0; i < npins; i += 2, ++pin)
@@ -115,8 +153,9 @@ res_120x144(void) {
             *sP++ = item;
         }
         outstripe(stripe, sP, 'L');
-        sP = stripe;
-        for (col = 0; col < cols; ++col) {
+        for (col = 0, sP = stripe; col < cols; ++col) {
+            unsigned int pin;
+            unsigned int item;
             item = 0;
             /* odd rows */
             for (i = 1, pin = 0; i < npins; i += 2, ++pin)
@@ -128,20 +167,29 @@ res_120x144(void) {
         printf("\033J\016");        /* 14/144 down, \n did 1/144 */
     }
     printf("\033@");
+
+    for (i = 0; i < LOW_RES_ROWS; ++i)
+        pbm_freerow(bitrows[i]);
+
     free(stripe);
 }
 
 
 
 int
-main(int argc, char * argv[]) {
+main(int argc, const char ** argv) {
 
     const char * fname;
+    static FILE * ifP;
+    int rows, cols, format;
+
+    bool isHighRes;
 
-    pbm_init( &argc, argv );
+    pm_proginit(&argc, argv);
 
+    isHighRes = false;  /* initial assumption */
     if (argc > 1 && argv[1][0] == '-' && argv[1][1] == 'h') {
-        highres = 1;
+        isHighRes = true;
         --argc;
         ++argv;
     }
@@ -152,17 +200,18 @@ main(int argc, char * argv[]) {
     else
         fname = "-";
     
-    ifp = pm_openr(fname);
+    ifP = pm_openr(fname);
 
-    pbm_readpbminit(ifp, &cols, &rows, &format);
+    pbm_readpbminit(ifP, &cols, &rows, &format);
 
-    if (highres)
-        res_120x144();
+    if (isHighRes)
+        res_120x144(ifP, rows, cols, format);
     else
-        res_60x72();
+        res_60x72(ifP, rows, cols, format);
+
+    pm_close(ifP);
 
-    pm_close(ifp);
-    exit(0);
+    return 0;
 }
 
 
diff --git a/converter/pbm/pbmtoatk.c b/converter/pbm/pbmtoatk.c
index 9399f602..ea5b7abe 100644
--- a/converter/pbm/pbmtoatk.c
+++ b/converter/pbm/pbmtoatk.c
@@ -118,63 +118,52 @@ process_atk_byte(int *           const pcurcount,
 
 
 int
-main(int argc, char *argv[]) {
+main(int argc, const char ** argv) {
 
-    FILE *ifd;
-    bit *bitrow;
-    register bit *bP;
-    int rows, cols, format, row;
-    int col;
-    unsigned char curbyte, newbyte;
-    int curcount, gather;
+    FILE * ifP;
+    bit * bitrow;
+    int rows, cols, format;
+    unsigned int row;
+    unsigned char curbyte;
+    int curcount;
 
-    pbm_init ( &argc, argv );
+    pm_proginit(&argc, argv);
 
     if (argc-1 > 1)
         pm_error("Too many arguments.  Only argument is file name");
 
     else if (argc-1 == 1) {
-        ifd = pm_openr( argv[1] );
+        ifP = pm_openr(argv[1]);
     } else {
-        ifd = stdin;
+        ifP = stdin;
     }
 
-    pbm_readpbminit(ifd, &cols, &rows, &format);
-    bitrow = pbm_allocrow(cols);
+    pbm_readpbminit(ifP, &cols, &rows, &format);
+    bitrow = pbm_allocrow_packed(cols);
 
-    printf ("\\begindata{raster,%d}\n", 1);
-    printf ("%d %d %d %d ", RASTERVERSION, 0, DEFAULTSCALE, DEFAULTSCALE);
-    printf ("%d %d %d %d\n", 0, 0, cols, rows); /* subraster */
-    printf ("bits %d %d %d\n", 1, cols, rows);
+    printf("\\begindata{raster,%d}\n", 1);
+    printf("%d %d %d %d ", RASTERVERSION, 0, DEFAULTSCALE, DEFAULTSCALE);
+    printf("%d %d %d %d\n", 0, 0, cols, rows); /* subraster */
+    printf("bits %d %d %d\n", 1, cols, rows);
 
     for (row = 0; row < rows; ++row) {
-        pbm_readpbmrow(ifd, bitrow, cols, format);
-        bP = bitrow;
-        gather = 0;
-        newbyte = 0;
-        curbyte = 0;
-        curcount = 0;
-        col = 0;
-        while (col < cols) {
-            if (gather > 7) {
-                process_atk_byte (&curcount, &curbyte, stdout, newbyte, FALSE);
-                gather = 0;
-                newbyte = 0;
-            }
-            newbyte = (newbyte << 1) | (*bP++);
-            gather += 1;
-            col += 1;
-        }
-
-        if (gather > 0) {
-            newbyte = (newbyte << (8 - gather));
-            process_atk_byte (&curcount, &curbyte, stdout, newbyte, TRUE);
+        unsigned int const byteCt = pbm_packed_bytes(cols);
+        unsigned int i;
+
+        pbm_readpbmrow_packed(ifP, bitrow, cols, format);
+        pbm_cleanrowend_packed(bitrow, cols);
+        
+        for (i = 0, curbyte = 0, curcount = 0; i < byteCt; ++i) {
+            process_atk_byte(&curcount, &curbyte, stdout,
+                             bitrow[i],
+                             i + 1 < byteCt ? FALSE : TRUE );
         }
     }
 
-    pm_close( ifd );
+    pbm_freerow_packed(bitrow);
+    pm_close(ifP);
     
-    printf ("\\enddata{raster, %d}\n", 1);
+    printf("\\enddata{raster, %d}\n", 1);
 
     return 0;
 }
diff --git a/converter/pbm/pbmtoepson.c b/converter/pbm/pbmtoepson.c
index 8e9d75a9..bb36791d 100644
--- a/converter/pbm/pbmtoepson.c
+++ b/converter/pbm/pbmtoepson.c
@@ -11,13 +11,12 @@
 ** implied warranty.
 */
 
-#define _BSD_SOURCE    /* Make sure strcasecmp() is in string.h */
-
+#define _BSD_SOURCE    /* Make sure strcaseeq() is in nstring.h */
 #include <stdio.h>
-#include <string.h>
 
 #include "pm_c_util.h"
 #include "mallocvar.h"
+#include "nstring.h"
 #include "shhopt.h"
 
 #include "pbm.h"
@@ -29,22 +28,22 @@ enum epsonProtocol {ESCP9, ESCP};
 
 enum adjacence {ADJACENT_ANY, ADJACENT_YES, ADJACENT_NO};
 
-struct cmdlineInfo {
+struct CmdlineInfo {
     /* All the information the user supplied in the command line,
        in a form easy for the program to use.
     */
-    const char *inputFilespec;  /* '-' if stdin */
-    unsigned int dpi;  /* zero means "any" */
-    enum adjacence adjacence;
+    const char *       inputFileName;  /* '-' if stdin */
+    unsigned int       dpi;  /* zero means "any" */
+    enum adjacence     adjacence;
     enum epsonProtocol protocol;
 };
 
 
 
 static void
-parseCommandLine(int                 argc, 
-                 char **             argv,
-                 struct cmdlineInfo *cmdlineP ) {
+parseCommandLine(int                  argc, 
+                 const char **        argv,
+                 struct CmdlineInfo * cmdlineP ) {
 /*----------------------------------------------------------------------------
    Parse program command line described in Unix standard form by argc
    and argv.  Return the information in the options as *cmdlineP.  
@@ -69,20 +68,20 @@ parseCommandLine(int                 argc,
     MALLOCARRAY_NOFAIL(option_def, 100);
 
     option_def_index = 0;   /* incremented by OPTENT3 */
-    OPTENT3(0, "protocol",   OPT_STRING,   &protocol,
+    OPTENT3(0, "protocol",     OPT_STRING,   &protocol,
             &protocolSpec,                    0);
-    OPTENT3(0, "dpi",        OPT_UINT,   &cmdlineP->dpi,
-            &dpiSpec,                    0);
-    OPTENT3(0, "adjacent",   OPT_FLAG,   NULL,
+    OPTENT3(0, "dpi",          OPT_UINT,     &cmdlineP->dpi,
+            &dpiSpec,                         0);
+    OPTENT3(0, "adjacent",     OPT_FLAG,     NULL,
             &adjacentSpec,                    0);
-    OPTENT3(0, "nonadjacent",   OPT_FLAG,   NULL,
-            &nonadjacentSpec,                    0);
+    OPTENT3(0, "nonadjacent",  OPT_FLAG,     NULL,
+            &nonadjacentSpec,                 0);
 
     opt.opt_table = option_def;
     opt.short_allowed = FALSE;  /* We have no short (old-fashioned) options */
     opt.allowNegNum = FALSE;  /* We have no parms that are negative numbers */
 
-    pm_optParseOptions3( &argc, argv, opt, sizeof(opt), 0);
+    pm_optParseOptions3( &argc, (char **)argv, opt, sizeof(opt), 0);
         /* Uses and sets argc, argv, and some of *cmdlineP and others. */
 
 
@@ -96,11 +95,11 @@ parseCommandLine(int                 argc,
     if (!protocolSpec)
         cmdlineP->protocol = ESCP9;
     else {
-        if (strcasecmp(protocol, "escp9") == 0)
+        if (strcaseeq(protocol, "escp9"))
             cmdlineP->protocol = ESCP9;
-        else if (strcasecmp(protocol, "escp") == 0)
+        else if (strcaseeq(protocol, "escp"))
             cmdlineP->protocol = ESCP;
-        else if (strcasecmp(protocol, "escp2") == 0)
+        else if (strcaseeq(protocol, "escp2"))
             pm_error("This program cannot do ESC/P2.  Try Pbmtoescp2.");
         else
             pm_error("Unrecognized value '%s' for -protocol.  "
@@ -118,13 +117,15 @@ parseCommandLine(int                 argc,
         cmdlineP->adjacence = ADJACENT_ANY;
 
     if (argc-1 < 1)
-        cmdlineP->inputFilespec = "-";
+        cmdlineP->inputFileName = "-";
     else {
-        cmdlineP->inputFilespec = argv[1];
+        cmdlineP->inputFileName = argv[1];
         if (argc-1 > 1)
             pm_error("Too many arguments (%d).  The only non-option argument "
                      "is the file name", argc-1);
     }
+
+    free(option_def);
 }
 
 
@@ -273,7 +274,7 @@ convertToEpson(const bit **       const bits,
                enum adjacence     const adjacence) {
     
     unsigned int const rowsPerStripe = 8;
-    unsigned int const stripes = (rows + rowsPerStripe-1) / rowsPerStripe;
+    unsigned int const stripeCt = (rows + rowsPerStripe-1) / rowsPerStripe;
 
     unsigned int stripe;
     char m;
@@ -288,7 +289,7 @@ convertToEpson(const bit **       const bits,
        stripe can be fewer than 8 rows.
     */
 
-    for (stripe = 0; stripe < stripes; ++stripe) {
+    for (stripe = 0; stripe < stripeCt; ++stripe) {
         const bit ** const stripeBits = &bits[stripe*rowsPerStripe];
         unsigned int const stripeRows = 
             MIN(rowsPerStripe, rows - stripe * rowsPerStripe);
@@ -313,18 +314,18 @@ convertToEpson(const bit **       const bits,
 
 
 int
-main(int argc, char *argv[]) {
+main(int argc, const char ** argv) {
 
-    struct cmdlineInfo cmdline;
-    FILE* ifP;
+    struct CmdlineInfo cmdline;
+    FILE * ifP;
     const bit** bits;
     int rows, cols;
 
-    pbm_init(&argc, argv);
+    pm_proginit(&argc, argv);
 
     parseCommandLine(argc, argv, &cmdline);
 
-    ifP = pm_openr(cmdline.inputFilespec);
+    ifP = pm_openr(cmdline.inputFileName);
 
     bits = (const bit **)pbm_readpbm(ifP, &cols, &rows);
 
diff --git a/converter/pbm/pbmtog3.c b/converter/pbm/pbmtog3.c
index cd96c9dc..f0fd1252 100644
--- a/converter/pbm/pbmtog3.c
+++ b/converter/pbm/pbmtog3.c
@@ -65,7 +65,7 @@ struct outStream {
 static struct outStream out;
 
 
-struct cmdlineInfo {
+struct CmdlineInfo {
     /* All the information the user supplied in the command line,
        in a form easy for the program to use.
     */
@@ -79,7 +79,7 @@ struct cmdlineInfo {
 
 static void
 parseCommandLine(int argc, char ** const argv,
-                 struct cmdlineInfo * const cmdlineP) {
+                 struct CmdlineInfo * const cmdlineP) {
 /*----------------------------------------------------------------------------
    Note that the file spec array we return is stored in the storage that
    was passed to us as the argv array.
@@ -407,7 +407,7 @@ int
 main(int    argc,
      char * argv[]) {
 
-    struct cmdlineInfo cmdline;
+    struct CmdlineInfo cmdline;
     FILE * ifP;
     unsigned char * bitrow;
        /* This is the bits of the current row, as read from the input and
diff --git a/converter/pbm/pbmtomacp.c b/converter/pbm/pbmtomacp.c
index 82ccce06..7ddb1ef5 100644
--- a/converter/pbm/pbmtomacp.c
+++ b/converter/pbm/pbmtomacp.c
@@ -1,294 +1,497 @@
-/* pbmtomacp.c - read a portable bitmap and produce a MacPaint bitmap file
-**
-** Copyright (C) 1988 by Douwe vand der Schaaf.
-**
-** Permission to use, copy, modify, and distribute this software and its
-** documentation for any purpose and without fee is hereby granted, provided
-** that the above copyright notice appear in all copies and that both that
-** copyright notice and this permission notice appear in supporting
-** documentation.  This software is provided "as is" without express or
-** implied warranty.
+/*=============================================================================
+                                  pbmtomacp
+===============================================================================
+  Read a PBM file and produce a MacPaint bitmap file
+
+  Copyright (C) 2015 by Akira Urushibata ("douso").
+
+  Replacement of a previous program of the same name written in 1988
+  by Douwe van der Schaaf (...!mcvax!uvapsy!vdschaaf).
+
+  Permission to use, copy, modify, and distribute this software and its
+  documentation for any purpose and without fee is hereby granted, provided
+  that the above copyright notice appear in all copies and that both that
+  copyright notice and this permission notice appear in supporting
+  documentation.  This software is provided "as is" without express or implied
+  warranty.
+=============================================================================*/
+
+/*
+
+  Implemention notes
+
+  Header size is 512 bytes.  There is no MacBinary header.
+
+  White margin which is added for input files with small dimensions
+  is treated separately from the active image raster.  The margins
+  are directly coded based on the number of rows/columns.
+
+  Output file size never exceeds 53072 bytes.  When -norle is specified,
+  output is always 53072 bytes.  It is conceivable that decoders which
+  examine the size of Macpaint files (for general validation or for
+  determination of header type and size) do exist.
+
+  The uncompressed output (-norle case) fully conforms to Macpaint
+  specifications.  No special treatment by the decoder is required.
 */
 
-#include <string.h>
+#include <assert.h>
 
 #include "pm_c_util.h"
 #include "pbm.h"
+#include "shhopt.h"
+#include "mallocvar.h"
 #include "macp.h"
 
-#define EQUAL		1
-#define UNEQUAL		0
-
 #define MIN3(a,b,c)     (MIN((MIN((a),(b))),(c)))
 
-static void fillbits ARGS(( bit **bits, bit **bitsr, int top, int left, int bottom, int right ));
-static void writemacp ARGS(( bit **bits ));
-static int packit ARGS(( bit *pb, bit *bits ));
-static void filltemp ARGS(( bit *dest, bit *src ));
-static void sendbytes ARGS(( bit *pb, register int npb ));
-static void header ARGS(( void ));
+struct CmdlineInfo {
+    /* All the information the user supplied in the command line, in a form
+       easy for the program to use.
+    */
+    const char * inputFileName;  /* File name of input file */
+    unsigned int left;
+    unsigned int right;
+    unsigned int top;
+    unsigned int bottom;
+    unsigned int leftSpec;
+    unsigned int rightSpec;
+    unsigned int topSpec;
+    unsigned int bottomSpec;
+    bool         norle;
+};
 
-static FILE *fdout;
 
-int
-main(argc, argv)
-int argc;
-char *argv[];
-{ FILE *ifp;
-  register bit **bits, **bitsr;
-  int argn, rows, cols;
-  int left,bottom,right,top;
-  int lflg, rflg, tflg, bflg;
-  const char * const usage = "[-l left] [-r right] [-b bottom] [-t top] [pbmfile]";
-
-
-  pbm_init( &argc, argv );
-
-  argn = 1;
-  fdout = stdout;
-  lflg = rflg = tflg = bflg = 0;
-  left = right = top = bottom = 0;  /* To quiet compiler warning */
-
-  while ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
-  { switch ( argv[argn][1] )
-    { case 'l':
-      lflg++;
-      argn++;
-      left = atoi( argv[argn] );
-      break;
-
-      case 'r':
-      rflg++;
-      argn++;
-      right = atoi( argv[argn] );
-      break;
-
-      case 't':
-      tflg++;
-      argn++;
-      top = atoi( argv[argn] );
-      break;
-
-      case 'b':
-      bflg++;
-      argn++;
-      bottom = atoi( argv[argn] );
-      break;
-
-      case '?':
-      default:
-      pm_usage( usage );
+
+static void
+parseCommandLine(int                        argc,
+                 const char **        const argv,
+                 struct CmdlineInfo * const cmdlineP) {
+/*----------------------------------------------------------------------------
+   Parse program command line described in Unix standard form by argc
+   and argv.  Return the information in the options as *cmdlineP.
+-----------------------------------------------------------------------------*/
+    optEntry * option_def;  /* malloc'ed */
+        /* Instructions to OptParseOptions3 on how to parse our options.  */
+    optStruct3 opt;
+
+    unsigned int norleSpec;
+
+    unsigned int option_def_index;
+
+    MALLOCARRAY_NOFAIL(option_def, 100);
+
+    option_def_index = 0;   /* incremented by OPTENTRY */
+    OPTENT3(0, "left",     OPT_UINT,  &cmdlineP->left,
+            &cmdlineP->leftSpec,     0);
+    OPTENT3(0, "right",    OPT_UINT,  &cmdlineP->right,
+            &cmdlineP->rightSpec,    0);
+    OPTENT3(0, "top",      OPT_UINT,  &cmdlineP->top,
+            &cmdlineP->topSpec,      0);
+    OPTENT3(0, "bottom",   OPT_UINT,  &cmdlineP->bottom,
+            &cmdlineP->bottomSpec,   0);
+    OPTENT3(0, "norle", OPT_FLAG,  NULL,
+            &norleSpec, 0);
+
+    opt.opt_table = option_def;
+    opt.short_allowed = FALSE;  /* We have no short (old-fashioned) options */
+    opt.allowNegNum = FALSE;  /* We have no parms that are negative numbers */
+
+    pm_optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0);
+        /* Uses and sets argc, argv, and some of *cmdlineP and others. */
+
+    cmdlineP->norle = norleSpec;
+
+    if (argc-1 < 1)
+        cmdlineP->inputFileName = "-";
+    else {
+        cmdlineP->inputFileName = argv[1];
+        if (argc-1 > 1)
+            pm_error("Program takes zero or one argument (filename).  You "
+                     "specified %d", argc-1);
     }
-    ++argn;
-  }
 
-  if ( argn == argc )
-  { ifp = stdin;
-  }
-  else
-  { ifp = pm_openr( argv[argn] );
-    ++argn;
-  }
+    free(option_def);
+}
+
+
+
+struct CropPadDimensions {
+    unsigned int imageWidth;   /* Active image content */
+    unsigned int imageHeight;
+    unsigned int leftCrop;     /* Cols cropped off from input */
+    unsigned int topCrop;      /* Rows cropped off from input */
+    unsigned int topMargin;    /* White padding for output */
+    unsigned int bottomMargin;
+    unsigned int leftMargin;
+};
+
+
 
-  if ( argn != argc )
-    pm_usage( usage );
+static void
+calculateCropPad(struct CmdlineInfo         const cmdline,
+                 unsigned int               const cols,
+                 unsigned int               const rows,
+                 struct CropPadDimensions * const cropPadP) {
+/*--------------------------------------------------------------------------
+  Validate -left -right -top -bottom from command line.
+
+  Determine what rows, columns to take from input if any of these are
+  specified and return it as *cropPadP.
+
+  'cols and 'rows' are the dimensions of the input image.
+
+  Center image if it is smaller than the fixed Macpaint format size.
+----------------------------------------------------------------------------*/
+    unsigned int const left = cmdline.leftSpec ? cmdline.left : 0;
+    unsigned int const top  = cmdline.topSpec  ? cmdline.top  : 0;
+
+    unsigned int right, bottom, width, height;
+
+    if (cmdline.leftSpec) {
+        if (cmdline.rightSpec && left >= cmdline.right)
+            pm_error("-left value must be smaller than -right value");
+        else if (left + 1 > cols)
+            pm_error("Specified -left value is beyond right edge "
+                     "of input image");
+    }
+    if (cmdline.topSpec) {
+        if (cmdline.bottomSpec && top >= cmdline.bottom)
+            pm_error("-top value must be smaller than -bottom value");
+        else if (top + 1 > rows)
+            pm_error("Specified -top value is beyond bottom edge "
+                     "of input image");
+    }
+    if (cmdline.rightSpec) {
+        if (cmdline.right + 1 > cols)
+            pm_message("Specified -right value %u is beyond edge of "
+                       "input image", cmdline.right);
 
-  bitsr = pbm_readpbm( ifp, &cols, &rows );
+        right = MIN3(cmdline.right, cols - 1, left + MACP_COLS - 1);
+    } else
+        right = MIN(cols - 1,  left + MACP_COLS - 1);
 
-  pm_close( ifp );
+    if (cmdline.bottomSpec) {
+        if (cmdline.bottom + 1 > rows)
+            pm_message("Specified -bottom value %u is beyond edge of "
+                       "input image", cmdline.bottom);
 
-  bits = pbm_allocarray( MAX_COLS, MAX_LINES );
+            bottom = MIN3(cmdline.bottom, rows - 1, top + MACP_ROWS - 1);
+    } else
+        bottom = MIN(rows - 1, top + MACP_ROWS - 1);
 
-  if( !lflg )
-    left = 0;
+    cropPadP->leftCrop = left;
+    cropPadP->topCrop  = top;
 
-  if( rflg )
-    right = MIN3( right, cols - 1, left + MAX_COLS - 1 );
-  else
-    right = MIN( cols - 1,  left + MAX_COLS - 1 );
+    assert(right >= left);
 
-  if( !tflg )
-    top = 0;
+    width = right - left + 1;
+    assert(width > 0 && width <= MACP_COLS);
 
-  if( bflg )
-    bottom = MIN3( bottom, rows - 1, top + MAX_LINES - 1);
-  else
-    bottom = MIN( rows - 1, top + MAX_LINES - 1 );
+    cropPadP->leftMargin = (MACP_COLS - width) / 2;
 
-    if( right <= left || left < 0 || right - left + 1 > MAX_COLS )
-      pm_error("error in right (= %d) and/or left (=%d)",right,left );
-    if( bottom <= top || top < 0 || bottom - top + 1 > MAX_LINES )
-      pm_error("error in bottom (= %d) and/or top (=%d)",bottom,top );
+    if (width < cols)
+        pm_message("%u of %u input columns will be output", width, cols);
 
-  fillbits( bits, bitsr, top, left, bottom, right );
+    height = bottom - top + 1;
+    assert(height > 0 && height <= MACP_ROWS);
 
-  writemacp( bits );
+    cropPadP->topMargin    = (MACP_ROWS - height) / 2;
+    cropPadP->bottomMargin = cropPadP->topMargin + height - 1;
 
-  exit( 0 );
+    if (height < rows)
+        pm_message("%u out of %u input rows will be output", height, rows);
 
+    cropPadP->imageWidth  = width;
+    cropPadP->imageHeight = height;
 }
 
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-/* centreer het over te zenden plaatje in het MacPaint document
- *
- * Het plaatje wordt vanaf al of niet opgegeven (left, bottom)
- * in een pbm bitmap van de juist macpaint afmetingen gezet,
- * en eventueel afgekapt.
- */
+
 static void
-fillbits( bits, bitsr, top, left, bottom, right )
-bit **bits, **bitsr;
-int top, left, bottom, right;
-{ register bit *bi, *bir;
-  register int i, j;
-  register int bottomr, leftr, topr, rightr;
-  int width, height;
-
-  width = right - left + 1;
-  leftr = (MAX_COLS - width) / 2;
-  rightr = leftr + width - 1;
-
-  height = bottom - top + 1;
-  topr = ( MAX_LINES - height ) / 2;
-  bottomr = topr + height - 1;
-
-  for( i = 0; i < topr; i++ )
-  { bi = bits[i];
-    for( j = 0; j < MAX_COLS; j++ )
-      *bi++ = 0;
-  }
-
-  for( i = topr; i <= bottomr; i++ )
-  { bi = bits[i];
-    { for( j = 0; j < leftr; j++ )
-	*bi++ = 0;
-      bir = bitsr[ i - topr + top ];
-      for( j = leftr; j <= rightr; j++ )
-	*bi++ = bir[j - leftr + left];
-      for( j = rightr + 1; j < MAX_COLS; j++ )
-	*bi++ = 0;
-  } }
-
-  for( i = bottomr + 1; i < MAX_LINES; i++ )
-  { bi = bits[i];
-    for( j = 0; j < MAX_COLS; j++ )
-      *bi++ = 0;
-  }
-} /* fillbits */
-      
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - */
+writeMacpHeader(FILE * const ofP) {
+
+    char const ch = 0x00;    /* header contains nothing */
+
+    unsigned int i;
+
+    for (i = 0; i < MACP_HEAD_LEN; ++i)
+        fputc(ch, ofP);
+}
+
+
 
 static void
-writemacp( bits )
-bit **bits;
-{ register int i;
-  bit pb[MAX_COLS * 2];
-  int npb;
-
-  header();
-  for( i=0; i < MAX_LINES; i++ )
-  { npb = packit( pb, bits[i] );
-    sendbytes( pb, npb );
-  }
-} /* writemacp */
-
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - */
-
-/* pack regel van MacPaint doc in Apple's format
- * return value = # of bytes in pb 
- */
-static int
-packit( pb, bits )
-     bit *pb, *bits;
-{ register int charcount, npb, newcount, flg;
-  bit temp[72];
-  bit *count, *srcb, *destb, save;
-
-  srcb = bits; destb = temp;
-  filltemp( destb, srcb );
-  srcb = temp;
-  destb = pb;
-  npb = 0;
-  charcount = BYTES_WIDE;
-  flg = EQUAL;
-  while( charcount ) { 
-      save = *srcb++;
-      charcount--;
-      newcount = 1;
-      while( charcount && (*srcb == save) ) { 
-          srcb++;
-          newcount++;
-          charcount--;
-      }
-      if( newcount > 2 ) { 
-          count = destb++;
-          *count = 257 - newcount;
-          *destb++ = save;
-          npb += 2;
-          flg = EQUAL;
-      } else { 
-          if( flg == EQUAL ) { 
-              count = destb++;
-              *count = newcount - 1;
-              npb++;
-          } else
-            *count += newcount;
-          while( newcount-- ) { 
-              *destb++ = save;
-              npb++;
-          }
-          flg = UNEQUAL;
-      } 
-  }
-  return npb;
-} /* packit */
-
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - */
+writeMacpRowUnpacked(const bit  * const imageBits,
+                     unsigned int const leftMarginCharCt,
+                     unsigned int const imageColCharCt,
+                     FILE *       const ofP) {
+/*--------------------------------------------------------------------------
+  Encode (without compression) and output one row.  The row comes divided into
+  three parts: left margin, image, right margin.
+----------------------------------------------------------------------------*/
+    char const marginByte = 0x00;  /* White bits for margin */
+    unsigned int const rightMarginCharCt =
+        MACP_COLCHARS - leftMarginCharCt - imageColCharCt;
+    
+    unsigned int i;
+
+    fputc(MACP_COLCHARS - 1, ofP);
+
+    for (i = 0; i < leftMarginCharCt; ++i)
+        fputc(marginByte, ofP);
+
+    if (imageColCharCt > 0)
+        fwrite(imageBits, 1, imageColCharCt, ofP);
+
+    for (i = 0; i < rightMarginCharCt; ++i)
+        fputc(marginByte, ofP);
+}
+
+
 
 static void
-filltemp( dest, src )
-bit *dest, *src;
-{ register unsigned char ch, zero, acht;
-  register int i, j;
-
-  zero = '\0';
-  acht = 8;
-  i = BYTES_WIDE;
-  while( i-- )
-  { ch = zero; 
-    j = acht;
-    while( j-- )
-    { ch <<= 1;
-      if( *src++ )
-	ch++;
+writeMacpRowPacked(const bit  * const packedBits,
+                   unsigned int const leftMarginCharCt,
+                   unsigned int const imageColCharCt,
+                   unsigned int const rightMarginCharCt,
+                   FILE *       const ofP) {
+/*--------------------------------------------------------------------------
+  Encode one row and write it to *ofP.
+
+  As in the unpacked case, the row comes divided into three parts: left
+  margin, image, right margin.  Unlike the unpacked case we need to know both
+  the size of the packed data and the size of the right margin.
+----------------------------------------------------------------------------*/
+    char const marginByte = 0x00;  /* White bits for margin */
+
+    if (leftMarginCharCt > 0) {
+        fputc(257 - leftMarginCharCt, ofP);
+        fputc(marginByte, ofP);
     }
-    *dest++ = ch;
-  }
-} /* filltemp */
 
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - */
+    if (imageColCharCt > 0)
+        fwrite(packedBits, 1, imageColCharCt, ofP);
+
+    if (rightMarginCharCt > 0) {
+        fputc(257 - rightMarginCharCt, ofP);
+        fputc(marginByte, ofP);
+    }
+}
+
+
 
 static void
-sendbytes( pb, npb )
-bit *pb;
-register int npb;
-{ register bit *b;
+packit(const bit *     const sourceBits,
+       unsigned int    const imageColCharCt,
+       unsigned char * const packedBits,
+       unsigned int  * const packedImageLengthP ) {
+/*--------------------------------------------------------------------------
+  Compress according to packbits algorithm, a byte-level run-length encoding
+  scheme.
+
+  Each row is encoded separately.
+
+  The following code does not produce optimum output when there are 2-byte
+  long sequences between longer ones: the 2-byte run in between does not get
+  packed, using up 3 bytes where 2 would do.
+----------------------------------------------------------------------------*/
+    int charcount, packcount;
+    enum {EQUAL, UNEQUAL} status;
+    bit * count;
+
+    for (packcount = 0, charcount = 0, status = EQUAL;
+         charcount < imageColCharCt;
+        ) {
+        bit const save = sourceBits[charcount++];
+
+        int newcount;
+
+        newcount = 1;
+        while (charcount < imageColCharCt && sourceBits[charcount] == save) {
+            ++charcount;
+            ++newcount;
+        }
+        if (newcount > 2) {
+            count = (unsigned char *) &packedBits[packcount++];
+            *count = 257 - newcount;
+            packedBits[packcount++] = save;
+            status = EQUAL;
+        } else {
+            if (status == EQUAL) {
+                count = (unsigned char *) &packedBits[packcount++];
+                *count = newcount - 1;
+             } else
+                *count += newcount;
+
+            for( ; newcount > 0; --newcount) {
+                packedBits[packcount++] = save;
+            }
+            status = UNEQUAL;
+        }
+    }
+    *packedImageLengthP = packcount;
+}
+
+
+
+static void
+writeMacpRow(bit        * const imageBits,
+             unsigned int const leftMarginCharCt,
+             unsigned int const imageColCharCt,
+             bool         const norle,
+             FILE *       const ofP) {
+/*--------------------------------------------------------------------------
+  Write the row 'imageBits' to Standard Output.
+
+  Write it packed, unless packing would lead to unnecessary bloat or 'norle'
+  is true.
+----------------------------------------------------------------------------*/
+    if (norle)
+        writeMacpRowUnpacked(imageBits, leftMarginCharCt, imageColCharCt, ofP);
+    else {
+        unsigned int const rightMarginCharCt =
+            MACP_COLCHARS - leftMarginCharCt - imageColCharCt;
+        unsigned char * const packedBits = malloc(MACP_COLCHARS+1);
+        
+        unsigned int packedImageLength;
+
+        if (packedBits == NULL)
+            pm_error("Failed to get memory for a %u-column row buffer",
+                     MACP_COLCHARS);
+
+        packit(imageBits, imageColCharCt, packedBits, &packedImageLength);
+
+        /* Check if we are we better off with compression.  If not, send row
+           unpacked.  See note at top of file.
+        */
+        
+        if (packedImageLength +
+            (leftMarginCharCt  > 0 ? 1 : 0) * 2 +
+            (rightMarginCharCt > 0 ? 1 : 0) * 2
+            < MACP_COLCHARS)
+            writeMacpRowPacked(packedBits, leftMarginCharCt,
+                               packedImageLength, rightMarginCharCt, ofP);
+        else /* Extremely rare */
+            writeMacpRowUnpacked(imageBits, leftMarginCharCt, imageColCharCt,
+                                 ofP);
+
+        free(packedBits);
+    }
+}
 
-  b = pb;
-  while( npb-- )
-    (void) putc( *b++, fdout );
-} /* sendbytes */
 
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
 static void
-header()
-{ register int i;
-  register char ch;
-
-  /* header contains nothing ... */
-  ch = '\0';
-  for(i = 0; i < HEADER_LENGTH; i++ )
-    (void) putc( ch, fdout );
-} /* header */
+encodeRowsWithShift(bit *                    const bitrow,
+                    FILE *                   const ifP,
+                    int                      const inCols,
+                    int                      const format,
+                    bool                     const norle,
+                    struct CropPadDimensions const cropPad,
+                    FILE *                   const ofP) {
+/*--------------------------------------------------------------------------
+  Shift input rows to put only specified columns to output.  Add padding on
+  left and right if necessary.
+
+  No shift if the input image is the exact size (576 columns) of the Macpaint
+  format.  If the input image is too wide and -left was not specified, extra
+  content on the right is discarded.
+----------------------------------------------------------------------------*/
+    unsigned int const offset     =
+        (cropPad.leftMargin + 8 - cropPad.leftCrop % 8) % 8;
+    unsigned int const leftTrim   =
+        cropPad.leftMargin % 8;
+    unsigned int const rightTrim  =
+        (8 - (leftTrim + cropPad.imageWidth) % 8 ) % 8;
+    unsigned int const startChar  =
+        (cropPad.leftCrop + offset) / 8;
+    unsigned int const imageCharCt =
+        pbm_packed_bytes(leftTrim + cropPad.imageWidth);
+    unsigned int const leftMarginCharCt =
+        cropPad.leftMargin / 8;
+
+    unsigned int row;
+
+    for (row = 0; row < cropPad.imageHeight; ++row) {
+        pbm_readpbmrow_bitoffset(ifP, bitrow, inCols, format, offset);
+        
+        /* Trim off fractional margin portion in first byte of image data */
+        if (leftTrim > 0) {
+            bitrow[startChar] <<= leftTrim;
+            bitrow[startChar] >>= leftTrim;
+        }
+        /* Do the same with bits in last byte of relevant image data */
+        if (rightTrim > 0) {
+            bitrow[startChar + imageCharCt - 1] >>= rightTrim;
+            bitrow[startChar + imageCharCt - 1] <<= rightTrim;
+        }
+
+        writeMacpRow(&bitrow[startChar], leftMarginCharCt,
+                     imageCharCt, norle, ofP);
+    }
+}
+
+
+
+static void
+writeMacp(unsigned int             const cols,
+          unsigned int             const rows,
+          int                      const format,
+          FILE *                   const ifP,
+          bool                     const norle,
+          struct CropPadDimensions const cropPad,
+          FILE *                   const ofP) {
+
+    unsigned int row, skipRow;
+    bit * bitrow;
+
+    writeMacpHeader(ofP);
+
+    /* Write top padding */
+    for (row = 0; row < cropPad.topMargin; ++row)
+        writeMacpRow(NULL, MACP_COLCHARS, 0, norle, ofP);
+
+    /* Allocate PBM row with one extra byte for the shift case. */
+    bitrow = pbm_allocrow_packed(cols + 8);
+
+    for (skipRow = 0; skipRow < cropPad.topCrop; ++skipRow)
+        pbm_readpbmrow_packed(ifP, bitrow, cols, format);
+
+    encodeRowsWithShift(bitrow, ifP, cols, format, norle, cropPad, ofP);
+
+    pbm_freerow_packed(bitrow);
+
+    /* Add bottom padding */
+    for (row = cropPad.bottomMargin + 1; row < MACP_ROWS; ++row)
+        writeMacpRow(NULL, MACP_COLCHARS, 0, norle, ofP);
+}
+
+
+
+int
+main(int argc, const char *argv[]) {
+
+    FILE * ifP;
+    int rows, cols;
+    int format;
+    struct CmdlineInfo cmdline;
+    struct CropPadDimensions cropPad;
+
+    pm_proginit(&argc, argv);
+
+    parseCommandLine(argc, argv, &cmdline);
+
+    ifP = pm_openr(cmdline.inputFileName);
+
+    pbm_readpbminit(ifP, &cols, &rows, &format);
+
+    calculateCropPad(cmdline, cols, rows, &cropPad);
+
+    writeMacp(cols, rows, format, ifP, cmdline.norle, cropPad, stdout);
+
+    pm_close(ifP);
+
+    return 0;
+}
+
diff --git a/converter/pbm/pbmtomatrixorbital.c b/converter/pbm/pbmtomatrixorbital.c
index 96e1406a..41f8e260 100644
--- a/converter/pbm/pbmtomatrixorbital.c
+++ b/converter/pbm/pbmtomatrixorbital.c
@@ -1,3 +1,5 @@
+#include <stdio.h>
+
 #include "pbm.h"
 
 /* By Bryan Henderson, San Jose CA 2003.09.06.
@@ -12,10 +14,10 @@
 
 
 static void
-generateMo(FILE * const ofP, 
-           bit ** const bits,
-           int    const cols,
-           int    const rows) {
+generateMo(FILE *       const ofP, 
+           bit **       const bits,
+           unsigned int const cols,
+           unsigned int const rows) {
 
     unsigned int col;
 
@@ -51,37 +53,40 @@ generateMo(FILE * const ofP,
 
 
 int
-main(int argc, char * argv[]) {
+main(int argc, const char ** argv) {
 
-    FILE* ifp;
-    bit** bits;
+    FILE * ifP;
+    bit ** bits;
     int rows, cols;
     const char * inputFilename;
 
-    pbm_init(&argc, argv);
+    pm_proginit(&argc, argv);
 
     if (argc-1 > 1)
-        pm_error("Too many arguments (%d).  The only valid argument is an "
+        pm_error("Too many arguments (%u).  The only valid argument is an "
                  "input file name.", argc-1);
     else if (argc-1 == 1) 
         inputFilename = argv[1];
     else
         inputFilename = "-";
 
-    ifp = pm_openr(inputFilename);
+    ifP = pm_openr(inputFilename);
     
-    bits = pbm_readpbm(ifp, &cols, &rows);
+    bits = pbm_readpbm(ifP, &cols, &rows);
 
     if (rows > 255)
-        pm_error("Image is too high:  %d rows.  Max height: 255 rows", rows);
+        pm_error("Image is too high:  %u rows.  Max height: 255 rows", rows);
     if (cols > 255)
-        pm_error("Image is too wide:  %d cols.  Max width: 255 cols", cols);
+        pm_error("Image is too wide:  %u cols.  Max width: 255 cols", cols);
 
     generateMo(stdout, bits, cols, rows);
     
-    pm_close(ifp);
+    pm_close(ifP);
 
     pbm_freearray(bits, rows);
 
-    exit(0);
+    return 0;
 }
+
+
+
diff --git a/converter/pbm/pbmtomgr.c b/converter/pbm/pbmtomgr.c
index d12e6635..e8e30148 100644
--- a/converter/pbm/pbmtomgr.c
+++ b/converter/pbm/pbmtomgr.c
@@ -89,11 +89,7 @@ main(int argc,
         size_t bytesWritten;
 
         pbm_readpbmrow_packed(ifP, bitrow, cols, format);
-        
-        if (padright > 0) {
-            bitrow[bytesPerRow-1] >>= padright;
-            bitrow[bytesPerRow-1] <<= padright;
-        }
+        pbm_cleanrowend_packed(bitrow, cols);
 
         bytesWritten = fwrite(bitrow, 1, bytesPerRow, stdout);
         if (bytesWritten != bytesPerRow )
diff --git a/converter/pbm/pbmtopi3.c b/converter/pbm/pbmtopi3.c
index 6a60af62..791bcb50 100644
--- a/converter/pbm/pbmtopi3.c
+++ b/converter/pbm/pbmtopi3.c
@@ -1,4 +1,4 @@
-/* pbmtopi3.c - read a portable bitmap and produce a Atari Degas .pi3 file
+/* pbmtopi3.c - read a PBM image and produce a Atari Degas .pi3 file
 **
 ** Module created from other pbmplus tools by David Beckemeyer.
 **
@@ -12,106 +12,87 @@
 ** implied warranty.
 */
 
+/* Output file should always be 32034 bytes. */
+
 #include <stdio.h>
+#include "pm_c_util.h"
 #include "pbm.h"
 
-static void putinit ARGS(( void ));
-static void putbit ARGS(( bit b ));
-static void putrest ARGS(( void ));
-static void putitem ARGS(( void ));
-
-int
-main( argc, argv )
-    int argc;
-    char* argv[];
-    {
-    FILE* ifp;
-    bit* bitrow;
-    register bit* bP;
-    int rows, cols, format, padright, row, col;
-
-
-    pbm_init( &argc, argv );
-
-    if ( argc > 2 )
-	pm_usage( "[pbmfile]" );
-
-    if ( argc == 2 )
-	ifp = pm_openr( argv[1] );
-    else
-	ifp = stdin;
-
-    pbm_readpbminit( ifp, &cols, &rows, &format );
-    if (cols > 640)
-	cols = 640;
-    if (rows > 400)
-	rows = 400;
-    bitrow = pbm_allocrow( cols );
-    
-    /* Compute padding to round cols up to 640 */
-    padright = 640 - cols;
-
-    putinit( );
-    for ( row = 0; row < rows; ++row )
-	{
-	pbm_readpbmrow( ifp, bitrow, cols, format );
-        for ( col = 0, bP = bitrow; col < cols; ++col, ++bP )
-	    putbit( *bP );
-	for ( col = 0; col < padright; ++col )
-	    putbit( 0 );
-        }
-    while (row++ < 400)
-	for ( col = 0; col < 640; ++col)
-	    putbit( 0 );
-
-    pm_close( ifp );
-
-    putrest( );
-
-    exit( 0 );
-    }
 
-static char item;
-static short bitsperitem, bitshift;
 
 static void
-putinit( )
-    {
-    int i;
-    if (pm_writebigshort (stdout, (short) 2) == -1
-	|| pm_writebigshort (stdout, (short) 0x777) == -1)
-      pm_error ("write error");
-    for (i = 1; i < 16; i++)
-      if (pm_writebigshort (stdout, (short) 0) == -1)
-	pm_error ("write error");
-    item = 0;
-    bitsperitem = 0;
-    bitshift = 7;
+putinit(FILE * const ofP)  {
+
+    unsigned int i;
+
+    pm_writebigshort(ofP, (short) 2);
+    pm_writebigshort(ofP, (short) 0x777);
+
+    for (i = 1; i < 16; ++i) {
+        pm_writebigshort (ofP, (short) 0);
     }
+}
 
-static void
-putbit( bit b )
-    {
-    if (bitsperitem == 8)
-	putitem( );
-    ++bitsperitem;
-    if ( b == PBM_BLACK )
-	item += 1 << bitshift;
-    --bitshift;
+
+
+int
+main(int argc, const char ** argv) {
+
+    unsigned int const outRows = 400;
+    unsigned int const outCols = 640;
+    unsigned int const outColByteCt = pbm_packed_bytes(outCols);
+
+    FILE * ifP;
+
+    int inRows, inCols, format;
+    unsigned int row;
+    unsigned int inColByteCt;
+    unsigned int i;
+    bit * bitrow;
+
+    pm_proginit(&argc, argv);
+
+    if (argc-1 < 1)
+        ifP = stdin;
+    else  {
+        ifP = pm_openr(argv[1]);
+
+        if (argc-1 > 1)
+            pm_error("Too many arguments.  The only possible argument "
+                     "is the input file name");
     }
 
-static void
-putrest( )
-    {
-    if ( bitsperitem > 0 )
-	putitem( );
+    pbm_readpbminit(ifP, &inCols, &inRows, &format);
+
+    inColByteCt = pbm_packed_bytes(inCols);
+
+    bitrow = pbm_allocrow_packed(MAX(outCols, inCols));
+    
+    /* Add padding to round cols up to 640 */
+    for (i = inColByteCt; i < outColByteCt; ++i)
+        bitrow[i] = 0x00;
+
+    putinit(stdout);
+
+    for (row = 0; row < MIN(inRows, outRows); ++row) {
+        pbm_readpbmrow_packed(ifP, bitrow, inCols, format);
+        pbm_cleanrowend_packed(bitrow, inCols);
+        fwrite (bitrow, outColByteCt, 1, stdout);
     }
+    pm_close(ifP);
 
-static void
-putitem( )
-    {
-    putc (item, stdout);
-    item = 0;
-    bitsperitem = 0;
-    bitshift = 7;
+    if (row < outRows)  {
+        unsigned int i;
+
+        /* Clear entire row */
+        for (i = 0; i < outColByteCt; ++i)
+            bitrow[i] = 0x00;
+
+        while (row++ < outRows)
+            fwrite(bitrow, outColByteCt, 1, stdout);
     }
+
+    pbm_freerow_packed(bitrow);
+
+    return 0;
+}
diff --git a/converter/pbm/pbmtopk.c b/converter/pbm/pbmtopk.c
index fc94f855..3948ae0d 100644
--- a/converter/pbm/pbmtopk.c
+++ b/converter/pbm/pbmtopk.c
@@ -1,7 +1,12 @@
 /*
   pbmtopk, adapted from "pxtopk.c by tomas rokicki" by AJCD 1/8/90
   
-  compile with: cc -o pbmtopk pbmtopk.c -lm -lpbm
+  References (retrieved May 31 2015):
+  Packed (PK) Font File Format 
+  https://www.tug.org/TUGboat/tb06-3/tb13pk.pdf
+
+  Tex Font Metric Files (TFM)
+  https://www.tug.org/TUGboat/tb06-1/tb11gf.pdf
 */
 
 #define _BSD_SOURCE 1      /* Make sure strdup() is in string.h */
@@ -26,6 +31,29 @@
 #define MAXPARAMS 30
 #define NAMELENGTH 80
 
+/*-----------------------------------------------------------------------
+Macros to handle fixed point numbers
+
+This program uses uses fixed-point numbers to store data where
+normally a floating-point data type (float or double) would be
+employed.
+
+Numbers that contain fractions are stored as signed integers.
+The 20 least-significant bits are for the fractional part, the rest
+(12 bits assuming that int is 32 bit) are for the integer part.
+The technical term for this is "Q20" or "Q12.20" notation.
+
+Float/double data is converted to Q20 fixed point by multiplying
+by 2^20 (= 1048576).  The opposite conversion is conducted by
+dividing by 2^20.
+
+The Q20 data must be within the range -16 < r < 16.  The reason
+behind this restriction is unclear.  The program generally writes
+Q20 data to the output files in 32 bits.  (Exception: in function
+shipchar() there is a provision to write Q20 data in 24 bits,
+provided that 24 bits is sufficient.)
+---------------------------------------------------------------------*/
+
 #define fixword(d) ((int)((double)(d)*1048576))
 #define unfixword(f) ((double)(f) / 1048576)
 #define fixrange(f) ((f) < 16777216 && (f) > -16777216)
diff --git a/converter/pbm/pbmtoptx.c b/converter/pbm/pbmtoptx.c
index 8cd60326..c0fb0f80 100644
--- a/converter/pbm/pbmtoptx.c
+++ b/converter/pbm/pbmtoptx.c
@@ -12,84 +12,79 @@
 
 #include "pbm.h"
 
-static void putinit ARGS(( void ));
-static void putbit ARGS(( bit b ));
-static void putrest ARGS(( void ));
-static void putitem ARGS(( void ));
+/* Follwing is obtained by reversing bit order (MFS-LFS) and adding 64. */
+/* Note the two escape sequences: \\ and \x7f . */
 
-int
-main( argc, argv )
-int argc;
-char *argv[];
-    {
-    FILE *ifp;
-    register bit *bitrow, *bP;
-    int rows, cols, format, row, col;
-    const char * const usage = "[pbmfile]";
-
-    pbm_init( &argc, argv );
-
-    if ( argc > 2 )
-	pm_usage( usage );
-
-    if ( argc == 2 )
-	ifp = pm_openr( argv[1] );
-    else
-	ifp = stdin;
-
-    pbm_readpbminit( ifp, &cols, &rows, &format );
-    bitrow = pbm_allocrow( cols );
-
-    putinit( );
-    for ( row = 0; row < rows; row++ )
-	{
-	pbm_readpbmrow( ifp, bitrow, cols, format );
-        for ( col = 0, bP = bitrow; col < cols; col++, bP++ )
-	    putbit( *bP );
-	putrest( );
-	putchar( 5 );
-	putchar( '\n' );
-        }
+static unsigned char const ptxchar[64] = 
+  "@`PpHhXxDdTtLl\\|BbRrJjZzFfVvNn^~AaQqIiYyEeUuMm]}CcSsKk[{GgWwOo_\x7f";
 
-    pm_close( ifp );
-    
-    exit( 0 );
-    }
 
-static char item;
-static int bitsperitem, bitshift;
 
 static void
-putinit( )
-    {
-    bitsperitem = 0;
-    item = 64;
-    bitshift = 0;
-    }
+putBitrow(const bit *  const bitrow,
+          unsigned int const cols) {
+/*----------------------------------------------------------------------------
+  Pick up items in 6 bit units from bitrow and convert each to ptx format.
+----------------------------------------------------------------------------*/
+    unsigned int itemCnt;
 
-static void
-putbit( bit b )
-    {
-    if ( bitsperitem == 6 )
-	putitem( );
-    if ( b == PBM_BLACK )
-	item += 1 << bitshift;
-    bitsperitem++;
-    bitshift++;
+    for (itemCnt = 0; itemCnt * 6 < cols; ++itemCnt) {
+        unsigned int const byteCnt = (itemCnt * 6) / 8;
+        bit const byteCur  = bitrow[byteCnt];
+        bit const byteNext = bitrow[byteCnt + 1];
+        
+        unsigned int item;
+
+        switch (itemCnt % 4) {
+        case 0: item = byteCur >> 2;                 break;
+        case 1: item = byteCur << 4 | byteNext >> 4; break;
+        case 2: item = byteCur << 2 | byteNext >> 6; break;
+        case 3: item = byteCur;                      break;
+        }
+        putchar(ptxchar[item & 0x3f]);
     }
+    putchar(5); putchar('\n');  /* end of row mark */
+}
 
-static void
-putrest( )
-    {
-    if ( bitsperitem > 0 )
-	putitem( );
+
+
+int
+main(int argc, const char ** argv)  {
+
+    FILE * ifP;
+    bit * bitrow;
+    int rows, cols, format;
+    unsigned int row;
+
+    pm_proginit(&argc, argv);
+
+    if (argc-1 < 1)
+        ifP = stdin;
+    else {
+        ifP = pm_openr(argv[1]);
+        
+        if (argc-1 > 1)
+            pm_error("Too many arguments.  The only possible argument is "
+                     "the input fil name");
     }
 
-static void
-putitem( )
-    {
-    putchar( item );
-    bitsperitem = 0;
-    item = 64;
-    bitshift = 0;
+    pbm_readpbminit(ifP, &cols, &rows, &format);
+
+    bitrow = pbm_allocrow_packed(cols + 8);
+
+    bitrow[pbm_packed_bytes(cols)] = 0x00;
+
+    for (row = 0; row < rows; ++row) {
+        pbm_readpbmrow_packed(ifP, bitrow, cols, format);
+        pbm_cleanrowend_packed(bitrow, cols);
+        putBitrow(bitrow, cols);
     }
+
+    pbm_freerow_packed(bitrow);
+    pm_close(ifP);
+    
+    return 0;
+}
+
+
+
diff --git a/converter/pbm/pbmtoxbm.c b/converter/pbm/pbmtoxbm.c
index c6c4a9e6..14c6b85e 100644
--- a/converter/pbm/pbmtoxbm.c
+++ b/converter/pbm/pbmtoxbm.c
@@ -23,6 +23,7 @@
 #define _BSD_SOURCE 1      /* Make sure strdup() is in string.h */
 #define _XOPEN_SOURCE 500  /* Make sure strdup() is in string.h */
 
+#include <assert.h>
 #include <string.h>
 
 #include "pm_c_util.h"
@@ -35,7 +36,7 @@
 
 enum xbmVersion { X10, X11 };
 
-struct cmdlineInfo {
+struct CmdlineInfo {
     /* All the information the user supplied in the command line,
        in a form easy for the program to use.
     */
@@ -46,8 +47,8 @@ struct cmdlineInfo {
 
 static void
 parseCommandLine(int                 argc, 
-                 char **             argv,
-                 struct cmdlineInfo *cmdlineP ) {
+                 const char **       argv,
+                 struct CmdlineInfo *cmdlineP ) {
 /*----------------------------------------------------------------------------
    Parse program command line described in Unix standard form by argc
    and argv.  Return the information in the options as *cmdlineP.  
@@ -58,7 +59,7 @@ parseCommandLine(int                 argc,
    Note that the strings we return are stored in the storage that
    was passed to us as the argv array.  We also trash *argv.
 -----------------------------------------------------------------------------*/
-    optEntry *option_def;
+    optEntry * option_def;
     /* Instructions to pm_optParseOptions3 on how to parse our options. */
 
     optStruct3 opt;
@@ -76,7 +77,7 @@ parseCommandLine(int                 argc,
     opt.short_allowed = FALSE;  /* We have no short (old-fashioned) options */
     opt.allowNegNum = FALSE;  /* We have no parms that are negative numbers */
 
-    pm_optParseOptions3( &argc, argv, opt, sizeof(opt), 0);
+    pm_optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0);
         /* Uses and sets argc, argv, and some of *cmdlineP and others. */
 
     if (!nameSpec)
@@ -111,6 +112,7 @@ parseCommandLine(int                 argc,
             pm_error("Program takes zero or one argument (filename).  You "
                      "specified %u", argc-1);
     }
+    free(option_def);
 }
 
 
@@ -242,18 +244,22 @@ puttermX10(void) {
 
     unsigned int i;
 
+    assert(itemCnt % 2 == 0);
+
     for (i = 0; i < itemCnt; i += 2) {
         int rc;
 
+        assert(i + 1 < itemCnt);
+
         rc = printf("%s0x%02x%02x%s",
                     (i == 0) ? " " : "",
                     itemBuff[i+1],
                     itemBuff[i], 
-                    (i == itemCnt - 2) ? "" : ",");
+                    (i + 2 >= itemCnt) ? "" : ",");
         if (rc < 0)        
-            pm_error("Error writing end of X10 bitmap raster.  "
+            pm_error("Error writing Item %u at end of X10 bitmap raster.  "
                      "printf() failed with errno %d (%s)",
-                     errno, strerror(errno));
+                     i, errno, strerror(errno));
     }
 }
 
@@ -270,12 +276,12 @@ puttermX11(void) {
         rc = printf("%s0x%02x%s",
                     (i == 0)  ? " " : "",
                     itemBuff[i],
-                    (i == itemCnt - 1) ? "" : ",");
+                    (i + 1 >= itemCnt) ? "" : ",");
 
         if (rc < 0)        
-            pm_error("Error writing end of X11 bitmap raster.  "
+            pm_error("Error writing Item %u at end of X11 bitmap raster.  "
                      "printf() failed with errno %d (%s)",
-                     errno, strerror(errno));
+                     i, errno, strerror(errno));
     }
 }
 
@@ -319,8 +325,8 @@ writeXbmHeader(enum xbmVersion const xbmVersion,
                unsigned int    const height,
                FILE *          const ofP) {
 
-    printf("#define %s_width %d\n", name, width);
-    printf("#define %s_height %d\n", name, height);
+    printf("#define %s_width %u\n", name, width);
+    printf("#define %s_height %u\n", name, height);
     printf("static %s %s_bits[] = {\n",
            xbmVersion == X10 ? "short" : "char",
            name);
@@ -337,8 +343,7 @@ convertRaster(FILE *          const ifP,
               enum xbmVersion const xbmVersion) {
               
     unsigned int const bitsPerUnit = xbmVersion == X10 ? 16 : 8;   
-    unsigned int const padright =
-        ((cols + bitsPerUnit - 1 ) / bitsPerUnit) * bitsPerUnit - cols;
+    unsigned int const padright = ROUNDUP(cols, bitsPerUnit) - cols;
         /* Amount of padding to round cols up to the nearest multiple of 
            8 (if x11) or 16 (if x10).
         */
@@ -352,21 +357,15 @@ convertRaster(FILE *          const ifP,
     bitrow = pbm_allocrow_packed(cols + padright);
     
     for (row = 0; row < rows; ++row) {
-        int const bitrowInBytes = pbm_packed_bytes(cols);
-        int const padrightIn    = bitrowInBytes * 8 - cols;
-
         unsigned int i;
 
         pbm_readpbmrow_packed(ifP, bitrow, cols, format);
+        pbm_cleanrowend_packed(bitrow, cols);
 
-        if (padrightIn > 0) {
-            bitrow[bitrowInBytes - 1] >>= padrightIn;
-            bitrow[bitrowInBytes - 1] <<= padrightIn;
-        }
-
-        if (padright >= 8)
+        if (padright >= 8) {
+            assert(bitrowBytes > 0);
             bitrow[bitrowBytes-1] = 0x00;
-
+        }
         for (i = 0; i < bitrowBytes; ++i)
             putitem(bitrow[i]);
     }
@@ -379,15 +378,15 @@ convertRaster(FILE *          const ifP,
 
 
 int
-main(int    argc,
-     char * argv[]) {
+main(int           argc,
+     const char ** argv) {
 
-    struct cmdlineInfo cmdline; 
+    struct CmdlineInfo cmdline; 
     FILE * ifP;
     int rows, cols, format;
     const char * name;
 
-    pbm_init(&argc, argv);
+    pm_proginit(&argc, argv);
 
     parseCommandLine(argc, argv, &cmdline);
     if (cmdline.name == NULL) 
@@ -409,3 +408,5 @@ main(int    argc,
     return 0;
 }
 
+
+
diff --git a/converter/pbm/pbmtoybm.c b/converter/pbm/pbmtoybm.c
index 3fdd805d..27ce6cb1 100644
--- a/converter/pbm/pbmtoybm.c
+++ b/converter/pbm/pbmtoybm.c
@@ -19,26 +19,11 @@
 
 #include "pm.h"
 #include "pbm.h"
+#include "bitreverse.h"
 
 #define YBM_MAGIC  ( ( '!' << 8 ) | '!' )
 #define INT16MAX 32767
 
-static long item;
-static int bitsperitem, bitshift;
-
-
-static void
-putitem(void) {
-
-    pm_writebigshort(stdout, item);
-
-    item        = 0;
-    bitsperitem = 0;
-    bitshift    = 0;
-}
-
-
-
 static void
 putinit(int const cols,
         int const rows) {
@@ -46,35 +31,6 @@ putinit(int const cols,
     pm_writebigshort(stdout, YBM_MAGIC);
     pm_writebigshort(stdout, cols);
     pm_writebigshort(stdout, rows);
-
-    item        = 0;
-    bitsperitem = 0;
-    bitshift    = 0;
-}
-
-
-
-static void
-putbit(bit const b) {
-
-    if (bitsperitem == 16)
-        putitem();
-
-    ++bitsperitem;
-
-    if (b == PBM_BLACK)
-        item += 1 << bitshift;
-
-    ++bitshift;
-}
-
-
-
-static void
-putrest(void) {
-
-    if (bitsperitem > 0)
-        putitem();
 }
 
 
@@ -87,51 +43,55 @@ main(int argc, const char *argv[]) {
     int rows;
     int cols;
     int format;
-    unsigned int padright;
     unsigned int row;
-    const char * inputFile;
+    const char * inputFileName;
 
     pm_proginit(&argc, argv);
 
     if (argc-1 < 1)
-        inputFile = "-";
+        inputFileName = "-";
     else {
-        inputFile = argv[1];
+        inputFileName = argv[1];
 
-        if (argc-1 > 2)
+        if (argc-1 > 1)
             pm_error("Too many arguments.  The only argument is the optional "
                      "input file name");
     }
 
-    ifP = pm_openr(inputFile);
+    ifP = pm_openr(inputFileName);
 
     pbm_readpbminit(ifP, &cols, &rows, &format);
 
     if (rows > INT16MAX || cols > INT16MAX)
         pm_error("Input image is too large.");
 
-    bitrow = pbm_allocrow(cols);
+    bitrow = pbm_allocrow_packed(cols + 8);
     
-    /* Compute padding to round cols up to the nearest multiple of 16. */
-    padright = ((cols + 15) / 16) * 16 - cols;
-
     putinit(cols, rows);
+
+    bitrow[pbm_packed_bytes(cols + 8) - 1] = 0x00;
     for (row = 0; row < rows; ++row) {
-        unsigned int col;
+        uint16_t *   const itemrow = (uint16_t *) bitrow;
+        unsigned int const itemCt   = (cols + 15) / 16;
+
+        unsigned int i;
 
-        pbm_readpbmrow(ifP, bitrow, cols, format);
+        pbm_readpbmrow_packed(ifP, bitrow, cols, format);
+        pbm_cleanrowend_packed(bitrow, cols);
 
-        for (col = 0; col < cols; ++col)
-            putbit(bitrow[col]);
+        for (i = 0; i < pbm_packed_bytes(cols); ++i)
+            bitrow[i] = bitreverse[bitrow[i]];
 
-        for (col = 0; col < padright; ++col)
-            putbit(0);
+        for (i = 0; i < itemCt; ++i)
+            pm_writebigshort(stdout, itemrow[i]);
     }
 
+    pbm_freerow_packed(bitrow);
+
     if (ifP != stdin)
         fclose(ifP);
 
-    putrest();
-
     return 0;
 }
+
+
diff --git a/converter/pbm/pbmtozinc.c b/converter/pbm/pbmtozinc.c
index 2df39f0d..66ec5582 100644
--- a/converter/pbm/pbmtozinc.c
+++ b/converter/pbm/pbmtozinc.c
@@ -1,4 +1,4 @@
-/* pbmtozinc.c - read a portable bitmap and produce an bitmap file
+/* pbmtozinc.c - read a PBM image and produce a bitmap file
 **               in the format used by the Zinc Interface Library (v1.0)
 **               November 1990.
 **
@@ -21,108 +21,163 @@
 #include <stdio.h>
 #include <string.h>
 
+#include "mallocvar.h"
 #include "nstring.h"
 #include "pbm.h"
 
-int
-main(int argc, char * argv[]) {
-
-    FILE* ifp;
-    bit* bitrow;
-    register bit* bP;
-    int rows, cols, format, padright, row;
-    register int col;
-    char name[100];
-    char* cp;
-    int itemsperline;
-    register int bitsperitem;
-    register int item;
-    int firstitem;
-    const char * const hexchar = "084c2a6e195d3b7f";
-
-    pbm_init( &argc, argv );
-
-    if ( argc > 2 )
-        pm_usage( "[pbmfile]" );
-
-    if ( argc == 2 )
-	{
-        ifp = pm_openr( argv[1] );
-        strcpy( name, argv[1] );
-        if ( streq( name, "-" ) )
-            strcpy( name, "noname" );
-
-        if ( ( cp = strchr( name, '.' ) ) != 0 )
+static void
+parseCommandLine(int           const argc,
+                 const char ** const argv,
+                 const char ** const inputFileNameP) {
+
+    if (argc-1 > 0) {
+        *inputFileNameP = argv[1];
+
+        if (argc-1 > 1)
+            pm_error("To many arguments: %u.  "
+                     "The only possible argument is the "
+                     "name of the input file", argc-1);
+    } else
+        *inputFileNameP = "-";
+}
+
+
+
+static const char *
+imageName(const char * const inputFileName) {
+/*----------------------------------------------------------------------------
+   The image name to put in the Zinc file, based on the input file name
+   'inputFileName' ("-" to indicate Standard Input).
+
+   Result is newly malloc'ed space that Caller must free.
+-----------------------------------------------------------------------------*/
+    const char * retval;
+
+    if (streq(inputFileName, "-"))
+        pm_asprintf(&retval, "noname");
+    else {
+        char * nameBuf;
+        char * cp;
+
+        MALLOCARRAY_NOFAIL(nameBuf, strlen(inputFileName) + 1);
+
+        strcpy(nameBuf, inputFileName);
+
+        cp = strchr(nameBuf, '.' );
+        if (cp)
             *cp = '\0';
-	}
-    else
-	{
-        ifp = stdin;
-        strcpy( name, "noname" );
-	}
-
-    pbm_readpbminit( ifp, &cols, &rows, &format );
-    bitrow = pbm_allocrow( cols );
-
-    /* Compute padding to round cols up to the nearest multiple of 16. */
-    padright = ( ( cols + 15 ) / 16 ) * 16 - cols;
-
-    printf( "USHORT %s[] = {\n",name);
-    printf( "  %d\n", cols );
-    printf( "  %d\n", rows );
-
-    itemsperline = 0;
-    bitsperitem = 0;
-    item = 0;
-    firstitem = 1;
-
-#define PUTITEM \
-    { \
-    if ( firstitem ) \
-	firstitem = 0; \
-    else \
-	putchar( ',' ); \
-    if ( itemsperline == 11 ) \
-	{ \
-	putchar( '\n' ); \
-	itemsperline = 0; \
-	} \
-    if ( itemsperline == 0 ) \
-	putchar( ' ' ); \
-    ++itemsperline; \
-    putchar('0'); \
-    putchar('x'); \
-    putchar(hexchar[item & 15]); \
-    putchar(hexchar[(item >> 4) & 15]); \
-    putchar(hexchar[(item >> 8) & 15]); \
-    putchar(hexchar[item >> 12]); \
-    bitsperitem = 0; \
-    item = 0; \
+
+        retval = nameBuf;
     }
+    return retval;
+}
 
-#define PUTBIT(b) \
-    { \
-    if ( bitsperitem == 16 ) \
-	PUTITEM; \
-    if ( (b) == PBM_BLACK ) \
-	item += 1 << bitsperitem; \
-    ++bitsperitem; \
+
+
+typedef struct {
+    unsigned int itemsperline;
+    uint16_t     item;
+    unsigned int firstitem;
+} Packer;
+
+
+
+static void
+packer_init(Packer * const packerP) {
+
+    packerP->itemsperline = 0;
+    packerP->firstitem = 1;
+}
+
+
+
+static void
+packer_putitem(Packer * const packerP) {
+
+    if (packerP->firstitem)
+        packerP->firstitem = 0;
+    else
+        putchar(',');
+
+    if (packerP->itemsperline == 11) {
+        putchar('\n');
+        packerP->itemsperline = 0;
     }
+    if (packerP->itemsperline == 0)
+        putchar(' ');
+
+    ++packerP->itemsperline;
+    printf ("0x%02x%02x", packerP->item & 255, packerP->item >> 8);
 
-    for ( row = 0; row < rows; ++row )
-	{
-        pbm_readpbmrow( ifp, bitrow, cols, format );
-        for ( col = 0, bP = bitrow; col < cols; ++col, ++bP )
-            PUTBIT( *bP );
-        for ( col = 0; col < padright; ++col )
-            PUTBIT( 0 );
+}
+
+
+
+static void
+writeRaster(FILE *       const ifP,
+            unsigned int const rows,
+            unsigned int const cols,
+            int          const format) {
+
+    bit * const bitrow = pbm_allocrow_packed(cols + 8);
+
+    Packer packer;
+    unsigned int row;
+
+    packer_init(&packer);
+
+    bitrow[pbm_packed_bytes(cols+8) -1 ] = 0x00;
+
+    for (row = 0; row < rows; ++row) {
+        uint16_t * const itemrow = (uint16_t *) bitrow;
+        unsigned int const itemCt = (cols + 15 ) / 16;
+
+        unsigned int i;
+
+        pbm_readpbmrow_packed(ifP, bitrow, cols, format);
+
+        pbm_cleanrowend_packed(bitrow, cols);
+
+        for (i = 0; i < itemCt; ++i) {
+            packer.item = itemrow[i];
+            packer_putitem(&packer);
+        }
     }
+    pbm_freerow_packed(bitrow);
+}
+
+
+
+int
+main(int argc, const char * argv[]) {
+
+    const char * inputFileName;
+    FILE * ifP;
+    int rows, cols;
+    int format;
+    const char * name;
+
+    pm_proginit(&argc, argv);
+
+    parseCommandLine(argc, argv, &inputFileName);
+
+    ifP = pm_openr(inputFileName);
+
+    name = imageName(inputFileName);
+
+    pbm_readpbminit(ifP, &cols, &rows, &format);
+
+    printf("USHORT %s[] = {\n", name);
+    printf("  %d\n", cols);
+    printf("  %d\n", rows);
+
+    writeRaster(ifP, rows, cols, format);
+
+    printf("};\n");
+
+    pm_close(ifP);
 
-    pm_close( ifp );
-    
-    if ( bitsperitem > 0 )
-        PUTITEM;
-    printf( "};\n" );
+    pm_strfree(name);
 
     return 0;
 }
diff --git a/converter/pbm/pi3topbm.c b/converter/pbm/pi3topbm.c
index 8b3b21e3..17b07d6f 100644
--- a/converter/pbm/pi3topbm.c
+++ b/converter/pbm/pi3topbm.c
@@ -22,91 +22,147 @@
  */
 
 #include <stdio.h>
+
+#include "pm_c_util.h"
+#include "mallocvar.h"
+#include "shhopt.h"
 #include "pbm.h"
 
+
+
+struct CmdlineInfo {
+    /* All the information the user supplied in the command line,
+       in a form easy for the program to use.
+    */
+    const char * inputFileName;  /* Filename of input file */
+    unsigned int debug;
+};
+
+
+
+static void 
+parseCommandLine(int argc, 
+                 const char ** argv, 
+                 struct CmdlineInfo * const cmdlineP) {
+/* --------------------------------------------------------------------------
+   Parse program command line described in Unix standard form by argc
+   and argv.  Return the information in the options as *cmdlineP.  
+
+   If command line is internally inconsistent (invalid options, etc.),
+   issue error message to stderr and abort program.
+
+   Note that the strings we return are stored in the storage that
+   was passed to us as the argv array.  We also trash *argv.
+--------------------------------------------------------------------------*/
+    optEntry * option_def;
+    optStruct3 opt;
+        /* Instructions to pm_optParseOptions3 on how to parse our options. */
+    unsigned int option_def_index;
+  
+    MALLOCARRAY_NOFAIL(option_def, 100);
+
+    option_def_index = 0;   /* incremented by OPTENT3 */
+    OPTENT3(0, "debug",    OPT_FLAG,    NULL,       &cmdlineP->debug,       0);
+  
+    opt.opt_table = option_def;
+    opt.short_allowed = FALSE;  /* We have no short (old-fashioned) options */
+    opt.allowNegNum = FALSE;   /* We have no parms that are negative numbers */
+
+    pm_optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0);
+        /* Uses and sets argc, argv, and some of *cmdlineP and others. */
+
+    if (argc-1 < 1) 
+        cmdlineP->inputFileName = "-";
+    else {
+        cmdlineP->inputFileName = argv[1];
+
+        if (argc-1 > 1)
+            pm_error("Program takes zero or one argument (filename).  You "
+                     "specified %u", argc-1);
+    }
+}
+
+
+
+static void
+readAndValidateHeader(FILE * const ifP,
+                      bool   const debug,
+                      bool * const reverseP) {
+
+    short item;
+
+    pm_readbigshort(ifP, &item);
+
+    if (debug)
+        pm_message("resolution is %d", item);
+
+    /* only handles hi-rez 640x400 */
+    if (item != 2)
+        pm_error("bad resolution %d", item);
+
+    pm_readbigshort(ifP, &item);
+
+    *reverseP = (item == 0);
+
+    {
+        unsigned int i;
+
+        for (i = 1; i < 16; ++i)
+            pm_readbigshort (ifP, &item);
+    }
+}
+
+
+
 int
-main(argc, argv)
-	int             argc;
-	char           *argv[];
-{
-	int             debug = 0;
-	FILE           *f;
-	int             x;
-	int             i, k;
-	int             c;
-	int		rows, cols;
-	bit		*bitrow;
-	short res;
-	int black, white;
-	const char * const usage = "[-debug] [pi3file]";
-	int argn = 1;
-
-	pbm_init( &argc, argv );
-
-	while (argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0')
-	  {
-	    if (pm_keymatch(argv[1], "-debug", 2))
-	      debug = 1;
-	    else
-	      pm_usage (usage);
-	    ++argn;
-	  }
-
-	if (argn == argc)
-	    f = stdin;
-	else
-	  {
-	    f = pm_openr (argv[argn]);
-	    ++argn;
-	  }
-
-	if (argn != argc)
-	  pm_usage (usage);
-
-	if (pm_readbigshort (f, &res) == -1)
-		pm_error ("EOF / read error");
-
-	if (debug)
-		pm_message ("resolution is %d", res);
-
-	/* only handles hi-rez 640x400 */
-	if (res != 2)
-		pm_error( "bad resolution" );
-
-	pm_readbigshort (f, &res);
-	if (res == 0)
-	  {
-	    black = PBM_WHITE;
-	    white = PBM_BLACK;
-	  }
-	else
-	  {
-	    black = PBM_BLACK;
-	    white = PBM_WHITE;
-	  }
-
-	for (i = 1; i < 16; i++)
-	  if (pm_readbigshort (f, &res) == -1)
-	    pm_error ("EOF / read error");
-
-	cols = 640;
-	rows = 400;
-	pbm_writepbminit( stdout, cols, rows, 0 );
-	bitrow = pbm_allocrow( cols );
-
-	for (i = 0; i < rows; ++i) {
-		x = 0;
-		while (x < cols) {
-			if ((c = getc(f)) == EOF)
-				pm_error( "end of file reached" );
-			for (k = 0x80; k; k >>= 1) {
-				bitrow[x] = (k & c) ? black : white;
-				++x;
-			}
-		}
-		pbm_writepbmrow( stdout, bitrow, cols, 0 );
-	}
-	pm_close( f );
-	pm_close( stdout );
-	exit(0);
+main(int argc, const char ** argv) {
+
+    unsigned int const rows = 400;
+    unsigned int const cols = 640;
+
+    struct CmdlineInfo cmdline;
+    FILE * ifP;
+    unsigned int row;
+    bit * bitrow;
+    bool reverse;
+
+    pm_proginit(&argc, argv);
+
+    parseCommandLine(argc, argv, &cmdline);
+
+    ifP = pm_openr(cmdline.inputFileName);
+
+    readAndValidateHeader(ifP, cmdline.debug, &reverse);
+
+    pbm_writepbminit(stdout, cols, rows, 0);
+
+    bitrow = pbm_allocrow_packed(cols);
+
+    for (row = 0; row < rows; ++row) {
+        unsigned int const colChars = cols / 8;
+
+        unsigned int bytesReadCt;
+
+        bytesReadCt = fread(bitrow, cols / 8, 1, ifP);
+        if (bytesReadCt != 1) {
+            if (feof(ifP))
+                pm_error( "EOF reached while reading image data" );
+            else
+                pm_error("read error while reading image data");
+        }
+
+        if (reverse) {
+            /* flip all pixels */
+            unsigned int colChar;
+            for (colChar = 0; colChar < colChars; ++colChar)
+                bitrow[colChar] = ~bitrow[colChar];
+        }
+        pbm_writepbmrow_packed(stdout, bitrow, cols, 0);
+    }
+
+    pbm_freerow_packed(bitrow);
+    pm_close(ifP);
+    pm_close(stdout);
+
+    return 0;
 }
diff --git a/converter/pbm/xbmtopbm.c b/converter/pbm/xbmtopbm.c
index 0cbebc5e..bbf4e395 100644
--- a/converter/pbm/xbmtopbm.c
+++ b/converter/pbm/xbmtopbm.c
@@ -362,12 +362,8 @@ main(int    argc,
         
         for (i = 0; i < bytesPerRow; ++i)
             bitrow[i] = bitreverse[*p++];
-            
-        if (cols % 8 > 0) {
-            bitrow[bytesPerRow-1] >>= 8 - cols % 8;
-            bitrow[bytesPerRow-1] <<= 8 - cols % 8;
-        }
-            
+
+        pbm_cleanrowend_packed(bitrow, cols);
         pbm_writepbmrow_packed(stdout, bitrow, cols, 0);
     }
 
diff --git a/converter/pbm/ybmtopbm.c b/converter/pbm/ybmtopbm.c
index 3d012483..2a429086 100644
--- a/converter/pbm/ybmtopbm.c
+++ b/converter/pbm/ybmtopbm.c
@@ -12,23 +12,17 @@
 
 #include "pm.h"
 #include "pbm.h"
+#include "bitreverse.h"
 
 static short const ybmMagic = ( ( '!' << 8 ) | '!' );
 
 
 
-
-static int item;
-static int bitsInBuffer, bitshift;
-
-
-
 static void
 getinit(FILE *  const ifP,
         short * const colsP,
         short * const rowsP,
-        short * const depthP,
-        short * const padrightP) {
+        short * const depthP) {
 
     short magic;
     int rc;
@@ -49,31 +43,10 @@ getinit(FILE *  const ifP,
         pm_error("EOF / read error");
 
     *depthP = 1;
-    *padrightP = ((*colsP + 15) / 16) * 16 - *colsP;
 }
 
 
 
-static bit
-getbit(FILE * const ifP) {
-
-    bit b;
-
-    if (bitsInBuffer == 0) {
-        item = (getc(ifP) << 8) | (getc(ifP) << 0);
-
-        if (item == EOF)
-            pm_error("EOF / read error");
-
-        bitsInBuffer = 16;
-        bitshift = 0;
-    }
-
-    b = ((item >> bitshift) & 1 ) ? PBM_BLACK : PBM_WHITE;
-    --bitsInBuffer;
-    ++bitshift;
-    return b;
-}
 
 
 
@@ -82,7 +55,7 @@ main(int argc, const char * argv[]) {
 
     FILE * ifP;
     bit * bitrow;
-    short rows, cols, padright;
+    short rows, cols;
     unsigned int row;
     short depth;
     const char * inputFile;
@@ -94,36 +67,42 @@ main(int argc, const char * argv[]) {
     else {
         inputFile = argv[1];
 
-        if (argc-1 > 2)
+        if (argc-1 > 1)
             pm_error("Too many arguments.  The only argument is the optional "
                      "input file name");
     }
 
     ifP = pm_openr(inputFile);
 
-    bitsInBuffer = 0;
-
-    getinit(ifP, &cols, &rows, &depth, &padright);
+    getinit(ifP, &cols, &rows, &depth);
     if (depth != 1)
         pm_error("YBM file has depth of %u, must be 1", (unsigned)depth);
     
     pbm_writepbminit(stdout, cols, rows, 0);
 
-    bitrow = pbm_allocrow(cols);
+    bitrow = pbm_allocrow_packed(cols + 8);
 
     for (row = 0; row < rows; ++row) {
+        uint16_t *   const itemrow = (uint16_t *) bitrow;
+        unsigned int const itemCt  = (cols + 15) / 16;
+
+        unsigned int i;
+
         /* Get raster. */
-        unsigned int col;
+        for (i = 0; i < itemCt; ++i) {
+            short int item;
+            pm_readbigshort(ifP, &item);
+            itemrow[i] = (uint16_t) item; 
+        }
 
-        for (col = 0; col < cols; ++col)
-            bitrow[col] = getbit(ifP);
+        for (i = 0; i < pbm_packed_bytes(cols); ++i)
+            bitrow[i] = bitreverse[bitrow[i]];
 
-        /* Discard line padding */
-        for (col = 0; col < padright; ++col)
-            getbit(ifP);
-        pbm_writepbmrow(stdout, bitrow, cols, 0);
+        pbm_cleanrowend_packed(bitrow, cols);
+        pbm_writepbmrow_packed(stdout, bitrow, cols, 0);
     }
 
+    pbm_freerow_packed(bitrow);
     pm_close(ifP);
     pm_close(stdout);
 
diff --git a/converter/ppm/ppmtoarbtxt.c b/converter/ppm/ppmtoarbtxt.c
index 93b3605b..83a93441 100644
--- a/converter/ppm/ppmtoarbtxt.c
+++ b/converter/ppm/ppmtoarbtxt.c
@@ -225,8 +225,9 @@ writeIcol(FILE *           const ofP,
     */
 
     struct Icdat * const icdataP = &objectP->odata.icolData;
-    unsigned int const outValue = icdataP->icolmin +
-        ROUNDU(((double) icdataP->icolmax - icdataP->icolmin) * value);
+    unsigned int const outValue =
+        ROUNDU( icdataP->icolmin +
+                ((double)icdataP->icolmax - icdataP->icolmin) * value);
 
     fprintf(ofP, icdataP->icformat, outValue);
 }
@@ -470,7 +471,7 @@ validateFormatWithPpf(const char *       const format,
 
     default:
         pm_asprintf(errorP, "Has %lu extra transformation%s ",
-                    n-1, n-1 > 1 ? "s" : "");
+                    (unsigned long)n-1, n-1 > 1 ? "s" : "");
         break;
     }
 }
diff --git a/converter/ppm/ppmtobmp.c b/converter/ppm/ppmtobmp.c
index 24b1b3e5..6d65d744 100644
--- a/converter/ppm/ppmtobmp.c
+++ b/converter/ppm/ppmtobmp.c
@@ -20,6 +20,7 @@
 #include <string.h>
 
 #include "pm_c_util.h"
+#include "nstring.h"
 #include "mallocvar.h"
 #include "shhopt.h"
 #include "bmp.h"
@@ -131,13 +132,22 @@ parseCommandLine(int argc, const char ** argv,
         cmdlineP->mapfile = NULL;
 
     if (argc - 1 == 0)
-        cmdlineP->inputFilename = strdup("-");  /* he wants stdin */
+        cmdlineP->inputFilename = pm_strdup("-");  /* he wants stdin */
     else if (argc - 1 == 1)
-        cmdlineP->inputFilename = strdup(argv[1]);
+        cmdlineP->inputFilename = pm_strdup(argv[1]);
     else 
         pm_error("Too many arguments.  The only argument accepted "
                  "is the input file specificaton");
 
+    free(option_def);
+}
+
+
+
+static void
+freeCommandLine(struct CmdlineInfo const cmdline) {
+
+    pm_strfree(cmdline.inputFilename);
 }
 
 
@@ -821,7 +831,6 @@ doPbm(FILE *       const ifP,
         32 bit borders and that in BMP the bottom row comes first in
         order.
     */
-    int const CHARBITS = (sizeof(unsigned char)*8); 
     int const colChars = pbm_packed_bytes(cols);
     int const adjustedCols = (cols+31) /32 * 32;
     int const packedBytes  =  adjustedCols /8;
@@ -853,11 +862,8 @@ doPbm(FILE *       const ifP,
            some BMP viewers may get confused with that.
         */
 
-        if (cols % 8 >0) {
-            /* adjust final partial byte */
-            thisRow[colChars-1] >>= CHARBITS - cols % CHARBITS;
-            thisRow[colChars-1] <<= CHARBITS - cols % CHARBITS;
-        }
+        /* Clean off remainder of fractional last character */
+        pbm_cleanrowend_packed(thisRow, cols);
     }
 
     bmpEncodePbm(ofP, class, cols, rows, bitrow);
@@ -907,6 +913,8 @@ doPgmPpm(FILE *       const ifP,
               cols, rows, (const pixel**)pixels, maxval, &colorMap);
     
     freeColorMap(&colorMap);
+
+    ppm_freearray(pixels, rows);
 }
 
 
@@ -937,6 +945,8 @@ main(int           argc,
                  cmdline.class, cmdline.bppSpec, cmdline.bpp, cmdline.mapfile,
                  stdout);
 
+    freeCommandLine(cmdline);
+
     pm_close(ifP);
     pm_close(stdout);
 
diff --git a/converter/ppm/ppmtoicr.c b/converter/ppm/ppmtoicr.c
index feca0c18..3c8be421 100644
--- a/converter/ppm/ppmtoicr.c
+++ b/converter/ppm/ppmtoicr.c
@@ -10,311 +10,255 @@
 ** implied warranty.
 */
 
+#include <stdbool.h>
+#include <assert.h>
 #include "ppm.h"
 
-#define MAXCOLORS 256
-#define CLUTCOLORS 768
+#define MAXCOLORCT 256
+#define CLUTCOLORCT 768
 
-static int colorstobpp ARGS(( int colors ));
-static int GetPixel ARGS(( int x, int y ));
-static int rleit ARGS(( char* buf, char* bufto, int len ));
 
-static pixel** pixels;
-static colorhash_table cht;
-static char* testimage;
 
-int
-main(argc, argv)
-int argc;
-char* argv[];
-{
-	FILE* ifp;
-	int argn, rows, cols, colors, i, j, BitsPerPixel, newxsize;
-	pixval maxval;
-	colorhist_vector chv;
-	char rgb[CLUTCOLORS];
-	const char* windowname;
-	char* thischar;
-	char* thisline;
-	char* space;
-	register unsigned char c;
-	register char* p;
-	int display, expand;
-	int rleflag, winflag;
-	const char* const usage = "[-windowname windowname] [-expand expand] [-display display] [-rle] [ppmfile]";
-
-
-	ppm_init( &argc, argv );
-
-	argn = 1;
-	windowname = "untitled";
-	winflag = 0;
-	expand = 1;
-	display = 0;
-	rleflag = 0;
-
-	while ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
-	    {
-	    if ( pm_keymatch(argv[argn],"-windowname",2) && argn + 1 < argc )
-		{
-		++argn;
-		windowname = argv[argn];
-		winflag = 1;
-		}
-	    else if ( pm_keymatch(argv[argn],"-expand",2) && argn + 1 < argc )
-		{
-		++argn;
-		if ( sscanf( argv[argn], "%d",&expand ) != 1 )
-		    pm_usage( usage );
-		}
-	    else if ( pm_keymatch(argv[argn],"-display",2) && argn + 1 < argc )
-		{
-		++argn;
-		if ( sscanf( argv[argn], "%d",&display ) != 1 )
-		    pm_usage( usage );
-		}
-	    else if ( pm_keymatch(argv[argn],"-rle",2) )
-		rleflag = 1;
-	    else if ( pm_keymatch(argv[argn],"-norle",2) )
-		rleflag = 0;
-	    else
-		pm_usage( usage );
-	    }
-
-	if ( argn < argc )
-	    {
-	    ifp = pm_openr( argv[argn] );
-	    if ( ! winflag )
-		windowname = argv[argn];
-	    ++argn;
-	    }
-	else
-	    ifp = stdin;
-
-	if ( argn != argc )
-	    pm_usage( usage );
-
-	pixels = ppm_readppm( ifp, &cols, &rows, &maxval );
-
-	pm_close( ifp );
-
-	for (i = 0; i < CLUTCOLORS; i++)
-	    rgb[i] = 0;
-
-	/* Figure out the colormap. */
-	pm_message("computing colormap..." );
-	chv = ppm_computecolorhist(pixels, cols, rows, MAXCOLORS, &colors);
-	if (chv == (colorhist_vector) 0)
-	pm_error( "too many colors - try doing a 'pnmquant %d'", MAXCOLORS );
-	pm_message("%d colors found", colors );
-
-	/* Turn the ppm colormap into an ICR colormap. */
-	if (maxval > 255)
-	pm_message(
-		"maxval is not 255 - automatically rescaling colors" );
-	for (i = 0; i < colors; i++)
-	{
-	j = (3 * i);
-	if (maxval == 255)
-		{
-		rgb[j] = PPM_GETR(chv[i].color) ;
-		j++;
-		rgb[j] = PPM_GETG(chv[i].color) ;
-		j++;
-		rgb[j] = PPM_GETB(chv[i].color) ;
-		}
-	else
-		{
-		rgb[j] = (int) PPM_GETR(chv[i].color) * 255 / maxval;
-		j++;
-		rgb[j] = (int) PPM_GETG(chv[i].color) * 255 / maxval;
-		j++;
-		rgb[j] = (int) PPM_GETB(chv[i].color) * 255 / maxval;
-		}
-	}
-	BitsPerPixel = colorstobpp(colors);
-
-	/* And make a hash table for fast lookup. */
-	cht = ppm_colorhisttocolorhash(chv, colors);
-	ppm_freecolorhist(chv);
-
-
-	/************** Create a new window using ICR protocol *********/
-	/* Format is "ESC^W;left;top;width;height;display;windowname"  */
-
-	pm_message("creating window %s ...", windowname );
-	(void)printf("\033^W;%d;%d;%d;%d;%d;%s^",0,0,cols*expand,rows*expand,display,windowname);
-	fflush(stdout);
-
-
-	/****************** Download the colormap.  ********************/
-	pm_message("downloading colormap for %s ...", windowname );
-
-	(void)printf("\033^M;%d;%d;%d;%s^",0,MAXCOLORS,CLUTCOLORS,windowname);
-	thischar = rgb;
-	for (j=0; j<CLUTCOLORS; j++) {
-	c = *thischar++;
-		if (c > 31 && c < 123 ) {	 /* printable ASCII */
-		putchar(c);
-		}
-		else {
-		putchar((c>>6)+123);	 /* non-printable, so encode it */
-		putchar((c & 0x3f) + 32);
-		}
-	}
-	fflush(stdout);
-
-	/**************** send out picture *************************/
-	/* Protocol's RLE scheme is quicker but buggy              */
-
-	if (rleflag) {	
-		pm_message("sending run-length encoded picture data ..." );
-		testimage = (char*) malloc(rows*cols);
-		p = testimage;
-		for (i=0; i<rows; i++)
-			for (j=0; j<cols; j++) 
-			*p++ = GetPixel(j,i);
-		space = (char*) malloc(rows*3);
-		thisline = testimage;
-		for (i = 0; i < rows; i++) {
-			newxsize = rleit(thisline,space,cols);
-			thisline += cols;	/* increment to next line */
-		(void)printf("\033^R;%d;%d;%d;%d;%s^",0,i*expand,expand,newxsize,windowname);
-		thischar = space;
-		for (j=0; j< newxsize; j++) {
-			c= *thischar++;  /*get byte to send */
-			if (c>31 && c <123) {
-				putchar(c);
-				}
-			else {
-				putchar((c>>6) + 123);
-				putchar((c & 0x3f) + 32);
-				}
-			}
-			fflush(stdout);
-		}
-		free(space);
-		exit(0);
-		}
-
-	/* Otherwise, send out uncompressed pixel data via the slow method */
-
-		else {
-		pm_message("sending picture data ..." );
-		for (i = 0; i < rows; i++) {
-			(void)printf("\033^P;%d;%d;%d;%d;%s^",0,i*expand,expand,cols,windowname);
-			for (j = 0; j < cols; j++) {
-				c  = GetPixel(j,i);
-				if (c > 31 && c < 123) {
-						putchar(c);
-						}
-				else		{
-						putchar((c>>6)+123);
-						putchar((c & 0x3f) + 32);
-						}
-				}
-			}
-		fflush(stdout);
-		exit(0);
-		}
-	}
+static void
+makeIcrColormap(colorhist_vector const chv,
+                unsigned int     const colorCt,
+                pixval           const maxval,
+                char *           const rgb) {
+
+    unsigned int i;
+
+    if (maxval > 255)
+        pm_message("Maxval is not 255 - automatically rescaling colors" );
+
+    for (i = 0; i < CLUTCOLORCT; ++i)
+        rgb[i] = 0;
+
+    for (i = 0; i < colorCt; ++i) {
+        unsigned int j;
+
+        j = (3 * i);
+
+        if (maxval == 255) {
+            rgb[j++] = PPM_GETR(chv[i].color) ;
+            rgb[j++] = PPM_GETG(chv[i].color) ;
+            rgb[j++] = PPM_GETB(chv[i].color) ;
+        } else {
+            rgb[j++] = (unsigned int) PPM_GETR(chv[i].color) * 255 / maxval;
+            rgb[j++] = (unsigned int) PPM_GETG(chv[i].color) * 255 / maxval;
+            rgb[j++] = (unsigned int) PPM_GETB(chv[i].color) * 255 / maxval;
+        }
+    }
+}
+
+
 
 static int
-colorstobpp(colors)
-int colors;
-	{
-	int bpp;
-
-	if (colors <= 2)
-	bpp = 1;
-	else if (colors <= 4)
-	bpp = 2;
-	else if (colors <= 8)
-	bpp = 3;
-	else if (colors <= 16)
-	bpp = 4;
-	else if (colors <= 32)
-	bpp = 5;
-	else if (colors <= 64)
-	bpp = 6;
-	else if (colors <= 128)
-	bpp = 7;
-	else if (colors <= 256)
-	bpp = 8;
-	else
-	pm_error("can't happen" );
-	return bpp;
-	}
+bppFromColorCt(unsigned int const colorCt) {
+
+    unsigned int bpp;
+
+    if (colorCt <= 2)
+        bpp = 1;
+    else if (colorCt <= 4)
+        bpp = 2;
+    else if (colorCt <= 8)
+        bpp = 3;
+    else if (colorCt <= 16)
+        bpp = 4;
+    else if (colorCt <= 32)
+        bpp = 5;
+    else if (colorCt <= 64)
+        bpp = 6;
+    else if (colorCt <= 128)
+        bpp = 7;
+    else if (colorCt <= 256)
+        bpp = 8;
+    else
+        assert(false);
+
+    return bpp;
+}
+
+
 
 static int
-GetPixel(x, y)
-int x, y;
-	{
-	int color;
+colorIndexAtPosition(unsigned int    const x,
+                     unsigned int    const y,
+                     pixel **        const pixels,
+                     colorhash_table const cht) {
 
-	color = ppm_lookupcolor(cht, &pixels[y][x]);
-	return color;
-	}
+    int rc;
 
+    rc = ppm_lookupcolor(cht, &pixels[y][x]);
 
-/* rleit   compress with run length encoding as per NCSA's documentation */
+    /* Every color in the image is in the palette */
+    assert(rc >= 0);
 
-static int
-rleit(buf,bufto,len)
-	char* buf;
-	char* bufto;
-	int len;
-	{
-	register char* p;
-	register char* q;
-	register char* cfoll;
-	register char* clead;
-	char* begp;
-	int i;
-
-	p = buf;
-	cfoll = bufto;
-	clead = cfoll + 1;
-
-	begp = p;
-	while (len > 0 ) {		/* encode until gone */
-		
-		q = p + 1;
-		i = len-1;
-	while (*p == *q && i+120 > len && i) {
-		q++;
-		i--;
-	}
-
-	if (q > p +2) {			/* three in a row */
-		if (p > begp) {
-			*cfoll = p - begp;
-			cfoll = clead;
-		}
-		*cfoll++ = 128 | (q-p);		/*len of seq*/
-		*cfoll++ = *p;			/* char of seq */
-		len -= q-p;		/* subtract len of seq */
-		p = q;
-		clead = cfoll+1;
-		begp = p;
-	}
-	else {
-		*clead++ = *p++;	/* copy one char */
-		len--;
-		if (p>begp + 120) {
-			*cfoll = p - begp;
-			cfoll = clead++;
-			begp = p;
-		}
-	}
-	}
-
-/* fillin last bytecount */
-
-	if (p>begp)
-		*cfoll = (p - begp);
-	else
-		clead--;
-
-	return((int) (clead-bufto));	/*how many stored as encoded */
+    return rc;
 }
+
+
+
+static void
+downloadColormap(char         const rgb[CLUTCOLORCT],
+                 const char * const windowName) {
+
+    unsigned int i;
+
+    pm_message("Downloading colormap for %s ...", windowName);
+
+    printf("\033^M;%d;%d;%d;%s^",
+           0, MAXCOLORCT, CLUTCOLORCT, windowName);
+
+    for (i = 0; i < CLUTCOLORCT; ++i) {
+        unsigned char const c = rgb[i];
+
+        if (c > 31 && c < 123) {
+            /* printable ASCII */
+            putchar(c);
+        } else {
+            /* non-printable, so encode it */
+            putchar((c >> 6) + 123);
+            putchar((c & 0x3f) + 32);
+        }
+    }
+    fflush(stdout);
+}
+
+
+
+static void
+sendOutPicture(pixel **        const pixels,
+               unsigned int    const rows,
+               unsigned int    const cols,
+               colorhash_table const cht,
+               int             const expand,
+               const char *    const windowName) {
+
+    unsigned int row;
+
+    pm_message("Sending picture data ..." );
+
+    for (row = 0; row < rows; ++row) {
+        unsigned int col;
+        printf("\033^P;%d;%d;%d;%d;%s^",
+               0, row * expand, expand, cols, windowName);
+        for (col = 0; col < cols; ++col) {
+            unsigned char const c =
+                colorIndexAtPosition(col, row, pixels, cht);
+            if (c > 31 && c < 123) {
+                putchar(c);
+            } else {
+                putchar((c >> 6) + 123);
+                putchar((c & 0x3f) + 32);
+            }
+        }
+    }
+    fflush(stdout);
+}
+
+
+
+int
+main(int argc, const char ** const argv) {
+
+    FILE * ifP;
+    int rows, cols;
+    int colorCt;
+    int argn;
+    unsigned int bitsPerPixel;
+    pixval maxval;
+    colorhist_vector chv;
+    char rgb[CLUTCOLORCT];
+    const char * windowName;
+    int display, expand;
+    int winflag;
+    const char* const usage = "[-windowname windowname] [-expand expand] [-display display] [ppmfile]";
+    pixel** pixels;
+    colorhash_table cht;
+
+    pm_proginit(&argc, argv);
+
+    argn = 1;
+    windowName = "untitled";
+    winflag = 0;
+    expand = 1;
+    display = 0;
+
+    while ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
+    {
+        if ( pm_keymatch(argv[argn],"-windowname",2) && argn + 1 < argc )
+        {
+            ++argn;
+            windowName = argv[argn];
+            winflag = 1;
+        }
+        else if ( pm_keymatch(argv[argn],"-expand",2) && argn + 1 < argc )
+        {
+            ++argn;
+            if ( sscanf( argv[argn], "%d",&expand ) != 1 )
+                pm_usage( usage );
+        }
+        else if ( pm_keymatch(argv[argn],"-display",2) && argn + 1 < argc )
+        {
+            ++argn;
+            if ( sscanf( argv[argn], "%d",&display ) != 1 )
+                pm_usage( usage );
+        }
+        else
+            pm_usage( usage );
+    }
+
+    if ( argn < argc )
+    {
+        ifP = pm_openr( argv[argn] );
+        if ( ! winflag )
+            windowName = argv[argn];
+        ++argn;
+    }
+    else
+        ifP = stdin;
+
+    if ( argn != argc )
+        pm_usage( usage );
+
+    pixels = ppm_readppm(ifP, &cols, &rows, &maxval);
+
+    pm_close(ifP);
+
+    /* Figure out the colormap. */
+    pm_message("Computing colormap..." );
+    chv = ppm_computecolorhist(pixels, cols, rows, MAXCOLORCT, &colorCt);
+    if (!chv)
+        pm_error("Too many colors - try doing a 'pnmquant %u'", MAXCOLORCT);
+    pm_message("%u colors found", colorCt );
+
+    makeIcrColormap(chv, colorCt, maxval, rgb);
+
+    bitsPerPixel = bppFromColorCt(colorCt);
+
+    /* And make a hash table for fast lookup. */
+    cht = ppm_colorhisttocolorhash(chv, colorCt);
+
+    ppm_freecolorhist(chv);
+
+    /************** Create a new window using ICR protocol *********/
+    /* Format is "ESC^W;left;top;width;height;display;windowname"  */
+
+    pm_message("Creating window %s ...", windowName);
+
+    printf("\033^W;%d;%d;%d;%d;%d;%s^",
+           0, 0, cols * expand, rows * expand, display, windowName);
+    fflush(stdout);
+
+    /****************** Download the colormap.  ********************/
+
+    downloadColormap(rgb, windowName);
+
+    sendOutPicture(pixels, rows, cols, cht, expand, windowName);
+
+    return 0;
+}
+
+
+
diff --git a/converter/ppm/ppmtompeg/Makefile b/converter/ppm/ppmtompeg/Makefile
index 49aeb7f8..eeab9727 100644
--- a/converter/ppm/ppmtompeg/Makefile
+++ b/converter/ppm/ppmtompeg/Makefile
@@ -31,9 +31,6 @@ endif
 #	1) long's are 32 bits and
 #	2) int's are not
 #
-# if you are using a non-ANSI compiler, then use:
-#	-DNON_ANSI_COMPILER
-#
 # one other option:
 #	-DHEINOUS_DEBUG_MODE
 #
diff --git a/converter/ppm/ppmtompeg/headers/all.h b/converter/ppm/ppmtompeg/headers/all.h
index 5c559528..8f095d8e 100644
--- a/converter/ppm/ppmtompeg/headers/all.h
+++ b/converter/ppm/ppmtompeg/headers/all.h
@@ -80,7 +80,6 @@
 #include <time.h>
 #endif
 
-#include "ansi.h"
 #include "general.h"
 
 /* some machines have #define index strchr; get rid of this nonsense */
diff --git a/converter/ppm/ppmtompeg/headers/ansi.h b/converter/ppm/ppmtompeg/headers/ansi.h
deleted file mode 100644
index b3c3ab17..00000000
--- a/converter/ppm/ppmtompeg/headers/ansi.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*===========================================================================*
- * ansi.h								     *
- *									     *
- *	macro for non-ansi compilers					     *
- *									     *
- *===========================================================================*/
-
-/*
- * Copyright (c) 1995 The Regents of the University of California.
- * All rights reserved.
- *
- * Permission to use, copy, modify, and distribute this software and its
- * documentation for any purpose, without fee, and without written agreement is
- * hereby granted, provided that the above copyright notice and the following
- * two paragraphs appear in all copies of this software.
- *
- * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
- * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
- * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- */
-
-/*  
- *  $Header: /n/picasso/project/mpeg/mpeg_dist/mpeg_encode/headers/RCS/ansi.h,v 1.6 1995/08/15 23:43:13 smoot Exp $
- *  $Log: ansi.h,v $
- *  Revision 1.6  1995/08/15 23:43:13  smoot
- *  *** empty log message ***
- *
- *  Revision 1.5  1995/01/19 23:54:35  eyhung
- *  Changed copyrights
- *
- * Revision 1.4  1994/11/12  02:12:13  keving
- * nothing
- *
- * Revision 1.3  1993/07/22  22:24:23  keving
- * nothing
- *
- * Revision 1.2  1993/07/09  00:17:23  keving
- * nothing
- *
- * Revision 1.1  1993/06/14  22:50:22  keving
- * nothing
- *
- */
-
-
-#ifndef ANSI_INCLUDED
-#define ANSI_INCLUDED
-
-
-/*  
- *  _ANSI_ARGS_ macro stolen from Tcl6.5 by John Ousterhout
- */
-#undef _ANSI_ARGS_
-#undef const
-#ifdef NON_ANSI_COMPILER
-#define _ANSI_ARGS_(x)       ()
-#define CONST
-#else
-#define _ANSI_ARGS_(x)   x
-#define CONST const
-#ifdef __cplusplus
-#define VARARGS (...)
-#else
-#define VARARGS ()
-#endif
-#endif
-
-
-#endif /* ANSI_INCLUDED */
diff --git a/converter/ppm/ppmtompeg/headers/bitio.h b/converter/ppm/ppmtompeg/headers/bitio.h
index a24c21cd..931bcdd9 100644
--- a/converter/ppm/ppmtompeg/headers/bitio.h
+++ b/converter/ppm/ppmtompeg/headers/bitio.h
@@ -63,7 +63,6 @@
 #include <stdio.h>
 
 #include "general.h"
-#include "ansi.h"
 
 
 /*===========*
diff --git a/converter/ppm/ppmtompeg/headers/dct.h b/converter/ppm/ppmtompeg/headers/dct.h
index d5ea9f4a..3b824cf0 100644
--- a/converter/ppm/ppmtompeg/headers/dct.h
+++ b/converter/ppm/ppmtompeg/headers/dct.h
@@ -31,7 +31,6 @@
 #define DCT_INCLUDED
 
 
-#include "ansi.h"
 
 
 
@@ -47,12 +46,12 @@ typedef DCTELEM DCTBLOCK_2D[DCTSIZE][DCTSIZE];
 /*  
  *  from mfwddct.c:
  */
-void init_fdct _ANSI_ARGS_((void));
-extern void mp_fwd_dct_block2 _ANSI_ARGS_((DCTBLOCK_2D src, DCTBLOCK_2D dest));
+void init_fdct (void);
+extern void mp_fwd_dct_block2 (DCTBLOCK_2D src, DCTBLOCK_2D dest);
 
 /* jrevdct.c */
-extern void init_pre_idct _ANSI_ARGS_((void ));
-extern void mpeg_jrevdct _ANSI_ARGS_((DCTBLOCK data ));
+extern void init_pre_idct (void );
+extern void mpeg_jrevdct (DCTBLOCK data );
 
 
 /* We assume that right shift corresponds to signed division by 2 with
diff --git a/converter/ppm/ppmtompeg/headers/frame.h b/converter/ppm/ppmtompeg/headers/frame.h
index 1f460ac2..e1f587a2 100644
--- a/converter/ppm/ppmtompeg/headers/frame.h
+++ b/converter/ppm/ppmtompeg/headers/frame.h
@@ -35,7 +35,6 @@
  *==============*/
 
 #include "netpbm/pm_c_util.h"
-#include "ansi.h"
 #include "mtypes.h"
 
 /*===========*
diff --git a/converter/ppm/ppmtompeg/headers/frames.h b/converter/ppm/ppmtompeg/headers/frames.h
index 966d9214..2ec11d69 100644
--- a/converter/ppm/ppmtompeg/headers/frames.h
+++ b/converter/ppm/ppmtompeg/headers/frames.h
@@ -13,7 +13,6 @@
  *==============*/
 
 #include "pm_config.h"  /* For __inline__ */
-#include "ansi.h"
 #include "mtypes.h"
 #include "mheaders.h"
 #include "iframe.h"
diff --git a/converter/ppm/ppmtompeg/headers/frametype.h b/converter/ppm/ppmtompeg/headers/frametype.h
index 63bee964..33b604e6 100644
--- a/converter/ppm/ppmtompeg/headers/frametype.h
+++ b/converter/ppm/ppmtompeg/headers/frametype.h
@@ -7,7 +7,7 @@ FType_Type(unsigned int const frameNum);
 unsigned int
 FType_FutureRef(unsigned int const currFrameNum);
 
-int	FType_PastRef _ANSI_ARGS_((int currFrameNum));
+int	FType_PastRef (int currFrameNum);
 
 void SetFramePattern(const char * const pattern);
 
diff --git a/converter/ppm/ppmtompeg/headers/jpeg.h b/converter/ppm/ppmtompeg/headers/jpeg.h
index 17aa0808..76d73d9e 100644
--- a/converter/ppm/ppmtompeg/headers/jpeg.h
+++ b/converter/ppm/ppmtompeg/headers/jpeg.h
@@ -1,5 +1,4 @@
 #include <stdio.h>
-#include "ansi.h"
 #include "frame.h"
 
 void
diff --git a/converter/ppm/ppmtompeg/headers/mheaders.h b/converter/ppm/ppmtompeg/headers/mheaders.h
index 21d43e3d..edd9552d 100644
--- a/converter/ppm/ppmtompeg/headers/mheaders.h
+++ b/converter/ppm/ppmtompeg/headers/mheaders.h
@@ -54,7 +54,6 @@
  *==============*/
 
 #include "general.h"
-#include "ansi.h"
 #include "bitio.h"
 
 
@@ -62,7 +61,7 @@
  * EXTERNAL PROCEDURE prototypes *
  *===============================*/
 
-void	SetGOPStartTime _ANSI_ARGS_((int index));
+void	SetGOPStartTime (int index);
 
 void
 Mhead_GenSequenceHeader(BitBucket *   const bbPtr, 
@@ -80,21 +79,21 @@ Mhead_GenSequenceHeader(BitBucket *   const bbPtr,
                         uint8 *       const user_data,
                         int32         const user_data_size);
 
-void	Mhead_GenSequenceEnder _ANSI_ARGS_((BitBucket *bbPtr));
-void	Mhead_GenGOPHeader _ANSI_ARGS_((BitBucket *bbPtr,
+void	Mhead_GenSequenceEnder (BitBucket *bbPtr);
+void	Mhead_GenGOPHeader (BitBucket *bbPtr,
 	   int32 drop_frame_flag,
            int32 tc_hrs, int32 tc_min,
            int32 tc_sec, int32 tc_pict,
            int32 closed_gop, int32 broken_link,
            uint8 *ext_data, int32 ext_data_size,
-           uint8 *user_data, int32 user_data_size));
-void	Mhead_GenPictureHeader _ANSI_ARGS_((BitBucket *bbPtr, int frameType,
-					    int pictCount, int f_code));
-void	Mhead_GenSliceHeader _ANSI_ARGS_((BitBucket *bbPtr, uint32 slicenum,
+           uint8 *user_data, int32 user_data_size);
+void	Mhead_GenPictureHeader (BitBucket *bbPtr, int frameType,
+					    int pictCount, int f_code);
+void	Mhead_GenSliceHeader (BitBucket *bbPtr, uint32 slicenum,
 					  uint32 qscale, uint8 *extra_info,
-					  uint32 extra_info_size));
-void	Mhead_GenSliceEnder _ANSI_ARGS_((BitBucket *bbPtr));
-void	Mhead_GenMBHeader _ANSI_ARGS_((BitBucket *bbPtr,
+					  uint32 extra_info_size);
+void	Mhead_GenSliceEnder (BitBucket *bbPtr);
+void	Mhead_GenMBHeader (BitBucket *bbPtr,
 	  uint32 pict_code_type, uint32 addr_incr,
           uint32 q_scale,
           uint32 forw_f_code, uint32 back_f_code,
@@ -103,7 +102,7 @@ void	Mhead_GenMBHeader _ANSI_ARGS_((BitBucket *bbPtr,
           int32 motion_forw, int32 m_horiz_forw,
           int32 m_vert_forw, int32 motion_back,
           int32 m_horiz_back, int32 m_vert_back,
-          uint32 mb_pattern, uint32 mb_intra));
+          uint32 mb_pattern, uint32 mb_intra);
 
 
 #endif /* MHEADERS_INCLUDED */
diff --git a/converter/ppm/ppmtompeg/headers/motion_search.h b/converter/ppm/ppmtompeg/headers/motion_search.h
index 117b914a..d00509c4 100644
--- a/converter/ppm/ppmtompeg/headers/motion_search.h
+++ b/converter/ppm/ppmtompeg/headers/motion_search.h
@@ -9,7 +9,6 @@
  * HEADER FILES *
  *==============*/
 
-#include "ansi.h"
 
 
 /*===========*
diff --git a/converter/ppm/ppmtompeg/headers/mpeg.h b/converter/ppm/ppmtompeg/headers/mpeg.h
index 56862c42..fbfaaf2c 100644
--- a/converter/ppm/ppmtompeg/headers/mpeg.h
+++ b/converter/ppm/ppmtompeg/headers/mpeg.h
@@ -34,7 +34,6 @@
 
 #include "pm_c_util.h"
 #include "ppm.h"
-#include "ansi.h"
 #include "mtypes.h"
 #include "frame.h"
 
@@ -80,7 +79,7 @@ ComputeGOPFrames(int            const whichGOP,
                  unsigned int * const lastFrameP, 
                  unsigned int   const numFrames);
 
-extern void	IncrementTCTime _ANSI_ARGS_((void));
+extern void	IncrementTCTime (void);
 void SetReferenceFrameType(const char * const type);
 
 boolean
@@ -93,7 +92,7 @@ ReadDecodedRefFrame(MpegFrame *  const frameP,
 void
 SetBitRateFileName(const char * const fileName);
 
-extern void	SetFrameRate _ANSI_ARGS_((void));
+extern void	SetFrameRate (void);
 
 
 /*==================*
diff --git a/converter/ppm/ppmtompeg/headers/mproto.h b/converter/ppm/ppmtompeg/headers/mproto.h
index d8fefd84..5b003b2e 100644
--- a/converter/ppm/ppmtompeg/headers/mproto.h
+++ b/converter/ppm/ppmtompeg/headers/mproto.h
@@ -70,7 +70,6 @@
  *==============*/
 
 #include "general.h"
-#include "ansi.h"
 #include "bitio.h"
 
 
@@ -86,39 +85,39 @@ typedef DCTELEM DCTBLOCK[DCTSIZE2];
 /*  
  *  from mbasic.c:
  */
-void mp_reset _ANSI_ARGS_((void));
-void mp_free _ANSI_ARGS_((MpegFrame *mf));
-MpegFrame *mp_new _ANSI_ARGS_((int fnumber, char type, MpegFrame *oldFrame));
-void mp_ycc_calc _ANSI_ARGS_((MpegFrame *mf));
-void mp_dct_blocks _ANSI_ARGS_((MpegFrame *mf));
-void	AllocDecoded _ANSI_ARGS_((MpegFrame *frame));
+void mp_reset (void);
+void mp_free (MpegFrame *mf);
+MpegFrame *mp_new (int fnumber, char type, MpegFrame *oldFrame);
+void mp_ycc_calc (MpegFrame *mf);
+void mp_dct_blocks (MpegFrame *mf);
+void	AllocDecoded (MpegFrame *frame);
 
 /*  
  *  from moutput.c:
  */
-boolean mp_quant_zig_block _ANSI_ARGS_((Block in, FlatBlock out, int qscale, int iblock));
-void	UnQuantZig _ANSI_ARGS_((FlatBlock in, Block out, int qscale, boolean iblock));
-void mp_rle_huff_block _ANSI_ARGS_((FlatBlock in, BitBucket *out));
-void mp_rle_huff_pblock _ANSI_ARGS_((FlatBlock in, BitBucket *out));
-void mp_create_blocks _ANSI_ARGS_((MpegFrame *mf));
+boolean mp_quant_zig_block (Block in, FlatBlock out, int qscale, int iblock);
+void	UnQuantZig (FlatBlock in, Block out, int qscale, boolean iblock);
+void mp_rle_huff_block (FlatBlock in, BitBucket *out);
+void mp_rle_huff_pblock (FlatBlock in, BitBucket *out);
+void mp_create_blocks (MpegFrame *mf);
 
 
 
 
-void	ReadEYUV _ANSI_ARGS_((MpegFrame * mf, FILE *fpointer, int width,
-			    int height));
-boolean	ReadPPM _ANSI_ARGS_((MpegFrame *mf, FILE *fpointer));
-void PPMtoYCC _ANSI_ARGS_((MpegFrame * mf));
+void	ReadEYUV (MpegFrame * mf, FILE *fpointer, int width,
+			    int height);
+boolean	ReadPPM (MpegFrame *mf, FILE *fpointer);
+void PPMtoYCC (MpegFrame * mf);
 
-void	ComputeHalfPixelData _ANSI_ARGS_((MpegFrame *frame));
-void mp_validate_size _ANSI_ARGS_((int *x, int *y));
-void AllocYCC _ANSI_ARGS_((MpegFrame * mf));
+void	ComputeHalfPixelData (MpegFrame *frame);
+void mp_validate_size (int *x, int *y);
+void AllocYCC (MpegFrame * mf);
 
 
 /* jrevdct.c */
-void init_pre_idct _ANSI_ARGS_((void ));
-void j_rev_dct_sparse _ANSI_ARGS_((DCTBLOCK data , int pos ));
-void j_rev_dct _ANSI_ARGS_((DCTBLOCK data ));
-void j_rev_dct_sparse _ANSI_ARGS_((DCTBLOCK data , int pos ));
-void j_rev_dct _ANSI_ARGS_((DCTBLOCK data ));
+void init_pre_idct (void );
+void j_rev_dct_sparse (DCTBLOCK data , int pos );
+void j_rev_dct (DCTBLOCK data );
+void j_rev_dct_sparse (DCTBLOCK data , int pos );
+void j_rev_dct (DCTBLOCK data );
 
diff --git a/converter/ppm/ppmtompeg/headers/opts.h b/converter/ppm/ppmtompeg/headers/opts.h
index 5901a677..1756334e 100644
--- a/converter/ppm/ppmtompeg/headers/opts.h
+++ b/converter/ppm/ppmtompeg/headers/opts.h
@@ -38,7 +38,6 @@
  */
 
 #include "general.h"
-#include "ansi.h"
 #include "mtypes.h"
 
 /*
@@ -110,14 +109,14 @@ extern int LaplaceNum, LaplaceCnum;
 extern boolean BSkipBlocks;
 
 /* Procedures Prototypes */
-int	GetIQScale _ANSI_ARGS_((void));
-int	GetPQScale _ANSI_ARGS_((void));
-int	GetBQScale _ANSI_ARGS_((void));
-void	Tune_Init _ANSI_ARGS_((void));
-int     CalcRLEHuffLength _ANSI_ARGS_((FlatBlock in));
+int	GetIQScale (void);
+int	GetPQScale (void);
+int	GetBQScale (void);
+void	Tune_Init (void);
+int     CalcRLEHuffLength (FlatBlock in);
 void    ParseTuneParam(const char * const charPtr);
-int     mse _ANSI_ARGS_((Block blk1, Block blk2));
-void    Mpost_UnQuantZigBlockLaplace _ANSI_ARGS_((FlatBlock in, Block out, int qscale, boolean iblock));
+int     mse (Block blk1, Block blk2);
+void    Mpost_UnQuantZigBlockLaplace (FlatBlock in, Block out, int qscale, boolean iblock);
 extern void CalcLambdas(void);
 
 
diff --git a/converter/ppm/ppmtompeg/headers/parallel.h b/converter/ppm/ppmtompeg/headers/parallel.h
index 90edd874..0a31fac2 100644
--- a/converter/ppm/ppmtompeg/headers/parallel.h
+++ b/converter/ppm/ppmtompeg/headers/parallel.h
@@ -30,7 +30,6 @@
  * HEADER FILES *
  *==============*/
 
-#include "ansi.h"
 #include "bitio.h"
 #include "frame.h"
 
diff --git a/converter/ppm/ppmtompeg/headers/param.h b/converter/ppm/ppmtompeg/headers/param.h
index 0c6d8e5c..46a544b3 100644
--- a/converter/ppm/ppmtompeg/headers/param.h
+++ b/converter/ppm/ppmtompeg/headers/param.h
@@ -1,7 +1,6 @@
 /* COPYRIGHT information is at end of file */
 
 #include "pm_c_util.h"
-#include "ansi.h"
 #include "input.h"
 
 
diff --git a/converter/ppm/ppmtompeg/headers/prototypes.h b/converter/ppm/ppmtompeg/headers/prototypes.h
index b421af35..432062e3 100644
--- a/converter/ppm/ppmtompeg/headers/prototypes.h
+++ b/converter/ppm/ppmtompeg/headers/prototypes.h
@@ -30,7 +30,6 @@
  *==============*/
 
 #include "general.h"
-#include "ansi.h"
 #include "frame.h"
 
 
@@ -38,34 +37,34 @@
  * EXTERNAL PROCEDURE prototypes *
  *===============================*/
 
-int GetBQScale _ANSI_ARGS_((void));
-int GetPQScale _ANSI_ARGS_((void));
-void    ResetBFrameStats _ANSI_ARGS_((void));
-void    ResetPFrameStats _ANSI_ARGS_((void));
+int GetBQScale (void);
+int GetPQScale (void);
+void    ResetBFrameStats (void);
+void    ResetPFrameStats (void);
 void SetSearchRange (int const pixelsP,
                      int const pixelsB);
 void
 SetPixelSearch(const char * const searchType);
-void    SetPQScale _ANSI_ARGS_((int qP));
-void    SetBQScale _ANSI_ARGS_((int qB));
-float   EstimateSecondsPerPFrame _ANSI_ARGS_((void));
-float   EstimateSecondsPerBFrame _ANSI_ARGS_((void));
-void    SetGOPSize _ANSI_ARGS_((int size));
+void    SetPQScale (int qP);
+void    SetBQScale (int qB);
+float   EstimateSecondsPerPFrame (void);
+float   EstimateSecondsPerBFrame (void);
+void    SetGOPSize (int size);
 void
 SetStatFileName(const char * const fileName);
 
 
-void DCTFrame _ANSI_ARGS_((MpegFrame * mf));
+void DCTFrame (MpegFrame * mf);
 
-void PPMtoYCC _ANSI_ARGS_((MpegFrame * mf));
+void PPMtoYCC (MpegFrame * mf);
 
-void    MotionSearchPreComputation _ANSI_ARGS_((MpegFrame *frame));
+void    MotionSearchPreComputation (MpegFrame *frame);
 
-void    ComputeHalfPixelData _ANSI_ARGS_((MpegFrame *frame));
-void mp_validate_size _ANSI_ARGS_((int *x, int *y));
+void    ComputeHalfPixelData (MpegFrame *frame);
+void mp_validate_size (int *x, int *y);
 
 
 /* psearch.c */
-void    ShowPMVHistogram _ANSI_ARGS_((FILE *fpointer));
-void    ShowBBMVHistogram _ANSI_ARGS_((FILE *fpointer));
-void    ShowBFMVHistogram _ANSI_ARGS_((FILE *fpointer));
+void    ShowPMVHistogram (FILE *fpointer);
+void    ShowBBMVHistogram (FILE *fpointer);
+void    ShowBFMVHistogram (FILE *fpointer);
diff --git a/converter/ppm/ppmtompeg/headers/rate.h b/converter/ppm/ppmtompeg/headers/rate.h
index 8d691174..a5f5076f 100644
--- a/converter/ppm/ppmtompeg/headers/rate.h
+++ b/converter/ppm/ppmtompeg/headers/rate.h
@@ -68,7 +68,7 @@ targetRateControl(MpegFrame * const frameP);
  *
  * RETURNS:     nothing
  *===========================================================================*/
-extern void MB_RateOut _ANSI_ARGS_((int type));
+extern void MB_RateOut (int type);
 
 
 /*===========================================================================*
@@ -92,7 +92,7 @@ updateRateControl(int const type);
  *
  * RETURNS:     new Qscale
  *===========================================================================*/
-extern int needQScaleChange _ANSI_ARGS_((int oldQScale,  Block blk0, Block blk1, Block blk2, Block blk3));
+extern int needQScaleChange (int oldQScale,  Block blk0, Block blk1, Block blk2, Block blk3);
 
 /*===========================================================================*
  *
@@ -101,7 +101,7 @@ extern int needQScaleChange _ANSI_ARGS_((int oldQScale,  Block blk0, Block blk1,
  *
  * RETURNS:   nothing
  *===========================================================================*/
-extern void incNumBlocks _ANSI_ARGS_((int num));
+extern void incNumBlocks (int num);
 
 
 /*===========================================================================*
@@ -113,7 +113,7 @@ extern void incNumBlocks _ANSI_ARGS_((int num));
  *
  * RETURNS:   nothing
  *===========================================================================*/
-extern void incMacroBlockBits _ANSI_ARGS_((int num));
+extern void incMacroBlockBits (int num);
 
 
 /*===========================================================================*
@@ -125,7 +125,7 @@ extern void incMacroBlockBits _ANSI_ARGS_((int num));
  *
  * RETURNS:     nothing
  *===========================================================================*/
-extern void SetRateControl _ANSI_ARGS_((char *charPtr));
+extern void SetRateControl (char *charPtr);
 
 
 /*===========================================================================*
@@ -150,7 +150,7 @@ setBufferSize(const char * const charPtr);
  *
  * RETURNS:     int (or -1 if invalid)
  *===========================================================================*/
-extern int getBufferSize _ANSI_ARGS_((void));
+extern int getBufferSize (void);
 
 
 /*===========================================================================*
@@ -178,7 +178,7 @@ setBitRate(const char * const charPtr);
  *
  * RETURNS:     int (-1 if Variable mode operation)
  *===========================================================================*/
-extern int getBitRate _ANSI_ARGS_((void));
+extern int getBitRate (void);
 
 
 /*===========================================================================*
@@ -189,7 +189,7 @@ extern int getBitRate _ANSI_ARGS_((void));
  *
  * RETURNS:     integer
  *===========================================================================*/
-extern int getRateMode _ANSI_ARGS_((void));
+extern int getRateMode (void);
 
 
 /*===========================================================================*
@@ -200,5 +200,5 @@ extern int getRateMode _ANSI_ARGS_((void));
  *
  * RETURNS:   nothing
  *===========================================================================*/
-extern void incQuantOverride  _ANSI_ARGS_((int num));
+extern void incQuantOverride  (int num);
 
diff --git a/converter/ppm/ppmtompeg/headers/specifics.h b/converter/ppm/ppmtompeg/headers/specifics.h
index 7bcf4ace..4f5c7074 100644
--- a/converter/ppm/ppmtompeg/headers/specifics.h
+++ b/converter/ppm/ppmtompeg/headers/specifics.h
@@ -1,4 +1,3 @@
-#include "ansi.h"
 
 
 /*===========*
@@ -29,8 +28,8 @@ typedef struct fsl_def {
 } FrameSpecList;
 
 
-void	Specifics_Init _ANSI_ARGS_((void));
-int     SpecLookup _ANSI_ARGS_((int fn, int typ, int num, 
-				BlockMV **info, int start_qs));
-int SpecTypeLookup _ANSI_ARGS_((int fn));
+void	Specifics_Init (void);
+int     SpecLookup (int fn, int typ, int num,
+			    BlockMV **info, int start_qs);
+int SpecTypeLookup (int fn);
 
diff --git a/converter/ppm/ppmtompeg/jrevdct.c b/converter/ppm/ppmtompeg/jrevdct.c
index c3379d7a..bf9196c4 100644
--- a/converter/ppm/ppmtompeg/jrevdct.c
+++ b/converter/ppm/ppmtompeg/jrevdct.c
@@ -28,7 +28,6 @@
 
 #include <memory.h>
 #include "all.h"
-#include "ansi.h"
 #include "dct.h"
 
 
@@ -162,9 +161,9 @@ ones here or successive P-frames will drift too much with Reference frame coding
 /*
   Switch on reverse_dct choices
 */
-void reference_rev_dct _ANSI_ARGS_((int16 *block));
-void mpeg_jrevdct_quick _ANSI_ARGS_((int16 *block));
-void init_idctref _ANSI_ARGS_((void));
+void reference_rev_dct (int16 *block);
+void mpeg_jrevdct_quick (int16 *block);
+void init_idctref (void);
 
 extern boolean pureDCT;
 
diff --git a/converter/ppm/ppmtompeg/mpeg.c b/converter/ppm/ppmtompeg/mpeg.c
index 5cd7b099..24d337ed 100644
--- a/converter/ppm/ppmtompeg/mpeg.c
+++ b/converter/ppm/ppmtompeg/mpeg.c
@@ -126,9 +126,9 @@ int32 bit_rate, buf_size;
  * INTERNAL PROCEDURE prototypes *
  *===============================*/
 
-static void ComputeDHMSTime _ANSI_ARGS_((int32 someTime, char *timeText));
-static void OpenBitRateFile _ANSI_ARGS_((void));
-static void CloseBitRateFile _ANSI_ARGS_((void));
+static void ComputeDHMSTime (int32 someTime, char *timeText);
+static void OpenBitRateFile (void);
+static void CloseBitRateFile (void);
 
 
 static void
diff --git a/converter/ppm/ppmtompeg/opts.c b/converter/ppm/ppmtompeg/opts.c
index 9eee971f..841efdab 100644
--- a/converter/ppm/ppmtompeg/opts.c
+++ b/converter/ppm/ppmtompeg/opts.c
@@ -52,7 +52,7 @@ extern int32   qtable[], niqtable[];
 extern int     ZAG[];
 extern boolean printSNR, decodeRefFrames;
 
-void init_idctref _ANSI_ARGS_((void));
+void init_idctref (void);
 
 
 /*===================*
diff --git a/converter/ppm/ppmtompeg/ppmtompeg.c b/converter/ppm/ppmtompeg/ppmtompeg.c
index bc788552..cd94db39 100644
--- a/converter/ppm/ppmtompeg/ppmtompeg.c
+++ b/converter/ppm/ppmtompeg/ppmtompeg.c
@@ -59,7 +59,7 @@
 
 #include <time.h>
 
-int main _ANSI_ARGS_((int argc, char **argv));
+int main (int argc, char **argv);
 
 
 /*==================*
@@ -92,7 +92,7 @@ const char * hostname;
  * External PROCEDURE prototypes  *
  *================================*/
 
-void init_idctref _ANSI_ARGS_((void));
+void init_idctref (void);
 
 
 struct cmdlineInfo {
diff --git a/converter/ppm/ppmtompeg/rate.c b/converter/ppm/ppmtompeg/rate.c
index d92afb64..c775e055 100644
--- a/converter/ppm/ppmtompeg/rate.c
+++ b/converter/ppm/ppmtompeg/rate.c
@@ -204,13 +204,13 @@ extern int framePatternLen;
  * INTERNAL PROCEDURE prototypes *
  *===============================*/
 
-int initGOPRateControl _ANSI_ARGS_((void));
-int determineMBCount _ANSI_ARGS_((void));
-void checkBufferFullness _ANSI_ARGS_((int count));
-void checkSpatialActivity _ANSI_ARGS_((Block blk0, Block blk1, Block blk2, Block blk3));
-void incNumBlocks _ANSI_ARGS_((int num));
-void calculateVBVDelay _ANSI_ARGS_((int num));
-int BlockExperiments  _ANSI_ARGS_((int16 *OrigBlock, int16 *NewBlock, int control));
+int initGOPRateControl (void);
+int determineMBCount (void);
+void checkBufferFullness (int count);
+void checkSpatialActivity (Block blk0, Block blk1, Block blk2, Block blk3);
+void incNumBlocks (int num);
+void calculateVBVDelay (int num);
+int BlockExperiments  (int16 *OrigBlock, int16 *NewBlock, int control);
      
      
 
diff --git a/converter/ppm/ppmtompeg/readframe.c b/converter/ppm/ppmtompeg/readframe.c
index cac6bdad..23752706 100644
--- a/converter/ppm/ppmtompeg/readframe.c
+++ b/converter/ppm/ppmtompeg/readframe.c
@@ -74,19 +74,19 @@ const char *CurrFile;
  * INTERNAL PROCEDURE prototypes *
  *===============================*/
 
-static void ReadEYUV _ANSI_ARGS_((MpegFrame * mf, FILE *fpointer,
-                 int width, int height));
-static void ReadAYUV _ANSI_ARGS_((MpegFrame * mf, FILE *fpointer,
-                 int width, int height));
-static void SeparateLine _ANSI_ARGS_((FILE *fpointer, struct YuvLine *lineptr,
-                     int width));
-static void ReadY _ANSI_ARGS_((MpegFrame * mf, FILE *fpointer,
-                 int width, int height));
-static void ReadSub4 _ANSI_ARGS_((MpegFrame * mf, FILE *fpointer,
-                  int width, int height));
-static void DoGamma  _ANSI_ARGS_((MpegFrame *mf, int width, int height));
-
-static void DoKillDim _ANSI_ARGS_((MpegFrame *mf, int w, int h));
+static void ReadEYUV (MpegFrame * mf, FILE *fpointer,
+                 int width, int height);
+static void ReadAYUV (MpegFrame * mf, FILE *fpointer,
+                 int width, int height);
+static void SeparateLine (FILE *fpointer, struct YuvLine *lineptr,
+                     int width);
+static void ReadY (MpegFrame * mf, FILE *fpointer,
+                 int width, int height);
+static void ReadSub4 (MpegFrame * mf, FILE *fpointer,
+                  int width, int height);
+static void DoGamma  (MpegFrame *mf, int width, int height);
+
+static void DoKillDim (MpegFrame *mf, int w, int h);
 
 #define safe_fread(ptr,sz,len,fileptr)                           \
     if ((safe_read_count=fread(ptr,sz,len,fileptr))!=sz*len) {   \
diff --git a/converter/ppm/ppmtompeg/specifics.c b/converter/ppm/ppmtompeg/specifics.c
index ffbce80a..fb5e3649 100644
--- a/converter/ppm/ppmtompeg/specifics.c
+++ b/converter/ppm/ppmtompeg/specifics.c
@@ -58,14 +58,14 @@ FrameSpecList *fsl;
  * Internal procedures *
  *=====================*/
 
-void Parse_Specifics_File _ANSI_ARGS_((FILE *fp));
-void Parse_Specifics_File_v1 _ANSI_ARGS_((FILE *fp));
-void Parse_Specifics_File_v2 _ANSI_ARGS_((FILE *fp));
-FrameSpecList *MakeFslEntry _ANSI_ARGS_((void));
-void AddSlc _ANSI_ARGS_((FrameSpecList *c,int snum, int qs));
-Block_Specifics *AddBs _ANSI_ARGS_((FrameSpecList *c,int bnum, 
-				    boolean rel, int qs));
-FrameSpecList *MakeFslEntry _ANSI_ARGS_((void));
+void Parse_Specifics_File (FILE *fp);
+void Parse_Specifics_File_v1 (FILE *fp);
+void Parse_Specifics_File_v2 (FILE *fp);
+FrameSpecList *MakeFslEntry (void);
+void AddSlc (FrameSpecList *c,int snum, int qs);
+Block_Specifics *AddBs (FrameSpecList *c,int bnum, 
+				    boolean rel, int qs);
+FrameSpecList *MakeFslEntry (void);
 #define my_upper(c) (((c>='a') && (c<='z')) ? (c-'a'+'A') : c)
 #define CvtType(x) ReallyCvt(my_upper(x))
 #define ReallyCvt(x) (x=='I' ? 1 : (x=='P')?2: ((x=='B')?3:-1))
diff --git a/converter/ppm/ppmtopcx.c b/converter/ppm/ppmtopcx.c
index 4c25ca29..fa68edc5 100644
--- a/converter/ppm/ppmtopcx.c
+++ b/converter/ppm/ppmtopcx.c
@@ -12,6 +12,10 @@
 **
 ** 11/Dec/94: first version
 ** 12/Dec/94: added handling of "packed" format (16 colors or less)
+** 
+** ZSoft PCX File Format Technical Reference Manual
+** http://bespin.org/~qz/pc-gpe/pcx.txt
+** http://web.archive.org/web/20100206055706/http://www.qzx.com/pc-gpe/pcx.txt
 */
 #include <assert.h>
 
@@ -158,6 +162,8 @@ parseCommandLine(int argc, char ** argv,
         pm_error("Program takes at most one argument "
                  "(input file specification).  You specified %d",
                  argc-1);
+
+    free(option_def);
 }
 
 
@@ -632,6 +638,16 @@ generateStandardPalette(struct pcxCmapEntry ** const pcxcmapP,
         putPcxColorInHash(cht, pcxColor, colorIndex, maxval);
     }
 
+    /* Set remaining slots in palette to black.  The values are not
+       meaningful, but this suppresses a Valgrind warning about our writing
+       undefined values to the file and makes our output constant with input.
+    */
+    for ( ; colorIndex < MAXCOLORS; ++colorIndex) {
+        pcxcmap[colorIndex].r = 0;
+        pcxcmap[colorIndex].g = 0;
+        pcxcmap[colorIndex].b = 0;
+    }
+
     *chtP = cht;
     *colorsP = stdPaletteSize;
 }
diff --git a/doc/CONTRIBUTORS b/doc/CONTRIBUTORS
new file mode 100644
index 00000000..d44cfe79
--- /dev/null
+++ b/doc/CONTRIBUTORS
@@ -0,0 +1,37 @@
+As an open source project, Netpbm has been written and otherwise supported by
+myriad people from all over.  Most of them have made isolated contributions
+such as a single program, a single new feature, or a single bug fix.  To save
+clerical effort, we do not list them here and instead refer you to the HISTORY
+file.  This file lists people who have made broad contributions that wouldn't
+be well summarized by the HISTORY file.
+
+Jef Poskanzer had the original idea for what is now Netpbm and wrote dozens of
+programs and the original library code, as well as inventing and designing the
+PNM formats and writing documentation.  Jef's code contributions stopped in
+1991 and because of rewrites, there is not much of Jef's code still remaining,
+with what does remain being mostly obsolete.  Nonetheless, the impact of that
+original code is enormous, as everything in Netpbm today is derived in some
+way from Jef's work.
+
+Bryan Henderson has been maintaining Netpbm since 1999 and has written more
+code, in lines, than anyone else.  Most of that is just rewriting old code in
+a more maintainable style.  But Bryan has also fixed more bugs than anyone,
+since the normal bug reporting procedure is to tell the maintainer, and Bryan
+normally fixes bugs reported that way himself.  Bryan has also added many
+features and whole programs at the suggestion of users.  Bryan has written
+most of the documentation, whether by writing manuals for programs whose
+authors declined to do so or by rewriting manuals to make them more clear when
+users had trouble using Netpbm.
+
+Akira F Urushibata has made myriad contributions since 2004.  Much of the PBM
+processing code is his, as he rewrote existing programs to be much faster, in
+particular by using special bit-processing machine instructions.  He also
+created the entire test framework and regression test suite and runs those
+regression tests and other tests regularly, and often develops fixes for the
+bugs found.  Nobody else has done significant alpha testing of Netpbm except
+where developers have done it to test code they just wrote.  This testing has
+turned up many bugs in code going all the way back to 1989.
+
+Scott Pakin has contributed numerous programs over the years including the
+fairly significant work 'pamstereogram'.
+
diff --git a/doc/HISTORY b/doc/HISTORY
index 4304cab7..becf84a0 100644
--- a/doc/HISTORY
+++ b/doc/HISTORY
@@ -4,7 +4,25 @@ Netpbm.
 CHANGE HISTORY 
 --------------
 
-15.06.19 BJH  Release 10.70.07
+15.06.28 BJH  Release 10.71.00
+
+              Add pamtopng.  Thanks Willem vanSchaik (willem@schaik.com).
+
+              pnmtopng: Add -srgbintent.
+
+              pamstereogram: Add -xbegin.  Change default to render from
+              center outwards intead of from right to left, thus making the
+              center of the image the crispest part.  Thanks Scott Pakin
+              (scott@pakin.org).
+
+              pamstereogram: Allow -xshift and -yshift to be negative.  Thanks
+              Scott Pakin (scott@pakin.org).
+
+              pnmpsnr: Add -rgb.
+
+              ppmtoicr: remove -rle option.  Actually, it never worked
+              because of a bug.  Now it isn't expected to.  Ppmtoicr was
+              new in 1991.
 
               pnmtopalm: Fix arithmetic overflow with ridiculously large
               image.  Introduced after Netpbm 10.26 (January 2005) but before
@@ -25,6 +43,12 @@ CHANGE HISTORY
               file name argument.  Always broken.  (pbmtomatrixorbital was
               new in Netpbm 10.18 (Setpember 2003).
 
+              sbigtopgm: fix detection of camera type.  Always broken
+              (sbigtopgm was new in Netpbm 8.3 (March 2000)).
+
+              sbigtopgm: fix recognition of compressed image.  Broken in
+              Netpbm 10.70 (March 2015).
+
               pbmtogo: Fix bug: garbage first row.  Broken at least since
               November 1989.
 
@@ -37,29 +61,25 @@ CHANGE HISTORY
               escp2topbm: Fix buffer overrun on certain input.  Always broken
               (escp2topbm was new in Netpbm 10.18 (September 2003)).
 
-15.05.27 BJH  Release 10.70.06
-
-              sbigtopgm: fix detection of camera type.  Always broken
-              (sbigtopgm was new in Netpbm 8.3 (March 2000)).
-
-              sbigtopgm: fix recognition of compressed image.  Broken in
-              Netpbm 10.70.00 (March 2015).
-
               libnetpbm: pm_stripeq: fix bug: wild pointer access when
               comparator is shorter than comparand.  Doesn't affect function,
               but could cause crash or privacy exposure.  Affects reading of a
               PAM file by any program.  Introduced in one of Netpbm 10.27
               (March 2005) through 10.35 (August 2006).
 
+              pnmconvol: Fix bug: wrong output for pixels that convolve to
+              negative values (should be clipped to zero).  Introduced in
+              Netpbm 10.68 (September 2014).
+
               pbmtog3: Fix buffer overrun.  Introduced in Netpbm 10.23
               (July 2004).
 
-              pbmtoatk: Fix crash with very long input file name argument.
-              Always broken (pbmtoatk was new in 1991).
-
               cameratopam: Fix arithmetic underflow in JPEG processing;
               unknown effect.
 
+              pbmtoxbm: Fix bug: crash with zero width input.  Broken in
+              Netpbm 10.37 (December 2006).
+
               sbigtopgm: fix buffer overrun with invalid input image.  Always
               present (sbigtopgm was new in Netpbm 8.3 (March 2000)).
 
@@ -80,10 +100,9 @@ CHANGE HISTORY
               than 640 pixels.  Always broken (pbmtopi3 was new in September
               1991).
 
-15.05.18 BJH  Release 10.70.05
-
-              pbmtoxbm: Fix bug: crash with zero width input.  Broken in
-              Netpbm 10.37 (December 2006).
+              st4topgm: Fix bug: with no argument, uses file named "'" instead
+              of Standard Input.  Always present (st45topgm was new in Netpbm
+              10.70 (March 2015).
 
               pbmtomgr: Fix incorrect output when input is too large (must be
               at most 4095 pixels high or wide).  Always broken.  (pbmtomgr
@@ -93,27 +112,26 @@ CHANGE HISTORY
               image height.  Always broken.  (pbmtomacp was new in X.V11R3
               (March 1988).
 
-              Build: don't build and install libjbig and libjasper if we
-              are using external versions of them instead.
+              ppmtorgb3: Fix buffer overflow with long input file name.
+              Always present.  (ppmtorgb3 was new in X.V11R4 (November 1989).
 
-15.04.30 BJH  Release 10.70.04
+              ppmtoarbtxt: fix bug: wrong output when high numbers represent
+              darker.  Broken in Netpbm 10.69 (November 2014).
 
-              pnmconvol: Fix bug: wrong output for pixels that convolve to
-              negative values (should be clipped to zero).  Introduced in
-              Netpbm 10.68 (September 2014).
+              ppmtoarbtxt: better rounding in sample values.
 
-15.04.29 BJH  Release 10.70.03
+              libnetpbm: Remove bitio.h as an external interface.
 
-              st4topgm: Fix bug: with no argument, uses file named "'" instead
-              of Standard Input.  Always present (st45topgm was new in Netpbm
-              10.70.00 (March 2015).
+              test: replace some GNU-only code with more portable code that
+              works on OS X.  Thanks Ryan Schmidt <ryandesign@macports.org>.
 
-              ppmtorgb3: Fix buffer overflow with long input file name.
-              Always present.  (ppmtorgb3 was new in X.V11R4 (November 1989).
+              makeman: deal properly with backlash in source.  Thanks Willem
+              van Schaik <willem@schaik.com>.
 
-15.04.17 BJH  Release 10.70.02
+              Build: don't build and install libjbig and libjasper if we
+              are using external versions of them instead.
 
-              Fix typo in doc/TESTS.
+              Build: various cross-compile fixes, especially for MinGW.
 
               Build: work around bug in GCC < 4.2 related to SSE2 builtins
               that causes compile of pamflip to fail.
@@ -121,12 +139,7 @@ CHANGE HISTORY
               Build: fix 'make package' where config.mk sets a subdirectory
               other than 'man' for the manual.
 
-15.04.05 BJH  Release 10.70.01
-
-              ppmtoarbtxt: fix bug: wrong output when high numbers represent
-              darker.  Broken in Netpbm 10.69 (November 2014).
-
-              ppmtoarbtxt: better rounding in sample values.
+              Build: improve pointer man page text.
 
 15.03.29 BJH  Release 10.70.00
 
@@ -189,7 +202,7 @@ CHANGE HISTORY
               pnmnorm: add -bsingle, -wsingle.
 
               ppmtoarbtxt: Do some validation of format strings.  Thanks
-              Prophet of the Way <afu@wta.att.ne.jp>.
+              Akira F Urushibata <afu@wta.att.ne.jp>.
 
               pamcrater: Add -verbose.
 
@@ -305,15 +318,15 @@ CHANGE HISTORY
 14.06.29 BJH  Release 10.67.00
 
               sgitopnm: add ability to convert 2-channel SGI image.
-              Thanks Prophet of the Way <afu@wta.att.ne.jp>.
+              Thanks Akira F Urushibata <afu@wta.att.ne.jp>.
 
               sgitopnm: add ability to work with non-seekable input (e.g. a
-              pipe).  Thanks Prophet of the Way <afu@wta.att.ne.jp>.
+              pipe).  Thanks Akira F Urushibata <afu@wta.att.ne.jp>.
 
               pamtotiff: add -output, use Standard Output normally (before, it
               had to be seekable.  Also, you could do an append operation to
               Standard Output; now you have to use -output for that).  Thanks
-              Prophet of the Way <afu@wta.att.ne.jp>.
+              Akira F Urushibata <afu@wta.att.ne.jp>.
 
               pamsharpness: put primary output on Standard Output instead of
               on Standard Error as a Netpbm message.
@@ -323,7 +336,7 @@ CHANGE HISTORY
               10.65 (December 2013).
 
               sgitopnm: fix bug: no output if input is RLE compressed.  Broken
-              in Netpbm 10.53 (December 2010).  Thanks Prophet of the Way
+              in Netpbm 10.53 (December 2010).  Thanks Akira F Urushibata
               <afu@wta.att.ne.jp>.
 
               jpegtopnm -dumpexif: fix incorrect display of resolution.
@@ -354,7 +367,7 @@ CHANGE HISTORY
 
 14.03.30 BJH  Release 10.66.00
 
-              Add pamvalidate.  Thanks Prophet of the Way <afu@wta.att.ne.jp>.
+              Add pamvalidate.  Thanks Akira F Urushibata <afu@wta.att.ne.jp>.
 
               Add pamfix: Does what pamfixtrunc did, plus repairs excessive
               sample values.
@@ -362,20 +375,20 @@ CHANGE HISTORY
               pamfixtrunc: implement as call to new pamfix.
 
               pgmhist, ppmhist: Add -forensic: Analyze invalid >maxval pixels.
-              Thanks Prophet of the Way <afu@wta.att.ne.jp>.
+              Thanks Akira F Urushibata <afu@wta.att.ne.jp>.
 
-              pgmramp: add -diagonal.  Thanks Prophet of the Way
+              pgmramp: add -diagonal.  Thanks Akira F Urushibata
               <afu@wta.att.ne.jp>.
 
               libnetpbm: Read functions validate that sample values do not
-              exceed maxval.  Thanks Prophet of the Way <afu@wta.att.ne.jp>.
+              exceed maxval.  Thanks Akira F Urushibata <afu@wta.att.ne.jp>.
 
               libnetpbm: Validate image dimensions are small enough that you
-              can allocate a row buffer.  Thanks Prophet of the Way
+              can allocate a row buffer.  Thanks Akira F Urushibata
               <afu@wta.att.ne.jp>.
 
               pgmhist: fix incorrect report of quantiles or crash due to array
-              bounds violation in some builds.  Thanks Prophet of the Way
+              bounds violation in some builds.  Thanks Akira F Urushibata
               <afu@wta.att.ne.jp>.  Always broken.  Quantile reporting was
               new in Netpbm 10.61 (December 2012).
 
@@ -393,22 +406,22 @@ CHANGE HISTORY
               both -xsize and -ysize.  Introduced in 10.65.
 
               pgmramp: fix bogus output with really large images.  Thanks
-              Prophet of the Way <afu@wta.att.ne.jp>.  Always broken.
+              Akira F Urushibata <afu@wta.att.ne.jp>.  Always broken.
 
               ppmrelief: fix out-of-bound values in output.  Always broken.
               ppmrelief was new in primordial Netpbm in 1989.
-              Thanks Prophet of the Way <afu@wta.att.ne.jp>.
+              Thanks Akira F Urushibata <afu@wta.att.ne.jp>.
 
               ppmrelief: fix crash when input image is too small.  Always
               broken.  ppmrelief was new in primordial Netpbm in 1989.  Thanks
-              Prophet of the Way <afu@wta.att.ne.jp>.
+              Akira F Urushibata <afu@wta.att.ne.jp>.
 
               pgmtexture: fix buffer overflow.  Always broken.  (Program
               was added in primordial Netpbm in 1991).
 
               pamdeinterlace: fix incorrect output with -takeodd and image has
               only one row.  Always broken (pamdeinterlace was introduced in
-              Netpbm 9.21 (January 2001)).  Thanks Prophet of the Way
+              Netpbm 9.21 (January 2001)).  Thanks Akira F Urushibata
               <afu@wta.att.ne.jp>.
 
               configure: warn if user says JPEG library is in the linker's
@@ -451,7 +464,7 @@ CHANGE HISTORY
               (September 2011).
 
               pnmtops: Fix crash with 12 bits per sample.  Introduced in 10.53
-              (December 2010).  Thanks Prophet of the Way <afu@wta.att.ne.jp>.
+              (December 2010).  Thanks Akira F Urushibata <afu@wta.att.ne.jp>.
 
               pnmtops: Fix bug: wrong output with -ascii85.  Introduced in
               10.63 (June 2013).
@@ -467,16 +480,16 @@ CHANGE HISTORY
               (September 2011).
 
               pbmtoepsi: fix handling of all-white image.  Always broken.
-              Thanks Prophet of the Way <afu@wta.att.ne.jp>.
+              Thanks Akira F Urushibata <afu@wta.att.ne.jp>.
 
               pbmtoepsi: fix excessively long raster line.  Always broken.
-              Thanks Prophet of the Way <afu@wta.att.ne.jp>.
+              Thanks Akira F Urushibata <afu@wta.att.ne.jp>.
 
               pnmshear: fix incorrect determination of background color.
               Always broken.
 
               ppmpat: fix crash with -squig with aspect ratio < 1:25 or
-              > 25:1. Thanks Prophet of the Way <afu@wta.att.ne.jp>.
+              > 25:1. Thanks Akira F Urushibata <afu@wta.att.ne.jp>.
               Always broken.
 
               pgmkernel: fix some pixels 1 less than they should be.
@@ -496,7 +509,7 @@ CHANGE HISTORY
               as done already with GCC.
 
               Build: Use <emmintrin.h> interface for SSE intrinsics
-              instead of GCC-specific versions.  Thanks Prophet of the Way
+              instead of GCC-specific versions.  Thanks Akira F Urushibata
               <afu@wta.att.ne.jp>.
 
               Build on system without vasprintf (not GNU libc): fix compiler
@@ -519,7 +532,7 @@ CHANGE HISTORY
               Add pamtowinicon, winicontopam.  Thanks Ludolf Holzheid
               (lholzheid@bihl-wiedemann.de).
 
-              pgmnoise: add -maxval, speed up.  Thanks Prophet of the Way
+              pgmnoise: add -maxval, speed up.  Thanks Akira F Urushibata
               <afu@wta.att.ne.jp>.
 
               Perl programs: make them shell programs that reinvoke themselves
@@ -586,11 +599,11 @@ CHANGE HISTORY
               memory access.
 
               ppmforge. fix crash when -mesh is 1 or less.  Always broken
-              (program was added in Pbmplus (October 1991).  Thanks Prophet of
-              the Way <afu@wta.att.ne.jp>.
+              (program was added in Pbmplus (October 1991).  Thanks 
+              Akira F Urushibata <afu@wta.att.ne.jp>.
 
               ppmforge: fix array bounds violation.  Always broken (program
-              was added in Pbmplus (October 1991).  Thanks Prophet of the Way
+              was added in Pbmplus (October 1991).  Thanks Akira F Urushibata
               <afu@wta.att.ne.jp>.
 
               install: fix Perl warning in installnetpbm.  Broken in 
@@ -677,8 +690,8 @@ CHANGE HISTORY
               pamtompfont, since Netpbm 10.50 (March 2010) in pbmpscale, since
               10.44 (September 2008) in pgmhist.
 
-              xbmtopbm: fix incorrect output, memory leak.  Thanks Prophet of
-              the Way <afu@wta.att.ne.jp>.
+              xbmtopbm: fix incorrect output, memory leak.  Thanks Akira F
+              Urushibata <afu@wta.att.ne.jp>.
 
               sunicontopnm: Fix incorrect output for depth 8.  Always broken
               (depth = 8 capability was added in Netpbm 10.53 (December 2010).
@@ -690,7 +703,7 @@ CHANGE HISTORY
               ppmpat: Fix bug: wrong output with -poles.  Broken in Netpbm
               10.47 (June 2009).
 
-              Add tests.  Thanks Prophet of the Way <afu@wta.att.ne.jp>.
+              Add tests.  Thanks Akira F Urushibata <afu@wta.att.ne.jp>.
 
 12.09.30 BJH  Release 10.60.00
 
@@ -702,7 +715,7 @@ CHANGE HISTORY
               in Netpbm 10.49 (December 2009).
 
               pnm_hashtuple: slight performance improvement from new hash
-              function.  Thanks Prophet of the Way <afu@wta.att.ne.jp>.
+              function.  Thanks Akira F Urushibata <afu@wta.att.ne.jp>.
 
               ppmtospu: wild memory accesses.  Always broken (program added in
               Netpbm 10.58 (March 2012).
@@ -813,11 +826,11 @@ CHANGE HISTORY
 
               pamcomp: Retain opacity information from underlying image.
 
-              pnmtops: Add PBM fast path.  Thanks Prophet of the Way
+              pnmtops: Add PBM fast path.  Thanks Akira F Urushibata
               <afu@wta.att.ne.jp>.
 
               libnetpbm and most programs that use color maps: speedup with
-              new color hash function.  Thanks Prophet of the Way
+              new color hash function.  Thanks Akira F Urushibata
               <afu@wta.att.ne.jp>.
 
               pnmquant: use File::Temp::tempfile() instead of local
@@ -935,10 +948,10 @@ CHANGE HISTORY
               pngtopam: include tuple type in output.  Thanks
               Thomas Henlich <thenlich@users.sourceforge.net>.
 
-              sunicontopnm: Understands Depth=8.  Thanks Prophet of the Way
+              sunicontopnm: Understands Depth=8.  Thanks Akira F Urushibata
               <afu@wta.att.ne.jp>.
 
-              sunicontopnm: Validate header.  Thanks Prophet of the Way
+              sunicontopnm: Validate header.  Thanks Akira F Urushibata
               <afu@wta.att.ne.jp>.
 
               bmptopnm: Don't crash on invalid zero value of image height in
@@ -954,11 +967,11 @@ CHANGE HISTORY
               ilbmtoppm: Don't crash on image that has a transparent color
               index, but no color map.
 
-              sunicontopnm: fix for 32 bit items in input.  Thanks Prophet of
-              the Way <afu@wta.att.ne.jp>.
+              sunicontopnm: fix for 32 bit items in input.  Thanks Akira F
+              Urushibata <afu@wta.att.ne.jp>.
 
-              sunicontopnm: fix arithmetic overflows.  Thanks Prophet of the
-              Way <afu@wta.att.ne.jp>.
+              sunicontopnm: fix arithmetic overflows.  Thanks Akira F
+              Urushibata <afu@wta.att.ne.jp>.
 
               icontopbm: rename to sunicontopnm.
 
@@ -968,14 +981,14 @@ CHANGE HISTORY
               pamstereogram: slight change to dpi and eye separation defaults.
               invert near/far dark/light association.  Thanks Scott Pakin.
 
-              pnmtops: Fix incorrect output with -flate.  Thanks Prophet of
-              the Way <afu@wta.att.ne.jp>.
+              pnmtops: Fix incorrect output with -flate.  Thanks Akira F
+              Urushibata <afu@wta.att.ne.jp>.
 
               sgitopnm: Fix arithmetic overflow on -channel option.  Thanks
-              Prophet of the Way <afu@wta.att.ne.jp>.
+              Akira F Urushibata <afu@wta.att.ne.jp>.
 
               sgitopnm: Fix crash with -channel on verbatim SGI image.  Thanks
-              Prophet of the Way <afu@wta.att.ne.jp>.
+              Akira F Urushibata <afu@wta.att.ne.jp>.
 
               fitstopnm: Deal properly with NaN in input image.
 
@@ -986,7 +999,7 @@ CHANGE HISTORY
 
               pdbimgtopam: fix corrupted output image.  Thanks Scott Pakin.
 
-              pnmtops: fix arithmetic overflows.  Thanks Prophet of the Way
+              pnmtops: fix arithmetic overflows.  Thanks Akira F Urushibata
               <afu@wta.att.ne.jp>.
 
               Rename all external symbols that don't have a Netpbm prefix
@@ -1048,20 +1061,20 @@ CHANGE HISTORY
               pamx: Make exit status 0 instead of 10 when window manager
               requests termination.
 
-              pnmsmooth: Respect -plain.  Thanks Prophet of the Way
+              pnmsmooth: Respect -plain.  Thanks Akira F Urushibata
               <afu@wta.att.ne.jp>.
 
               pnmsmooth: Don't display pnmconvol messages (i.e. run
               pnmconvol with -quiet).
 
               pamflip: speedup for PBM.  Use SSE2 and skip some idempotent
-              pixel movement.  Thanks Prophet of the Way <afu@wta.att.ne.jp>.
+              pixel movement.  Thanks Akira F Urushibata <afu@wta.att.ne.jp>.
 
               anytopnm: recognize "PC bitmap" in 'file' response as BMP.
               (in addition to existing "PC bitmap data").
 
               libnetpbm, various PBM programs: Use SSE insted of MMX.  Thanks
-              Prophet of the Way <afu@wta.att.ne.jp>.
+              Akira F Urushibata <afu@wta.att.ne.jp>.
 
               pbmtext/libpbmfont: Fix wild pointer; probably asymptomatic.
               Introduced in Netpbm 10.39.
@@ -1088,14 +1101,14 @@ CHANGE HISTORY
               avstopam: fix incorrect output.
 
               pnmsmooth: fix arithmetic overflow with absurdly large
-              convolution matrix dimensions.  Thanks Prophet of the Way
+              convolution matrix dimensions.  Thanks Akira F Urushibata
               <afu@wta.att.ne.jp>.
 
               pnmsmooth: fix wild pointer: causes wrong arguments to
-              'pnmconvol'.  Introduced in Netpbm 10.50.  Thanks Prophet of the
-              Way <afu@wta.att.ne.jp>.
+              'pnmconvol'.  Introduced in Netpbm 10.50.  Thanks Akira F
+              Urushibata <afu@wta.att.ne.jp>.
 
-              pamscale: fix -reduce.  Introduced in Netpbm 10.27.
+              pamscale: fix -reduce.  Introduced in Netpbm 10.27 (March 2005).
 
               pampaintspill: fix incorrect output.
 
@@ -1132,10 +1145,10 @@ CHANGE HISTORY
               strange combination of luminosity and HSV value.
 
               pamenlarge: Make special fast path for scale factors up to 10
-              (2, 3, and 5 already existed).  Thanks Prophet of the Way
+              (2, 3, and 5 already existed).  Thanks Akira F Urushibata
               <afu@wta.att.ne.jp>.
 
-              pamflip: Speed up for most images.  Thanks Prophet of the Way
+              pamflip: Speed up for most images.  Thanks Akira F Urushibata
               <afu@wta.att.ne.jp>.
 
               ybmtopbm: Assume YBM format has raster in natural order
@@ -1462,7 +1475,7 @@ CHANGE HISTORY
               computing means.
 
               pamcut, pnmcat, pnmpaste, pnmpad, g3topbm: Add fast PBM
-              path.  Thanks Prophet of the Way <afu@wta.att.ne.jp>.
+              path.  Thanks Akira F Urushibata <afu@wta.att.ne.jp>.
 
               pnmpaste: fail if user specified stdin for both images.
 
@@ -1477,10 +1490,10 @@ CHANGE HISTORY
 
               pamcut: don't crash when cutting a region entirely to
               the left or right of the input image, with -pad.  Thanks
-              Prophet of the Way <afu@wta.att.ne.jp>.
+              Akira F Urushibata <afu@wta.att.ne.jp>.
 
               pamcut: don't crash when left > right or top > bottom with
-              -pad.  Thanks Prophet of the Way <afu@wta.att.ne.jp>.
+              -pad.  Thanks Akira F Urushibata <afu@wta.att.ne.jp>.
 
               pgmhist: arbitrary output when total pixels doesn't fit in an
               integer.
@@ -1571,7 +1584,7 @@ CHANGE HISTORY
               tag).
 
               pbmtext: fail cleanly if -width, -space, or -lspace is
-              too large for computation.  Thanks Prophet of the Way
+              too large for computation.  Thanks Akira F Urushibata
               <afu@wta.att.ne.jp>.
 
               pnmmargin: don't crash with zero margin request.
@@ -1612,8 +1625,8 @@ CHANGE HISTORY
               
 07.12.27 BJH  Release 10.41.00
 
-              pamenlarge: much faster for PBM.  Thanks Prophet of the
-              Way <afu@wta.att.ne.jp>.
+              pamenlarge: much faster for PBM.  Thanks Akira F Urushibata
+              <afu@wta.att.ne.jp>.
 
               pamenlarge: remove arithmetic overflow.
 
@@ -1675,14 +1688,14 @@ CHANGE HISTORY
               <pebolle@tiscali.nl>.
 
               pnmmargin: add -plain option.    Thanks
-              Prophet of the Way <afu@wta.att.ne.jp>.
+              Akira F Urushibata <afu@wta.att.ne.jp>.
 
               pnmgamma: improve error messages.
 
               pamstack: accept Standard Input properly.
 
               pnmmargin: recognize invalid options better.  Thanks
-              Prophet of the Way <afu@wta.att.ne.jp>.
+              Akira F Urushibata <afu@wta.att.ne.jp>.
 
               anytopnm, pnmmargin, pamstretch-gen, ppmquantall: fix
               small temporary file security exposure.
@@ -1775,7 +1788,7 @@ CHANGE HISTORY
               Add pamfixtrunc.
 
               pamtogif: Add -aspect.  Thanks
-              Prophet of the Way <afu@wta.att.ne.jp>.
+              Akira F Urushibata <afu@wta.att.ne.jp>.
 
               pamditherbw: Add -atkinson.
 
@@ -1801,11 +1814,11 @@ CHANGE HISTORY
               misinterpretations.
 
               pamtogif: Speed up for monochrome images.  Thanks
-              Prophet of the Way <afu@wta.att.ne.jp>.
+              Akira F Urushibata <afu@wta.att.ne.jp>.
 
               pamtogif: Speed up for small images by using smaller
               hash table (so smaller memory footprint).  Thanks
-              Prophet of the Way <afu@wta.att.ne.jp>.
+              Akira F Urushibata <afu@wta.att.ne.jp>.
 
               libnetpbm: add pm_drain().
               
@@ -1879,21 +1892,21 @@ CHANGE HISTORY
               -interlace.
 
               pbmtoxbm: add -name option.
-              Thanks Prophet of the Way <afu@wta.att.ne.jp>.
+              Thanks Akira F Urushibata <afu@wta.att.ne.jp>.
 
               ppmshift, ppmspread, ppmforge, pgmnoise, pgmcrater: better
               randomization; won't produce the same image if you run it
               twice within the same second.
 
               pbmtoxbm: Use packed PBM functions for efficiency.
-              Thanks Prophet of the Way <afu@wta.att.ne.jp>.
+              Thanks Akira F Urushibata <afu@wta.att.ne.jp>.
               
               xbmtopbm: Use packed PBM functions for efficiency.
-              Thanks Prophet of the Way <afu@wta.att.ne.jp>.
+              Thanks Akira F Urushibata <afu@wta.att.ne.jp>.
 
               cmuwmtopbm, mgrtopbm, pbmtocmuwm, pbmtoicon, pbmtomgr:
               Use packed PBM functions for efficiency.
-              Thanks Prophet of the Way <afu@wta.att.ne.jp>.
+              Thanks Akira F Urushibata <afu@wta.att.ne.jp>.
 
               libnetpbm: add pnm_colorname().
 
@@ -1917,10 +1930,10 @@ CHANGE HISTORY
               rgb:0/0/0 style color name.
 
               pbmtoxbm, pbmtox10bm: merge.
-              Thanks Prophet of the Way <afu@wta.att.ne.jp>.
+              Thanks Akira F Urushibata <afu@wta.att.ne.jp>.
 
               pbmtox10bm: Fix generation of name in XBM file.
-              Thanks Prophet of the Way <afu@wta.att.ne.jp>.
+              Thanks Akira F Urushibata <afu@wta.att.ne.jp>.
 
               pbmtextps: Fix buffer overrun -- typical symptom: extra
               text generated.
@@ -2160,7 +2173,7 @@ CHANGE HISTORY
               Add pgmmake.
 
               bmptopnm: Understands RLE4/RLE8 compressed BMP.  Thanks
-              Prophet of the Way <afu@wta.att.ne.jp>.
+              Akira F Urushibata <afu@wta.att.ne.jp>.
 
               pnmgamma: Add -bt709tosrgb -srgbtobt709, -bt709tolinear,
               -lineartobt709, -gamma, -rgamma, -ggamma, -bgamma (gammma
@@ -2204,11 +2217,11 @@ CHANGE HISTORY
               being verbose.
 
               ppmtobmp, bmptopnm: major speed improvement for PBM.  Thanks
-              Prophet of the Way <afu@wta.att.ne.jp>.
+              Akira F Urushibata <afu@wta.att.ne.jp>.
 
               pbmtog3: Use new GCC features instead of assembly language
               for superspeed operations.  Thanks
-              Prophet of the Way <afu@wta.att.ne.jp>.
+              Akira F Urushibata <afu@wta.att.ne.jp>.
 
               pm_make_tmpfile(): Use TEMP and TMP environment variables if
               TMPDIR not set.
@@ -2526,7 +2539,7 @@ CHANGE HISTORY
               has pointer size != word size and uses the general case code.
 
               libnetpbm: fix basic pm_readlittleshort() bug introduced
-              in 10.27.  Affects mdatopbm, rawtopgm, lispmtopgm,
+              in 10.27 (March 2005).  Affects mdatopbm, rawtopgm, lispmtopgm,
               pcxtoppm, winicontoppm, bmptopnm, sirtopnm, xwdtopnm,
               cameratopam.
 
@@ -2571,8 +2584,9 @@ CHANGE HISTORY
               ppmtompeg: fix insecure temp file.  Thanks Alexey
               Tourbin <at@altlinux.ru>.
 
-              libnetpbm: fix basic readlittlelong() bug introduced in 10.27.
-              Affects xwdtopnm, bmptopnm, winicontoppm, lispmtopgm.
+              libnetpbm: fix basic readlittlelong() bug introduced in 10.27
+              (March 2005).  Affects xwdtopnm, bmptopnm, winicontoppm,
+              lispmtopgm.
 
               pbmtext/libnetpbm: fix crash with -builtin=fixed.
 
@@ -2865,37 +2879,34 @@ CHANGE HISTORY
 
               pamtopnm: accept extra planes (ignore them).
 
-              pamcut: major speedup.  Thanks Prophet of the Way
-              <afu@wta.att.ne.jp> (Akira Urushibata ("Douso")).
+              pamcut: major speedup.  Thanks Akira F Urushibata
+              <afu@wta.att.ne.jp>
 
               libnetpbm: Add pnm_getopacity().
 
               libnetpbm: Add pnm_applyopacityrown(), pnm_unapplyopacityrown().
 
               libnetpbm: "pam" read and write routines much more
-              efficient.  Thanks Prophet of the Way
-              <afu@wta.att.ne.jp> (Akira Urushibata ("Douso")).
+              efficient.  Thanks Akira F Urushibata
+              <afu@wta.att.ne.jp>
 
               Add pnm_formatpamrow(), pnm_allocrowimage(),
-              pnm_freerowimage().  Thanks Thanks Prophet of the Way
-              <afu@wta.att.ne.jp> (Akira Urushibata ("Douso")).
+              pnm_freerowimage().  Thanks Thanks Akira F Urushibata
+              <afu@wta.att.ne.jp>
 
               pnm_readpamrow(): Add option to have "tuplerow" argument
               NULL and not get the row's contents.  Thanks Thanks
-              Prophet of the Way <afu@wta.att.ne.jp> (Akira Urushibata
-              ("Douso")).
+              Akira F Urushibata <afu@wta.att.ne.jp>
 
-              Add pnm_writepamrowmult().  Thanks Thanks Prophet of the
-              Way <afu@wta.att.ne.jp> (Akira Urushibata ("Douso")).
+              Add pnm_writepamrowmult().  Thanks Thanks Akira F Urushibata
+              <afu@wta.att.ne.jp>.
 
               libnetpbm: format plain format images more nicely.
-              Thanks Thanks Prophet of the Way <afu@wta.att.ne.jp>
-              (Akira Urushibata ("Douso")).  
+              Thanks Thanks Akira F Urushibata <afu@wta.att.ne.jp>
 
               pamcut: fix bug: Blows up instead of failing cleanly
               when you try to cut beyond the bounds of the image.
-              Thanks Thanks Prophet of the Way <afu@wta.att.ne.jp>
-              (Akira Urushibata ("Douso")).
+              Thanks Thanks Akira F Urushibata <afu@wta.att.ne.jp>
 
               fix bug: MMX/SSE fast PBM writing (with gcc -msse) all wrong.
 
@@ -2905,7 +2916,7 @@ CHANGE HISTORY
               to enlarge.
 
               Speed up pbm_writepbmrow() (and all PBM output programs)
-              by going a byte at a time.  Thanks Prophet of the Way
+              by going a byte at a time.  Thanks Akira F Urushibata
               <afu@wta.att.ne.jp>.
 
               pamperspective: fix bug that can cause memory corruption
@@ -2936,11 +2947,11 @@ CHANGE HISTORY
               <esr@thyrsus.com>.
 
               pamflip: Large speed, memory improvements for
-              non-diagonal flips.  Thanks Prophet of the Way
+              non-diagonal flips.  Thanks Akira F Urushibata
               <afu@wta.att.ne.jp>.
 
               jbigtopnm, pnmtojbig: Use packed PBM functions to speed up
-              greatly.  Thanks Prophet of the Way <afu@wta.att.ne.jp>.
+              greatly.  Thanks Akira F Urushibata <afu@wta.att.ne.jp>.
 
               g3topbm: Don't fail on premature EOF; produce partial
               output instead.
@@ -3007,13 +3018,13 @@ CHANGE HISTORY
               maketuplergb(), makerowrgb(), makearrayrgb().
 
               pnminvert: much faster for PBMs.  Thanks 
-              Prophet of the Way <afu@wta.att.ne.jp>.
+              Akira F Urushibata <afu@wta.att.ne.jp>.
 
-              pbmmake: use packed bits to speed up.  Thanks Prophet of
-              the Way <afu@wta.att.ne.jp> (Akira Urushibata ("Douso")).
+              pbmmake: use packed bits to speed up.  Thanks
+              Akira F Urushibata <afu@wta.att.ne.jp>.
 
-              pbmtog3: speedups.  Thanks Prophet of the Way
-              <afu@wta.att.ne.jp> (Akira Urushibata ("Douso")).
+              pbmtog3: speedups.  Thanks Akira F Urushibata
+              <afu@wta.att.ne.jp>.
 
               Fix gamma value (from .45 to 2.2) in pm_gamma709(), 
               pm_ungamma709().
@@ -3144,7 +3155,7 @@ CHANGE HISTORY
               Thanks David Jones <drj@pobox.com>.
 
               pbmtog3: fix buffer overrun when image > 1728 columns.
-              Thanks Prophet of the Way <afu@wta.att.ne.jp>.
+              Thanks Akira F Urushibata <afu@wta.att.ne.jp>.
 
               pnmsvgalib: Correct error message - too wide -> too tall.
 
diff --git a/doc/Netpbm.programming b/doc/Netpbm.programming
index 62e4c569..c4d38ed4 100644
--- a/doc/Netpbm.programming
+++ b/doc/Netpbm.programming
@@ -65,6 +65,14 @@ named such as "pbmtog3.test".  You can use those to verify your
 changes.  You should also add to these tests and create new ones.  But
 most developers don't.
 
+As you code and test, do 'make dep' to create the header file dependency files
+(depend.mk).  Do it after 'configure' and every time you change the
+dependencies.  If you don't, 'make' won't know to recompile things when you
+change the header files.  For the convenience of users who are just building,
+and not changing anything, the make files do work without a 'make dep', but do
+so by automatically generating empty depend.mk files.  This is not what you
+want as a developer.
+
 
 CODING GUIDELINES
 -----------------
@@ -111,7 +119,7 @@ before you read these.
   cause problems to other programs when you do a "merge build" of 
   Netpbm.
 
-* Always start the code in main() with a call to p?m_init().
+* Always start the code in main() with a call to pm_proginit().
 
 * Use shhopt for option processing.  i.e. call optParseOptions3().
   This is really easy if you just copy the parseCommandLine() function
@@ -197,9 +205,38 @@ before you read these.
   compose code just as easily with spaces as with tabs.
 
 * Limit your C code to original ANSI C.  Not C99.  Not C89.  Not C++.  Don't
-  use // for comments or put declarations in the interior of block.
+  use // for comments or put declarations in the interior of a block.
   Interpreted languages are OK, with Perl being preferred.
 
+* Make output invariant with input.  The program should produce the same output
+  when fed the same input.  This helps with testing and also reduces the chance
+  of bugs being encountered randomly.
+
+  This is an issue when there are "don't care" bits in the output.  You should
+  normally make those zero.
+
+  The valgrind utility helps you identify instances of undefined bits and
+  bytes getting to output.
+
+  A common place to find "don't care" bits is padding at the end of a raster
+  row.  You can use pbm_cleanrowend_packed() to clear padding bits when you
+  use pbm_writepbmrow_packed().
+
+  Some programs are designed to produce random output.  For those, include a
+  -seed option to specify the seed of the random number generator so that a
+  tester can make the output predictable.
+
+
+* Never assume that input will be valid; make sure your program can
+  handle corrupt input gracefully.
+
+  Watch out for arithmetic overflows caused by large numbers in the input.
+
+  Be careful when writing decoders.  Make sure that corruptions in the
+  input image do not cause buffer overruns.
+
+
+
 
 DISCONTINUED CODING GUIDELINES
 ------------------------------
@@ -207,6 +244,9 @@ DISCONTINUED CODING GUIDELINES
 Here are some things you will see in old Netpbm programs, but they are
 obsolete and you shouldn't propagate them into a new program:
 
+* Use of pbm_init(), pgm_init(), ppm_init(), and pnm_init().  We use
+  pm_proginit() now.
+
 * Tolerating non-standard C libraries.  You may assume all users have
   ANSI and POSIX compliant C libraries.  E.g. use strrchr() and forget
   about rindex().
@@ -305,6 +345,10 @@ code.  Modular and structured above all.
 
   Declare a variable in the most local scope possible.
 
+  Global constants are OK.
+
+* Do not use static variables, except for global constants.
+
 * Keep subroutines small.  Generally under 50 lines.  But if the
   routine is a long sequence of simple, similar things, it's OK for it
   run on ad infinitem.
@@ -314,7 +358,7 @@ code.  Modular and structured above all.
 
 * Do not say "if (a)" when you mean "if (a != 0)".  Use "if (a)" only if a is
   a boolean variable.  Or where it's defined so that zero is a special value
-  that means ("doesn't exist").
+  that means "doesn't exist".
 
 * Do multiword variable names in camel case: "multiWordName".  Underscores
   waste valuable screen real estate.
@@ -325,6 +369,10 @@ code.  Modular and structured above all.
   variable's value is a pointer to a color value, name it "colorP", not
   "color".
 
+* A variable that represents the number of widgets should be "widgetCt",
+  ("widget count"), not "widgets".  The latter should represent the actual
+  widgets instead.
+
 * Put "const" as close as possible to the thing that is constant.
   "int const width", not "const int width".  When pointers to
   constants are involved, it makes it much easier to read.
@@ -332,4 +380,46 @@ code.  Modular and structured above all.
 * Free something in the same subroutine that allocates it.  Have exactly 
   one free per allocate (this comes naturally if you eliminate gotos).
 
+* Dynamically allocate buffers, for example raster buffers, rather than use
+  automatic variables.  Accidentally overrunning an automatic variable,
+  typically stored on the stack, is much more dangerous than overrunning a
+  variable stored in the heap.
+
+* Use pm_asprintf() to compose strings, instead of sprintf(), strcat(), and
+  strcpy().  pm_asprintf() is essentially the same as GNU asprintf(), i.e.
+  sprintf(), except it dynamically allocates the result memory.  This
+  effortlessly makes it impossible to overrun the result buffer.  Use
+  pm_strfree() to free the result memory.  You usually need not worry about
+  the pathological case that there is no memory available for the result,
+  because in that case, pm_asprintf() returns a constant string "OUT OF MEMORY"
+  and in most cases, that won't cause a disaster - just incorrect behavior that
+  is reasonable in the face of such a pathological situation.
+
+* Do not use the "register" qualifier of a variable.
+
+
+MISCELLANEOUS
+-------------
+
+Object code immutability across compilations
+--------------------------------------------
+
+In a normal build process the same source code always produces the same object
+code.  (Of course this depends on your compiler and its settings: if your
+compiler writes time stamps into the objects, they will naturally be different
+with each compilation.)
+
+The file lib/compile.h has a time stamp which gets written into libnetpbm.a
+and libnetpbm.so .  This will affect individual binary executables if they are
+statically linked.
+
+If compile.h does not exist it will be created by the program
+buildtools/stamp-date.  Once created, compile.h will stay unchanged until you
+do "make clean".
+
+If you make alterations to source which are entirely cosmetic (for example,
+changes to comments or amount of indentation) and need to confirm that the
+actual program logic is not affected, compare the object files.  If you need
+to compare library files (or for some reason, statically linked binaries) make
+sure that the same compile.h is used throughout.
 
diff --git a/doc/TESTS b/doc/TESTS
index 9352b207..65f91d26 100644
--- a/doc/TESTS
+++ b/doc/TESTS
@@ -8,10 +8,11 @@ Contents
   1.4 Repeatability
   1.5 Execution time
   1.6 Testing package in designated directory
-  1.7 Post-install check
-  1.8 Skipping test items
-  1.9 Valgrind
-
+  1.7 Pre-packaging check
+  1.8 Post-install check
+  1.9 Skipping test items
+  1.10 Valgrind
+  
 2. Troubleshooting
   2.1 Missing programs
   2.2 Broken programs
@@ -66,31 +67,47 @@ appear at the end:
 1.3 Prerequisites
 =================
 
-The tests require the Bash command shell.  The script Execute-Tests has some
-expressions unique to bash.  Quite old versions work, at least back to bash
-v. 2.05b.
+The tests require the Bash command shell.  The script Execute-Tests has
+some expressions unique to bash.  Quite old versions work, at least back
+to bash v. 2.05b.
 
 The tests also use the following utilities:
 
-  - awk 
-  - cat
-  - cmp
-  - egrep
-  - head
-  - mktemp
-  - sed
-  - seq
-  - tee
+ - sh
+ - awk
+ - perl
+
+ - cat
+ - cksum
+ - cmp
+ - cp
+ - cut
+ - date
+ - dirname
+ - egrep
+ - fgrep
+ - grep
+ - file
+ - head
+ - mkdir
+ - mktemp
+ - rm
+ - sed
+ - seq
+ - tee
+ - tr
+ - uniq
 
 
 
 1.4 Repeatability
 =================
 
-The current version of the test package produces identical results if you run
-"make check" repeatedly.  The tests contain no random elements; some
-Netpbm programs use randomness internally, but the tests seed their random
-number generators with fixed values so that they too have repeatable results.
+The current version of the test package produces identical results if
+you run "make check" repeatedly.  The tests contain no random elements;
+some Netpbm programs use randomness internally, but the tests seed
+their random number generators with fixed values so that they too have
+repeatable results.
 
 
 
@@ -114,64 +131,99 @@ you must do the same with "make check":
 
 
 
-1.7 Post-install check
-======================
+1.7 Pre-packaging check
+=======================
+
+You can run the tests to check executables after compilation, before
+packaging.  This feature is intended for developers.
+
+   make check-tree
 
-You can run the tests after installation as well as from the package
-directory.  Just set $PBM_TESTPREFIX to the bin directory.  For example, if
-the Netpbm executables are in /usr/local/bin/ do
+This test method is incompatible with merge build.
 
-   PBM_TESTPREFIX=/usr/local/bin make check
+Currently this test method reports several errors when Netpbm is compiled in a
+separate build directory.
 
-If you want to test the executables in the default search path do
 
-   PBM_TESTPREFIX="" make check
 
-If the color dictionary file rgb.txt is in a non-standard location, you must
-set RGBDEF.  If you don't, the tests will report several false positives.
+1.8 Post-install check
+======================
+
+You can run the tests after installation.  Run this way, the tests are of
+programs in the default search path.
+
+  make check-install
 
-   PBM_TESTPREFIX=/usr/local/bin RGBDEF=/etc/colors/rgb.txt make check
+Make sure to set RGBDEF if the color dictionary file rgb.txt is in
+a non-standard location.  This must be an absolute path.  
 
+  RGBDEF=/etc/colors/rgb.txt make check-install
 
 
-1.8 Skipping test items
+
+1.9 Skipping test items
 =======================
 
 The file test/Test-Order is a list of tests which are run.  If you want to
 skip any test, remove the line or comment it out with a "#".
 
+The variable "target", a comma-separated list of Netpbm programs
+provides another way to run only select tests.  For example to run
+only the test scripts which examine giftopnm and pamtogif, do:
+
+  make check target=giftopnm,pamtogif
 
 
-1.9 Valgrind
+
+1.10 Valgrind
 ============
 
 You can run the whole test under Valgrind.  This is an advanced feature
 intended for programmers who work on Netpbm code.
 
-To turn on Valgrind, uncomment this line in test/Execute:
+To turn on Valgrind, set VALGRIND_TESTS to "on":
+
+  make check VALGRIND_TESTS="on"
+
+Valgrind version 3.6.0 or newer is required.  For information on
+valgrind, visit http://www.valgrind.org/ .
+
+Valgrind results are output to files, one per process in the directory
+/tmp/netpbm-test/valgrind .  The file name consists of the test script
+name, process ID and the suffix ".vout", e.g.: "ppmmake.18420.vout" .
+
+Valgrind errors are not reported in the summary report and do not
+influence the success/failure count in any way.  The following awk
+one-liner will report ".vout" files with a positive error count in
+the ERROR SUMMARY line:
 
-# export PBM_TESTPREFIX="valgrind --log-fd=4 "${PBM_TESTPREFIX}
+  awk '/ERROR SUMMARY/ && $4>0 {print FILENAME}' \
+       /tmp/netpbm-test/valgrind/*.vout  
 
-   make check 4> valgrind.log
 
-Note that Valgrind output is directed to file descriptor 4.
+You can add or alter valgrind options by editing this line in
+test/Execute-Tests:
 
-Valgrind version 3.5.0 or newer is recommended.  Older versions do
-not report the command that is being executed.
+  vg_command_base="valgrind --trace-children=yes"
 
-You can add any options for Valgrind should by editing the above mentioned
-line.  To run "valgrind --track-origins=yes", you must make two changes in
+To run "valgrind --track-origins=yes", you must make two changes in
 config.mk:
 
-  - Add -g to CFLAGS.
-  - Turn stripping off.
+  - Add -g to CFLAGS
+  - Turn stripping off: STRIPFLAG =
 
-Valgrind significantly increases execution time.  You should consider paring
-down the items in Test-Order.  You probably don't need to run
-"all-in-place.test", which has restrictions in the way errors are reported
-when PBM_TESTPREFIX is not a simple directory path.  Another test
-"pamslice-roundtrip.test" is time-consuming, you may want to skip this one
-too.
+Valgrind significantly increases execution time.  If ordinary
+"make check" requires 10 seconds, "make check VALGRIND_TESTS=on"
+will require roughly 12 minutes, maybe more.  You should consider
+either setting "target=..." or paring down the items in Test-Order.
+In the latter case, you probably don't need to run "all-in-place.test"
+and "legacy-names.test".
+
+The option "--trace-children-skip" is used to prevent valgrind from
+stepping into child processes that are not relevant.  This option
+appears in valgrind v. 3.6.0.  If you wish to conduct valgrind tests
+with an older version, comment out the line in Execute-Tests with
+"--trace-children-skip".
 
 
 
@@ -181,7 +233,8 @@ too.
 2.1 Missing programs
 ====================
 
-The first test run, "all-in-place.test" detects missing programs.
+The first two tests run, "all-in-place.test" and "legacy-names.test"
+detect missing programs.
 
 If you work around a build glitch with "make --keep-going" you
 will get a few errors here.
@@ -191,10 +244,10 @@ problem, such as a misconfigured dynamic library or a directory-wide
 permission issue.  This kind of failure is known to happen when N is
 set too high with "make -jN" (overambitious parallel make.) 
 
-The current test routines assume a typical build configuration - they are not
-aware of the actual configuration you chose.  If a choice you make during
-configure causes "make" to skip compilation of certain programs, the test
-routines won't know and will report failures.
+The current test routines assume a typical build configuration - they are
+not aware of the actual configuration you chose.  If a choice you make
+during configure causes "make" to skip compilation of certain programs,
+the test routines won't know and will report failures.
 
 For details read 'Netpbm Library Prerequisites':
 http://netpbm.sourceforge.net/prereq.html .
@@ -205,8 +258,8 @@ http://netpbm.sourceforge.net/prereq.html .
 ===================
 
 Broken programs will invariably lead to failures.  Certain programs
-(for instance, image generators 'pbmmake' and 'pgmmake') are used in numerous
-test scripts.  Problems in them will lead to multiple failures.
+(for instance, image generators 'pbmmake' and 'pgmmake') are used in
+numerous test scripts.  Problems in them will lead to multiple failures.
 
 To aid you in this situation each test routine lists the necessary programs
 near the top.
@@ -232,7 +285,7 @@ the color dictionary file rgb.txt.
   pathname of your rgb.txt file or don't use color names.
 
 This is highly unlikely to occur with "make check" right after packaging,
-but may appear after installation.
+but may appear in the post-installation check "make check-install".
 
 To check manually after installation, execute the following and see
 whether the proper output or the error message appears:
@@ -249,6 +302,10 @@ Proper output:
 The simple remedy is properly setting the environment value RGBDEF to
 the location of rgb.txt.
 
+RGBDEF must be an absolute path.  The following will not work:
+
+  RGBDEF=./lib/rgb.txt make check-install
+
 If you want to hardcode the path, modify RGB_DB_PATH in pm_config.h
 and run "make" again.  Note that running "configure" will cause
 pm_config.h to be overwritten; changes by editing will be lost.
@@ -264,17 +321,19 @@ the newly built version is in place and in working condition.
 
 The test routines can test binaries other than the intended
 target, for example pre-compiled binaries distributed in .rpm
-or .deb format.  If PBM_TESTPREFIX is explicitly set to a directory
-that contains programs from such a source, you should expect multiple
-failures due to missing programs, missing features, etc.  If
-PBM_TESTPREFIX is set to "" (null), the outcome will depend heavily
-on what version has precedence in PATH.
+or .deb format.  If the default binary search path gives priority
+to a directory that contains programs from such a source, you should
+expect multiple failures due to missing features, etc. with
+"make check-install".
 
 Netpbm distributed with Debian or Ubuntu is called "Netpbm-Free" and
 is based on a fork which broke off in 2002.  There are many differences.
 Many tests will fail.  However, the test framework itself is valid for
-these distributions.
+these distributions.  The following procedure will allow you to run
+the tests on installed Netpbm programs, regardless of the version:
 
+   ./configure           # accept the defaults
+   make check-install
 
 
 2.5 System dependent issues
@@ -294,6 +353,7 @@ is the one from glibc and skips certain tests if a different one is
 detected.
 
 
+
 3. Reporting test failures
 ==========================
 
diff --git a/doc/patent_summary b/doc/patent_summary
index 324fec0d..b9623d09 100644
--- a/doc/patent_summary
+++ b/doc/patent_summary
@@ -60,8 +60,8 @@ http://burnalljpegs.org contains information on this issue.
 MPEG patents
 ------------
 
-The original University of California distributeion of the Ppmtompeg code
-conatins this statement in a README file:
+The original University of California distribution of the Ppmtompeg code
+contains this statement in a README file:
 
   ... patents are held by several companies on various aspects of the MPEG
   video standard.  Companies or individuals who want to develop commercial
diff --git a/editor/pamenlarge.c b/editor/pamenlarge.c
index dd61f2cf..187bfb6e 100644
--- a/editor/pamenlarge.c
+++ b/editor/pamenlarge.c
@@ -312,11 +312,8 @@ enlargePbm(struct pam * const inpamP,
         pbm_readpbmrow_packed(inpamP->file, inrow, inpamP->width,
                               inpamP->format);
 
-        if (outcols % 8 > 0) {
-            /* clean final partial byte */ 
-            inrow[inColChars-1] >>= 8 - inpamP->width % 8;
-            inrow[inColChars-1] <<= 8 - inpamP->width % 8;
-        }
+        if (outcols % 8 > 0)           /* clean final partial byte */ 
+            pbm_cleanrowend_packed(inrow, inpamP->width);
 
         enlargePbmRowHorizontally(inpamP, inrow, inColChars, outColChars,
                                   scaleFactor, outrow);
diff --git a/editor/pamscale.c b/editor/pamscale.c
index 48b0f8dd..7c6ee256 100644
--- a/editor/pamscale.c
+++ b/editor/pamscale.c
@@ -411,7 +411,7 @@ enum scaleType {SCALE_SEPARATE, SCALE_BOXFIT, SCALE_BOXFILL, SCALE_PIXELMAX};
        size.
     */
 
-struct cmdlineInfo {
+struct CmdlineInfo {
     /* All the information the user supplied in the command line,
      * in a form easy for the program to use.
      */
@@ -484,7 +484,7 @@ processFilterOptions(unsigned int const         filterSpec,
                      const char                 filterOpt[],
                      unsigned int const         windowSpec,
                      const char                 windowOpt[],
-                     struct cmdlineInfo * const cmdlineP) {
+                     struct CmdlineInfo * const cmdlineP) {
 
     if (filterSpec) {
         filter baseFilter;
@@ -544,7 +544,7 @@ parseSizeParm(const char *   const sizeString,
 static void
 parseXyParms(int                  const argc, 
              const char **        const argv,
-             struct cmdlineInfo * const cmdlineP) {
+             struct CmdlineInfo * const cmdlineP) {
 
     /* parameters are box width (columns), box height (rows), and
        optional filespec 
@@ -573,7 +573,7 @@ parseXyParms(int                  const argc,
 static void
 parseScaleParms(int                   const argc, 
                 const char **         const argv,
-                struct cmdlineInfo  * const cmdlineP) {
+                struct CmdlineInfo  * const cmdlineP) {
 /*----------------------------------------------------------------------------
    Parse the parameters as a scale factor and optional filespec
    (e.g. 'pamscale .5' or 'pamscale .5 testimg.ppm').
@@ -608,7 +608,7 @@ parseScaleParms(int                   const argc,
 static void
 parseFilespecOnlyParms(int                   const argc, 
                        const char **         const argv,
-                       struct cmdlineInfo  * const cmdlineP) {
+                       struct CmdlineInfo  * const cmdlineP) {
 
     /* Only parameter allowed is optional filespec */
     if (argc-1 < 1)
@@ -621,7 +621,7 @@ parseFilespecOnlyParms(int                   const argc,
 static void 
 parseCommandLine(int argc, 
                  const char ** argv, 
-                 struct cmdlineInfo  * const cmdlineP) {
+                 struct CmdlineInfo  * const cmdlineP) {
 /* --------------------------------------------------------------------------
    Parse program command line described in Unix standard form by argc
    and argv.  Return the information in the options as *cmdlineP.  
@@ -747,7 +747,7 @@ parseCommandLine(int argc,
 
 
 static void 
-computeOutputDimensions(struct cmdlineInfo  const cmdline, 
+computeOutputDimensions(struct CmdlineInfo  const cmdline, 
                         unsigned int        const cols, 
                         unsigned int        const rows, 
                         int *               const newcolsP,
@@ -2139,7 +2139,7 @@ scaleWithoutMixing(const struct pam * const inpamP,
 static void
 pamscale(FILE *             const ifP,
          FILE *             const ofP,
-         struct cmdlineInfo const cmdline) {
+         struct CmdlineInfo const cmdline) {
     
     struct pam inpam, outpam;
     float xscale, yscale;
@@ -2203,7 +2203,7 @@ pamscale(FILE *             const ifP,
 int
 main(int argc, const char **argv ) {
 
-    struct cmdlineInfo cmdline;
+    struct CmdlineInfo cmdline;
     FILE * ifP;
     int eof;
 
diff --git a/editor/pbmclean.c b/editor/pbmclean.c
index 6d813090..46e7dee6 100644
--- a/editor/pbmclean.c
+++ b/editor/pbmclean.c
@@ -361,10 +361,8 @@ setupInputBuffers(FILE *       const ifP,
 
     pbm_readpbmrow_packed(ifP, nextRow, cols, format);
 
-    if (cols % 8 > 0){
-        nextRow[pbm_packed_bytes(cols) -1 ] >>= (8 - cols % 8);
-        nextRow[pbm_packed_bytes(cols) -1 ] <<= (8 - cols % 8);
-    }
+    pbm_cleanrowend_packed(nextRow, cols);
+
     *bufferP  = buffer;
     *edgeRowP = edgeRow;
     *thisRowP = &edgeRow[1];
@@ -418,10 +416,8 @@ cleanSimple(FILE *             const ifP,
                handling of the initial edgerow.
             */
             pbm_readpbmrow_packed(ifP, nextRow, cols, format);
-            if (cols % 8 > 0){
-                nextRow[pbm_packed_bytes(cols) -1 ] >>= (8 - cols % 8);
-                nextRow[pbm_packed_bytes(cols) -1 ] <<= (8 - cols % 8);
-            }
+            pbm_cleanrowend_packed(nextRow, cols);
+
         } else  /* Bottom of image.  */
             nextRow = &edgeRow[1];
 
diff --git a/editor/pbmpscale.c b/editor/pbmpscale.c
index 15302c56..9ab89350 100644
--- a/editor/pbmpscale.c
+++ b/editor/pbmpscale.c
@@ -412,11 +412,7 @@ main(int argc, const char ** argv) {
     /* Read the top line into nextrow and clean the right end. */
 
     pbm_readpbmrow_packed(ifP, nextrow, cols, format);
-
-    if (cols % 8 > 0) {
-        nextrow[pbm_packed_bytes(cols) - 1] >>= (8 - cols % 8);
-        nextrow[pbm_packed_bytes(cols) - 1] <<= (8 - cols % 8);
-    }
+    pbm_cleanrowend_packed(nextrow, cols);
 
     outrow = pbm_allocrow_packed(outcols);
     for (i = 0; i < pbm_packed_bytes(outcols); ++i)
@@ -440,10 +436,7 @@ main(int argc, const char ** argv) {
                This provision is for proper handling of the initial edgerow.
             */
             pbm_readpbmrow_packed(ifP, nextrow, cols, format);
-            if (cols % 8 > 0) {
-                nextrow[pbm_packed_bytes(cols) - 1] >>= (8 - cols % 8);
-                nextrow[pbm_packed_bytes(cols) - 1] <<= (8 - cols % 8);
-            }
+            pbm_cleanrowend_packed(nextrow, cols);
         } else
             /* Bottom of image.  */
             nextrow = edgerow;
diff --git a/editor/pnminvert.c b/editor/pnminvert.c
index ceb1ef81..4bee8837 100644
--- a/editor/pnminvert.c
+++ b/editor/pnminvert.c
@@ -50,11 +50,8 @@ invertPbm(FILE * const ifP,
         for (colChar = 0; colChar < colChars; ++colChar)
             bitrow[colChar] = ~ bitrow[colChar];
         
-        /* Clean off remainder of fractional last character */
-        if (cols % CHARBITS > 0) {
-            bitrow[colChars-1] >>= CHARBITS - cols % CHARBITS;
-            bitrow[colChars-1] <<= CHARBITS - cols % CHARBITS;
-        }
+        /* Clean off remainder of fractional last character and write */
+        pbm_cleanrowend_packed(bitrow, cols);
         pbm_writepbmrow_packed(ofP, bitrow, cols, 0);
     }
     pbm_freerow_packed(bitrow);
diff --git a/generator/pamstereogram.c b/generator/pamstereogram.c
index 15cf1a2c..6e5f5ce0 100644
--- a/generator/pamstereogram.c
+++ b/generator/pamstereogram.c
@@ -8,12 +8,15 @@
  * The core of this program is a simple adaptation of the code in
  * "Displaying 3D Images: Algorithms for Single Image Random Dot
  * Stereograms" by Harold W. Thimbleby, Stuart Inglis, and Ian
- * H. Witten in IEEE Computer, 27(10):38-48, October 1994.  See that
- * paper for a thorough explanation of what's going on here.
+ * H. Witten in IEEE Computer, 27(10):38-48, October 1994 plus some
+ * enhancements presented in "Stereograms: Technical Details" by
+ * W. A. Steer at http://www.techmind.org/stereo/stech.html.  See
+ * those references for a thorough explanation of what's going on
+ * here.
  *
  * ----------------------------------------------------------------------
  *
- * Copyright (C) 2006-2012 Scott Pakin <scott+pbm@pakin.org>
+ * Copyright (C) 2006-2015 Scott Pakin <scott+pbm@pakin.org>
  *
  * All rights reserved.
  *
@@ -48,6 +51,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <time.h>
+#include <limits.h>
 #include <assert.h>
 
 #include "pm_config.h"
@@ -79,8 +83,8 @@ struct cmdlineInfo {
     unsigned int guidebottom;    /* -guidebottom option count */
     unsigned int guidesize;      /* -guidesize option value */
     unsigned int magnifypat;     /* -magnifypat option */
-    unsigned int xshift;         /* -xshift option */
-    unsigned int yshift;         /* -yshift option */
+    int xshift;                  /* -xshift option */
+    int yshift;                  /* -yshift option */
     const char * patfile;        /* -patfile option.  Null if none */
     const char * texfile;        /* -texfile option.  Null if none */
     const char * bgcolor;        /* -bgcolor option */
@@ -88,6 +92,8 @@ struct cmdlineInfo {
     unsigned int randomseed;     /* -randomseed option */
     unsigned int randomseedSpec; /* -randomseed option count */
     enum outputType outputType;  /* Type of output file */
+    unsigned int xbegin;         /* -xbegin option */
+    unsigned int xbeginSpec;     /* -xbegin option count */
 };
 
 
@@ -147,7 +153,7 @@ parseCommandLine(int                  argc,
 
     unsigned int patfileSpec, texfileSpec, dpiSpec, eyesepSpec, depthSpec,
         guidesizeSpec, magnifypatSpec, xshiftSpec, yshiftSpec,
-        bgcolorSpec, smoothingSpec, planesSpec;
+      bgcolorSpec, smoothingSpec, planesSpec;
 
     unsigned int blackandwhite, grayscale, color;
     const char ** planes;
@@ -183,9 +189,9 @@ parseCommandLine(int                  argc,
             &guidesizeSpec,           0);
     OPTENT3(0, "magnifypat",      OPT_UINT,   &cmdlineP->magnifypat,
             &magnifypatSpec,          0);
-    OPTENT3(0, "xshift",          OPT_UINT,   &cmdlineP->xshift,
+    OPTENT3(0, "xshift",          OPT_INT,    &cmdlineP->xshift,
             &xshiftSpec,              0);
-    OPTENT3(0, "yshift",          OPT_UINT,   &cmdlineP->yshift,
+    OPTENT3(0, "yshift",          OPT_INT,    &cmdlineP->yshift,
             &yshiftSpec,              0);
     OPTENT3(0, "patfile",         OPT_STRING, &cmdlineP->patfile,
             &patfileSpec,             0);
@@ -199,6 +205,8 @@ parseCommandLine(int                  argc,
             &smoothingSpec,           0);
     OPTENT3(0, "planes",          OPT_STRINGLIST, &planes,
             &planesSpec,              0);
+    OPTENT3(0, "xbegin",          OPT_UINT,   &cmdlineP->xbegin,
+            &cmdlineP->xbeginSpec,    0);
 
     opt.opt_table = option_def;
     opt.short_allowed = FALSE;  /* We have no short (old-fashioned) options */
@@ -494,8 +502,8 @@ struct patternPixelState {
     /* This is the state of a patternPixel generator.*/
     struct pam   patPam;     /* Descriptor of pattern image */
     tuple **     patTuples;  /* Entire image read from the pattern file */
-    unsigned int xshift;
-    unsigned int yshift;
+    int xshift;
+    int yshift;
     unsigned int magnifypat;
 };
 
@@ -766,7 +774,7 @@ drawguides(unsigned int       const guidesize,
     unsigned int const far = separation(0, eyesep, dpi, depthOfField);
         /* Space between the two guide boxes. */
     unsigned int const width = outPamP->width;  /* Width of the output image */
-    
+
     tuple * outrow;             /* One row of output data */
     tuple blackTuple;
     unsigned int col;
@@ -774,7 +782,7 @@ drawguides(unsigned int       const guidesize,
     pnm_createBlackTuple(outPamP, &blackTuple);
 
     outrow = pnm_allocpamrow(outPamP);
-    
+
     /* Put some white rows before the guides */
     writeWhiteRows(outPamP, guidesize);
 
@@ -795,7 +803,7 @@ drawguides(unsigned int       const guidesize,
         if (far + guidesize > width) {
             pm_message("warning: the guide boxes are partially out of bounds "
                        "at %u DPI", dpi);
-            
+
             leftBeg  = 0;
             rightEnd = width;
         } else {
@@ -803,7 +811,7 @@ drawguides(unsigned int       const guidesize,
             leftBeg  = (width - far - guidesize)/2;
             rightEnd = (width + far + guidesize)/2;
         }
-        
+
         /* Draw the left guide black in the buffer */
         assert(leftEnd < outPamP->width);
         for (col = leftBeg; col < leftEnd; ++col)
@@ -829,83 +837,80 @@ drawguides(unsigned int       const guidesize,
 static void
 makeStereoRow(const struct pam * const inPamP,
               tuple *            const inRow,
-              unsigned int *     const same,
+              unsigned int *     const sameL,
+              unsigned int *     const sameR,
               double             const depthOfField,
               double             const eyesep,
               unsigned int       const dpi,
               unsigned int       const optWidth,
               unsigned int       const smoothing) {
 
-/* Do the bulk of the work.  See the paper cited above for code
- * comments.  All I (Scott) did was transcribe the code and make
- * minimal changes for Netpbm.  And some style changes by Bryan to
- * match Netpbm style.
- */ 
+/* Given a row of the depth map, compute the sameL and sameR arrays,
+ * which indicate for each pixel which pixel to its left and right it
+ * should be colored the same as.
+ */
 #define Z(X) (inRow[X][0]/(double)inPamP->maxval)
 
-    unsigned int const pixelEyesep = ROUNDU(eyesep * dpi);
-        /* Separation in pixels between the viewer's eyes */
-
     unsigned int col;
 
-    for (col = 0; col < inPamP->width; ++col)
-        same[col] = col;
+    for (col = 0; col < inPamP->width; ++col) {
+        sameL[col] = col;
+        sameR[col] = col;
+    }
 
     for (col = 0; col < inPamP->width; ++col) {
-        unsigned int const s = separation(Z(col), eyesep, dpi, depthOfField);
-
-        if (col >= s/2 && col + s/2 < inPamP->width) {
-            unsigned int left, right;
-
-            bool visible;
-            unsigned int t;
-            double zt;
-
-            left  = col - s/2;  /* initial value */
-            right = col + s/2;  /* initial value */
-            t = 1;  /* initial value */
-
-            do {
-                double const dof = depthOfField;
-                zt = Z(col) + 2.0*(2.0 - dof*Z(col))*t/(dof*pixelEyesep);
-                assert(col >= t);
-                assert(col + t < inPamP->width);
-                visible = Z(col-t) < zt && Z(col+t) < zt;
-                ++t;
-            } while (visible && zt < 1);
-
-            if (visible) {
-                unsigned int l;
-                
-                l = same[left];
-                while (l != left && l != right) {
-                    if (l < right) {
-                        left = l;
-                        l = same[left];
-                    } else {
-                        same[left] = right;
-                        left = right;
-                        l = same[left];
-                        right = l;
-                    }
-                }
-                same[left] = right;
+        unsigned int const sep = separation(Z(col), eyesep, dpi, depthOfField);
+        int const left = col - sep/2;
+        int const right = left + sep;
+
+        if (left >= 0 && right < inPamP->width) {
+            bool isVisible;
+        
+            if (sameL[right] != right) {
+                /* Right point already linked */
+                if (sameL[right] < left) {
+                    /* Deeper than current */
+                    sameR[sameL[right]] = sameL[right];  /* Break old links. */
+                    sameL[right] = right;
+                    isVisible = TRUE;
+                } else
+                    isVisible = FALSE;
+            } else
+                isVisible = TRUE;
+
+            if (sameR[left] != left) {
+                /* Left point already linked */
+                if (sameR[left] > right) {
+                    /* Deeper than current */
+                    sameL[sameR[left]] = sameR[left];  /* Break old links. */
+                    sameR[left] = left;
+                    isVisible = TRUE;
+                } else
+                    isVisible = FALSE;
+            } else
+                isVisible = TRUE;
+
+            if (isVisible) {
+                /* Make a link. */
+                sameL[right] = left;
+                sameR[left] = right;
             }
         }
     }
 
     /* If smoothing is enabled, replace each non-duplicate pixel with
-       the pixel adjacent to its right neighbor. */
+       the pixel adjacent to its right neighbor.
+    */
     if (smoothing > 0) {
         int const baseCol = inPamP->width - optWidth - 1;
 
         int col;
 
         for (col = inPamP->width - 1; col >= 0; --col)
-            same[col] = same[same[col]];
+            sameR[col] = sameR[sameR[col]];
         for (col = baseCol; col >= 0; --col) {
-            if (same[col] == col)
-                same[col] = same[col+1] - 1;
+            if (sameR[col] == col)
+                sameR[col] = sameR[col+1] - 1;
         }
     }
 }
@@ -914,12 +919,24 @@ makeStereoRow(const struct pam * const inPamP,
 
 static void
 makeMaskRow(const struct pam *   const outPamP,
-            const unsigned int * const same,
+            unsigned int         const xbegin,
+            const unsigned int * const sameL,
+            const unsigned int * const sameR,
             const tuple *        const outRow) {
     int col;
 
-    for (col = outPamP->width-1; col >= 0; --col) {
-        bool const duplicate = (same[col] != col);
+    for (col = (int)xbegin; col < outPamP->width; ++col) {
+        bool const duplicate = (sameL[col] != col && sameL[col] >= xbegin);
+
+        unsigned int plane;
+
+        for (plane = 0; plane < outPamP->depth; ++plane)
+            outRow[col][plane] = duplicate ? outPamP->maxval : 0;
+    }
+
+    for (col = (int)xbegin - 1; col >= 0; --col) {
+        bool const duplicate = (sameR[col] != col);
+
         unsigned int plane;
 
         for (plane = 0; plane < outPamP->depth; ++plane)
@@ -1148,35 +1165,65 @@ makeImageRowMts(outGenerator *       const outGenP,
 static void
 makeImageRow(outGenerator *       const outGenP,
              unsigned int         const row,
-             const unsigned int * const same,
+             unsigned int         const optWidth,
+             unsigned int         const xbegin,
+             const unsigned int * const sameL,
+             const unsigned int * const sameR,
              const tuple *        const outRow) {
 /*----------------------------------------------------------------------------
-  same[N] is one of two things:
+  sameR[N] is one of two things:
+
+  sameR[N] == N means to generate a value for Column N independent of
+  other columns in the row.
+
+  sameR[N] > N means Column N should be identical to Column sameR[N].
+
+  sameR[N] < N is not allowed.
+
+  sameL[N] is one of two things:
 
-  same[N] == N means to generate a value for Column N independent of
+  sameL[N] == N means to generate a value for Column N independent of
   other columns in the row.
 
-  same[N] > N means Column N should be identical to Column same[N].
+  sameL[N] < N means Column N should be identical to Column sameL[N].
 
-  same[N] < N is not allowed.
+  sameL[N] > N is not allowed.
 -----------------------------------------------------------------------------*/
     int col;
-    for (col = outGenP->pam.width-1; col >= 0; --col) {
-        bool const duplicate = (same[col] != col);
-            /* This column is a duplicate of an earlier (farther to the right)
-               column, to wit Column same[col]
-            */
+    int lastLinked;
+
+    for (col = (int)xbegin, lastLinked = INT_MIN;
+         col < outGenP->pam.width;
+         ++col) {
 
         tuple newtuple;
 
-        if (duplicate) {
-            assert(same[col] > col);
-            assert(same[col] < outGenP->pam.width);
+        if (sameL[col] == col || sameL[col] < (int)xbegin) {
+            if (lastLinked == col - 1)
+                newtuple = outRow[col - 1];
+            else
+                newtuple = outGenP->getTuple(outGenP, col, row);
+        } else {
+          newtuple = outRow[sameL[col]];
+          lastLinked = col;
+              /* Keep track of the last pixel to be constrained. */
+        }
+        pnm_assigntuple(&outGenP->pam, outRow[col], newtuple);
+    }
 
-            newtuple = outRow[same[col]];
-        } else
-            newtuple = outGenP->getTuple(outGenP, col, row);
+    for (col = (int)xbegin - 1, lastLinked = INT_MIN; col >= 0; --col) {
+        tuple newtuple;
 
+        if (sameR[col] == col) {
+            if (lastLinked == col + 1)
+                newtuple = outRow[col + 1];
+            else
+                newtuple = outGenP->getTuple(outGenP, col, row);
+        } else {
+            newtuple = outRow[sameR[col]];
+            lastLinked = col;
+                /* Keep track of the last pixel to be constrained. */
+        }
         pnm_assigntuple(&outGenP->pam, outRow[col], newtuple);
     }
 }
@@ -1204,28 +1251,36 @@ makeImageRows(const struct pam * const inPamP,
               bool               const crossEyed,
               bool               const makeMask,
               unsigned int       const magnifypat,
-              unsigned int       const smoothing) {
+              unsigned int       const smoothing,
+              unsigned int       const xbegin) {
 
     tuple * inRow;     /* One row of pixels read from the height-map file */
     tuple * outRow;    /* One row of pixels to write to the height-map file */
-    unsigned int * same;
-        /* Malloced array: same[N] is the column number of a pixel to the
+    unsigned int * sameR;
+        /* Malloced array: sameR[N] is the column number of a pixel to the
            right forced to have the same color as the one in column N
         */
-    unsigned int * sameFp;
-        /* Malloced array: Fixed point of same[] */
+    unsigned int * sameL;
+        /* Malloced array: sameL[N] is the column number of a pixel to the
+           left forced to have the same color as the one in column N
+        */
+    unsigned int * sameRfp;
+        /* Malloced array: Fixed point of sameR[] */
     tuple * rowBuffer;     /* Scratch row needed for texture manipulation */
     unsigned int row;      /* Current row in the input and output files */
 
     inRow = pnm_allocpamrow(inPamP);
     outRow = pnm_allocpamrow(&outputGeneratorP->pam);
-    MALLOCARRAY(same, inPamP->width);
-    if (same == NULL)
-        pm_error("Unable to allocate space for \"same\" array.");
-
-    MALLOCARRAY(sameFp, inPamP->width);
-    if (sameFp == NULL)
-        pm_error("Unable to allocate space for \"sameFp\" array.");
+    MALLOCARRAY(sameR, inPamP->width);
+    if (sameR == NULL)
+        pm_error("Unable to allocate space for \"sameR\" array.");
+    MALLOCARRAY(sameL, inPamP->width);
+    if (sameL == NULL)
+        pm_error("Unable to allocate space for \"sameL\" array.");
+
+    MALLOCARRAY(sameRfp, inPamP->width);
+    if (sameRfp == NULL)
+        pm_error("Unable to allocate space for \"sameRfp\" array.");
     rowBuffer = pnm_allocpamrow(&outputGeneratorP->pam);
 
     for (row = 0; row < inPamP->height; ++row) {
@@ -1237,26 +1292,29 @@ makeImageRows(const struct pam * const inPamP,
             invertHeightRow(inPamP, inRow);
 
         /* Determine color constraints. */
-        makeStereoRow(inPamP, inRow, same, depthOfField, eyesep, dpi,
+        makeStereoRow(inPamP, inRow, sameL, sameR, depthOfField, eyesep, dpi,
                       ROUNDU(eyesep * dpi)/(magnifypat * 2),
                       smoothing);
 
         if (makeMask)
-            makeMaskRow(&outputGeneratorP->pam, same, outRow);
+            makeMaskRow(&outputGeneratorP->pam, xbegin, sameL, sameR, outRow);
         else {
             if (outputGeneratorP->textureP)
-                makeImageRowMts(outputGeneratorP, row, same, sameFp,
+                makeImageRowMts(outputGeneratorP, row, sameR, sameRfp,
                                 rowBuffer, outRow);
             else
-                makeImageRow(outputGeneratorP, row, same, outRow);
+                makeImageRow(outputGeneratorP, row,
+                             ROUNDU(eyesep * dpi)/(magnifypat * 2),
+                             xbegin, sameL, sameR, outRow);
         }
         /* Write the resulting row. */
         pnm_writepamrow(&outputGeneratorP->pam, outRow);
     }
 
     pnm_freepamrow(rowBuffer);
-    free(sameFp);
-    free(same);
+    free(sameRfp);
+    free(sameL);
+    free(sameR);
     pnm_freepamrow(outRow);
     pnm_freepamrow(inRow);
 }
@@ -1270,6 +1328,8 @@ produceStereogram(FILE *             const ifP,
     struct pam inPam;    /* PAM information for the height-map file */
     outGenerator * outputGeneratorP;
         /* Handle of an object that generates background pixels */
+    unsigned int xbegin;
+        /* x coordinate separating left-to-right from right-to-left coloring */
 
     pnm_readpaminit(ifP, &inPam, PAM_STRUCT_SIZE(tuple_type));
 
@@ -1285,6 +1345,15 @@ produceStereogram(FILE *             const ifP,
 
     pnm_writepaminit(&outputGeneratorP->pam);
 
+    if (cmdline.xbeginSpec == 0)
+        xbegin = outputGeneratorP->pam.width/2;
+    else {
+        xbegin = cmdline.xbegin;
+        if (xbegin >= outputGeneratorP->pam.width)
+            pm_error("-xbegin must be less than the image width (%d)",
+                     outputGeneratorP->pam.width);
+    }
+
     if (cmdline.guidetop)
         drawguides(cmdline.guidesize, &outputGeneratorP->pam,
                    cmdline.eyesep,
@@ -1293,7 +1362,7 @@ produceStereogram(FILE *             const ifP,
     makeImageRows(&inPam, outputGeneratorP,
                   cmdline.depth, cmdline.eyesep, cmdline.dpi,
                   cmdline.crosseyed, cmdline.makemask, cmdline.magnifypat,
-                  cmdline.smoothing);
+                  cmdline.smoothing, xbegin);
 
     if (cmdline.guidebottom)
         drawguides(cmdline.guidesize, &outputGeneratorP->pam,
@@ -1332,7 +1401,7 @@ reportParameters(struct cmdlineInfo const cmdline) {
                sep1, cmdline.magnifypat, sep1 / cmdline.magnifypat);
     pm_message("Unique 3-D depth levels possible: %u", sep0 - sep1 + 1);
     if (cmdline.patfile && (cmdline.xshift || cmdline.yshift))
-        pm_message("Pattern shift: (%u, %u)", cmdline.xshift, cmdline.yshift);
+        pm_message("Pattern shift: (%d, %d)", cmdline.xshift, cmdline.yshift);
 }
 
 
diff --git a/generator/pbmmake.c b/generator/pbmmake.c
index fb47bd10..600440f0 100644
--- a/generator/pbmmake.c
+++ b/generator/pbmmake.c
@@ -101,13 +101,11 @@ writeGrayRaster(unsigned int const cols,
         bitrow1[i] = (PBM_WHITE*0x55) | (PBM_BLACK*0xaa);
         /* 0xaa = 10101010 ; 0x55 = 01010101 */
     }
-    if (cols % 8 > 0) { 
-        bitrow0[lastCol] >>= 8 - cols % 8;
-        bitrow0[lastCol] <<= 8 - cols % 8;
-        bitrow1[lastCol] >>= 8 - cols % 8;
-        bitrow1[lastCol] <<= 8 - cols % 8;
-    }
-    if (rows > 1) {
+
+    pbm_cleanrowend_packed(bitrow0, cols);
+    pbm_cleanrowend_packed(bitrow1, cols);
+
+  if (rows > 1) {
         unsigned int row;
         for (row = 1; row < rows; row += 2) {
             pbm_writepbmrow_packed(ofP, bitrow0, cols, 0);
@@ -139,11 +137,10 @@ writeSingleColorRaster(unsigned int const cols,
     for (i = 0; i <= lastCol; ++i) 
         bitrow0[i] = color*0xff;
 
-    if (cols % 8 > 0) { 
-        bitrow0[lastCol] >>= 8 - cols % 8;
-        bitrow0[lastCol] <<= 8 - cols % 8;
-        /* row end trimming, really not necessary with white */
-    }
+    if (color != 0)
+        pbm_cleanrowend_packed(bitrow0, cols);
+    /* row end trimming, not necessary with white */
+
     {
         unsigned int row;
         for (row = 0; row < rows; ++row)
diff --git a/icon/Makefile b/icon/Makefile
index 0bd33bf4..2181c88b 100644
--- a/icon/Makefile
+++ b/icon/Makefile
@@ -15,7 +15,8 @@ include $(SRCDIR)/common.mk
 
 %.o:%.ico
 	echo "id ICON \"$<\"" >rc
-	windres --input-format rc --input rc --output-format coff --output $@
+	$(WINDRES) --input-format rc --input rc --output-format coff \
+	   --output $@
 	rm rc
 
 distclean clean: cleanlocal
diff --git a/lib/Makefile b/lib/Makefile
index 19557909..fa73d194 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -25,7 +25,7 @@ else
   LIBSYSTEM = libsystem.o
 endif
 
-LIBOBJECTS = libpm.o pmfileio.o fileio.o bitio.o colorname.o \
+LIBOBJECTS = libpm.o pmfileio.o fileio.o colorname.o \
 	libpamd.o \
 	libpbm1.o libpbm2.o libpbm3.o libpbmfont.o \
 	libpgm1.o libpgm2.o \
@@ -39,6 +39,7 @@ LIBOBJECTS = libpm.o pmfileio.o fileio.o bitio.o colorname.o \
 
 # Library objects to be linked but not built by common.mk:
 LIBOBJECTS_X = \
+  util/bitio.o \
   util/filename.o \
   util/io.o \
   util/mallocvar.o \
@@ -52,7 +53,7 @@ LIBOBJECTS_X = \
 MANUALS3 = libnetpbm
 MANUALS5 = pbm pgm ppm pnm pam
 
-INTERFACE_HEADERS = bitio.h colorname.h \
+INTERFACE_HEADERS = colorname.h \
 	pam.h pamdraw.h pammap.h pbm.h pbmfont.h \
 	pgm.h pm.h pm_gamma.h pm_system.h pnm.h \
 	ppm.h ppmcmap.h ppmdfont.h ppmdraw.h ppmfloyd.h \
diff --git a/lib/libpbm2.c b/lib/libpbm2.c
index a77fa0ae..f199c51a 100644
--- a/lib/libpbm2.c
+++ b/lib/libpbm2.c
@@ -10,6 +10,7 @@
 ** implied warranty.
 */
 
+#include <assert.h>
 #include <limits.h>
 
 #include "pbm.h"
@@ -34,11 +35,9 @@ getbit (FILE * const file) {
 
 
 void
-pbm_readpbminitrest( file, colsP, rowsP )
-    FILE* file;
-    int* colsP;
-    int* rowsP;
-    {
+pbm_readpbminitrest( FILE * const file,
+                     int  * const colsP,
+                     int  * const rowsP ) {
     /* Read size. */
     *colsP = (int)pm_getuint( file );
     *rowsP = (int)pm_getuint( file );
@@ -55,7 +54,7 @@ pbm_readpbminitrest( file, colsP, rowsP )
         pm_error("Number of columns in header is too large.");
     if (*rowsP < 0)
         pm_error("Number of columns in header is too large.");
-    }
+}
 
 
 
@@ -122,32 +121,29 @@ pbm_readpbminit(FILE * const ifP,
 
 
 void
-pbm_readpbmrow( file, bitrow, cols, format )
-    FILE* file;
-    bit* bitrow;
-    int cols, format;
-    {
-    register int col, bitshift;
-    register bit* bP;
+pbm_readpbmrow( FILE * const file,
+                bit * const bitrow,
+                int const cols,
+                int const format) {
+
+    int col, bitshift;
 
     switch ( format )
     {
     case PBM_FORMAT:
-    for ( col = 0, bP = bitrow; col < cols; ++col, ++bP )
-        *bP = getbit( file );
+    for ( col = 0; col < cols; ++col )
+        bitrow[col] = getbit( file );
     break;
 
     case RPBM_FORMAT: {
-        register unsigned char item;
+        unsigned char item;
         bitshift = -1;  item = 0;  /* item's value is meaningless here */
-        for ( col = 0, bP = bitrow; col < cols; ++col, ++bP )
-          {
-              if ( bitshift == -1 )
-                {
+        for ( col = 0; col < cols; ++col ) {
+              if ( bitshift == -1 ) {
                     item = pm_getrawbyte( file );
                     bitshift = 7;
                 }
-              *bP = ( item >> bitshift ) & 1;
+              bitrow[col] = ( item >> bitshift ) & 1;
               --bitshift;
           }
     }
@@ -156,7 +152,7 @@ pbm_readpbmrow( file, bitrow, cols, format )
     default:
     pm_error( "can't happen" );
     }
-    }
+}
 
 
 
@@ -184,12 +180,12 @@ pbm_readpbmrow_packed(FILE *          const fileP,
     break;
 
     case RPBM_FORMAT: {
-        int bytes_read;
-        bytes_read = fread(packedBits, 1, pbm_packed_bytes(cols), fileP);
+        unsigned int bytesReadCt;
+        bytesReadCt = fread(packedBits, 1, pbm_packed_bytes(cols), fileP);
              
-        if (bytes_read < pbm_packed_bytes(cols)) {
+        if (bytesReadCt < pbm_packed_bytes(cols)) {
             if (feof(fileP)) 
-                if (bytes_read == 0) 
+                if (bytesReadCt == 0) 
                     pm_error("Attempt to read a raw PBM image row, but "
                              "no more rows left in file.");
                 else
@@ -201,7 +197,7 @@ pbm_readpbmrow_packed(FILE *          const fileP,
     break;
     
     default:
-        pm_error( "Internal error in pbm_readpbmrow_packed." );
+        pm_error("Internal error in pbm_readpbmrow_packed.");
     }
 }
 
@@ -262,17 +258,36 @@ pbm_readpbmrow_bitoffset(FILE *          const ifP,
 
         window[last] =  leftBits | rightBits;
     }
-} 
+}
+
+
+
+void
+pbm_cleanrowend_packed(unsigned char * const packedBits,
+                       unsigned int    const cols) {
+/*----------------------------------------------------------------------------
+  Set fractional "don't care" bits at end of row to zero.
+----------------------------------------------------------------------------*/
+    unsigned int const bitsPerChar = 8;
+
+    if (cols % bitsPerChar > 0) {
+        unsigned int const last = pbm_packed_bytes(cols) - 1;
+
+        assert(pbm_packed_bytes(cols) > 0);
+
+        packedBits[last] >>= bitsPerChar - cols % bitsPerChar;
+        packedBits[last] <<= bitsPerChar - cols % bitsPerChar;
+    }
+}
 
 
 
 bit**
-pbm_readpbm( file, colsP, rowsP )
-    FILE* file;
-    int* colsP;
-    int* rowsP;
-    {
-    register bit** bits;
+pbm_readpbm( FILE * const file,
+             int  * const colsP,
+             int  * const rowsP) {
+
+    bit ** bits;
     int format, row;
 
     pbm_readpbminit( file, colsP, rowsP, &format );
@@ -283,4 +298,4 @@ pbm_readpbm( file, colsP, rowsP )
         pbm_readpbmrow( file, bits[row], *colsP, format );
 
     return bits;
-    }
+}
diff --git a/lib/libpnm1.c b/lib/libpnm1.c
index adfacd03..db21b078 100644
--- a/lib/libpnm1.c
+++ b/lib/libpnm1.c
@@ -47,15 +47,12 @@ pnm_allocrow(unsigned int const cols) {
 
 
 void
-pnm_init( argcP, argv )
-    int* argcP;
-    char* argv[];
-    {
+pnm_init(int * const argcP, char ** const argv) {
     ppm_init( argcP, argv );
-    }
+}
 
 void
-pnm_nextimage(FILE *file, int * const eofP) {
+pnm_nextimage(FILE * const file, int * const eofP) {
     pm_nextimage(file, eofP);
 }
 
diff --git a/lib/libppm1.c b/lib/libppm1.c
index a3be5d3b..c1eb152c 100644
--- a/lib/libppm1.c
+++ b/lib/libppm1.c
@@ -49,12 +49,11 @@ ppm_allocrow(unsigned int const cols) {
 
 
 void
-ppm_init( argcP, argv )
-    int* argcP;
-    char* argv[];
-    {
+ppm_init(int * const argcP, char ** const argv) {
     pgm_init( argcP, argv );
-    }
+}
+
+
 
 void
 ppm_nextimage(FILE * const fileP, 
diff --git a/lib/pbm.h b/lib/pbm.h
index 24574d07..a29adb48 100644
--- a/lib/pbm.h
+++ b/lib/pbm.h
@@ -58,9 +58,21 @@ pbm_allocrow(unsigned int const cols);
 #define pbm_freearray_packed(packed_bits, rows) \
     pm_freearray((char **) packed_bits, rows)
 
-bit** pbm_readpbm(FILE* file, int* colsP, int* rowsP);
-void pbm_readpbminit(FILE* file, int* colsP, int* rowsP, int* formatP);
-void pbm_readpbmrow(FILE* file, bit* bitrow, int cols, int format);
+bit**
+pbm_readpbm(FILE * const file,
+            int  * const colsP,
+            int  * const rowsP);
+
+void
+pbm_readpbminit(FILE * const file,
+                int  * const colsP,
+                int  * const rowsP, int * const formatP);
+
+void
+pbm_readpbmrow(FILE * const file,
+               bit  * const bitrow,
+               int    const cols,
+               int    const format);
 
 void
 pbm_readpbmrow_packed(FILE *          const file, 
@@ -76,6 +88,10 @@ pbm_readpbmrow_bitoffset(FILE *          const fileP,
                          unsigned int    const offset);
 
 void
+pbm_cleanrowend_packed(unsigned char * const packedBits,
+                       unsigned int    const cols);
+
+void
 pbm_writepbminit(FILE * const fileP, 
                  int    const cols, 
                  int    const rows, 
diff --git a/lib/pnm.h b/lib/pnm.h
index de5f1d91..3b490552 100644
--- a/lib/pnm.h
+++ b/lib/pnm.h
@@ -37,7 +37,7 @@ pnm_init(int *   const argcP,
          char ** const argv);
 
 void
-pnm_nextimage(FILE *file, int * const eofP);
+pnm_nextimage(FILE * const file, int * const eofP);
 
 xel *
 pnm_allocrow(unsigned int const cols);
diff --git a/lib/ppm.h b/lib/ppm.h
index 7a24f926..82241b70 100644
--- a/lib/ppm.h
+++ b/lib/ppm.h
@@ -77,7 +77,7 @@ ppm_blackpixel(void) {
     return retval;
 }
 
-void ppm_init(int * argcP, char* argv[]);
+void ppm_init(int * const argcP, char ** const argv);
 
 #define ppm_allocarray(cols, rows) \
   ((pixel**) pm_allocarray(cols, rows, sizeof(pixel)))
diff --git a/lib/util/Makefile b/lib/util/Makefile
index 28dfddfe..c8522a04 100644
--- a/lib/util/Makefile
+++ b/lib/util/Makefile
@@ -12,6 +12,7 @@ include $(BUILDDIR)/config.mk
 # nstring is required for asprintf(), etc.  Also some systems don't have
 # snprintf(), e.g. Solaris 2.5.1.  2002.03.29.
 UTILOBJECTS = \
+  bitio.o \
   filename.o \
   io.o \
   mallocvar.o \
diff --git a/lib/bitio.c b/lib/util/bitio.c
index ca1b55f9..ca1b55f9 100644
--- a/lib/bitio.c
+++ b/lib/util/bitio.c
diff --git a/lib/bitio.h b/lib/util/bitio.h
index dfc5a153..dfc5a153 100644
--- a/lib/bitio.h
+++ b/lib/util/bitio.h
diff --git a/lib/util/nstring.c b/lib/util/nstring.c
index 039c2b3b..711cfca9 100644
--- a/lib/util/nstring.c
+++ b/lib/util/nstring.c
@@ -897,49 +897,59 @@ pm_stripeq(const char * const comparand,
 
   Return 1 (true) if the strings are identical; 0 (false) otherwise.
 -----------------------------------------------------------------------------*/
-    char *p, *q, *px, *qx;
-    char equal;
+    const char * p;
+    const char * q;
+    const char * px;
+    const char * qx;
+    bool equal;
   
     /* Make p and q point to the first non-blank character in each string.
-     If there are no non-blank characters, make them point to the terminating
-     NULL.
-     */
+       If there are no non-blank characters, make them point to the terminating
+       NUL.
+    */
 
-    p = (char *) comparand;
-    while (ISSPACE(*p)) p++;
-    q = (char *) comparator;
-    while (ISSPACE(*q)) q++;
+    p = &comparand[0];
+    while (ISSPACE(*p))
+        p++;
+    q = &comparator[0];
+    while (ISSPACE(*q))
+        q++;
 
     /* Make px and qx point to the last non-blank character in each string.
        If there are no nonblank characters (which implies the string is
-       null), make them point to the terminating NULL.
+       null), make them point to the terminating NUL.
     */
 
-    if (*p == '\0') px = p;
+    if (*p == '\0')
+        px = p;
     else {
         px = p + strlen(p) - 1;
-        while (ISSPACE(*px)) px--;
+        while (ISSPACE(*px))
+            --px;
     }
 
-    if (*q == '\0') qx = q;
+    if (*q == '\0')
+        qx = q;
     else {
         qx = q + strlen(q) - 1;
-        while (ISSPACE(*qx)) qx--;
+        while (ISSPACE(*qx))
+            --qx;
     }
 
-    equal = 1;   /* initial assumption */
-  
-    /* If the stripped strings aren't the same length, 
-       we know they aren't equal 
-     */
-    if (px - p != qx - q) equal = 0;
-
-    else
-    while (p <= px) {
-        if (*p != *q) equal = 0;
-        p++; q++;
+    if (px - p != qx - q) {
+        /* The stripped strings aren't the same length, so we know they aren't
+           equal.
+        */
+        equal = false;
+    } else {
+        /* Move p and q through the nonblank characters, comparing. */
+        for (equal = true; p <= px; ++p, ++q) {
+            assert(q <= qx);  /* Because stripped strings are same length */
+            if (*p != *q)
+                equal = false;
+        }
     }
-    return equal;
+    return equal ? 1 : 0;
 }
 
 
diff --git a/test/411toppm.test b/test/411toppm.test
index 335cdcc8..98170c67 100755
--- a/test/411toppm.test
+++ b/test/411toppm.test
@@ -1,9 +1,7 @@
 #! /bin/bash
 # This script tests: 411toppm
-# Also requires: 
+# Also requires:
 
-  alias 411toppm="${PBM_TESTPREFIX}411toppm"
-  shopt -s expand_aliases
 
 # Test 1. should produce: 240376509 9229
 # The above value is what 411toppm has been always producing.
diff --git a/test/BLOCK b/test/BLOCK
new file mode 100644
index 00000000..f928dc09
--- /dev/null
+++ b/test/BLOCK
@@ -0,0 +1,4 @@
+#! /bin/sh
+
+echo `basename $0` : command not found in test path 1>&2
+exit 88
diff --git a/test/Execute-Tests b/test/Execute-Tests
index 68dd5581..78091e6b 100755
--- a/test/Execute-Tests
+++ b/test/Execute-Tests
@@ -1,43 +1,49 @@
 #! /bin/bash
 
-# Confirm that PBM_TESTPREFIX is set.
-# PBM_TESTPREFIX is the directory with the Netpbm programs you want to
-# test.  If set to null, executables will be sought from the default
-# execution path ($PATH).  Usually you should explicitly set this.
+# See if PBM_TEST_PATH is set.
+# PBM_TEST_PATH is the list of directories with the Netpbm programs
+# you want to test.
+#
+# (1) check-tree: set to a long list of directories which contain
+# the relevant executables.
+#
+# (2) check-package: set to the [package]/bin directory.
+# 
+# (3) check-install: empty string.  Executables will be sought from
+# the default execution path ($PATH).
 #
 # You can set it here by de-commenting and modifying the next line:
-#export PBM_TESTPREFIX="/usr/local/bin/"
+#export PBM_TEST_PATH="/usr/local/bin/"
 
-if [ -z $PBM_TESTPREFIX ]
+case ${CHECK_TYPE} in
+tree)
+    echo
+    echo "Checking programs in source tree" ;;
+package)  if [ -z $PBM_TEST_PATH ]
   then
-  echo "Warning: PBM_TESTPREFIX is not set."
+    echo "Error: PBM_TEST_PATH is not set."
+    exit 1
+  elif [ ! -d $PBM_TEST_PATH ]
+    then
+    echo
+    echo "Error: No directory named $PBM_TEST_PATH."
+    echo
+    echo "You must run \"make package\" before this test."
+    echo
+    echo "If you specified the package directory for \"make package\""
+    echo "you must do the same for \"make check\"."
+    echo
+  exit 1
+  fi ;;
+install)
+  echo
   echo "Programs in the default execution path:"
   echo $PATH
-  echo "will be tested."
-elif [ ! -d $PBM_TESTPREFIX ]
-  then
-  echo "Error: No directory named $PBM_TESTPREFIX"
-  exit 1
-else
-  # append "/" to end of string if necessary
-  export PBM_TESTPREFIX=$(echo $PBM_TESTPREFIX | sed '/\/$/!s@$@/@')
-fi
-
-# Set PBM_BINPREFIX.
-# PBM_BINPREFIX is the directory where Netpbm programs which play
-# auxiliary roles in tests (such as image generators for producing
-# test images, analyzers to summarize output and so forth).
-#
-# If testing a fresh install, this should be the same as PBM_TESTPREFIX.
-# If you are developing a single Netpbm program, you may want to
-# set this to a directory with stable executables.  (Final "/" is
-# mandatory.)
-# If set to null, executables in the default execution path will
-# be used.
-
-# export PBM_BINPREFIX="/usr/local/bin/"
-# export PBM_BINPREFIX=""
-export PBM_BINPREFIX=${PBM_TESTPREFIX}
+  echo "will be tested." ;;
+*)
+  echo "Invalid test type: ${CHECK_TYPE}"
+  exit 1 ;;
+esac
 
 # Set srcdir, which is the directory which contains Execute-Tests (this
 # script), programs that run the test, including *.test and helpers that they
@@ -46,9 +52,6 @@ export PBM_BINPREFIX=${PBM_TESTPREFIX}
 
 srcdir=$(dirname $0)
 
-# Provision to run programs under valgrind.
-# export PBM_TESTPREFIX="valgrind --log-fd=4 "${PBM_TESTPREFIX}
-
 # Set tmpdir, which is used in some of the test scripts.  By default
 # this is created by mktemp.  The user can override and specify tmpdir,
 # but in this case it must be an existing directory and must not be
@@ -56,7 +59,7 @@ srcdir=$(dirname $0)
 
 if [ -z $tmpdir ]
   then
-    tmpdir_created=$(mktemp -d) || exit 1;
+    tmpdir_created=$(mktemp -d "${TMPDIR:-/tmp}/netpbm.XXXXXXXX") || exit 1;
   export tmpdir=${tmpdir_created}
   else
   tmpdir_created="";
@@ -72,19 +75,29 @@ if [ -z $tmpdir ]
   fi
 fi
 
-
 # If necessary set the RGBDEF environment variable.
 #export RGBDEF=/etc/rgb.txt
 #export RGBDEF=/usr/local/netpbm/lib/rgb.txt
 #export RGBDEF=/usr/share/emacs/*/etc/rgb.txt
 
+
 # Declare arrays used to count and report test results.
-# For now only "SUCCESS" and "FAILURE" are used.
-declare -a array=(0 0 0 0 0 0)
-declare -a status=("SUCCESS" "FAILURE" "UNEXPECTED SUCCESS"
-                   "EXPECTED FAILURE" "NOT TESTABLE" "TOTAL TESTABLE")
+# "UNEXPECTED SUCCESS" and "EXPECTED FAILURE" are not used now;
+# they are reserved for future expansion.
+declare -a array=(0 0 0 0 0)
+
+# Older versions of bash get confused when array elements contain
+# spaces.
+
+status[0]="SUCCESS"
+status[1]="FAILURE"
+status[2]="UNEXPECTED SUCCESS"
+status[3]="EXPECTED FAILURE"
+status[4]="NOT TESTABLE"
+
+
 
-# Copy test files to the current work directory
+# Copy test image files to the current work directory
 
 if [ ! -f ./testgrid.pbm ]
   then cp -v ${srcdir}/testgrid.pbm ./testgrid.pbm
@@ -94,15 +107,45 @@ if [ ! -f ./testimg.ppm ]
   then cp -v ${srcdir}/testimg.ppm  ./testimg.ppm 
 fi
 
-# Add PBM_BINPREFIX to PATH.
-# This is necessary for Netpbm programs that call other Netpbm programs.
+# The block-bin directory
+#
+# This directory contains dummy executables with the names of the
+# Netpbm programs that are to be tested.  These dummy executables
+# exist to prevent execution of programs (typically from a previous
+# installation of Netpbm) in the default path during the tests.
+# They report error when accessed and nothing else.
+# The directory is placed in PATH between PBM_TEST_PATH and
+# default PATH.
+
+# Create block-bin.  If it already exists, erase and create anew.
 
-if [ ! -z $PBM_BINPREFIX ]
+if [ ! -z $PBM_TEST_PATH ]
   then
-  export PATH=${PBM_BINPREFIX}:$PATH
+  blockbin=$PWD/block-bin
+  if [ -d  $blockbin ]
+    then rm -rf $blockbin
+  fi
+  mkdir $blockbin
+  cp ${srcdir}/BLOCK $blockbin/BLOCK
+  chmod +x $blockbin/BLOCK
+
+# Populate the block-bin directory using all-in-place.ok and
+# legacy-names.ok which together make a complete list of programs.
+
+  sed 's/: ok$//' \
+       ${srcdir}/all-in-place.ok ${srcdir}/legacy-names.ok | \
+     tr ' ' '\n' | while read prog
+    do
+    ln -s $blockbin/BLOCK $blockbin/$prog
+    done
+
+  testpath=$PBM_TEST_PATH:$blockbin:$PATH:$BUILDDIR/test
+else
+# We don't need block-bin when testing after installation.
+  testpath=$PATH:$BUILDDIR/test
 fi
 
-export PATH=${srcdir}:$PATH
+
 
 # Execute the tests, as described in the "Test-Order" file.
 #
@@ -118,7 +161,42 @@ export PATH=${srcdir}:$PATH
 # By default the tests are executed in the order described in the
 # file Test-Order.  Copy this file from the source directory
 # to the work directory.
+
+
+# Provision for running programs under valgrind.
+# Note that valgrind tests consume time.
 #
+# Output from valgrind must be redirected in some manner because some
+# tests examine standard error (fd2) output.  Here we use --log-file.
+# (See below)
+
+if [ -z $VALGRIND_TESTS ]
+  then VALGRIND_TESTS="off";
+elif [ $VALGRIND_TESTS = "on" ]
+  then
+  valdir=$PWD/valgrind;
+  mkdir $valdir
+ 
+  vg_command_base="valgrind --trace-children=yes";
+
+  for i in awk cat cksum cmp cp cut date dirname egrep fgrep file grep gs \
+    head mkdir mktemp perl rm sed seq sh tee testrandom tr uniq
+
+    # Tell valgrind not to probe execution of the above programs.
+
+    do vg_skip=$vg_skip"/*/"$i","; done;
+
+  vg_command_base=$vg_command_base" --trace-children-skip="$vg_skip;
+  #
+  # If using an older version of valgrind (< v.3.6) that does not
+  # support --trace-children-skip=... , comment out the above line
+  # and let valgrind probe execution of all programs listed above.
+  # This greatly increases execution time.
+
+fi
+
+
+# Provision for running only chosen tests.
 # The string "target" is a comma-separated list of target programs.
 # When set only tests for programs in the list will be run.
 # 
@@ -126,43 +204,65 @@ export PATH=${srcdir}:$PATH
 # (pared-down) version of Test-Order.
 
 if [ ! -z $target ]
-  then echo $target | sed 's/,/\n/g' | \
-                       sed 's/^/\${PBM_TESTPREFIX}/' | \
-                       grep -f - ${srcdir}/*.test -l | \
-                       while read i ; do echo ${i##*/} ; done | 
-                       grep -f - ${srcdir}/Test-Order > ./Test-Order ; 
-  else 
+  then
+  echo $target | sed 's/,/\n/g' | \
+                 sed -e 's/^/# This script tests: .*\\</' -e 's/$/\\>/' \
+                     -e '/^$/q' | \
+                 grep -f - ${srcdir}/*.test -l | \
+                   while read i ; do echo ${i##*/} ; done | \
+                 grep -f - ${srcdir}/Test-Order > ./Test-Order ;
+  if [ ! -s ./Test-Order ]
+    then echo;
+         echo "Error: No testable program names in target: "$target;
+         echo; exit 1
+  fi
+else 
        cp ${srcdir}/Test-Order ./Test-Order ;
        #cp --no-clobber ${srcdir}/Test-Order ./Test-Order ;
 fi
 
-#let array[5]=0
+echo
 
-for t in `grep -v "^#" ./Test-Order | fgrep ".test"`
+for tname in `grep -v "^#" ./Test-Order | fgrep ".test"`
 do
-echo == $t ==
-${srcdir}/$t >  ${t%.test}.out ; let result=$?
+echo == $tname ==
+
+# If running tests under valgrind, complete vg_command by prepending
+# the valgrind output file, which is test-specific.
+  
+if [ $VALGRIND_TESTS = "on" ]
+  then
+  vg_command="$vg_command_base --log-file=${valdir}/${tname%.test}.%p.vout"
+fi
+
+# Execute a single test and test its result.
+
+PATH=${testpath} $vg_command ${srcdir}/$tname > ${tname%.test}.out;
+let result=$?
 case $result in
-0)   cmp -s ${t%.test}.out ${srcdir}/${t%.test}.ok ;
+0)   cmp -s ${tname%.test}.out ${srcdir}/${tname%.test}.ok ;
      if [ $? -eq 0 ]
-        then let result=0;  rm  ${t%.test}.out ;
+        then let result=0;  rm  ${tname%.test}.out ;
         else let result=1;
-             grep "^##" ${srcdir}/$t   # Print failure message.
-     fi
-     let testable=1 ;;
-80) let result=4 ; let testable=0;;
-*)  let result=1 ; let testable=1;;
+             grep "^##" ${srcdir}/$tname  # Print failure message.
+     fi ;;
+80) let result=4 ;;
+*)  let result=1 ;;
 esac
 
 # Report whether a single test succeeded or failed.
 # Increment counters.
 
-echo $t: ${status[${result}]}; echo
+echo $tname: ${status[${result}]}; echo
 let array[${result}]=${array[${result}]}+1
-let array[5]=${array[5]}+$testable
+let total_scripts=${total_scripts}+1
 
 done
 
+# Erase temporary bin directory and its contents.
+
+rm -rf ${srcdir}/bin
+
 
 # Erase temporary directory and its contents, if it was created.
 
@@ -185,21 +285,24 @@ fi
 echo "Test summary:"
 echo ==================
 
-for s in 0 1 2 3 4 5
+for s in 0 1 2 3 4
   do
-    if [[ ${array[${s}]} -gt 0 || s -eq 1 || s -eq 5 ]]
+    if [[ ${array[${s}]} -gt 0 || s -eq 1 ]]
     then echo ${status[${s}]} ${array[${s}]}
     fi
   done
 
+let total_testable=${total_scripts}-${array[4]}
+echo "TOTAL TESTABLE" $total_testable
+
 echo ==================
 echo "All tests done."
-date -R -u
+date -u +"%a, %d %b %Y %H:%M:%S %z"
 
 
 # Exit with status 0 if all possible tests succeeded, 1 otherwise.
 
-if [[ ${array[0]} -eq ${array[5]} ]]
+if [[ ${array[0]} -eq ${total_testable} ]]
 then exit 0
 else exit 1
 fi
diff --git a/test/Makefile b/test/Makefile
index 4d44285f..9b7ab047 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -12,8 +12,12 @@ PROGS = testrandom
 
 all: $(PROGS)
 
-PORTBINARIES = testrandom
-OBJECTS = $(PORTBINARIES:%=%.o)
+testrandom.o: testrandom.c
+	$(CC_FOR_BUILD) -c -o $@ $(CFLAGS_FOR_BUILD) $<
+
+testrandom: testrandom.o
+	$(LD_FOR_BUILD) -o $@ $(LDFLAGS_FOR_BUILD) $<
+
 
 OMIT_TEST_RULE = 1
 include $(SRCDIR)/common.mk
diff --git a/test/Test-Order b/test/Test-Order
index 3ab897ca..d21b9e8a 100644
--- a/test/Test-Order
+++ b/test/Test-Order
@@ -1,6 +1,7 @@
 # General test
 
 all-in-place.test
+legacy-names.test
 
 # Generator tests
 
@@ -102,6 +103,7 @@ pamslice-roundtrip.test
 
 # Round-trip tests : lossless converters
 
+ppmtoarbtxt-roundtrip.test
 atari-roundtrip.test
 atk-roundtrip.test
 avs-roundtrip.test
@@ -115,8 +117,10 @@ gem-roundtrip.test
 gif-roundtrip.test
 gif-quant-roundtrip.test
 hdiff-roundtrip.test
+ilbm-roundtrip.test
 jbig-roundtrip.test
 leaf-roundtrip.test
+macp-roundtrip.test
 mda-roundtrip.test
 mgr-roundtrip.test
 mrf-roundtrip.test
@@ -138,6 +142,7 @@ wbmp-roundtrip.test
 winicon-roundtrip.test
 xbm-roundtrip.test
 xpm-roundtrip.test
+xv-roundtrip.test
 xwd-roundtrip.test
 
 # Round-trip tests : lossy converter
diff --git a/test/all-in-place.ok b/test/all-in-place.ok
index 63a0f232..c58eb024 100644
--- a/test/all-in-place.ok
+++ b/test/all-in-place.ok
@@ -4,7 +4,6 @@ atktopbm: ok
 avstopam: ok
 bioradtopgm: ok
 bmptopnm: ok
-bmptoppm: ok
 brushtopbm: ok
 cameratopam: ok
 cistopbm: ok
@@ -15,13 +14,11 @@ eyuvtoppm: ok
 fitstopnm: ok
 fstopgm: ok
 g3topbm: ok
-gemtopbm: ok
 gemtopnm: ok
 giftopnm: ok
 gouldtoppm: ok
 hdifftopam: ok
 hipstopgm: ok
-icontopbm: ok
 ilbmtoppm: ok
 imgtoppm: ok
 infotopam: ok
@@ -43,6 +40,7 @@ pambackground: ok
 pambayer: ok
 pamchannel: ok
 pamcomp: ok
+pamcrater: ok
 pamcut: ok
 pamdeinterlace: ok
 pamdepth: ok
@@ -53,7 +51,7 @@ pamendian: ok
 pamenlarge: ok
 pamexec: ok
 pamfile: ok
-pamfixtrunc: ok
+pamfix: ok
 pamflip: ok
 pamfunc: ok
 pamgauss: ok
@@ -72,6 +70,7 @@ pamrgbatopng: ok
 pamrubber: ok
 pamscale: ok
 pamseq: ok
+pamshadedrelief: ok
 pamsharpmap: ok
 pamsharpness: ok
 pamsistoaglyph: ok
@@ -105,6 +104,7 @@ pamtouil: ok
 pamtowinicon: ok
 pamtoxvmini: ok
 pamundice: ok
+pamvalidate: ok
 pamwipeout: ok
 pamx: ok
 pbmclean: ok
@@ -132,7 +132,6 @@ pbmtog3: ok
 pbmtogem: ok
 pbmtogo: ok
 pbmtoibm23xx: ok
-pbmtoicon: ok
 pbmtolj: ok
 pbmtoln03: ok
 pbmtolps: ok
@@ -161,9 +160,7 @@ pdbimgtopam: ok
 pfmtopam: ok
 pgmabel: ok
 pgmbentley: ok
-pamcrater: ok
 pgmdeshadow: ok
-pgmedge: ok
 pgmenhance: ok
 pgmhist: ok
 pgmkernel: ok
@@ -172,10 +169,7 @@ pgmmedian: ok
 pgmminkowski: ok
 pgmmorphconv: ok
 pgmnoise: ok
-pgmnorm: ok
-pgmoil: ok
 pgmramp: ok
-pgmslice: ok
 pgmtexture: ok
 pgmtofs: ok
 pgmtolispm: ok
@@ -190,24 +184,15 @@ picttoppm: ok
 pjtoppm: ok
 pktopbm: ok
 pngtopam: ok
-pngtopnm: ok
 pnmalias: ok
-pnmarith: ok
 pnmcat: ok
 pnmcolormap: ok
-pnmcomp: ok
 pnmconvol: ok
 pnmcrop: ok
-pnmcut: ok
-pnmdepth: ok
-pnmenlarge: ok
-pnmfile: ok
-pnmflip: ok
 pnmgamma: ok
 pnmhisteq: ok
 pnmhistmap: ok
 pnmindex: ok
-pnminterp: ok
 pnminvert: ok
 pnmmercator: ok
 pnmmontage: ok
@@ -218,28 +203,23 @@ pnmpaste: ok
 pnmpsnr: ok
 pnmremap: ok
 pnmrotate: ok
-pnmscale: ok
 pnmscalefixed: ok
 pnmshear: ok
 pnmsmooth: ok
-pnmsplit: ok
 pnmstitch: ok
 pnmtile: ok
 pnmtoddif: ok
 pnmtofiasco: ok
-pnmtofits: ok
 pnmtojbig: ok
 pnmtojpeg: ok
 pnmtopalm: ok
 pnmtopclxl: ok
 pnmtopng: ok
-pnmtopnm: ok
 pnmtops: ok
 pnmtorast: ok
 pnmtorle: ok
 pnmtosgi: ok
 pnmtosir: ok
-pnmtotiff: ok
 pnmtotiffcmyk: ok
 pnmtoxwd: ok
 ppm3d: ok
@@ -262,7 +242,6 @@ ppmhist: ok
 ppmlabel: ok
 ppmmake: ok
 ppmmix: ok
-ppmnorm: ok
 ppmntsc: ok
 ppmpat: ok
 ppmrelief: ok
@@ -275,14 +254,11 @@ ppmtoarbtxt: ok
 ppmtoascii: ok
 ppmtobmp: ok
 ppmtoeyuv: ok
-ppmtogif: ok
 ppmtoicr: ok
 ppmtoilbm: ok
-ppmtojpeg: ok
 ppmtoleaf: ok
 ppmtolj: ok
 ppmtomitsu: ok
-ppmtompeg: ok
 ppmtoneo: ok
 ppmtopcx: ok
 ppmtopgm: ok
@@ -296,7 +272,6 @@ ppmtorgb3: ok
 ppmtosixel: ok
 ppmtospu: ok
 ppmtoterm: ok
-ppmtouil: ok
 ppmtowinicon: ok
 ppmtoxpm: ok
 ppmtoyuv: ok
@@ -343,15 +318,10 @@ fiascotopnm: ok
 manweb: ok
 pnmmargin: ok
 anytopnm: ok
-pbmtox10bm: ok
-pnmnoraw: ok
-pnmtoplainpnm: ok
 ppmtomap: ok
 ppmshadow: ok
 pnmquant: ok
 pnmquantall: ok
-ppmquant: ok
-ppmquantall: ok
 ppmrainbow: ok
 ppmfade: ok
 pamstretch-gen: ok
diff --git a/test/all-in-place.test b/test/all-in-place.test
index d307459a..79459f7a 100755
--- a/test/all-in-place.test
+++ b/test/all-in-place.test
@@ -3,6 +3,7 @@
 
 # We test by actually running all the executables.
 
+# Failure message
 # See Netpbm Library Prerequisites
 # http://netpbm.sourceforge.net/prereq.html
 # if make succeeds but this test fails.
@@ -15,21 +16,20 @@ function testExitStatus () {
 #   $3: actual exit status
 
     case $3 in
-      $2)  echo $1": ok" ;;
-      126) if [ ! -z "${PBM_TESTPREFIX}" ] && \
-              [   -d "${PBM_TESTPREFIX}" ] && \
-              [ ! -x "${PBM_TESTPREFIX}/$1" ]
+      126) if [ ! -x $1 ]
              then echo $1": NOT EXECUTABLE";
              else echo $1": ERROR: "$3;    echo $1": error: "$3 1>&2 ;
            fi ;;
-      127) if [ ! -z "${PBM_TESTPREFIX}" ] && \
-              [   -d "${PBM_TESTPREFIX}" ] && \
-              [ ! -f "${PBM_TESTPREFIX}/$1" ]
+      127) type -p $1 > /dev/null
+           if [ $? -ne 0 ]
              then echo $1": NO SUCH FILE";
              else echo $1": ERROR: "$3;    echo $1": error: "$3 1>&2 ;
            fi ;;
+      88)  echo $1": NO SUCH FILE" ;;
+      $2)  echo $1": ok" ;;
       *)   echo $1": ERROR: "$3;    echo $1": error: "$3 1>&2 ;;
     esac
+
 }
 
 
@@ -43,7 +43,6 @@ ordinary_testprogs="\
   avstopam \
   bioradtopgm \
   bmptopnm \
-  bmptoppm \
   brushtopbm \
   cameratopam \
   cistopbm \
@@ -54,13 +53,11 @@ ordinary_testprogs="\
   fitstopnm \
   fstopgm \
   g3topbm \
-  gemtopbm \
   gemtopnm \
   giftopnm \
   gouldtoppm \
   hdifftopam \
   hipstopgm \
-  icontopbm \
   ilbmtoppm \
   imgtoppm \
   infotopam \
@@ -82,6 +79,7 @@ ordinary_testprogs="\
   pambayer \
   pamchannel \
   pamcomp \
+  pamcrater \
   pamcut \
   pamdeinterlace \
   pamdepth \
@@ -92,7 +90,7 @@ ordinary_testprogs="\
   pamenlarge \
   pamexec \
   pamfile \
-  pamfixtrunc \
+  pamfix \
   pamflip \
   pamfunc \
   pamgauss \
@@ -111,6 +109,7 @@ ordinary_testprogs="\
   pamrubber \
   pamscale \
   pamseq \
+  pamshadedrelief \
   pamsharpmap \
   pamsharpness \
   pamsistoaglyph \
@@ -144,6 +143,7 @@ ordinary_testprogs="\
   pamtowinicon \
   pamtoxvmini \
   pamundice \
+  pamvalidate \
   pamwipeout \
   pamx \
   pbmclean \
@@ -171,7 +171,6 @@ ordinary_testprogs="\
   pbmtogem \
   pbmtogo \
   pbmtoibm23xx \
-  pbmtoicon \
   pbmtolj \
   pbmtoln03 \
   pbmtolps \
@@ -200,9 +199,7 @@ ordinary_testprogs="\
   pfmtopam \
   pgmabel \
   pgmbentley \
-  pamcrater \
   pgmdeshadow \
-  pgmedge \
   pgmenhance \
   pgmhist \
   pgmkernel \
@@ -211,10 +208,7 @@ ordinary_testprogs="\
   pgmminkowski \
   pgmmorphconv \
   pgmnoise \
-  pgmnorm \
-  pgmoil \
   pgmramp \
-  pgmslice \
   pgmtexture \
   pgmtofs \
   pgmtolispm \
@@ -229,24 +223,15 @@ ordinary_testprogs="\
   pjtoppm \
   pktopbm \
   pngtopam \
-  pngtopnm \
   pnmalias \
-  pnmarith \
   pnmcat \
   pnmcolormap \
-  pnmcomp \
   pnmconvol \
   pnmcrop \
-  pnmcut \
-  pnmdepth \
-  pnmenlarge \
-  pnmfile \
-  pnmflip \
   pnmgamma \
   pnmhisteq \
   pnmhistmap \
   pnmindex \
-  pnminterp \
   pnminvert \
   pnmmercator \
   pnmmontage \
@@ -257,28 +242,23 @@ ordinary_testprogs="\
   pnmpsnr \
   pnmremap \
   pnmrotate \
-  pnmscale \
   pnmscalefixed \
   pnmshear \
   pnmsmooth \
-  pnmsplit \
   pnmstitch \
   pnmtile \
   pnmtoddif \
   pnmtofiasco \
-  pnmtofits \
   pnmtojbig \
   pnmtojpeg \
   pnmtopalm \
   pnmtopclxl \
   pnmtopng \
-  pnmtopnm \
   pnmtops \
   pnmtorast \
   pnmtorle \
   pnmtosgi \
   pnmtosir \
-  pnmtotiff \
   pnmtotiffcmyk \
   pnmtoxwd \
   ppm3d \
@@ -301,7 +281,6 @@ ordinary_testprogs="\
   ppmlabel \
   ppmmake \
   ppmmix \
-  ppmnorm \
   ppmntsc \
   ppmpat \
   ppmrelief \
@@ -314,14 +293,11 @@ ordinary_testprogs="\
   ppmtoascii \
   ppmtobmp \
   ppmtoeyuv \
-  ppmtogif \
   ppmtoicr \
   ppmtoilbm \
-  ppmtojpeg \
   ppmtoleaf \
   ppmtolj \
   ppmtomitsu \
-  ppmtompeg \
   ppmtoneo \
   ppmtopcx \
   ppmtopgm \
@@ -335,7 +311,6 @@ ordinary_testprogs="\
   ppmtosixel \
   ppmtospu \
   ppmtoterm \
-  ppmtouil \
   ppmtowinicon \
   ppmtoxpm \
   ppmtoyuv \
@@ -382,7 +357,7 @@ ordinary_testprogs="\
 
 for i in $ordinary_testprogs
   do
-    ${PBM_TESTPREFIX}$i --version  2>&1 | \
+    $i --version  2>&1 | \
     egrep -v \
     "(Using libnetpbm|Compiled|(BSD|SYSV|MSDOS|AMIGA) defined|RGB_?ENV=)" \
       1>&2;
@@ -390,28 +365,24 @@ for i in $ordinary_testprogs
   done
 
 
-
 # Test fiascotopnm, which has a unique -v flag.
-
-${PBM_TESTPREFIX}fiascotopnm -v 2> /dev/null
+fiascotopnm -v 2> /dev/null
     testExitStatus fiascotopnm 2 $?
 
 
-
 # Test manweb and pnmmargin, which have --help.
-
-${PBM_TESTPREFIX}manweb --help > /dev/null
+manweb --help > /dev/null
     testExitStatus manweb 0 $?
 
-${PBM_TESTPREFIX}pnmmargin --help 2> /dev/null
+pnmmargin --help 2> /dev/null
     testExitStatus pnmmargin 1 $?
 
 
-
-# Test anytopnm, pbmtox10bm, pnmnoraw, pnmquant, pnmquantall,
-# pnmtoplainpnm, ppmquantall, ppmrainbow, ppmshadow, ppmtomap
+# Test anytopnm, pnmnoraw, pnmquant, pnmquantall
+# ppmrainbow, ppmshadow, ppmtomap
 # with trivial input.
 
+$i ${tmpdir}/test.pbm > /dev/null 2> /dev/null;
 tmpdir=${tmpdir:-/tmp}
 test_pbm=${tmpdir}/test.pbm
 
@@ -421,50 +392,37 @@ P1
 1
 EOF
 
-for i in anytopnm pbmtox10bm pnmnoraw pnmtoplainpnm ppmtomap ppmshadow
+for i in anytopnm ppmtomap ppmshadow
   do
-    ${PBM_TESTPREFIX}$i ${test_pbm} > /dev/null 2> /dev/null;
+    $i ${tmpdir}/test.pbm > /dev/null 2> /dev/null;
     testExitStatus $i 0 $?
   done
 
-for i in pnmquant pnmquantall ppmquant ppmquantall
+for i in pnmquant pnmquantall
   do
-    ${PBM_TESTPREFIX}$i 2 ${test_pbm} > /dev/null 2> /dev/null;
+    $i 2 ${tmpdir}/test.pbm > /dev/null 2> /dev/null;
     testExitStatus $i 0 $?
   done
 
 rm ${test_pbm}
-
-${PBM_TESTPREFIX}ppmrainbow rgb:00/00/00 rgb:ff/ff/ff \
+    ppmrainbow rgb:00/00/00 rgb:ff/ff/ff \
     -tmpdir=${tmpdir} -width=2 -height=2 > /dev/null
     testExitStatus ppmrainbow 0 $?
 
 
-
 # Test ppmfade with corrupt input.
 # Prevent the creation of output files by setting base to /dev/null.
 # Exit status should be 50.
-
-${PBM_TESTPREFIX}ppmfade -f /dev/zero -base /dev/null > /dev/null 2> /dev/null
+    ppmfade -f /dev/zero -base /dev/null > /dev/null 2> /dev/null
     testExitStatus ppmfade 50 $?
 
 
-
 # Test pamstretch-gen and pcdovtoppm with no input.
 # These two programs write a usage message on standout in this case.
 # Exit status should be 1.
 
 for i in pamstretch-gen pcdovtoppm
   do
-  ${PBM_TESTPREFIX}$i > /dev/null
+     $i > /dev/null
      testExitStatus $i 1 $?
   done
-
-
-
-# We do not test hpcdtoppm.
-# This is a stand-in which announces the absence of the real hpcdtoppm.
-# TODO: Provide for the case in which the real hpcdtoppm is encountered.
-
-#${PBM_TESTPREFIX}hpcdtoppm 2> /dev/null
-#    testExitStatus hpcdtoppm 1 $?
diff --git a/test/atari-roundtrip.test b/test/atari-roundtrip.test
index 85929a8b..413438a1 100755
--- a/test/atari-roundtrip.test
+++ b/test/atari-roundtrip.test
@@ -1,15 +1,7 @@
+#! /bin/bash
 # This script tests: ppmtopi1 pi1toppm ppmtoneo neotoppm
-# Also requires: pgmramp pamscale pbmmake rgb3toppm
-
-  alias ppmtopi1="${PBM_TESTPREFIX}ppmtopi1"
-  alias pi1toppm="${PBM_TESTPREFIX}pi1toppm"
-  alias ppmtoneo="${PBM_TESTPREFIX}ppmtoneo"
-  alias neotoppm="${PBM_TESTPREFIX}neotoppm"
-  alias pgmramp="${PBM_BINPREFIX}pgmramp"
-  alias pamscale="${PBM_BINPREFIX}pamscale"
-  alias pbmmake="${PBM_BINPREFIX}pbmmake"
-  alias rgb3toppm="${PBM_BINPREFIX}rgb3toppm"
-  shopt -s expand_aliases
+# Also requires: pgmramp pamscale pbmmake pamenlarge rgb3toppm pamdepth
+
 
 # Atari pi1 and neo files have the following characteristics:
 # Size: 320x200
diff --git a/test/atk-roundtrip.test b/test/atk-roundtrip.test
index 3d15eec4..6db3df6d 100755
--- a/test/atk-roundtrip.test
+++ b/test/atk-roundtrip.test
@@ -1,10 +1,7 @@
 #! /bin/bash
 # This script tests: pbmtoatk atktopbm
-# Also requires: 
+# Also requires:
 
-  alias atktopbm="${PBM_TESTPREFIX}atktopbm"
-  alias pbmtoatk="${PBM_TESTPREFIX}pbmtoatk"
-  shopt -s expand_aliases
 
 # Should print 2425386270 41, cksum of testgrid.pbm
 pbmtoatk testgrid.pbm | atktopbm | cksum
diff --git a/test/avs-roundtrip.test b/test/avs-roundtrip.test
index 44b4d8a4..042ce91e 100755
--- a/test/avs-roundtrip.test
+++ b/test/avs-roundtrip.test
@@ -2,10 +2,6 @@
 # This script tests: pamtoavs avstopam
 # Also requires: pamtopnm
 
-  alias avstopam="${PBM_TESTPREFIX}avstopam"
-  alias pamtoavs="${PBM_TESTPREFIX}pamtoavs"
-  alias pamtopnm="${PBM_BINPREFIX}pamtopnm"
-  shopt -s expand_aliases
 
 # Should produce 1926073387 101484, cksum of testimg.ppm
 pamtoavs testimg.ppm | \
diff --git a/test/bmp-roundtrip.test b/test/bmp-roundtrip.test
index 291f2669..be9a4548 100755
--- a/test/bmp-roundtrip.test
+++ b/test/bmp-roundtrip.test
@@ -1,10 +1,7 @@
 #! /bin/bash
 # This script tests: bmptopnm ppmtobmp
-# Also requires: 
+# Also requires:
 
-  alias bmptopnm="${PBM_TESTPREFIX}bmptopnm"
-  alias ppmtobmp="${PBM_TESTPREFIX}ppmtobmp"
-  shopt -s expand_aliases
 
 ppmtobmp testimg.ppm | bmptopnm | cksum
 ppmtobmp testgrid.pbm | bmptopnm | cksum
diff --git a/test/cis-roundtrip.test b/test/cis-roundtrip.test
index 895fe60e..62fcc3b9 100755
--- a/test/cis-roundtrip.test
+++ b/test/cis-roundtrip.test
@@ -1,13 +1,7 @@
 #! /bin/bash
 # This script tests: pbmtocis cistopbm
-# Also requires: pbmmake pamenlarge pamcut
+# Also requires: pbmmake pamcut
 
-  alias pbmtocis="${PBM_TESTPREFIX}pbmtocis"
-  alias cistopbm="${PBM_TESTPREFIX}cistopbm"
-  alias pbmmake="${PBM_BINPREFIX}pbmmake"
-  alias pamenlarge="${PBM_BINPREFIX}pamenlarge"
-  alias pamcut="${PBM_BINPREFIX}pamcut"
-  shopt -s expand_aliases
 
 # Output images produced by pbmtocis are of fixed size,
 # either 128x96 or 256x192.
diff --git a/test/cmuw-roundtrip.test b/test/cmuw-roundtrip.test
index ebb5eecf..e52adb70 100755
--- a/test/cmuw-roundtrip.test
+++ b/test/cmuw-roundtrip.test
@@ -1,10 +1,7 @@
 #! /bin/bash
 # This script tests: pbmtocmuwm cmuwmtopbm
-# Also requires: 
+# Also requires:
 
-  alias cmuwmtopbm="${PBM_TESTPREFIX}cmuwmtopbm"
-  alias pbmtocmuwm="${PBM_TESTPREFIX}pbmtocmuwm"
-  shopt -s expand_aliases
 
 # Should print 2425386270 41, cksum of testgrid.pbm
 pbmtocmuwm testgrid.pbm | cmuwmtopbm | cksum
diff --git a/test/cut-paste-roundtrip.test b/test/cut-paste-roundtrip.test
index 15e53219..9f466020 100755
--- a/test/cut-paste-roundtrip.test
+++ b/test/cut-paste-roundtrip.test
@@ -1,10 +1,7 @@
 #! /bin/bash
 # This script tests: pamcut pnmpaste
-# Also requires: 
+# Also requires:
 
-  alias pamcut="${PBM_TESTPREFIX}pamcut"
-  alias pnmpaste="${PBM_TESTPREFIX}pnmpaste"
-  shopt -s expand_aliases
 
 pamcut 50 40 100 70 testimg.ppm | \
 pnmpaste -replace - 50 40 testimg.ppm | cksum
diff --git a/test/eyuvtoppm.test b/test/eyuvtoppm.test
index 79c30237..b28b4539 100755
--- a/test/eyuvtoppm.test
+++ b/test/eyuvtoppm.test
@@ -1,9 +1,7 @@
 #! /bin/bash
 # This script tests: eyuvtoppm
-# Also requires: 
+# Also requires:
 
-  alias eyuvtoppm="${PBM_TESTPREFIX}eyuvtoppm"
-  shopt -s expand_aliases
 
 # Should produce 1719878124 253455
 
diff --git a/test/facesaver-roundtrip.test b/test/facesaver-roundtrip.test
index 76de380d..f4b8f069 100755
--- a/test/facesaver-roundtrip.test
+++ b/test/facesaver-roundtrip.test
@@ -1,10 +1,7 @@
 #! /bin/bash
 # This script tests: pgmtofs fstopgm
-# Also requires: pamchannel
+# Also requires: pamchannel pamtopnm
 
-  alias fstopgm="${PBM_TESTPREFIX}fstopgm"
-  alias pgmtofs="${PBM_TESTPREFIX}pgmtofs"
-  shopt -s expand_aliases
 
 # Should produce 1571496937 33838, cksum of testimg.red
 
diff --git a/test/fits-roundtrip.test b/test/fits-roundtrip.test
index 65589823..e793df9a 100755
--- a/test/fits-roundtrip.test
+++ b/test/fits-roundtrip.test
@@ -1,10 +1,7 @@
 #! /bin/bash
 # This script tests: pamtofits fitstopnm
-# Also requires: 
+# Also requires:
 
-  alias fitstopnm="${PBM_TESTPREFIX}fitstopnm"
-  alias pamtofits="${PBM_TESTPREFIX}pamtofits"
-  shopt -s expand_aliases
 
 # Should produce 1926073387 101484, cksum of testimg.ppm
 pamtofits testimg.ppm | fitstopnm | cksum
diff --git a/test/g3-roundtrip.test b/test/g3-roundtrip.test
index 323a26bf..47e20e1d 100755
--- a/test/g3-roundtrip.test
+++ b/test/g3-roundtrip.test
@@ -2,10 +2,6 @@
 # This script tests: g3topbm pbmtog3
 # Also requires: pnmcrop
 
-  alias g3topbm="${PBM_TESTPREFIX}g3topbm"
-  alias pbmtog3="${PBM_TESTPREFIX}pbmtog3"
-  alias pnmcrop="${PBM_BINPREFIX}pnmcrop"
-  shopt -s expand_aliases
 
 pbmtog3 -nofixedwidth testgrid.pbm | \
 g3topbm -width=14 | cmp -s - testgrid.pbm
diff --git a/test/gem-roundtrip.test b/test/gem-roundtrip.test
index 97f894c2..0fce59db 100755
--- a/test/gem-roundtrip.test
+++ b/test/gem-roundtrip.test
@@ -1,10 +1,7 @@
 #! /bin/bash
-# This script tests: pbmtogem gemtopbm
-# Also requires: gemtopnm
+# This script tests: pbmtogem gemtopnm
+# Also requires:
 
-  alias gemtopbm="${PBM_TESTPREFIX}gemtopbm"
-  alias pbmtogem="${PBM_TESTPREFIX}pbmtogem"
-  shopt -s expand_aliases
 
 # Should print 2425386270 41, cksum of testgrid.pbm
-pbmtogem testgrid.pbm | gemtopbm | cksum
+pbmtogem testgrid.pbm | gemtopnm | cksum
diff --git a/test/gif-quant-roundtrip.test b/test/gif-quant-roundtrip.test
index 7f99ca6e..8b911740 100755
--- a/test/gif-quant-roundtrip.test
+++ b/test/gif-quant-roundtrip.test
@@ -1,11 +1,7 @@
 #! /bin/bash
 # This script tests: giftopnm pamtogif pnmquant
-# Also requires: pnmcolormap pnmremap
+# Also requires:
 
-  alias giftopnm="${PBM_TESTPREFIX}giftopnm"
-  alias pamtogif="${PBM_TESTPREFIX}pamtogif"
-  alias pnmquant="${PBM_TESTPREFIX}pnmquant"
-  shopt -s expand_aliases
 
 # Should print 0
 
@@ -20,4 +16,3 @@ pamtogif ${quant_ppm} | giftopnm | \
 echo $?
 
 rm ${quant_ppm}
-
diff --git a/test/gif-roundtrip.test b/test/gif-roundtrip.test
index 8d1a9bbe..a6d0ec4c 100755
--- a/test/gif-roundtrip.test
+++ b/test/gif-roundtrip.test
@@ -1,14 +1,7 @@
 #! /bin/bash
 # This script tests: giftopnm pamtogif
-# Also requires: ppmtorgb3 rgb3toppm pbmmake
+# Also requires: ppmtorgb3 rgb3toppm pbmmake pnminvert
 
-  alias giftopnm="${PBM_TESTPREFIX}giftopnm"
-  alias pamtogif="${PBM_TESTPREFIX}pamtogif"
-  alias pbmmake="${PBM_BINPREFIX}pbmmake"
-  alias ppmtorgb3="${PBM_BINPREFIX}ppmtorgb3"
-  alias rgb3toppm="${PBM_BINPREFIX}rgb3toppm"
-  alias pnminvert="${PBM_BINPREFIX}pnminvert"
-  shopt -s expand_aliases
 
 tmpdir=${tmpdir:-/tmp}
 
@@ -20,7 +13,7 @@ tmpdir=${tmpdir:-/tmp}
 test_ppm=${tmpdir}/testimg.ppm
 
 cp testimg.ppm ${tmpdir} &&
-ppmtorgb3 ${test_ppm} &&
+ppmtorgb3 ${test_ppm}
 
 test_red=${tmpdir}/testimg.red
 test_grn=${tmpdir}/testimg.grn
diff --git a/test/hdiff-roundtrip.test b/test/hdiff-roundtrip.test
index 3a27a955..a4a4a906 100755
--- a/test/hdiff-roundtrip.test
+++ b/test/hdiff-roundtrip.test
@@ -1,10 +1,7 @@
 #! /bin/bash
 # This script tests: hdifftopam pamtohdiff
-# Also requires: 
+# Also requires:
 
-  alias hdifftopam="${PBM_TESTPREFIX}hdifftopam"
-  alias pamtohdiff="${PBM_TESTPREFIX}pamtohdiff"
-  shopt -s expand_aliases
 
 pamtohdiff testimg.ppm | \
   hdifftopam -pnm | cksum
diff --git a/test/ilbm-roundtrip.ok b/test/ilbm-roundtrip.ok
index 82eac5a8..cd357916 100644
--- a/test/ilbm-roundtrip.ok
+++ b/test/ilbm-roundtrip.ok
@@ -1 +1,2 @@
 1926073387 101484
+984199586 101484
diff --git a/test/ilbm-roundtrip.test b/test/ilbm-roundtrip.test
index 495daf53..a13fc8be 100755
--- a/test/ilbm-roundtrip.test
+++ b/test/ilbm-roundtrip.test
@@ -2,13 +2,6 @@
 # This script tests: ppmtoilbm ilbmtoppm
 # Also requires: pamseq pamdepth pamtopnm pnmremap
 
-  alias ppmtoilbm="${PBM_TESTPREFIX}ppmtoilbm"
-  alias ilbmtoppm="${PBM_TESTPREFIX}ilbmtoppm"
-  alias pamseq="${PBM_BINPREFIX}pamseq"
-  alias pamdepth="${PBM_BINPREFIX}pamdepth"
-  alias pamtopnm="${PBM_BINPREFIX}pamtopnm"
-  alias pnmremap="${PBM_BINPREFIX}pnmremap"
-  shopt -s expand_aliases
 
 #Test.  Should produce 1926073387 101484
 ppmtoilbm testimg.ppm | ilbmtoppm | cksum
@@ -16,5 +9,3 @@ ppmtoilbm testimg.ppm | ilbmtoppm | cksum
 #Test.  Should print 984199586 101484
 pamseq 3 5 -tupletype=RGB | pamdepth 255 | pamtopnm | \
   pnmremap -mapfile=- testimg.ppm | ppmtoilbm | ilbmtoppm | cksum
-
-
diff --git a/test/jbig-roundtrip.test b/test/jbig-roundtrip.test
index 9ce23f51..5e96a001 100755
--- a/test/jbig-roundtrip.test
+++ b/test/jbig-roundtrip.test
@@ -1,10 +1,7 @@
 #! /bin/bash
 # This script tests: pnmtojbig jbigtopnm
-# Also requires: pamchannel
+# Also requires: pamchannel pamtopnm
 
-  alias pnmtojbig="${PBM_TESTPREFIX}pnmtojbig"
-  alias jbigtopnm="${PBM_TESTPREFIX}jbigtopnm"
-  shopt -s expand_aliases
 
 # Test 1.  Should print 2425386270 41
 pnmtojbig testgrid.pbm | jbigtopnm | cksum
diff --git a/test/leaf-roundtrip.test b/test/leaf-roundtrip.test
index f8ac11d4..5628ed01 100755
--- a/test/leaf-roundtrip.test
+++ b/test/leaf-roundtrip.test
@@ -1,10 +1,7 @@
 #! /bin/bash
 # This script tests: ppmtoleaf leaftoppm
-# Also requires: 
+# Also requires:
 
-  alias leaftoppm="${PBM_TESTPREFIX}leaftoppm"
-  alias ppmtoleaf="${PBM_TESTPREFIX}ppmtoleaf"
-  shopt -s expand_aliases
 
 # Should produce 1926073387 101484, cksum of testimg.ppm
 ppmtoleaf testimg.ppm | leaftoppm | cksum
diff --git a/test/legacy-names.ok b/test/legacy-names.ok
new file mode 100644
index 00000000..57343afa
--- /dev/null
+++ b/test/legacy-names.ok
@@ -0,0 +1,36 @@
+bmptoppm: ok
+gemtopbm: ok
+icontopbm: ok
+pamfixtrunc: ok
+pbmtoicon: ok
+pgmedge: ok
+pgmnorm: ok
+pgmoil: ok
+pgmslice: ok
+pngtopnm: ok
+pnmarith: ok
+pnmcomp: ok
+pnmcut: ok
+pnmdepth: ok
+pnmenlarge: ok
+pnmfile: ok
+pnmflip: ok
+pnminterp: ok
+pnmscale: ok
+pnmsplit: ok
+pnmtofits: ok
+pnmtopnm: ok
+pnmtotiff: ok
+ppmnorm: ok
+ppmtogif: ok
+ppmtojpeg: ok
+ppmtompeg: ok
+ppmtotga: ok
+ppmtouil: ok
+pgmcrater: ok
+pbmtox10bm: ok
+pnmnoraw: ok
+pnmtoplainpnm: ok
+ppmquant: ok
+ppmquantall: ok
+hpcdtoppm: ok
diff --git a/test/legacy-names.test b/test/legacy-names.test
new file mode 100755
index 00000000..9940f207
--- /dev/null
+++ b/test/legacy-names.test
@@ -0,0 +1,131 @@
+#! /bin/bash
+# Tests whether the executable files listed below are in place.
+
+# We test with the methods used in all-in-place.test.
+# The sole exception is hpcdtoppm.  We just confirm that it exists.
+
+# Failure message
+## If all-in-place.test succeeds and this test fails, a likely cause is a
+## problem with symbolic links.
+##
+## Important: This test checks obsoleted names.
+## Programs here do not appear in other tests.
+
+
+# Skip this test if CHECK_TYPE = tree
+
+if [ ${CHECK_TYPE} = tree ]
+  then echo "Skipping." 1>&2
+  exit 80;
+fi
+
+
+function testExitStatus () {
+
+# This function takes 3 positional parameters:
+#   $1: filename
+#   $2: expected exit status   (In some cases we expect error.)
+#   $3: actual exit status
+
+    case $3 in
+      126) if [ ! -x $1 ]
+             then echo $1": NOT EXECUTABLE";
+             else echo $1": ERROR: "$3;    echo $1": error: "$3 1>&2 ;
+           fi ;;
+      127) type -p $1 > /dev/null
+           if [ $? -ne 0 ]
+             then echo $1": NO SUCH FILE";
+             else echo $1": ERROR: "$3;    echo $1": error: "$3 1>&2 ;
+           fi ;;
+      88)  echo $1": NO SUCH FILE" ;;
+      $2)  echo $1": ok" ;;
+      *)   echo $1": ERROR: "$3;    echo $1": error: "$3 1>&2 ;;
+    esac
+
+}
+
+
+# Test programs which have the --version flag.
+# See showVersion() in lib/libpm.c for the standard version announcement.
+
+ordinary_testprogs="\
+  bmptoppm \
+  gemtopbm \
+  icontopbm \
+  pamfixtrunc \
+  pbmtoicon \
+  pgmedge \
+  pgmnorm \
+  pgmoil \
+  pgmslice \
+  pngtopnm \
+  pnmarith \
+  pnmcomp \
+  pnmcut \
+  pnmdepth \
+  pnmenlarge \
+  pnmfile \
+  pnmflip \
+  pnminterp \
+  pnmscale \
+  pnmsplit \
+  pnmtofits \
+  pnmtopnm \
+  pnmtotiff \
+  ppmnorm \
+  ppmtogif \
+  ppmtojpeg \
+  ppmtompeg \
+  ppmtotga \
+  ppmtouil \
+"
+
+for i in $ordinary_testprogs
+  do
+    $i --version  2>&1 | \
+    egrep -v \
+    "(Using libnetpbm|Compiled|(BSD|SYSV|MSDOS|AMIGA) defined|RGB_?ENV=)" \
+      1>&2;
+    testExitStatus $i 0 ${PIPESTATUS[0]}
+  done
+
+
+# Test pgmcrater
+
+pgmcrater -number 1 -xsize 15 -ysize 15 -randomseed 1 > /dev/null
+testExitStatus pgmcrater 0 $?
+
+
+# Test pbmtox10bm, pnmnoraw, pnmtoplainpnm, ppmquantall, ppmrainbow
+# with trivial input.
+
+$i ${tmpdir}/test.pbm > /dev/null 2> /dev/null;
+tmpdir=${tmpdir:-/tmp}
+test_pbm=${tmpdir}/test.pbm
+
+cat > ${test_pbm} <<EOF
+P1
+1 1
+1
+EOF
+
+for i in pbmtox10bm pnmnoraw pnmtoplainpnm
+  do
+    $i ${tmpdir}/test.pbm > /dev/null 2> /dev/null;
+    testExitStatus $i 0 $?
+  done
+
+for i in ppmquant ppmquantall
+  do
+    $i 2 ${tmpdir}/test.pbm > /dev/null 2> /dev/null;
+    testExitStatus $i 0 $?
+  done
+
+
+rm ${test_pbm}
+
+
+# Test hpcdtoppm.  Simply confirm its existence.
+
+type -p hpcdtoppm > /dev/null
+testExitStatus hpcdtoppm 0 $?
diff --git a/test/macp-roundtrip.ok b/test/macp-roundtrip.ok
index 20e24348..9ff9d249 100644
--- a/test/macp-roundtrip.ok
+++ b/test/macp-roundtrip.ok
@@ -1,2 +1,5 @@
 2425386270 41
-1005016577 51851
+2425386270 41
+2329957971 51851
+2907103393 5086
+2907103393 5086
diff --git a/test/macp-roundtrip.test b/test/macp-roundtrip.test
index 39228e5a..4774a2c2 100755
--- a/test/macp-roundtrip.test
+++ b/test/macp-roundtrip.test
@@ -1,15 +1,31 @@
 #! /bin/bash
 # This script tests: pbmtomacp macptopbm
-# Also requires: pamcrop pbmmake
+# Also requires: pnmcrop pbmpage pbmupc pnmpad
 
-  alias pbmtomacp="${PBM_TESTPREFIX}pbmtomacp"
-  alias macptopbm="${PBM_TESTPREFIX}macptopbm"
-  alias pnmcrop="${PBM_BINPREFIX}pnmcrop"
-  alias pbmmake="${PBM_BINPREFIX}pbmmake"
-  shopt -s expand_aliases
+tmpdir=${tmpdir:-/tmp}
+temp1_pbm=${tmpdir}/temp1.ppm
+temp2_pbm=${tmpdir}/temp2.ppm
 
-#Test 1. Should produce 2425386270 41
-pbmtomacp testgrid.pbm | macptopbm | pnmcrop | cksum
 
-#Test 2. Should produce 1005016577 51851
-pbmmake -g 576 720 | pbmtomacp | macptopbm | cksum
+# Test 1. Should produce 2425386270 41 twice
+# Because Macpaint files are fixed size (576 x 720 pixels)
+# pbmtomacp automatically adds padding when input is smaller.
+
+pbmtomacp testgrid.pbm | macptopbm | tee ${temp1_pbm} | \
+    pnmcrop | cksum
+
+pbmtomacp ${temp1_pbm} | macptopbm | pnmcrop | cksum
+
+
+#Test 2. Should produce 2329957971 51851
+pbmpage 1 | pbmtomacp | macptopbm | cksum
+
+
+#Test 3. Should produce 2907103393 5086 twice
+pbmupc 0 12345 67890 | pnmpad -black -t 44 -b 20 -l 100 -r 251 | pbmtomacp | macptopbm | \
+    tee ${temp2_pbm} | \
+    pnmcrop | pnmcrop | cksum
+
+pbmtomacp ${temp2_pbm} | macptopbm | pnmcrop | pnmcrop | cksum
+
+rm ${temp1_pbm} ${temp2_pbm}
diff --git a/test/mda-roundtrip.test b/test/mda-roundtrip.test
index 3bde61ee..58376f3f 100755
--- a/test/mda-roundtrip.test
+++ b/test/mda-roundtrip.test
@@ -2,14 +2,8 @@
 # This script tests: pbmtomda mdatopbm
 # Also requires: pbmmake pnmpad pamcut
 
-  alias pbmtomda="${PBM_TESTPREFIX}pbmtomda"
-  alias mdatopbm="${PBM_TESTPREFIX}mdatopbm"
-  alias pbmmake="${PBM_BINPREFIX}pbmmake"
-  alias pnmpad="${PBM_BINPREFIX}pnmpad"
-  alias pamcut="${PBM_BINPREFIX}pamcut"
-  shopt -s expand_aliases
 
-# Pbmtomda requires input width and height to be multiples of 8. 
+# Pbmtomda requires input width and height to be multiples of 8.
 
 # Test 1.  Should print 1757803444 169
 pbmmake -g 32 40 | pbmtomda | mdatopbm | cksum
diff --git a/test/mgr-roundtrip.test b/test/mgr-roundtrip.test
index 4f5fdd81..252ae996 100755
--- a/test/mgr-roundtrip.test
+++ b/test/mgr-roundtrip.test
@@ -1,10 +1,7 @@
 #! /bin/bash
 # This script tests: pbmtomgr mgrtopbm
-# Also requires: 
+# Also requires:
 
-  alias mgrtopbm="${PBM_TESTPREFIX}mgrtopbm"
-  alias pbmtomgr="${PBM_TESTPREFIX}pbmtomgr"
-  shopt -s expand_aliases
 
 # Should print 2425386270 41, cksum of testgrid.pbm
 pbmtomgr testgrid.pbm | mgrtopbm | cksum
diff --git a/test/mrf-roundtrip.test b/test/mrf-roundtrip.test
index 5b9f77f4..c9d8ce3a 100755
--- a/test/mrf-roundtrip.test
+++ b/test/mrf-roundtrip.test
@@ -1,10 +1,7 @@
 #! /bin/bash
 # This script tests: pbmtomrf mrftopbm
-# Also requires: 
+# Also requires:
 
-  alias mrftopbm="${PBM_TESTPREFIX}mrftopbm"
-  alias pbmtomrf="${PBM_TESTPREFIX}pbmtomrf"
-  shopt -s expand_aliases
 
 # Should print 2425386270 41, cksum of testgrid.pbm
 pbmtomrf testgrid.pbm | mrftopbm | cksum
diff --git a/test/pad-crop-roundtrip.test b/test/pad-crop-roundtrip.test
index ae19f7d5..c7780d68 100755
--- a/test/pad-crop-roundtrip.test
+++ b/test/pad-crop-roundtrip.test
@@ -2,9 +2,6 @@
 # This script tests: pnmcrop pnmmargin
 # Also requires: pnmpad
 
-  alias pnmcrop="${PBM_TESTPREFIX}pnmcrop"
-  alias pnmmargin="${PBM_TESTPREFIX}pnmmargin"
-  shopt -s expand_aliases
 
 pnmmargin -white 10 testimg.ppm | \
   pnmcrop | cksum
diff --git a/test/pambackground.test b/test/pambackground.test
index 58526fdd..522f4823 100755
--- a/test/pambackground.test
+++ b/test/pambackground.test
@@ -1,15 +1,7 @@
 #! /bin/bash
-# This script tests: pambackground 
-# Also requires: pamgradient pamseq pbmmake pnmmargin pnmremap pnmtile
-
-  alias pambackground="${PBM_TESTPREFIX}pambackground"
-  alias pamgradient="${PBM_BINPREFIX}pamgradient"
-  alias pamseq="${PBM_BINPREFIX}pamseq"
-  alias pbmmake="${PBM_BINPREFIX}pbmmake"
-  alias pnmmargin="${PBM_BINPREFIX}pnmmargin"
-  alias pnmremap="${PBM_BINPREFIX}pnmremap"
-  alias pnmtile="${PBM_BINPREFIX}pnmtile"
-  shopt -s expand_aliases
+# This script tests: pambackground
+# Also requires: pamgradient pamseq pbmmake pnmmargin pnmremap pnmtile pnmpad
+
 
 tmpdir=${tmpdir:-/tmp}
 
diff --git a/test/pamchannel.test b/test/pamchannel.test
index 9ac71f13..3529f4fe 100755
--- a/test/pamchannel.test
+++ b/test/pamchannel.test
@@ -2,9 +2,6 @@
 # This script tests: pamchannel
 # Also requires: pamtopnm
 
-  alias pamchannel="${PBM_TESTPREFIX}pamchannel"
-  alias pamtopnm="${PBM_BINPREFIX}pamtopnm"
-  shopt -s expand_aliases
 
 # Extract planes one by one.
 # Convert output to pgm to make it identical to ppmtorgb3 output.
diff --git a/test/pamcrater.test b/test/pamcrater.test
index cc937731..4d3858b9 100755
--- a/test/pamcrater.test
+++ b/test/pamcrater.test
@@ -2,14 +2,6 @@
 # This script tests: pamcrater pamshadedrelief
 # Also requires: pamstack pamvalidate pamcut pamflip
 
-  alias pamcrater="${PBM_TESTPREFIX}pamcrater"
-  alias pamshadedrelief="${PBM_TESTPREFIX}pamshadedrelief"
-  alias pamstack="${PBM_BINPREFIX}pamstack"
-  alias pamvalidate="${PBM_BINPREFIX}pamvalidate"
-  alias pamcut="${PBM_BINPREFIX}pamcut"
-  alias pamflip="${PBM_BINPREFIX}pamflip"
-
-  shopt -s expand_aliases
 
 # We use the undocumented --test and --radius options of pamcrater.
 # pamcrater --test --radius=N
@@ -33,7 +25,7 @@ pamcrater --test --radius=100 > $test100_pam
 pamcrater --test --radius=150 > $test150_pam
 
 pamstack ${test10_pam} ${test50_pam} ${test100_pam} ${test150_pam} |
-  pamvalidate > ${test_pam} 
+  pamvalidate > ${test_pam}
 
 for i in 1 10 70
   do
diff --git a/test/pamcut.test b/test/pamcut.test
index 5a94de46..fd9185a3 100755
--- a/test/pamcut.test
+++ b/test/pamcut.test
@@ -1,18 +1,18 @@
 #! /bin/bash
 # This script tests: pamcut pbmmake
-# Also requires: 
+# Also requires:
 
-  alias pamcut="${PBM_TESTPREFIX}pamcut"
-  alias pbmmake="${PBM_TESTPREFIX}pbmmake"
-  shopt -s expand_aliases
 
 # Test 1.  Should print 2958909756 124815
 pamcut -top 0 -left 0 -width 260 -height 160 \
   -pad testimg.ppm | cksum
+
 # Test 2.  Should print 1550940962 10933
 pamcut -top 200 -left 120 -width 40 -height 40 \
   -pad testimg.ppm | cksum
+
 # Test 3.  Should print 708474423 14
 pamcut -top 5 -left 5 -bottom 5 -right 5 testimg.ppm | cksum
-# Test 3.  Should print 3412257956 129
+
+# Test 4.  Should print 3412257956 129
 pbmmake -g 50 50 | pamcut 5 5 30 30 | cksum
diff --git a/test/pamdepth-roundtrip.test b/test/pamdepth-roundtrip.test
index 6330aaf9..0c7cb8b0 100755
--- a/test/pamdepth-roundtrip.test
+++ b/test/pamdepth-roundtrip.test
@@ -1,10 +1,7 @@
 #! /bin/bash
 # This script tests: pamdepth pgmtopbm
-# Also requires: 
+# Also requires:
 
-  alias pamdepth="${PBM_TESTPREFIX}pamdepth"
-  alias pgmtopbm="${PBM_TESTPREFIX}pgmtopbm"
-  shopt -s expand_aliases
 
 for i in 300 500 1023 4095 5000 16383 65535
 do
diff --git a/test/pamdice-roundtrip.test b/test/pamdice-roundtrip.test
index 7b863bca..28997742 100755
--- a/test/pamdice-roundtrip.test
+++ b/test/pamdice-roundtrip.test
@@ -1,10 +1,7 @@
 #! /bin/bash
 # This script tests: pamdice pamundice
-# Also requires: 
+# Also requires:
 
-  alias pamdice="${PBM_TESTPREFIX}pamdice"
-  alias pamundice="${PBM_TESTPREFIX}pamundice"
-  shopt -s expand_aliases
 
 tmpdir=${tmpdir:-/tmp}
 fname_stem=${tmpdir}/a
@@ -13,4 +10,3 @@ pamdice testimg.ppm -outstem=${fname_stem} -width=50 -height=40
 pamundice ${fname_stem}_%1d_%1a.ppm -down=4 -across=5 | cksum
 
 rm ${fname_stem}_?_?.ppm
-
diff --git a/test/pamditherbw.test b/test/pamditherbw.test
index 1ac1391c..3f377f81 100755
--- a/test/pamditherbw.test
+++ b/test/pamditherbw.test
@@ -1,9 +1,7 @@
 #! /bin/bash
 # This script tests: pamditherbw
-# Also requires: pamchannel
+# Also requires: pamchannel pamtopnm
 
-  alias pamditherbw="${PBM_TESTPREFIX}pamditherbw"
-  shopt -s expand_aliases
 
 tmpdir=${tmpdir:-/tmp}
 test_red=${tmpdir}/testimg.red
diff --git a/test/pamedge.test b/test/pamedge.test
index d230424b..c63b30cc 100755
--- a/test/pamedge.test
+++ b/test/pamedge.test
@@ -2,13 +2,6 @@
 # This script tests: pamedge
 # Also requires: pbmpscale pbmtext pgmtopbm pgmtopgm ppmtopgm
 
-  alias pamedge="${PBM_TESTPREFIX}pamedge"
-  alias pbmpscale="${PBM_BINPREFIX}pbmpscale"
-  alias pbmtext="${PBM_BINPREFIX}pbmtext"
-  alias pgmtopbm="${PBM_BINPREFIX}pgmtopbm"
-  alias pgmtopgm="${PBM_BINPREFIX}pgmtopgm"
-  alias ppmtopgm="${PBM_BINPREFIX}ppmtopgm"
-  shopt -s expand_aliases
 
 pbmtext " F " -nom | pbmpscale 5 | \
 pgmtopgm | pamedge | \
diff --git a/test/pamenlarge.test b/test/pamenlarge.test
index ced156dd..3820f47e 100755
--- a/test/pamenlarge.test
+++ b/test/pamenlarge.test
@@ -2,11 +2,6 @@
 # This script tests: pamenlarge
 # Also requires: pamchannel pamseq pamtopnm
 
-  alias pamenlarge="${PBM_TESTPREFIX}pamenlarge"
-  alias pamchannel="${PBM_TESTPREFIX}pamchannel"
-  alias pamseq="${PBM_TESTPREFIX}pamseq"
-  alias pamchannel="${PBM_TESTPREFIX}pamchannel"
-  shopt -s expand_aliases
 
 # Test 1.  Should print 3424505894 913236
 pamenlarge 3 testimg.ppm | cksum
diff --git a/test/pamfile.test b/test/pamfile.test
index 1c1d3d23..ac927172 100755
--- a/test/pamfile.test
+++ b/test/pamfile.test
@@ -1,14 +1,9 @@
 #! /bin/bash
 # This script tests: pamfile
-# Also requires: pamchannel
+# Also requires: pamchannel pamtopnm
 
-  alias pamfile="${PBM_TESTPREFIX}pamfile"
-  shopt -s expand_aliases
 
 pamfile testimg.ppm
 pamfile testgrid.pbm
 pamchannel -infile=testimg.ppm -tupletype="GRAYSCALE" 0 | pamtopnm | pamfile
 pamchannel -tupletype="GRAYSCALE" -infile=testimg.ppm 0 | pamfile
-
-
-
diff --git a/test/pamflip-roundtrip.test b/test/pamflip-roundtrip.test
index 2b18eb8d..c5a34ad9 100755
--- a/test/pamflip-roundtrip.test
+++ b/test/pamflip-roundtrip.test
@@ -1,9 +1,7 @@
 #! /bin/bash
 # This script tests: pamflip
-# Also requires: 
+# Also requires:
 
-  alias pamflip="${PBM_TESTPREFIX}pamflip"
-  shopt -s expand_aliases
 
 pamflip -lr testimg.ppm | pamflip -lr | cksum
 pamflip -tb testimg.ppm | pamflip -tb | cksum
diff --git a/test/pamflip1.test b/test/pamflip1.test
index 0f60b72b..840cac73 100755
--- a/test/pamflip1.test
+++ b/test/pamflip1.test
@@ -1,12 +1,10 @@
 #! /bin/bash
 # This script tests: pamflip
-# Also requires: 
+# Also requires:
 
-  alias pamflip="${PBM_TESTPREFIX}pamflip"
-  shopt -s expand_aliases
 
 # Test 1.  Should print 2116496681 101484
-pamflip -lr testimg.ppm | cksum 
+pamflip -lr testimg.ppm | cksum
 # Test 2.  Should print 217037000 101484
 pamflip -cw testimg.ppm | cksum
 # Test 3.  Should print 2052917888 101484
diff --git a/test/pamflip2.test b/test/pamflip2.test
index d9418b25..4dddb770 100755
--- a/test/pamflip2.test
+++ b/test/pamflip2.test
@@ -1,9 +1,7 @@
 #! /bin/bash
 # This script tests: pamflip
-# Also requires: 
+# Also requires:
 
-  alias pamflip="${PBM_TESTPREFIX}pamflip"
-  shopt -s expand_aliases
 
 # Failure message
 ## Failure with this test indicates a problem with pamflip transpositions
diff --git a/test/pamseq.test b/test/pamseq.test
index acc5d1b1..e7b8060d 100755
--- a/test/pamseq.test
+++ b/test/pamseq.test
@@ -1,8 +1,6 @@
 #! /bin/bash
 # This script tests: pamseq
-# Also requires: 
+# Also requires:
 
-  alias pamseq="${PBM_TESTPREFIX}pamseq"
-  shopt -s expand_aliases
 
 pamseq 1 255 | cksum
diff --git a/test/pamslice-roundtrip.test b/test/pamslice-roundtrip.test
index f17765d1..6cb5533f 100755
--- a/test/pamslice-roundtrip.test
+++ b/test/pamslice-roundtrip.test
@@ -1,13 +1,7 @@
 #! /bin/bash
 # This script tests: pamslice pamdeinterlace
-# Also requires: pamcut pnmtopnm pamflip
+# Also requires: pamcut pamtopnm pamflip
 
-  alias pamslice="${PBM_TESTPREFIX}pamslice"
-  alias pamdeinterlace="${PBM_TESTPREFIX}pamdeinterlace"
-  alias pamcut="${PBM_BINPREFIX}pamcut"
-  alias pnmtopnm="${PBM_BINPREFIX}pnmtopnm"
-  alias pamflip="${PBM_BINPREFIX}pamflip"
-  shopt -s expand_aliases
 
 # Test 1.
 # Slice rows, one by one, out of testgrid.pbm.
@@ -19,9 +13,9 @@
  echo "14 16"
  seq 0 15 | while read i;
      do
-     pamslice -row=$i testgrid.pbm  | \
-      awk '{print $2}' | sed 'y/01/10/';
-     done ) |  pnmtopnm | cksum
+     pamslice -row=$i testgrid.pbm
+     done | awk '{print $2}' | sed 'y/01/10/' ) \
+ | pamtopnm | cksum
 
 # Test 2.
 # Slice rows, one by one, out of ppm test image
@@ -41,8 +35,9 @@ pamcut 50 50 49 33 testimg.ppm > ${test4933_ppm}
  echo "255"
  seq 0 32 | while read i;
      do
-     pamslice -row=$i ${test4933_ppm} | awk '{print $2, $3, $4}';
-     done ) | pnmtopnm | cksum
+     pamslice -row=$i ${test4933_ppm}
+     done | awk '{print $2, $3, $4}' ) \
+ | pamtopnm | cksum
 
 # Same as above test 2, but take cols instead of rows.
 # Should print 914327477 4864
@@ -52,8 +47,9 @@ pamcut 50 50 49 33 testimg.ppm > ${test4933_ppm}
  echo "255"
  seq 0 48 | while read i;
      do
-     pamslice -col=$i ${test4933_ppm} | awk '{print $2, $3, $4}';
-     done ) | pamflip -xy | cksum
+     pamslice -col=$i ${test4933_ppm}
+     done | awk '{print $2, $3, $4}' ) \
+ | pamflip -xy | cksum
 
 # Test 4.
 # Divide input image into two with pamdeinterlace and recombine.
@@ -67,12 +63,13 @@ pamdeinterlace -takeeven ${test4933_ppm} > ${testeven_ppm}
 (echo "P3"
  echo "49 33"
  echo "255"
- seq 0 15 | while read i;
+ ( seq 0 15 | while read i;
      do
-     pamslice -row=$i ${testeven_ppm} | awk '{print $2, $3, $4}';
-     pamslice -row=$i ${testodd_ppm} | awk '{print $2, $3, $4}';
+     pamslice -row=$i ${testeven_ppm}
+     pamslice -row=$i ${testodd_ppm}
      done
-     pamslice -row=16 ${testeven_ppm} | awk '{print $2, $3, $4}';
-  ) | pnmtopnm | tee /tmp/z | cksum
+     pamslice -row=16 ${testeven_ppm};
+ )  | awk '{print $2, $3, $4}' ) \
+ | pamtopnm | cksum
 
 rm ${test4933_ppm} ${testodd_ppm} ${testeven_ppm}
diff --git a/test/pamsumm.test b/test/pamsumm.test
index 9697a2b9..a99dea0e 100755
--- a/test/pamsumm.test
+++ b/test/pamsumm.test
@@ -1,9 +1,7 @@
 #! /bin/bash
 # This script tests: pamsumm
-# Also requires: 
+# Also requires:
 
-  alias pamsumm="${PBM_TESTPREFIX}pamsumm"
-  shopt -s expand_aliases
 
 for type in -sum -min -max -mean
   do
diff --git a/test/pamtopam.test b/test/pamtopam.test
index e2ec5adf..394d9904 100755
--- a/test/pamtopam.test
+++ b/test/pamtopam.test
@@ -1,9 +1,7 @@
 #! /bin/bash
 # This script tests: pamtopam
-# Also requires: 
+# Also requires:
 
-  alias pamtopam="${PBM_TESTPREFIX}pamtopam"
-  shopt -s expand_aliases
 
 pamtopam < testimg.ppm  | sed '/ENDHDR/q'
 pamtopam < testgrid.pbm | sed '/ENDHDR/q'
diff --git a/test/pbmclean.test b/test/pbmclean.test
index 5f324c5e..a8e469b1 100755
--- a/test/pbmclean.test
+++ b/test/pbmclean.test
@@ -2,11 +2,6 @@
 # This script tests: pbmclean
 # Also requires: pbmmake pbmpage pnmmargin pnmpad
 
-  alias pbmclean="${PBM_TESTPREFIX}pbmclean"
-  alias pbmmake="${PBM_BINPREFIX}pbmmake"
-  alias pbmpage="${PBM_BINPREFIX}pbmpage"
-  alias pnmmargin="${PBM_BINPREFIX}pnmmargin"
-  shopt -s expand_aliases
 
 tmpdir=${tmpdir:-/tmp}
 test_pbm=${tmpdir}/test.pbm
diff --git a/test/pbmmake.test b/test/pbmmake.test
index eb4b472d..4b18e3ea 100755
--- a/test/pbmmake.test
+++ b/test/pbmmake.test
@@ -1,9 +1,7 @@
 #! /bin/bash
 # This script tests: pbmmake
-# Also requires: 
+# Also requires:
 
-  alias pbmmake="${PBM_TESTPREFIX}pbmmake"
-  shopt -s expand_aliases
 
 for i in `seq 1 8`
 do
@@ -18,4 +16,3 @@ do
   pbmmake -b $i $i ;
   pbmmake  -g $i $i ) | cksum
 done
-
diff --git a/test/pbmminkowski.test b/test/pbmminkowski.test
index 120441f1..389ff44a 100755
--- a/test/pbmminkowski.test
+++ b/test/pbmminkowski.test
@@ -2,10 +2,6 @@
 # This script tests: pbmminkowski
 # Also requires: pbmmake pnmmargin pnmpad
 
-  alias pbmminkowski="${PBM_TESTPREFIX}pbmminkowski"
-  alias pbmmake="${PBM_BINPREFIX}pbmmake"
-  alias pnmmargin="${PBM_BINPREFIX}pnmmargin"
-  shopt -s expand_aliases
 
 pbmmake -w 1 1 | pnmmargin -b 1 | \
   pbmminkowski
diff --git a/test/pbmpage.test b/test/pbmpage.test
index c03ee8d7..e9bfe352 100755
--- a/test/pbmpage.test
+++ b/test/pbmpage.test
@@ -1,9 +1,7 @@
 #! /bin/bash
-# This script tests: pbmpage 
-# Also requires: 
+# This script tests: pbmpage
+# Also requires:
 
-  alias pbmpage="${PBM_TESTPREFIX}pbmpage"
-  shopt -s expand_aliases
 
 pbmpage 1 | cksum
 pbmpage 2 | cksum
diff --git a/test/pbmpscale.test b/test/pbmpscale.test
index 50ae470d..42046c74 100755
--- a/test/pbmpscale.test
+++ b/test/pbmpscale.test
@@ -2,12 +2,8 @@
 # This script tests: pbmpscale
 # Also requires: pamenlarge pbmtext
 
-  alias pbmpscale="${PBM_TESTPREFIX}pbmpscale"
-  alias pamenlarge="${PBM_BINPREFIX}pamenlarge"
-  alias pbmtext="${PBM_BINPREFIX}pbmtext"
-  shopt -s expand_aliases
 
-pbmtext -nomargin "F" | pbmpscale 3 -plain 
+pbmtext -nomargin "F" | pbmpscale 3 -plain
 
 for i in 2 3 4
 do
diff --git a/test/pbmtext.test b/test/pbmtext.test
index 21020969..dffb2cb4 100755
--- a/test/pbmtext.test
+++ b/test/pbmtext.test
@@ -1,9 +1,7 @@
 #! /bin/bash
 # This script tests: pbmtext
-# Also requires: 
+# Also requires:
 
-  alias pbmtext="${PBM_TESTPREFIX}pbmtext"
-  shopt -s expand_aliases
 
 for i in 0123456789 abcdefghijk lmnopqrst uzwxyz ABCDEFGHIJK LMNOPQRST UVWXYZ
 do
diff --git a/test/pbmtog3.test b/test/pbmtog3.test
index 74b901e3..15c0cdf9 100755
--- a/test/pbmtog3.test
+++ b/test/pbmtog3.test
@@ -2,9 +2,6 @@
 # This script tests: pbmtog3
 # Also requires: pbmmake
 
-  alias pbmtog3="${PBM_TESTPREFIX}pbmtog3"
-  alias pbmmake="${PBM_BINPREFIX}pbmmake"
-  shopt -s expand_aliases
 
 # Test 1.  Should print 3697098186 144
 pbmtog3 testgrid.pbm | cksum
diff --git a/test/pbmupc.test b/test/pbmupc.test
index 39e4c10c..275117d5 100755
--- a/test/pbmupc.test
+++ b/test/pbmupc.test
@@ -1,9 +1,7 @@
 #! /bin/bash
 # This script tests: pbmupc
-# Also requires: 
+# Also requires:
 
-  alias pbmupc="${PBM_TESTPREFIX}pbmupc"
-  shopt -s expand_aliases
 
 for type in -s1 -s2
 do
diff --git a/test/pcx-roundtrip.test b/test/pcx-roundtrip.test
index 5efbbca9..3dba42b9 100755
--- a/test/pcx-roundtrip.test
+++ b/test/pcx-roundtrip.test
@@ -1,10 +1,7 @@
+#! /bin/bash
 # This script tests: ppmtopcx pcxtoppm
 # Also requires: pnmremap
 
-  alias ppmtopcx="${PBM_TESTPREFIX}ppmtopcx"
-  alias pcxtoppm="${PBM_TESTPREFIX}pcxtoppm"
-  alias ppmremap="${PBM_BINPREFIX}ppmremap"
-  shopt -s expand_aliases
 
 tmpdir=${tmpdir:-/tmp}
 pcxstd_ppm=${tmpdir}/pcxstd_ppm
@@ -46,4 +43,3 @@ rm ${testpcx_ppm} ${pcxstd_ppm}
 # result of:
 # pgmtoppm < testgrid.pbm | cksum
 ppmtopcx -stdpalette -packed testgrid.pbm | pcxtoppm | cksum
-
diff --git a/test/pfm-roundtrip.test b/test/pfm-roundtrip.test
index 650cc4d0..f1b5d418 100755
--- a/test/pfm-roundtrip.test
+++ b/test/pfm-roundtrip.test
@@ -2,10 +2,6 @@
 # This script tests: pamtopfm pfmtopam
 # Also requires: pamtopnm
 
-  alias pamtopfm="${PBM_TESTPREFIX}pamtopfm"
-  alias pfmtopam="${PBM_TESTPREFIX}pfmtopam"
-  alias pamtopnm="${PBM_BINPREFIX}pamtopnm"
-  shopt -s expand_aliases
 
 # Should print 1926073387 101484, cksum of testimg.ppm
 pamtopfm testimg.ppm | pfmtopam | \
diff --git a/test/pgmbentley.test b/test/pgmbentley.test
index 8af2c59c..0429d54b 100755
--- a/test/pgmbentley.test
+++ b/test/pgmbentley.test
@@ -2,9 +2,6 @@
 # This script tests: pgmbentley
 # Also requires: pgmramp
 
-  alias pgmbentley="${PBM_TESTPREFIX}pgmbentley"
-  alias pgmramp="${PBM_BINPREFIX}pgmramp"
-  shopt -s expand_aliases
 
 # Test. Should produce 4127286153 16399
 pgmramp -rect 128 128 | pgmbentley | cksum
diff --git a/test/pgmcrater.ok b/test/pgmcrater.ok
deleted file mode 100644
index aa2592c9..00000000
--- a/test/pgmcrater.ok
+++ /dev/null
@@ -1 +0,0 @@
-3828822912 65551
diff --git a/test/pgmcrater.test b/test/pgmcrater.test
deleted file mode 100755
index ffba435f..00000000
--- a/test/pgmcrater.test
+++ /dev/null
@@ -1,31 +0,0 @@
-#! /bin/bash
-# This script tests: pgmcrater
-
-  alias pgmcrater="${PBM_TESTPREFIX}pgmcrater"
-  shopt -s expand_aliases
-
-# This test is sensitive to differences in floating point math.
-# With GCC slight results start to appear with -number 75 in
-# the following test.  Compiler type (GCC, Clang, etc.),
-# SSE math (by default off with x86 32 bit on with x86 64 bit)
-# and --ffast-math are factors.
-
-# We hope that by keeping the number of craters small the
-# difference will not show up.
-#
-# The slight differences in the image file are not discernable by
-# the naked eye.
-
-testrandom -q
-case $? in
-   81)
-      # Should print: 3828822912 65551
-      pgmcrater -quiet -number 25 -randomseed 1 | cksum
-      ;;
-
-   8[02-9] | 90)
-       echo "Skipping: random number generator is not glibc." 1>&2
-       exit 80;;
-
-   *)  exit 1;;  # testrandom failed
-esac
diff --git a/test/pgmhist.test b/test/pgmhist.test
index 32b18189..42666fbf 100755
--- a/test/pgmhist.test
+++ b/test/pgmhist.test
@@ -2,9 +2,6 @@
 # This script tests: pgmhist
 # Also requires: pgmramp
 
-  alias pgmhist="${PBM_TESTPREFIX}pgmhist"
-  alias pgmramp="${PBM_BINPREFIX}pgmramp"
-  shopt -s expand_aliases
 
 # Ignore differences in spaces.
 
diff --git a/test/pgmmake.test b/test/pgmmake.test
index 2c384e1b..4a3c4842 100755
--- a/test/pgmmake.test
+++ b/test/pgmmake.test
@@ -1,13 +1,7 @@
 #! /bin/bash
 # This script tests: pgmmake
-# Also requires: 
+# Also requires:
 
-  alias pgmmake="${PBM_TESTPREFIX}pgmmake"
-  shopt -s expand_aliases
 
 pgmmake 1 50 50 | cksum
-pgmmake .2 50 100 -maxval=5 | cksum 
-
-
-
- 
+pgmmake .2 50 100 -maxval=5 | cksum
diff --git a/test/pgmnoise.test b/test/pgmnoise.test
index a5c1c380..0b38553b 100755
--- a/test/pgmnoise.test
+++ b/test/pgmnoise.test
@@ -1,9 +1,7 @@
 #! /bin/bash
 # This script tests: pgmnoise
-# Also requires: 
+# Also requires:
 
-  alias pgmnoise="${PBM_TESTPREFIX}pgmnoise"
-  shopt -s expand_aliases
 
 # We first check whether random number generator is glibc rand().
 # If not, this test is skipped.
diff --git a/test/pgmramp.test b/test/pgmramp.test
index 231b9311..f6f770fe 100755
--- a/test/pgmramp.test
+++ b/test/pgmramp.test
@@ -1,11 +1,9 @@
 #! /bin/bash
 # This script tests: pgmramp
-# Also requires: 
+# Also requires:
 
-  alias pgmramp="${PBM_TESTPREFIX}pgmramp"
-  shopt -s expand_aliases
 
-for type in -lr -tb -rectangle -ellipse -diagonal 
+for type in -lr -tb -rectangle -ellipse -diagonal
 do
 pgmramp -maxval=6 $type 4 4 -plain
 done
@@ -15,4 +13,3 @@ do pgmramp $type 256 256 | cksum
 done
 
 pgmramp -diagonal -maxval=510 256 256 | cksum
-  
\ No newline at end of file
diff --git a/test/pgmtopgm.test b/test/pgmtopgm.test
index 388cca93..e919fdac 100755
--- a/test/pgmtopgm.test
+++ b/test/pgmtopgm.test
@@ -1,8 +1,6 @@
 #! /bin/bash
 # This script tests: pgmtopgm
-# Also requires: 
+# Also requires:
 
-  alias pgmtopgm="${PBM_TESTPREFIX}pgmtopgm"
-  shopt -s expand_aliases
 
 pgmtopgm < testgrid.pbm | cksum
diff --git a/test/pgmtoppm.test b/test/pgmtoppm.test
index f2d0fffb..70df0d97 100755
--- a/test/pgmtoppm.test
+++ b/test/pgmtoppm.test
@@ -2,11 +2,6 @@
 # This script tests: pgmtoppm
 # Also requires: pamseq pamtopnm pgmramp
 
-  alias pgmtoppm="${PBM_TESTPREFIX}pgmtoppm"
-  alias pamseq="${PBM_BINPREFIX}pamseq"
-  alias pamtopnm="${PBM_BINPREFIX}pamtopnm"
-  alias pgmramp="${PBM_BINPREFIX}pgmramp"
-  shopt -s expand_aliases
 
 tmpdir=${tmpdir:-/tmp}
 
@@ -25,5 +20,3 @@ pgmtoppm yellow-blue ${test_pgm} | cksum
 pgmtoppm -map=${palette} ${test_pgm} | cksum
 
 rm ${test_pgm} ${palette}
-
-
diff --git a/test/pi3-roundtrip.test b/test/pi3-roundtrip.test
index cd4232eb..5700337d 100755
--- a/test/pi3-roundtrip.test
+++ b/test/pi3-roundtrip.test
@@ -1,11 +1,7 @@
+#! /bin/bash
 # This script tests: pbmtopi3 pi3topbm
 # Also requires: pbmmake pamcut
 
-  alias pbmtopi3="${PBM_TESTPREFIX}pbmtopi3"
-  alias pi3topbm="${PBM_TESTPREFIX}pi3topbm"
-  alias pbmmake="${PBM_BINPREFIX}pbmmake"
-  alias pamcut="${PBM_BINPREFIX}pamcut"
-  shopt -s expand_aliases
 
 # The pi3 image format specifies a fixed image size of 640x400.
 # Pbmtopi3 rejects images that do not conform.
@@ -14,9 +10,7 @@
 # Should print: 3139449799 32011
 pbmmake -g 640 400 | pbmtopi3 | pi3topbm | cksum
 
-# Test 2. 
+# Test 2.
 # Should print: 2425386270 41
 pamcut -pad 0 0 640 400 testgrid.pbm | \
   pbmtopi3 | pi3topbm | pamcut 0 0 14 16 | cksum
-
-
diff --git a/test/pict-roundtrip.test b/test/pict-roundtrip.test
index 457cb4b8..cd207d48 100755
--- a/test/pict-roundtrip.test
+++ b/test/pict-roundtrip.test
@@ -2,13 +2,6 @@
 # This script tests: picttoppm ppmtopict
 # Also requires: pamseq pamdepth pamtopnm pnmremap
 
-  alias picttoppm="${PBM_TESTPREFIX}picttoppm"
-  alias ppmtopict="${PBM_TESTPREFIX}ppmtopict"
-  alias pamseq="${PBM_BINPREFIX}pamseq"
-  alias pamdepth="${PBM_BINPREFIX}pamdepth"
-  alias pamtopnm="${PBM_BINPREFIX}pamtopnm"
-  alias pnmremap="${PBM_BINPREFIX}pnmremap"
-  shopt -s expand_aliases
 
 #Test.  Should print 984199586 101484
 pamseq 3 5 -tupletype=RGB | pamdepth 255 | pamtopnm | \
diff --git a/test/png-roundtrip.test b/test/png-roundtrip.test
index dc05420a..e70f6765 100755
--- a/test/png-roundtrip.test
+++ b/test/png-roundtrip.test
@@ -1,10 +1,7 @@
 #! /bin/bash
-# This script tests: pngtopnm pnmtopng
-# Also requires: 
+# This script tests: pngtopam pnmtopng
+# Also requires:
 
-  alias pngtopnm="${PBM_TESTPREFIX}pngtopnm"
-  alias pnmtopng="${PBM_TESTPREFIX}pnmtopng"
-  shopt -s expand_aliases
 
 # Test 1.  Should print 1926073387 101484 18 times
 for flags in "" -interlace \
@@ -25,7 +22,7 @@ for flags in "" -interlace \
   -comp_strategy=filtered \
   -force
   do
-pnmtopng testimg.ppm $flags | pngtopnm | cksum
+pnmtopng testimg.ppm $flags | pngtopam | cksum
 done
 
 # Test 2.  Should print 2425386270 41 18 times
@@ -47,5 +44,5 @@ for flags in "" -interlace \
   -comp_strategy=filtered \
   -force
   do
-  pnmtopng testgrid.pbm $flags | pngtopnm | cksum
+  pnmtopng testgrid.pbm $flags | pngtopam | cksum
   done
diff --git a/test/pnm-pam-roundtrip.test b/test/pnm-pam-roundtrip.test
index 506d25aa..b8e60c88 100755
--- a/test/pnm-pam-roundtrip.test
+++ b/test/pnm-pam-roundtrip.test
@@ -1,11 +1,7 @@
 #! /bin/bash
 # This script tests: pamtopam pamtopnm
-# Also requires: 
+# Also requires:
 
-  alias pamtopam="${PBM_TESTPREFIX}pamtopam"
-  alias pamtopnm="${PBM_TESTPREFIX}pamtopnm"
-  shopt -s expand_aliases
 
 pamtopam < testimg.ppm | pamtopnm | cksum
 pamtopam < testgrid.pbm | pamtopnm | cksum
-
diff --git a/test/pnm-plain-roundtrip.test b/test/pnm-plain-roundtrip.test
index 7d0293ee..3779d761 100755
--- a/test/pnm-plain-roundtrip.test
+++ b/test/pnm-plain-roundtrip.test
@@ -1,12 +1,9 @@
 #! /bin/bash
-# This script tests: pnmtopnm
-# Also requires: pamtopnm
+# This script tests: pamtopnm
+#
 
-  alias pnmtopnm="${PBM_TESTPREFIX}pnmtopnm"
-  shopt -s expand_aliases
-
-pnmtopnm -plain testimg.ppm | \
-  pnmtopnm | cksum
-pnmtopnm -plain testgrid.pbm | \
-  pnmtopnm | cksum
 
+pamtopnm -plain testimg.ppm | \
+  pamtopnm | cksum
+pamtopnm -plain testgrid.pbm | \
+  pamtopnm | cksum
diff --git a/test/pnmcat.test b/test/pnmcat.test
index b77c90fd..c643320d 100755
--- a/test/pnmcat.test
+++ b/test/pnmcat.test
@@ -1,9 +1,7 @@
 #! /bin/bash
 # This script tests: pnmcat
-# Also requires: 
+# Also requires:
 
-  alias pnmcat="${PBM_TESTPREFIX}pnmcat"
-  shopt -s expand_aliases
 
 pnmcat -lr testgrid.pbm testgrid.pbm | cksum
 pnmcat -tb testgrid.pbm testgrid.pbm | cksum
diff --git a/test/pnminvert-roundtrip.test b/test/pnminvert-roundtrip.test
index eb3e2b35..52d15039 100755
--- a/test/pnminvert-roundtrip.test
+++ b/test/pnminvert-roundtrip.test
@@ -1,9 +1,7 @@
 #! /bin/bash
 # This script tests: pnminvert
-# Also requires: 
+# Also requires:
 
-  alias pnminvert="${PBM_TESTPREFIX}pnminvert"
-  shopt -s expand_aliases
 
 pnminvert testimg.ppm | pnminvert | cksum
 pnminvert testgrid.pbm | pnminvert | cksum
diff --git a/test/pnminvert.test b/test/pnminvert.test
index f779d574..b80716ef 100755
--- a/test/pnminvert.test
+++ b/test/pnminvert.test
@@ -1,10 +1,7 @@
 #! /bin/bash
 # This script tests: pnminvert
-# Also requires: pbmmake
+# Also requires: pbmmake pamchannel pamtopnm
 
-  alias pnminvert="${PBM_TESTPREFIX}pnminvert"
-  alias pbmmake="${PBM_BINPREFIX}pbmmake"
-  shopt -s expand_aliases
 
 # Test 1.  Should print 1240379484 41
 pnminvert testgrid.pbm | cksum
@@ -12,7 +9,7 @@ pnminvert testgrid.pbm | cksum
 # Test 2.  Should print 1416115901 101484
 pnminvert testimg.ppm | cksum
 
-# Test 3.  Should print 
+# Test 3.  Should print 1174803406 33838
 pamchannel -infile=testimg.ppm -tupletype="GRAYSCALE" 0 | pamtopnm | \
   pnminvert | cksum
 
diff --git a/test/pnmpsnr.ok b/test/pnmpsnr.ok
index eff18efa..b303cc9d 100644
--- a/test/pnmpsnr.ok
+++ b/test/pnmpsnr.ok
@@ -1,2 +1,2 @@
 0.00 dB
-don't differ.
+no difference
diff --git a/test/pnmpsnr.test b/test/pnmpsnr.test
index db1f0079..3e7408ec 100755
--- a/test/pnmpsnr.test
+++ b/test/pnmpsnr.test
@@ -2,9 +2,6 @@
 # This script tests: pnmpsnr
 # Also requires: pbmmake
 
-  alias pnmpsnr="${PBM_TESTPREFIX}pnmpsnr"
-  alias pbmmake="${PBM_BINPREFIX}pbmmake"
-  shopt -s expand_aliases
 
 tmpdir=${tmpdir:-/tmp}
 
@@ -16,8 +13,8 @@ pbmmake -w 10 10 > ${w_pbm}
 pbmmake -b 10 10 > ${b_pbm}
 
 pnmpsnr  ${w_pbm}  ${b_pbm} 2>&1 | \
- awk '{print $(NF-1),$NF}'
+ awk '$2=="lumina" {print $(NF-1),$NF}'
 pnmpsnr  ${w_pbm}  ${w_pbm} 2>&1 | \
- awk '{print $(NF-1),$NF}'
+ awk '$2=="lumina" {print $(NF-1),$NF}'
 
 rm ${b_pbm} ${w_pbm}
diff --git a/test/pnmremap1.test b/test/pnmremap1.test
index 20bee75d..d7c5189c 100755
--- a/test/pnmremap1.test
+++ b/test/pnmremap1.test
@@ -1,15 +1,10 @@
 #! /bin/bash
 # This script tests: pnmremap
-# Also requires: pamdepth pamseq pamtopnm
+# Also requires: pamseq pamtopnm
 
-  alias pnmremap="${PBM_TESTPREFIX}pnmremap"
-  alias pamdepth="${PBM_BINPREFIX}pamdepth"
-  alias pamseq="${PBM_BINPREFIX}pamseq"
-  alias pamtopnm="${PBM_BINPREFIX}pamtopnm"
-  shopt -s expand_aliases
 
 tmpdir=${tmpdir:-/tmp}
-palette=${tmpdir}/palette 
+palette=${tmpdir}/palette
 #palette255=${tmpdir}/palette255
 
 pamseq 3 5 -tupletype=RGB | pamtopnm > ${palette}
@@ -19,7 +14,7 @@ pamseq 3 5 -tupletype=RGB | pamtopnm > ${palette}
 # This fails with older versions of Netpbm and x86-64.
 # May also fail on other non-Intel architectures.
 # v. 10.59.2
-# x86-32: 2667816854 101482 
+# x86-32: 2667816854 101482
 # x86-64: 3602410851 101482
 
 pnmremap -mapfile=${palette} -floyd -norandom \
diff --git a/test/pnmremap2.test b/test/pnmremap2.test
index e5444fda..76c2d566 100755
--- a/test/pnmremap2.test
+++ b/test/pnmremap2.test
@@ -2,14 +2,9 @@
 # This script tests: pnmremap
 # Also requires: pamdepth pamseq pamtopnm
 
-  alias pnmremap="${PBM_TESTPREFIX}pnmremap"
-  alias pamdepth="${PBM_BINPREFIX}pamdepth"
-  alias pamseq="${PBM_BINPREFIX}pamseq"
-  alias pamtopnm="${PBM_BINPREFIX}pamtopnm"
-  shopt -s expand_aliases
 
 tmpdir=${tmpdir:-/tmp}
-palette=${tmpdir}/palette 
+palette=${tmpdir}/palette
 palette255=${tmpdir}/palette255
 
 pamseq 3 5 -tupletype=RGB | pamtopnm > ${palette}
diff --git a/test/pnmshear.test b/test/pnmshear.test
index 30ab45be..a19a9852 100755
--- a/test/pnmshear.test
+++ b/test/pnmshear.test
@@ -2,10 +2,6 @@
 # This script tests: pnmshear
 # Also requires: pbmmake pnmpad
 
-  alias pnmshear="${PBM_TESTPREFIX}pnmshear"
-  alias pbmmake="${PBM_BINPREFIX}pbmmake"
-  alias pnmpad="${PBM_BINPREFIX}pnmpad"
-  shopt -s expand_aliases
 
 # Test.  Should produce 598644601 24
 
diff --git a/test/pnmtile.test b/test/pnmtile.test
index 40d9cfc2..409c0e50 100755
--- a/test/pnmtile.test
+++ b/test/pnmtile.test
@@ -2,9 +2,6 @@
 # This script tests: pnmtile
 # Also requires: pnmcat
 
-  alias pnmtile="${PBM_TESTPREFIX}pnmtile"
-  alias pnmcat="${PBM_BINPREFIX}pnmcat"
-  shopt -s expand_aliases
 
 # Test 1.  Should print 4228632379 259
 pnmtile 40 50 testgrid.pbm | cksum
diff --git a/test/pnmtopnm-plain.test b/test/pnmtopnm-plain.test
index f4e0749e..5b7e4b48 100755
--- a/test/pnmtopnm-plain.test
+++ b/test/pnmtopnm-plain.test
@@ -1,15 +1,10 @@
 #! /bin/bash
-# This script tests: pnmtopnm
-# Also requires: pgmtopgm ppmtoppm pamtopnm
+# This script tests: pamtopnm
+# Also requires: pgmtopgm ppmtoppm
 
-  alias pnmtopnm="${PBM_TESTPREFIX}pnmtopnm"
-  alias pgmtopgm="${PBM_BINPREFIX}pgmtopgm"
-  alias ppmtoppm="${PBM_BINPREFIX}ppmtoppm"
-  shopt -s expand_aliases
+pamtopnm -plain testgrid.pbm
 
-pnmtopnm -plain testgrid.pbm
+pgmtopgm < testgrid.pbm | pamtopnm -plain
 
-pgmtopgm < testgrid.pbm | pnmtopnm -plain
-
-ppmtoppm < testgrid.pbm | pnmtopnm -plain | \
+ppmtoppm < testgrid.pbm | pamtopnm -plain | \
   head -n11
diff --git a/test/ppmbrighten.test b/test/ppmbrighten.test
index 29cfeb2c..fa7702d8 100755
--- a/test/ppmbrighten.test
+++ b/test/ppmbrighten.test
@@ -1,9 +1,7 @@
 #! /bin/bash
 # This script tests: ppmbrighten
-# Also requires: 
+# Also requires:
 
-  alias ppmbrighten="${PBM_TESTPREFIX}ppmbrighten"
-  shopt -s expand_aliases
 
 ppmbrighten -v 100 testimg.ppm | cksum
 ppmbrighten -v 100 -normalize testimg.ppm | cksum
diff --git a/test/ppmchange-roundtrip.test b/test/ppmchange-roundtrip.test
index 071c0b93..78f5b548 100755
--- a/test/ppmchange-roundtrip.test
+++ b/test/ppmchange-roundtrip.test
@@ -2,11 +2,6 @@
 # This script tests: ppmchange
 # Also requires: pgmtopbm pnminvert ppmtopgm
 
-  alias ppmchange="${PBM_TESTPREFIX}ppmchange"
-  alias pgmtopbm="${PBM_BINPREFIX}pgmtopbm"
-  alias pnminvert="${PBM_BINPREFIX}pnminvert"
-  alias ppmtopgm="${PBM_BINPREFIX}ppmtopgm"
-  shopt -s expand_aliases
 
 ppmchange black white white black testgrid.pbm | \
 pnminvert | ppmtopgm | \
diff --git a/test/ppmchange.test b/test/ppmchange.test
index 9805be0a..d29a699f 100755
--- a/test/ppmchange.test
+++ b/test/ppmchange.test
@@ -2,10 +2,6 @@
 # This script tests: ppmchange
 # Also requires: ppmrainbow pgmramp
 
-  alias ppmchange="${PBM_TESTPREFIX}ppmchange"
-  alias ppmrainbow="${PBM_BINPREFIX}ppmrainbow"
-  alias pgmramp="${PBM_BINPREFIX}pgmramp"
-  shopt -s expand_aliases
 
 #  Failure message
 ## If this test fails and ppmchange-roundtrip.test succeeds,
@@ -57,7 +53,7 @@ rm ${rainbow_ppm}
 #   -remainder=black -closeness=25  ${rainbow_ppm} | \
 #   pphist -sort=rgb -noheader
 #
-#     0     0     0	    0	     75 
-#     0     0   255	   29	     42 
-#     0    50     2	   30	     42 
-#   100     0     1	   30	     41 
+#     0     0     0	    0	     75
+#     0     0   255	   29	     42
+#     0    50     2	   30	     42
+#   100     0     1	   30	     41
diff --git a/test/ppmcie.test b/test/ppmcie.test
index 973787ec..0ce69dea 100755
--- a/test/ppmcie.test
+++ b/test/ppmcie.test
@@ -2,10 +2,6 @@
 # This script tests: ppmcie
 # Also requires: pamsumm pamsharpness
 
-  alias ppmcie="${PBM_TESTPREFIX}ppmcie"
-  alias pamsharpness="${PBM_BINPREFIX}pamsharpness"
-  alias pamsumm="${PBM_BINPREFIX}pamsumm"
-  shopt -s expand_aliases
 
 # Failure message
 ## Ppmcie is sensitive to system factors.  If this test fails, please
@@ -17,8 +13,8 @@ tmpdir=${tmpdir:-/tmp}
 # Without -nolabel -noaxes -nowpoint -noblack older versions of
 # Netpbm produce slightly different charts.
 # Output from "ppmcie | cksum" :
-# v. 10.35.86: 288356530 786447   
-# v. 10.59.2 : 2292601420 786447  
+# v. 10.35.86: 288356530 786447
+# v. 10.59.2 : 2292601420 786447
 
 ppmcie_ppm=${tmpdir}/ppmcie.ppm
 
diff --git a/test/ppmdfont.test b/test/ppmdfont.test
index 30f74a9c..7d894789 100755
--- a/test/ppmdfont.test
+++ b/test/ppmdfont.test
@@ -1,11 +1,7 @@
 #! /bin/bash
 # This script tests: ppmdmkfont ppmddumpfont ppmdcfont
-# Also requires: 
+# Also requires:
 
-  alias ppmdcfont="${PBM_TESTPREFIX}ppmdcfont"
-  alias ppmddumpfont="${PBM_TESTPREFIX}ppmddumpfont"
-  alias ppmdmkfont="${PBM_TESTPREFIX}ppmdmkfont"
-  shopt -s expand_aliases
 
 # Test 1. Should produce: 2726488777 48129
 ppmdmkfont | ppmddumpfont 2>&1 | cksum
@@ -13,7 +9,9 @@ ppmdmkfont | ppmddumpfont 2>&1 | cksum
 # Test 2. Should produce: 2845495212 75033
 ppmdmkfont | ppmdcfont | cksum
 
-# There is a strange glitch in output when ppmdcfont is compiled by clang:
+# There is a strange glitch in output when ppmdcfont is compiled by
+# clang version 3.2.  Optimization (-O3) seems to be a factor.
+# 
 # 3171,3173c3171,3173
 # <     0x01,
 # <     95,
diff --git a/test/ppmdim.test b/test/ppmdim.test
index cdd7df17..848e2e9f 100755
--- a/test/ppmdim.test
+++ b/test/ppmdim.test
@@ -1,12 +1,7 @@
 #! /bin/bash
 # This script tests: ppmdim
-# Also requires: pamfunc pnmarith pamarith pamsumm
+# Also requires: pamfunc pamarith pamsumm
 
-  alias ppmdim="${PBM_TESTPREFIX}ppmdim"
-  alias pamfunc="${PBM_BINPREFIX}pamfunc"
-  alias pamsumm="${PBM_BINPREFIX}pamsumm"
-  alias pnmarith="${PBM_BINPREFIX}pnmarith"
-  shopt -s expand_aliases
 
 tmpdir=${tmpdir:-/tmp}
 
@@ -22,9 +17,9 @@ for i in  0.125 0.25 0.5 0.75 0.1 0.0117 0.2 0.4 0.333 0.666 0.8 0.9 0.95
   do
   ppmdim $i testimg.ppm > ${dim1_ppm}
   pamfunc -mult=$i testimg.ppm > ${dim2_ppm}
-  pnmarith -diff ${dim1_ppm} ${dim2_ppm} | \
+  pamarith -diff ${dim1_ppm} ${dim2_ppm} | \
     pamsumm -mean -brief | \
-    awk '{print $1<0.75 ? "ok" : "fail"}'
+    awk '{print ($1<0.75) ? "ok" : "fail"}'
   done
 
 rm ${dim1_ppm} ${dim2_ppm}
diff --git a/test/ppmdither.test b/test/ppmdither.test
index a93a434a..7e32ef59 100755
--- a/test/ppmdither.test
+++ b/test/ppmdither.test
@@ -1,9 +1,7 @@
 #! /bin/bash
 # This script tests: ppmdither
-# Also requires: 
+# Also requires:
 
-  alias ppmdither="${PBM_TESTPREFIX}ppmdither"
-  shopt -s expand_aliases
 
 ppmdither testimg.ppm | cksum
 ppmdither -red 2 -green 2 -blue 2 testimg.ppm | cksum
diff --git a/test/ppmforge.test b/test/ppmforge.test
index 09a66916..65280d14 100755
--- a/test/ppmforge.test
+++ b/test/ppmforge.test
@@ -1,8 +1,6 @@
 #! /bin/bash
 # This script tests: ppmforge
-
-  alias ppmforge="${PBM_TESTPREFIX}ppmforge"
-  shopt -s expand_aliases
+# Also requires:
 
 # Use small x y values to avoid floating point issues.
 
diff --git a/test/ppmgauss.test b/test/ppmgauss.test
index 9dfdd2f6..213810c7 100755
--- a/test/ppmgauss.test
+++ b/test/ppmgauss.test
@@ -1,9 +1,7 @@
 #! /bin/bash
 # This script tests: pamgauss
-# Also requires: 
+# Also requires:
 
-  alias pamgauss="${PBM_TESTPREFIX}pamgauss"
-  shopt -s expand_aliases
 
 for i in `seq 3 11`
 do
diff --git a/test/ppmhist.test b/test/ppmhist.test
index 6dcbc762..97fbd79d 100755
--- a/test/ppmhist.test
+++ b/test/ppmhist.test
@@ -2,10 +2,6 @@
 # This script tests: ppmhist
 # Also requires: pgmramp
 
-  alias ppmhist="${PBM_TESTPREFIX}ppmhist"
-  alias pgmramp="${PBM_BINPREFIX}pgmramp"
-  shopt -s expand_aliases
 
 pgmramp -maxval=8 -lr 8 2 | ppmhist -sort=rgb
 ppmhist -map -sort=rgb testimg.ppm | cksum
-
diff --git a/test/ppmmake.test b/test/ppmmake.test
index faba1ace..879a367e 100755
--- a/test/ppmmake.test
+++ b/test/ppmmake.test
@@ -1,14 +1,7 @@
 #! /bin/bash
 # This script tests: ppmmake
-# Also requires: 
+# Also requires:
 
-  alias ppmmake="${PBM_TESTPREFIX}ppmmake"
-  shopt -s expand_aliases
 
 ppmmake rgb:ff/80/80 50 100 -maxval=5 | cksum
 ppmmake red 50 50  | cksum
-
-
-
-
- 
diff --git a/test/ppmmix.test b/test/ppmmix.test
index 9a54143f..e1c6486b 100755
--- a/test/ppmmix.test
+++ b/test/ppmmix.test
@@ -3,15 +3,6 @@
 # Also requires: pamdepth pamenlarge pamsumm pbmmake
 # Also requires: pgmtopgm pnminvert ppmtopgm
 
-  alias ppmmix="${PBM_TESTPREFIX}ppmmix"
-  alias pamdepth="${PBM_BINPREFIX}pamdepth"
-  alias pamenlarge="${PBM_BINPREFIX}pamenlarge"
-  alias pamsumm="${PBM_BINPREFIX}pamsumm"
-  alias pbmmake="${PBM_BINPREFIX}pbmmake"
-  alias pgmtopgm="${PBM_BINPREFIX}pgmtopgm"
-  alias pnminvert="${PBM_BINPREFIX}pnminvert"
-  alias ppmtopgm="${PBM_BINPREFIX}ppmtopgm"
-  shopt -s expand_aliases
 
 tmpdir=${tmpdir:-/tmp}
 
@@ -25,9 +16,9 @@ ppmmix 0.75 ${a1_pgm} ${a2_pgm} | ppmtopgm | pamdepth 3 -plain &&
 rm ${a1_pgm} ${a2_pgm}
 
 # Mix image with itself.
-# Output should match input regardless of ratio. 
+# Output should match input regardless of ratio.
 for i in 0 0.5 0.6 1
-do 
+do
 ppmmix $i testimg.ppm testimg.ppm | cksum
 done
 
diff --git a/test/ppmpat.test b/test/ppmpat.test
index bf1e9316..89f86f67 100755
--- a/test/ppmpat.test
+++ b/test/ppmpat.test
@@ -1,8 +1,6 @@
 #! /bin/bash
 # This script tests: ppmpat
-
-  alias ppmpat="${PBM_TESTPREFIX}ppmpat"
-  shopt -s expand_aliases
+# Also requires:
 
 # TODO: Write tests for squig and poles.  It appears that they are
 # sensitive to differences in floating point math.
diff --git a/test/ppmrelief.test b/test/ppmrelief.test
index 378a22c9..3467dcde 100755
--- a/test/ppmrelief.test
+++ b/test/ppmrelief.test
@@ -2,11 +2,6 @@
 # This script tests: ppmrelief
 # Also requires: pbmmake pgmramp pamflip
 
-  alias ppmrelief="${PBM_TESTPREFIX}ppmrelief"
-  alias pbmmake="${PBM_BINPREFIX}pbmmake"
-  alias pgmramp="${PBM_BINPREFIX}pgmramp"
-  alias pamflip="${PBM_BINPREFIX}pamflip"
-  shopt -s expand_aliases
 
 # Test 1.  Should print 3637356697 688
 pbmmake -w 15 15 | ppmrelief | cksum
@@ -39,4 +34,3 @@ pgmramp -diagonal -maxval=30 16 16 | pamflip -lr | ppmrelief | cksum
 # 0 14 14 14 14 14 14 14 14 14 14 14 14 14 14 0
 # 0 14 14 14 14 14 14 14 14 14 14 14 14 14 14 0
 # 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-
diff --git a/test/ppmrough.test b/test/ppmrough.test
index dbe92c29..cf948f9f 100755
--- a/test/ppmrough.test
+++ b/test/ppmrough.test
@@ -1,9 +1,6 @@
 #! /bin/bash
 # This script tests: ppmrough
-
-  alias ppmrough="${PBM_TESTPREFIX}ppmrough"
-  shopt -s expand_aliases
-
+# Also requires:
 
 testrandom -q
 case $? in
diff --git a/test/ppmtoarbtxt-roundtrip.ok b/test/ppmtoarbtxt-roundtrip.ok
new file mode 100644
index 00000000..a29d1c2b
--- /dev/null
+++ b/test/ppmtoarbtxt-roundtrip.ok
@@ -0,0 +1,2 @@
+1926073387 101484
+1926073387 101484
diff --git a/test/ppmtoarbtxt-roundtrip.test b/test/ppmtoarbtxt-roundtrip.test
new file mode 100755
index 00000000..dff78250
--- /dev/null
+++ b/test/ppmtoarbtxt-roundtrip.test
@@ -0,0 +1,34 @@
+#! /bin/bash
+# This script tests: ppmtoarbtxt
+# Also requires: pnminvert pamtopnm
+
+# Test.  Invert colors.
+# Should print 1926073387 101484
+
+tmpdir=${tmpdir:-/tmp}
+headskl=${tmpdir}/headskl
+bodyskl=${tmpdir}/bodyskl
+inv_ppm=${tmpdir}/inv.ppm
+
+cat > ${headskl} << EOF
+P3
+#(width) #(height)
+255
+
+EOF
+
+cat > ${bodyskl} << EOF
+#(ired %d 255 0) #(igreen %d 255 0) #(iblue %d 255 0)
+
+EOF
+
+ppmtoarbtxt ${bodyskl} -hd ${headskl} testimg.ppm | tee ${inv_ppm} |
+  pnminvert | cksum
+
+
+# Test 2.
+
+cat ${inv_ppm} | ppmtoarbtxt ${bodyskl} -hd ${headskl} | pamtopnm | cksum
+
+
+rm ${bodyskl} ${headskl}
diff --git a/test/ppmtopgm.test b/test/ppmtopgm.test
index 94e0ae91..8503194b 100755
--- a/test/ppmtopgm.test
+++ b/test/ppmtopgm.test
@@ -1,10 +1,7 @@
 #! /bin/bash
 # This script tests: ppmtopgm
-# Also requires: 
+# Also requires:
 
-  alias ppmtopgm="${PBM_TESTPREFIX}ppmtopgm"
-  shopt -s expand_aliases
 
 # Test 1. Should produce 2871603838 33838
 ppmtopgm testimg.ppm | cksum
-
diff --git a/test/ppmtoppm.test b/test/ppmtoppm.test
index 2d84809a..797c733d 100755
--- a/test/ppmtoppm.test
+++ b/test/ppmtoppm.test
@@ -1,8 +1,6 @@
 #! /bin/bash
 # This script tests: ppmtoppm
-# Also requires: 
+# Also requires:
 
-  alias ppmtoppm="${PBM_TESTPREFIX}ppmtoppm"
-  shopt -s expand_aliases
 
 ppmtoppm < testgrid.pbm | cksum
diff --git a/test/ppmwheel.test b/test/ppmwheel.test
index 89bab029..f528e209 100755
--- a/test/ppmwheel.test
+++ b/test/ppmwheel.test
@@ -1,9 +1,7 @@
 #! /bin/bash
 # This script tests: ppmwheel
-# Also requires: 
+# Also requires:
 
-  alias ppmwheel="${PBM_TESTPREFIX}ppmwheel"
-  shopt -s expand_aliases
 
 # For values 6 and above, x86(-32) and x86-64 produce different output.
 # SSE floating-point math is the probable cause.
@@ -110,7 +108,3 @@ done
 #  98:  4086203619 28825    1961862620 28825
 #  99:  3656777902 29416    2475351252 29416
 # 100:  2246720411 30015    4055518595 30015
-
-
-
- 
diff --git a/test/ps-alt-roundtrip.test b/test/ps-alt-roundtrip.test
index d61e55d9..d90c4ddb 100755
--- a/test/ps-alt-roundtrip.test
+++ b/test/ps-alt-roundtrip.test
@@ -1,14 +1,7 @@
 #! /bin/bash
 # This script tests: pbmtoepsi pbmtopsg3 pbmtolps psidtopgm pstopnm
-# Also requires: gs pnmtopnm pnmcrop
+# Also requires: gs pnmcrop
 
-  alias pbmtoepsi="${PBM_TESTPREFIX}pbmtoepsi"
-  alias pbmtolps="${PBM_TESTPREFIX}pbmtolps"
-  alias pbmtopsg3="${PBM_TESTPREFIX}pbmtopsg3"
-  alias psidtopgm="${PBM_TESTPREFIX}psidtopgm"
-  alias pstopnm="${PBM_TESTPREFIX}pstopnm"
-  alias pnmcrop="${PBM_BINPREFIX}pnmcrop"
-  shopt -s expand_aliases
 
 # This script is for testing alternative (or minor) utilities that
 # read/write Postscript and encapsulated Postscript:
@@ -25,8 +18,8 @@
 ## pbmtoepsi, pbmtopsg3, pbmtolps or psidtopgm.
 ## If both tests fail it indicates a problem with pstopnm or gs.
 
-# pstopnm does not use libnetpbm functions for output. 
-# Output is filtered through pnmtopnm.
+# pstopnm does not use libnetpbm functions for output.
+# Output is filtered through at least one Netpbm program.
 
 # Test 1. Should print: 2425386270 41
 testgrid1_ps=${tmpdir}/testgrid1.ps
@@ -54,7 +47,7 @@ rm ${testgrid2_ps}
 # Test 3. Should print: 2916080186 235
 # Output is pgm maxval=1 with black and white inverted.
 #
-testgrid_epsi=${tmpdir}/testgrid.epsi 
+testgrid_epsi=${tmpdir}/testgrid.epsi
 
 pbmtoepsi testgrid.pbm > ${testgrid_epsi} && \
 xysizebps=`awk  '/BeginPreview/ {print $2,$3,$4}' \
@@ -64,4 +57,4 @@ awk '/^%%BeginPreview:/ { p=1; next } /^%%EndImage/ { p=0; next } \
   p==1 {print "!"$0}' \
     ${testgrid_epsi} | psidtopgm $xysizebps | cksum
 
-rm ${testgrid_epsi} 
+rm ${testgrid_epsi}
diff --git a/test/ps-roundtrip.test b/test/ps-roundtrip.test
index 4773d4a6..873bbdef 100755
--- a/test/ps-roundtrip.test
+++ b/test/ps-roundtrip.test
@@ -1,15 +1,7 @@
 #! /bin/bash
 # This script tests: pnmtops pstopnm
-# Also requires: pnmtopnm pamtopnm gs pbmmake pnmshear pnmpad pnmcat
+# Also requires: pamtopnm gs pbmmake pnmshear pnmpad pnmcat
 
-  alias pnmtops="${PBM_TESTPREFIX}pnmtops"
-  alias pstopnm="${PBM_TESTPREFIX}pstopnm"
-  alias pbmmake="${PBM_BINPREFIX}pbmmake"
-  alias pnmcat="${PBM_BINPREFIX}pnmcat"
-  alias pnmpad="${PBM_BINPREFIX}pnmpad"
-  alias pnmshear="${PBM_BINPREFIX}pnmshear"
-  alias pnmtopnm="${PBM_BINPREFIX}pnmtopnm"
-  shopt -s expand_aliases
 
 # Failure message
 ## This test fails when:
@@ -18,8 +10,8 @@
 
 tmpdir=${tmpdir:-/tmp}
 
-# pstopnm does not use libnetpbm functions for output. 
-# Output is filtered through pnmtopnm.
+# pstopnm does not use libnetpbm functions for output.
+# Output is filtered through pamtopnm.
 
 # Test 1.  Should print: 1926073387 101484 five times
 # *NOTE* Fifth iteration fails if pnmtops was compiled without zlib
@@ -33,7 +25,7 @@ for flag in "" "-ps" "-rle" "-ps -ascii" "-ps -flate"
   xysize1=`awk  '/BoundingBox/ {print "-xsize="$4,"-ysize="$5}' \
     ${test1_ps}` && \
   pstopnm -portrait -xborder=0 -yborder=0 $xysize1 -stdout -quiet \
-    ${test1_ps} | pnmtopnm | cksum
+    ${test1_ps} | pamtopnm | cksum
   done
 
 rm ${test1_ps}
@@ -52,14 +44,14 @@ pbmmake -g 8 4 | \
   pnmcat -tb -jright - ${g_pbm} > ${t_pbm} &&
 for flag in "" "-rle" "-ps -rle -ascii" \
             "-bitspersample=2 -rle" "-ps -bitspersample=4 -rle" \
-            "-bitspersample=8 -rle" "-ps -bitspersample=12 -rle -dict" 
+            "-bitspersample=8 -rle" "-ps -bitspersample=12 -rle -dict"
   do
   pnmtops -nocenter -equalpixels -dpi 72 -noturn  ${flag} ${t_pbm} \
     > ${grid_ps} && \
   xysize2=`awk  '/BoundingBox/ {print "-xsize="$4,"-ysize="$5}' \
       ${grid_ps}` && \
   pstopnm -portrait -xborder=0 -yborder=0 $xysize2 -stdout \
-    -quiet ${grid_ps} -pbm | pnmtopnm | cksum
+    -quiet ${grid_ps} -pbm | pamtopnm | cksum
   done
 
 rm ${grid_ps} ${g_pbm} ${t_pbm}
@@ -74,7 +66,7 @@ rm ${grid_ps} ${g_pbm} ${t_pbm}
 # (2) awk: xy values are taken from the first "BoundingBox" encountered.
 #          Subsequent BoundingBox values are ignored.
 # (3) pstopnm: input must be an ordinary file.  Input from stdin
-#     (by pipe or input redirection: "< file" ) does not work.              
+#     (by pipe or input redirection: "< file" ) does not work.
 #
 
 test3_ps=${tmpdir}/testimg3.ps
@@ -88,7 +80,7 @@ pnmtops -nocenter -equalpixels -dpi 72 -noturn -setpage ${flag} \
 xysize3=`awk  '/BoundingBox/ {print "-xsize="$4,"-ysize="$5 ; exit}' \
   ${test3_ps}` &&
 pstopnm -portrait -xborder=0 -yborder=0 $xysize3 -stdout  ${test3_ps} | \
-  pnmtopnm | cksum
+  pamtopnm | cksum
   done
 
 rm ${test3_ps}
diff --git a/test/rgb3-roundtrip.test b/test/rgb3-roundtrip.test
index 091fe46b..cac52220 100755
--- a/test/rgb3-roundtrip.test
+++ b/test/rgb3-roundtrip.test
@@ -2,12 +2,6 @@
 # This script tests: ppmtorgb3 rgb3toppm
 # Also requires: pgmtopbm pgmtopgm ppmtopgm
 
-  alias ppmtorgb3="${PBM_TESTPREFIX}ppmtorgb3"
-  alias rgb3toppm="${PBM_TESTPREFIX}rgb3toppm"
-  alias pgmtopbm="${PBM_BINPREFIX}pgmtopbm"
-  alias pgmtopgm="${PBM_BINPREFIX}pgmtopgm"
-  alias ppmtopgm="${PBM_BINPREFIX}ppmtopgm"
-  shopt -s expand_aliases
 
 # Break an image into three monochrome planes, reassemble the
 # image from them and check whether the resulting output is
diff --git a/test/sbig-roundtrip.test b/test/sbig-roundtrip.test
index 7a339470..1fdaccfd 100755
--- a/test/sbig-roundtrip.test
+++ b/test/sbig-roundtrip.test
@@ -1,10 +1,7 @@
 #! /bin/bash
 # This script tests: pgmtosbig sbigtopgm
-# Also requires: pamchannel
+# Also requires: pamchannel pamtopnm
 
-  alias sbigtopgm="${PBM_TESTPREFIX}sbigtopgm"
-  alias pgmtosbig="${PBM_TESTPREFIX}pgmtosbig"
-  shopt -s expand_aliases
 
 # Should produce 1571496937 33838, cksum of testimg.red
 
diff --git a/test/sgi-roundtrip.test b/test/sgi-roundtrip.test
index 99b5735e..5012aab7 100755
--- a/test/sgi-roundtrip.test
+++ b/test/sgi-roundtrip.test
@@ -2,10 +2,6 @@
 # This script tests: pnmtosgi sgitopnm
 # Also requires: rgb3toppm
 
-  alias pnmtosgi="${PBM_TESTPREFIX}pnmtosgi"
-  alias sgitopnm="${PBM_TESTPREFIX}sgitopnm"
-  alias rgb3toppm="${PBM_BINPREFIX}rgb3toppm"
-  shopt -s expand_aliases
 
 a_sgi=${tmpdir}/a.sgi
 a_red=${tmpdir}/a.red
diff --git a/test/st4-roundtrip.test b/test/st4-roundtrip.test
index bd3da5f1..ffe8f348 100755
--- a/test/st4-roundtrip.test
+++ b/test/st4-roundtrip.test
@@ -2,9 +2,6 @@
 # This script tests: pgmtost4 st4topgm
 # Also requires: pamchannel pamtopnm pamcut
 
-  alias st4topgm="${PBM_TESTPREFIX}st4topgm"
-  alias pgmtost4="${PBM_TESTPREFIX}pgmtost4"
-  shopt -s expand_aliases
 
 # Input image of pgmtost4 must by 192x165
 
diff --git a/test/sunrast-roundtrip.test b/test/sunrast-roundtrip.test
index 78e4ae15..a5cfa8c7 100755
--- a/test/sunrast-roundtrip.test
+++ b/test/sunrast-roundtrip.test
@@ -1,10 +1,7 @@
 #! /bin/bash
 # This script tests: pnmtorast rasttopnm
-# Also requires: 
+# Also requires:
 
-  alias pnmtorast="${PBM_TESTPREFIX}pnmtorast"
-  alias rasttopnm="${PBM_TESTPREFIX}rasttopnm"
-  shopt -s expand_aliases
 
 # Should produce 1926073387 101484, cksum of testimg.ppm
-pnmtorast testimg.ppm | rasttopnm | cksum 
+pnmtorast testimg.ppm | rasttopnm | cksum
diff --git a/test/symmetry.test b/test/symmetry.test
index 596b67b2..e6a6b654 100755
--- a/test/symmetry.test
+++ b/test/symmetry.test
@@ -2,13 +2,6 @@
 # This script tests: pgmramp pamgauss pgmkernel pbmmake pbmpscale
 # Also requires: pamflip
 
-  alias pgmramp="${PBM_TESTPREFIX}pgmramp"
-  alias pamgauss="${PBM_TESTPREFIX}pamgauss"
-  alias pgmkernel="${PBM_TESTPREFIX}pgmkernel"
-  alias pbmmake="${PBM_TESTPREFIX}pbmmake"
-  alias pbmpscale="${PBM_TESTPREFIX}pbmpscale"
-  alias pamflip="${PBM_BINPREFIX}pamflip"
-  shopt -s expand_aliases
 
 # All tests print "ok" upon success, cksum results otherwise.
 # The "$3>0" is a kludge for preventing false positives with empty files.
@@ -102,4 +95,3 @@ pgmramp -ell 101 33 > ${ell_pgm}
   awk '$1==3 && $3>0 { print "ok"; exit }; { print }'
 
 rm ${ell_pgm}
-
diff --git a/test/targa-roundtrip.test b/test/targa-roundtrip.test
index 66e666c6..f646b8c1 100755
--- a/test/targa-roundtrip.test
+++ b/test/targa-roundtrip.test
@@ -1,11 +1,7 @@
 #! /bin/bash
 # This script tests: pamtotga tgatoppm
-# Also requires: pgmtopbm
+# Also requires: ppmtopgm pgmtopbm pamchannel
 
-  alias pamtotga="${PBM_TESTPREFIX}pamtotga"
-  alias tgatoppm="${PBM_TESTPREFIX}tgatoppm"
-  alias pgmtopbm="${PBM_BINPREFIX}pgmtopbm"
-  shopt -s expand_aliases
 
 #Test 1: Should print 2425386270 41, cksum of testgrid.pbm
 
diff --git a/test/testrandom.c b/test/testrandom.c
index 3f65f0d2..43414926 100644
--- a/test/testrandom.c
+++ b/test/testrandom.c
@@ -9,6 +9,9 @@
   Options:
     -q : quiet mode
     -v : verbose mode : Use to generate values for new table 
+
+  This is a self-contained program which does not require any libnetpbm
+  functions.
 =============================================================================*/
 #include <stdio.h>
 #include <stdlib.h>
diff --git a/test/tiff-roundtrip.test b/test/tiff-roundtrip.test
index 410148a5..a99425fa 100755
--- a/test/tiff-roundtrip.test
+++ b/test/tiff-roundtrip.test
@@ -1,10 +1,7 @@
 #! /bin/bash
 # This script tests: pamtotiff tifftopnm
-# Also requires: 
+# Also requires:
 
-  alias pamtotiff="${PBM_TESTPREFIX}pamtotiff"
-  alias tifftopnm="${PBM_TESTPREFIX}tifftopnm"
-  shopt -s expand_aliases
 
 # Failure message
 ## Second test fails if Netpbm was built without the flate library
@@ -12,14 +9,14 @@
 pamtotiff testimg.ppm 1<>${tmpdir}/test1.tiff &&
   tifftopnm ${tmpdir}/test1.tiff | cksum
 
-# test flate compression 
+# test flate compression
 pamtotiff -flate testimg.ppm 1<>${tmpdir}/test2.tiff &&
   tifftopnm ${tmpdir}/test2.tiff | cksum
 
 pamtotiff testgrid.pbm 1<>${tmpdir}/test3.tiff &&
   tifftopnm ${tmpdir}/test3.tiff | cksum
 
-# test G4 compression 
+# test G4 compression
 pamtotiff -g4 testgrid.pbm 1<>${tmpdir}/test4.tiff &&
   tifftopnm ${tmpdir}/test4.tiff | cksum
 
diff --git a/test/utahrle-roundtrip.test b/test/utahrle-roundtrip.test
index dd88265c..982b72a9 100755
--- a/test/utahrle-roundtrip.test
+++ b/test/utahrle-roundtrip.test
@@ -1,10 +1,7 @@
 #! /bin/bash
 # This script tests: pnmtorle rletopnm
-# Also requires: 
+# Also requires: pamchannel pamtopnm
 
-  alias pnmtorle="${PBM_TESTPREFIX}pnmtorle"
-  alias rletopnm="${PBM_TESTPREFIX}rletopnm"
-  shopt -s expand_aliases
 
 #Test 1.  Should produce 1571496937 33838, cksum of testimg.red
 pamchannel -infile=testimg.ppm -tupletype="GRAYSCALE" 0 | pamtopnm | \
diff --git a/test/wbmp-roundtrip.test b/test/wbmp-roundtrip.test
index 40988635..b651c3d0 100755
--- a/test/wbmp-roundtrip.test
+++ b/test/wbmp-roundtrip.test
@@ -1,10 +1,7 @@
 #! /bin/bash
 # This script tests: pbmtowbmp wbmptopbm
-# Also requires: 
+# Also requires:
 
-  alias pbmtowbmp="${PBM_TESTPREFIX}pbmtowbmp"
-  alias wbmptopbm="${PBM_TESTPREFIX}wbmptopbm"
-  shopt -s expand_aliases
 
 # Should print 2425386270 41, cksum of testgrid.pbm
 pbmtowbmp testgrid.pbm | wbmptopbm | cksum
diff --git a/test/winicon-roundtrip.test b/test/winicon-roundtrip.test
index 20b0a225..b37a33e1 100755
--- a/test/winicon-roundtrip.test
+++ b/test/winicon-roundtrip.test
@@ -1,17 +1,9 @@
 #! /bin/bash
 # This script tests: pamtowinicon winicontopam
-# Also requires: pnmcut pnmtile pamtopnm ppmtopgm pgmtopbm
+# Also requires: pamcut pnmtile pamtopnm ppmtopgm pgmtopbm
 
-  alias pamtowinicon="${PBM_TESTPREFIX}pamtowinicon"
-  alias winicontopam="${PBM_TESTPREFIX}winicontopam"
-  alias pamtopnm="${PBM_BINPREFIX}pamtopnm"
-  alias pgmtopbm="${PBM_BINPREFIX}pgmtopbm"
-  alias pnmcut="${PBM_BINPREFIX}pnmcut"
-  alias pnmtile="${PBM_BINPREFIX}pnmtile"
-  alias ppmtopgm="${PBM_BINPREFIX}ppmtopgm"
-  shopt -s expand_aliases
 
-pnmcut --left=30 --width=48 --height=48 testimg.ppm | \
+pamcut --left=30 --width=48 --height=48 testimg.ppm | \
 pamtowinicon | winicontopam | \
   pamtopnm | cksum
 
@@ -19,4 +11,3 @@ pnmtile 32 32 testgrid.pbm | \
 pamtowinicon | winicontopam | \
   pamtopnm | ppmtopgm | \
   pgmtopbm  -th -val=0.5 | cksum
-
diff --git a/test/xbm-roundtrip.test b/test/xbm-roundtrip.test
index 4823adfd..e84d6fc3 100755
--- a/test/xbm-roundtrip.test
+++ b/test/xbm-roundtrip.test
@@ -1,10 +1,7 @@
 #! /bin/bash
 # This script tests: pbmtoxbm xbmtopbm
-# Also requires: 
+# Also requires:
 
-  alias pbmtoxbm="${PBM_TESTPREFIX}pbmtoxbm"
-  alias xbmtopbm="${PBM_TESTPREFIX}xbmtopbm"
-  shopt -s expand_aliases
 
 pbmtoxbm testgrid.pbm | xbmtopbm | cksum
 pbmtoxbm -x10 testgrid.pbm | xbmtopbm | cksum
diff --git a/test/xpm-roundtrip.test b/test/xpm-roundtrip.test
index c3c9894d..fd0253b1 100755
--- a/test/xpm-roundtrip.test
+++ b/test/xpm-roundtrip.test
@@ -2,11 +2,6 @@
 # This script tests: ppmtoxpm xpmtoppm
 # Also requires: pgmtopbm ppmtopgm
 
-  alias ppmtoxpm="${PBM_TESTPREFIX}ppmtoxpm"
-  alias xpmtoppm="${PBM_TESTPREFIX}xpmtoppm"
-  alias pgmtopbm="${PBM_BINPREFIX}pgmtopbm"
-  alias ppmtopgm="${PBM_BINPREFIX}ppmtopgm"
-  shopt -s expand_aliases
 
 #ppmtoxpm -hexonly testimg.ppm | \
 # xpmtoppm  | cksum
diff --git a/test/xv-roundtrip.ok b/test/xv-roundtrip.ok
new file mode 100644
index 00000000..ac7f0d99
--- /dev/null
+++ b/test/xv-roundtrip.ok
@@ -0,0 +1 @@
+2418728144 101484
diff --git a/test/xv-roundtrip.test b/test/xv-roundtrip.test
new file mode 100755
index 00000000..d73933a1
--- /dev/null
+++ b/test/xv-roundtrip.test
@@ -0,0 +1,7 @@
+#! /bin/bash
+# This script tests: pamtoxvmini xvminitoppm
+# Also requires: pamdepth
+
+# Test.  Should print 2418728144 101484
+
+pamdepth 3 testimg.ppm | pamtoxvmini | xvminitoppm | cksum
diff --git a/test/xwd-roundtrip.test b/test/xwd-roundtrip.test
index 4dbd3020..cd0d38ad 100755
--- a/test/xwd-roundtrip.test
+++ b/test/xwd-roundtrip.test
@@ -1,11 +1,7 @@
 #! /bin/bash
 # This script tests: pnmtoxwd xwdtopnm
-# Also requires: pamdepth 
+# Also requires: pamchannel pamtopnm pamdepth
 
-  alias pnmtoxwd="${PBM_TESTPREFIX}pnmtoxwd"
-  alias xwdtopnm="${PBM_TESTPREFIX}xwdtopnm"
-  alias pamdepth="${PBM_BINPREFIX}pamdepth"
-  shopt -s expand_aliases
 
 # Test 1.  Should produce 1571496937 33838, cksum of testimg.red
 pamchannel -infile=testimg.ppm -tupletype="GRAYSCALE" 0 | pamtopnm | \
diff --git a/test/yuv-roundtrip.test b/test/yuv-roundtrip.test
index 8e0d4f1a..e339b418 100755
--- a/test/yuv-roundtrip.test
+++ b/test/yuv-roundtrip.test
@@ -2,10 +2,6 @@
 # This script tests: ppmtoyuv yuvtoppm
 # Also requires: pamgradient
 
-  alias ppmtoyuv="${PBM_TESTPREFIX}ppmtoyuv"
-  alias yuvtoppm="${PBM_TESTPREFIX}yuvtoppm"
-  alias pamgradient="${PBM_BINPREFIX}pamgradient"
-  shopt -s expand_aliases
 
 # Should produce 1904478375 253455
 
diff --git a/version.mk b/version.mk
index 03b6a600..efb5250b 100644
--- a/version.mk
+++ b/version.mk
@@ -1,3 +1,3 @@
 NETPBM_MAJOR_RELEASE = 10
-NETPBM_MINOR_RELEASE = 70
-NETPBM_POINT_RELEASE = 7
+NETPBM_MINOR_RELEASE = 71
+NETPBM_POINT_RELEASE = 0