summaryrefslogtreecommitdiff
path: root/graphics/netpbm
diff options
context:
space:
mode:
authortron <tron>1998-07-15 19:52:55 +0000
committertron <tron>1998-07-15 19:52:55 +0000
commit464cb18ad43b31452e84740ffaeb6b3dc56fd9fd (patch)
treea9a0c2b126b7164ff33a46687d38de3f6d6d3809 /graphics/netpbm
parentf1c4717f65f7a5abd26350b263fd26a8fdabe5a7 (diff)
downloadpkgsrc-464cb18ad43b31452e84740ffaeb6b3dc56fd9fd.tar.gz
Add well known fixes for "netpbm-1mar1994" supplied by John F. Woods
in PR pkg/5723.
Diffstat (limited to 'graphics/netpbm')
-rw-r--r--graphics/netpbm/patches/patch-ba50
-rw-r--r--graphics/netpbm/patches/patch-bb11
-rw-r--r--graphics/netpbm/patches/patch-bc13
-rw-r--r--graphics/netpbm/patches/patch-bd16
-rw-r--r--graphics/netpbm/patches/patch-be137
-rw-r--r--graphics/netpbm/patches/patch-bf13
-rw-r--r--graphics/netpbm/patches/patch-bg36
-rw-r--r--graphics/netpbm/patches/patch-bh11
-rw-r--r--graphics/netpbm/patches/patch-bi66
-rw-r--r--graphics/netpbm/patches/patch-bj1872
-rw-r--r--graphics/netpbm/patches/patch-bk164
-rw-r--r--graphics/netpbm/patches/patch-bl374
-rw-r--r--graphics/netpbm/patches/patch-bm29
-rw-r--r--graphics/netpbm/patches/patch-bn52
-rw-r--r--graphics/netpbm/patches/patch-bo24
-rw-r--r--graphics/netpbm/patches/patch-bp174
-rw-r--r--graphics/netpbm/patches/patch-bq23
-rw-r--r--graphics/netpbm/patches/patch-br38
-rw-r--r--graphics/netpbm/patches/patch-bs11
-rw-r--r--graphics/netpbm/patches/patch-bt13
-rw-r--r--graphics/netpbm/patches/patch-bu11
-rw-r--r--graphics/netpbm/patches/patch-bv11
-rw-r--r--graphics/netpbm/patches/patch-bw27
-rw-r--r--graphics/netpbm/patches/patch-bx211
-rw-r--r--graphics/netpbm/patches/patch-by113
-rw-r--r--graphics/netpbm/patches/patch-bz51
-rw-r--r--graphics/netpbm/pkg/PLIST4
27 files changed, 3554 insertions, 1 deletions
diff --git a/graphics/netpbm/patches/patch-ba b/graphics/netpbm/patches/patch-ba
new file mode 100644
index 00000000000..997750d9aba
--- /dev/null
+++ b/graphics/netpbm/patches/patch-ba
@@ -0,0 +1,50 @@
+--- ./pnm/anytopnm.orig Mon Oct 4 05:11:29 1993
++++ ./pnm/anytopnm Sat Jul 20 22:19:05 1996
+@@ -53,7 +53,7 @@
+ ;;
+
+ *GIF* )
+- giftoppm "$file"
++ giftopnm "$file"
+ break
+ ;;
+
+@@ -82,6 +82,15 @@
+ break
+ ;;
+
++ *JPEG* | *JFIF* )
++ djpeg "$file"
++ ;;
++
++ *PNG* )
++ pngtopnm "$file"
++ break
++ ;;
++
+ * )
+ # Can't figure out the file type from the magic number,
+ # try the extension.
+@@ -130,7 +139,7 @@
+ fitstopgm "$file"
+ ;;
+ *.gif | *.gif.* )
+- giftoppm "$file"
++ giftopnm "$file"
+ ;;
+ *.iff | *.iff.* | *.ilbm | *.ilbm.* )
+ ilbmtoppm "$file"
+@@ -168,6 +177,13 @@
+ *.ybm | *.ybm.* | *.face | *.face.* )
+ ybmtopbm "$file"
+ ;;
++ *.JPEG | *.jpeg | *.jpg | *.JPG )
++ djpeg "$file"
++ ;;
++ *.png | *.PNG )
++ pngtopnm "$file"
++ break
++ ;;
+ * )
+ echo "$0: unknown file type" 1>&2
+ exit 1
diff --git a/graphics/netpbm/patches/patch-bb b/graphics/netpbm/patches/patch-bb
new file mode 100644
index 00000000000..59910e104f3
--- /dev/null
+++ b/graphics/netpbm/patches/patch-bb
@@ -0,0 +1,11 @@
+--- ./pbm/libpbm1.c.orig Mon Jan 10 12:37:22 1994
++++ ./pbm/libpbm1.c Sun Aug 13 00:03:56 1995
+@@ -132,7 +132,7 @@
+ if ( isupper( c1 ) )
+ c1 = tolower( c1 );
+ if ( isupper( c2 ) )
+- c1 = tolower( c2 );
++ c2 = tolower( c2 );
+ if ( c1 != c2 )
+ return 0;
+ }
diff --git a/graphics/netpbm/patches/patch-bc b/graphics/netpbm/patches/patch-bc
new file mode 100644
index 00000000000..fde93cf1ea7
--- /dev/null
+++ b/graphics/netpbm/patches/patch-bc
@@ -0,0 +1,13 @@
+--- ./pbm/pbmmerge.c.orig Wed Nov 3 04:28:55 1993
++++ ./pbm/pbmmerge.c Sat Aug 12 23:51:57 1995
+@@ -29,6 +29,10 @@
+ {
+ ++argv;
+ --argc;
++ if(!*argv) {
++ fprintf(stderr, "Usage: pbmmerge pbm_program_name [args ...]\n");
++ exit(1);
++ }
+ goto again;
+ }
+
diff --git a/graphics/netpbm/patches/patch-bd b/graphics/netpbm/patches/patch-bd
new file mode 100644
index 00000000000..4f2d17fb84a
--- /dev/null
+++ b/graphics/netpbm/patches/patch-bd
@@ -0,0 +1,16 @@
+--- ./pbm/pbmtext.c.orig Wed Oct 27 03:27:04 1993
++++ ./pbm/pbmtext.c Sat Jul 20 21:48:12 1996
+@@ -105,10 +105,12 @@
+ else
+ { /* Read text from stdin. */
+ lines = 0;
+- while ( gets( buf ) != NULL )
++ while ( fgets( buf, sizeof(buf), stdin ) != NULL )
+ {
+ int l;
++ char *nl = strchr(buf, '\n');
+
++ if (nl) *nl = 0;
+ fix_control_chars( buf );
+ l = strlen( buf );
+ if ( lines >= maxlines )
diff --git a/graphics/netpbm/patches/patch-be b/graphics/netpbm/patches/patch-be
new file mode 100644
index 00000000000..7aa02036b6f
--- /dev/null
+++ b/graphics/netpbm/patches/patch-be
@@ -0,0 +1,137 @@
+--- ./pbm/pbmto10x.c.orig Mon Oct 4 05:10:42 1993
++++ ./pbm/pbmto10x.c Sat Aug 12 23:36:40 1995
+@@ -1,6 +1,6 @@
+ /* pbmto10x.c - read a portable bitmap and produce a Gemini 10X printer file
+ **
+-** Copyright (C) 1990 by Ken Yap
++** Copyright (C) 1990, 1994 by Ken Yap
+ **
+ ** Permission to use, copy, modify, and distribute this software and its
+ ** documentation for any purpose and without fee is hereby granted, provided
+@@ -8,6 +8,8 @@
+ ** copyright notice and this permission notice appear in supporting
+ ** documentation. This software is provided "as is" without express or
+ ** implied warranty.
++**
++** Modified to shorten stripes and eliminate blank stripes. Dec 1994.
+ */
+
+ #include "pbm.h"
+@@ -52,15 +54,40 @@
+ }
+
+ static void
++outstripe(stripe, sP, reschar)
++ register char *stripe, *sP;
++ register int reschar;
++{
++ register int ncols;
++
++ /* scan backwards, removing empty columns */
++ while (sP != stripe)
++ if (*--sP != 0)
++ {
++ ++sP;
++ break;
++ }
++ ncols = sP - stripe;
++ if (ncols > 0)
++ {
++ printf("\033%c%c%c", reschar, ncols % 256, ncols / 256);
++ fwrite(stripe, sizeof(char), ncols, stdout);
++ }
++ putchar('\n'); /* flush buffer */
++}
++
++static void
+ res_60x72()
+ {
+ register int i, item, npins, row, col;
+ bit *bitrows[LOW_RES_ROWS], *bP[LOW_RES_ROWS];
++ char *stripe, *sP;
+
++ stripe = malloc(cols);
+ for (i = 0; i < LOW_RES_ROWS; ++i)
+ bitrows[i] = pbm_allocrow(cols);
+ printf("\033A\010"); /* '\n' = 8/72 */
+- for (row = 0; row < rows; row += LOW_RES_ROWS)
++ for (row = 0, sP = stripe; row < rows; row += LOW_RES_ROWS, sP = stripe)
+ {
+ if (row + LOW_RES_ROWS <= rows)
+ npins = LOW_RES_ROWS;
+@@ -68,17 +95,18 @@
+ npins = rows - row;
+ for (i = 0; i < npins; ++i)
+ pbm_readpbmrow(ifp, bP[i] = bitrows[i], cols, format);
+- printf("\033K%c%c", cols % 256, cols / 256);
+ for (col = 0; col < cols; ++col)
+ {
+ item = 0;
+ for (i = 0; i < npins; ++i)
+ if (*(bP[i]++) == PBM_BLACK)
+ item |= 1 << (7 - i);
+- putchar(item);
++ *sP++ = item;
+ }
+- putchar('\n');
++ outstripe(stripe, sP, 'K');
+ }
++ printf("\033@");
++ free(stripe);
+ }
+
+ static void
+@@ -86,11 +114,13 @@
+ {
+ register int i, pin, item, npins, row, col;
+ bit *bitrows[HIGH_RES_ROWS], *bP[HIGH_RES_ROWS];
++ char *stripe, *sP;
+
++ stripe = malloc(cols);
+ for (i = 0; i < HIGH_RES_ROWS; ++i)
+ bitrows[i] = pbm_allocrow(cols);
+- putchar('\033'); putchar('3'); putchar('\0');
+- for (row = 0; row < rows; row += HIGH_RES_ROWS)
++ printf("\0333\001"); /* \n = 1/144" */
++ for (row = 0, sP = stripe; row < rows; row += HIGH_RES_ROWS, sP = stripe)
+ {
+ if (row + HIGH_RES_ROWS <= rows)
+ npins = HIGH_RES_ROWS;
+@@ -98,7 +128,6 @@
+ npins = rows - row;
+ for (i = 0; i < npins; ++i)
+ pbm_readpbmrow(ifp, bP[i] = bitrows[i], cols, format);
+- printf("\033L%c%c", cols % 256, cols / 256);
+ for (col = 0; col < cols; ++col)
+ {
+ item = 0;
+@@ -106,11 +135,10 @@
+ for (pin = i = 0; i < npins; i += 2, ++pin)
+ if (*(bP[i]++) == PBM_BLACK)
+ item |= 1 << (7 - pin);
+- putchar(item);
++ *sP++ = item;
+ }
+- putchar('\n'); /* flush buffer */
+- printf("\033J\001"); /* 1/144 down */
+- printf("\033L%c%c", cols % 256, cols / 256);
++ outstripe(stripe, sP, 'L');
++ sP = stripe;
+ for (col = 0; col < cols; ++col)
+ {
+ item = 0;
+@@ -118,9 +146,11 @@
+ for (i = 1, pin = 0; i < npins; i += 2, ++pin)
+ if (*(bP[i]++) == PBM_BLACK)
+ item |= 1 << (7 - pin);
+- putchar(item);
++ *sP++ = item;
+ }
+- putchar('\n'); /* flush buffer */
+- printf("\033J\017"); /* 15/144 down */
++ outstripe(stripe, sP, 'L');
++ printf("\033J\016"); /* 14/144 down, \n did 1/144 */
+ }
++ printf("\033@");
++ free(stripe);
+ }
diff --git a/graphics/netpbm/patches/patch-bf b/graphics/netpbm/patches/patch-bf
new file mode 100644
index 00000000000..2cf57738469
--- /dev/null
+++ b/graphics/netpbm/patches/patch-bf
@@ -0,0 +1,13 @@
+--- ./pgm/pgmmerge.c.orig Fri Jan 28 05:17:38 1994
++++ ./pgm/pgmmerge.c Sat Aug 12 23:51:14 1995
+@@ -29,6 +29,10 @@
+ {
+ ++argv;
+ --argc;
++ if(!*argv) {
++ fprintf(stderr, "Usage: pgmmerge pgm_program_name [args ...]\n");
++ exit(1);
++ }
+ goto again;
+ }
+
diff --git a/graphics/netpbm/patches/patch-bg b/graphics/netpbm/patches/patch-bg
new file mode 100644
index 00000000000..78db9a658e1
--- /dev/null
+++ b/graphics/netpbm/patches/patch-bg
@@ -0,0 +1,36 @@
+--- ./pnm/Makefile.orig Tue Jul 7 22:02:33 1998
++++ ./pnm/Makefile Wed Jul 8 07:43:20 1998
+@@ -61,19 +61,21 @@
+ pnminvert pnmnoraw pnmpad pnmpaste \
+ pnmtile pnmtoddif pnmtofits pnmtops pnmtorast \
+ pnmtorle pnmtosgi pnmtosir pnmtoxwd \
+- rasttopnm rletopnm sgitopnm sirtopnm xwdtopnm zeisstopnm
++ rasttopnm rletopnm sgitopnm sirtopnm xwdtopnm zeisstopnm \
++ pnmsmooth pnmhisteq
+ MATHBINARIES = pnmgamma pnmnlfilt pnmrotate pnmscale pnmshear
+ PNGBINARIES = pngtopnm pnmtopng
+ BINARIES = $(PORTBINARIES) $(MATHBINARIES) $(PNGBINARIES) $(TIFFBINARIES)
+-SCRIPTS = anytopnm pnmindex pnmmargin pnmsmooth pstopnm
++SCRIPTS = anytopnm pnmindex pnmmargin pstopnm
+
+ PORTOBJECTS = fitstopnm.o giftopnm.o \
+ pnmalias.o pnmarith.o pnmcat.o pnmcomp.o pnmconvol.o pnmcrop.o \
+ pnmcut.o pnmdepth.o pnmenlarge.o pnmfile.o pnmflip.o pnmhistmap.o \
+- pnminvert.o pnmnoraw.o pnmpad.o pnmpaste.o \
++ pnmhisteq.o pnminvert.o pnmnoraw.o pnmpad.o pnmpaste.o\
+ pnmtile.o pnmtoddif.o pnmtofits.o pnmtops.o pnmtorast.o \
+ pnmtosgi.o pnmtosir.o pnmtoxwd.o \
+ rasttopnm.o sgitopnm.o sirtopnm.o xwdtopnm.o zeisstopnm.o \
++ pnmsmooth.o pnmhisteq.o \
+ pnmgamma.o pnmnlfilt.o pnmrotate.o pnmscale.o pnmshear.o
+ OBJECTS = $(PORTOBJECTS)
+
+@@ -209,6 +211,8 @@
+ tifftopnm tifftopnm.o: tifftopnm.c
+ xwdtopnm xwdtopnm.o: xwdtopnm.c x10wd.h x11wd.h
+ zeisstopnm zeisstopnm.o: zeisstopnm.c
++pnmhisteq pnmhisteq.o: pnmhisteq.c
++pnmsmooth pnmsmooth.o: pnmsmooth.c
+
+ clean:
+ -rm -f *.o *.a *.cat *~ core $(BINARIES) pnmmerge
diff --git a/graphics/netpbm/patches/patch-bh b/graphics/netpbm/patches/patch-bh
new file mode 100644
index 00000000000..2454151e908
--- /dev/null
+++ b/graphics/netpbm/patches/patch-bh
@@ -0,0 +1,11 @@
+--- ./pnm/pnmarith.1.orig Sun Aug 13 00:08:22 1995
++++ ./pnm/pnmarith.1 Sun Aug 13 00:08:46 1995
+@@ -4,7 +4,7 @@
+ pnmarith - perform arithmetic on two portable anymaps
+ .SH SYNOPSIS
+ .B pnmarith
+-.BR -add | -subtract | -multiply | -difference
++.BR -add | -subtract | -multiply | -difference | -minimum | -maximum.
+ .I pnmfile1 pnmfile2
+ .SH DESCRIPTION
+ Reads two portable anymaps as input.
diff --git a/graphics/netpbm/patches/patch-bi b/graphics/netpbm/patches/patch-bi
new file mode 100644
index 00000000000..0c09a5ec15f
--- /dev/null
+++ b/graphics/netpbm/patches/patch-bi
@@ -0,0 +1,66 @@
+--- ./pnm/pnmarith.c.orig Sun Aug 13 00:04:38 1995
++++ ./pnm/pnmarith.c Sun Aug 13 00:08:04 1995
+@@ -29,7 +29,8 @@
+ xelval maxval1, maxval2, maxval3;
+ int argn, rows1, cols1, format1, rows2, cols2, format2, format3, row, col;
+ char function;
+- char* usage = "-add|-subtract|-multiply|-difference pnmfile1 pnmfile2";
++ char* usage =
++"-add|-subtract|-multiply|-difference|-minimum|-maximum pnmfile1 pnmfile2";
+
+
+ pnm_init( &argc, argv );
+@@ -48,6 +49,10 @@
+ function = '*';
+ else if ( pm_keymatch( argv[argn], "-difference", 2 ) )
+ function = 'D';
++ else if ( pm_keymatch( argv[argn], "-minimum", 2 ) )
++ function = 'N';
++ else if ( pm_keymatch( argv[argn], "-maximum", 2 ) )
++ function = 'X';
+ else
+ pm_usage( usage );
+ ++argn;
+@@ -112,7 +117,7 @@
+ pnm_promoteformatrow(
+ xelrow2, cols1, maxval2, format2, maxval3, format3 );
+
+- for ( col = 0, x1P = xelrow1, x2P = xelrow2;
++ for ( col = 0, x1P = xelrow1, x2P = xelrow2;
+ col < cols1; ++col, ++x1P, ++x2P )
+ {
+ switch ( PNM_FORMAT_TYPE(format3) )
+@@ -153,6 +158,18 @@
+ b1 = (b1>b2)?(b1-b2):(b2-b1);
+ break;
+
++ case 'N':
++ r1 = (r1>r2)?(r2):(r1);
++ g1 = (g1>g2)?(g2):(g1);
++ b1 = (b1>b2)?(b2):(b1);
++ break;
++
++ case 'X':
++ r1 = (r1>r2)?(r1):(r2);
++ g1 = (g1>g2)?(g1):(g2);
++ b1 = (b1>b2)?(b1):(b2);
++ break;
++
+ default:
+ pm_error( "can't happen" );
+ }
+@@ -188,6 +205,14 @@
+
+ case 'D':
+ g1 = (g1>g2)?(g1-g2):(g2-g1);
++ break;
++
++ case 'N':
++ g1 = (g1>g2)?(g2):(g1);
++ break;
++
++ case 'X':
++ g1 = (g1>g2)?(g1):(g2);
+ break;
+
+ default:
diff --git a/graphics/netpbm/patches/patch-bj b/graphics/netpbm/patches/patch-bj
new file mode 100644
index 00000000000..f067c9beabc
--- /dev/null
+++ b/graphics/netpbm/patches/patch-bj
@@ -0,0 +1,1872 @@
+--- ./pnm/pnmconvol.c.orig Mon Oct 4 05:11:36 1993
++++ ./pnm/pnmconvol.c Wed Jul 8 07:48:07 1998
+@@ -1,5 +1,10 @@
+ /* pnmconvol.c - general MxN convolution on a portable anymap
+ **
++** Version 2.0.1 January 30, 1995
++**
++** Major rewriting by Mike Burns
++** Copyright (C) 1994, 1995 by Mike Burns (burns@chem.psu.edu)
++**
+ ** Copyright (C) 1989, 1991 by Jef Poskanzer.
+ **
+ ** Permission to use, copy, modify, and distribute this software and its
+@@ -10,31 +15,109 @@
+ ** implied warranty.
+ */
+
++/* Version 2.0.1 Changes
++** ---------------------
++** Fixed four lines that were improperly allocated as sizeof( float ) when they
++** should have been sizeof( long ).
++**
++** Version 2.0 Changes
++** -------------------
++** Reduce run time by general optimizations and handling special cases of
++** convolution matrices. Program automatically determines if convolution
++** matrix is one of the types it can make use of so no extra command line
++** arguments are necessary.
++**
++** Examples of convolution matrices for the special cases are
++**
++** Mean Horizontal Vertical
++** x x x x x x x y z
++** x x x y y y x y z
++** x x x z z z x y z
++**
++** I don't know if the horizontal and vertical ones are of much use, but
++** after working on the mean convolution, it gave me ideas for the other two.
++**
++** Some other compiler dependent optimizations
++** -------------------------------------------
++** Created separate functions as code was getting too large to put keep both
++** PGM and PPM cases in same function and also because SWITCH statement in
++** inner loop can take progressively more time the larger the size of the
++** convolution matrix. GCC is affected this way.
++**
++** Removed use of MOD (%) operator from innermost loop by modifying manner in
++** which the current xelbuf[] is chosen.
++**
++*/
++
+ #include "pnm.h"
+
++/* Macros to verify that r,g,b values are within proper range */
++
++#define CHECK_GRAY \
++ if ( tempgsum < 0L ) g = 0; \
++ else if ( tempgsum > maxval ) g = maxval; \
++ else g = tempgsum;
++
++#define CHECK_RED \
++ if ( temprsum < 0L ) r = 0; \
++ else if ( temprsum > maxval ) r = maxval; \
++ else r = temprsum;
++
++#define CHECK_GREEN \
++ if ( tempgsum < 0L ) g = 0; \
++ else if ( tempgsum > maxval ) g = maxval; \
++ else g = tempgsum;
++
++#define CHECK_BLUE \
++ if ( tempbsum < 0L ) b = 0; \
++ else if ( tempbsum > maxval ) b = maxval; \
++ else b = tempbsum;
++
++
++static int check_convolve_type ARGS((xel **cxels));
++static void pgm_general_convolve ARGS((void));
++static void ppm_general_convolve ARGS((void));
++static void pgm_mean_convolve ARGS((void));
++static void ppm_mean_convolve ARGS((void));
++static void pgm_vertical_convolve ARGS((void));
++static void ppm_vertical_convolve ARGS((void));
++static void pgm_horizontal_convolve ARGS((void));
++static void ppm_horizontal_convolve ARGS((void));
++
++#define TRUE 1
++#define FALSE 0
++
++#define GENERAL_CONVOLVE 0
++#define MEAN_CONVOLVE 1
++#define HORIZONTAL_CONVOLVE 2
++#define VERTICAL_CONVOLVE 3
++
++static FILE* ifp;
++static float** rweights;
++static float** gweights;
++static float** bweights;
++static int crows, ccols, ccolso2, crowso2;
++static int cols, rows;
++static xelval maxval;
++static int format, newformat;
++static float rmeanweight, gmeanweight, bmeanweight;
++
+ int
+ main( argc, argv )
+ int argc;
+ char* argv[];
+ {
+ FILE* cifp;
+- FILE* ifp;
+ xel** cxels;
+- xel** xelbuf;
+- xel* outputrow;
+- xel x;
+- int argn, crows, ccols, cformat, ccolso2, crowso2;
+- int rows, cols, format, newformat, crow, row;
++ int argn, cformat;
++ int crow, row;
+ register int ccol, col;
+- xelval cmaxval, maxval;
++ xelval cmaxval;
+ xelval g;
+- float** gweights;
+ float gsum;
+- xelval r, b;
+- float** rweights;
+- float** bweights;
+ float rsum, bsum;
+ char* usage = "<convolutionfile> [pnmfile]";
++ int convolve_type;
+
+ pnm_init( &argc, argv );
+
+@@ -90,6 +173,7 @@
+ }
+ }
+
++
+ /* Set up the normalized weights. */
+ rweights = (float**) pm_allocarray( ccols, crows, sizeof(float) );
+ gweights = (float**) pm_allocarray( ccols, crows, sizeof(float) );
+@@ -115,6 +199,14 @@
+ break;
+ }
+ }
++
++ /* For mean_convolve routines. All weights of a single color are the same
++ ** so just grab any one of them.
++ */
++ rmeanweight = rweights[0][0];
++ gmeanweight = gweights[0][0];
++ bmeanweight = bweights[0][0];
++
+ switch ( PNM_FORMAT_TYPE(format) )
+ {
+ case PPM_TYPE:
+@@ -131,11 +223,199 @@
+ break;
+ }
+
++ /* Handle certain special cases when runtime can be improved. */
++
++ convolve_type = check_convolve_type(cxels);
++
++ switch ( PNM_FORMAT_TYPE(format) )
++ {
++ case PPM_TYPE:
++ switch (convolve_type)
++ {
++ case MEAN_CONVOLVE:
++ ppm_mean_convolve();
++ break;
++
++ case HORIZONTAL_CONVOLVE:
++ ppm_horizontal_convolve();
++ break;
++
++ case VERTICAL_CONVOLVE:
++ ppm_vertical_convolve();
++ break;
++
++ default: /* GENERAL_CONVOLVE */
++ ppm_general_convolve();
++ break;
++ }
++ break;
++
++ default:
++ switch (convolve_type)
++ {
++ case MEAN_CONVOLVE:
++ pgm_mean_convolve();
++ break;
++
++ case HORIZONTAL_CONVOLVE:
++ pgm_horizontal_convolve();
++ break;
++
++ case VERTICAL_CONVOLVE:
++ pgm_vertical_convolve();
++ break;
++
++ default: /* GENERAL_CONVOLVE */
++ pgm_general_convolve();
++ break;
++ }
++ break;
++ } /* PNM_TYPE */
++
++ pm_close( ifp );
++ exit( 0 );
++ }
++
++
++
++/* check_convolve_type
++**
++** Determine if the convolution matrix is one of the special cases that
++** can be processed faster than the general form.
++**
++** Does not check for the case where one of the PPM colors can have differing
++** types. Only handles cases where all PPM's are of the same special case.
++*/
++
++static int
++check_convolve_type (cxels)
++ xel **cxels;
++ {
++ int convolve_type;
++ int horizontal, vertical;
++ int tempcxel, rtempcxel, gtempcxel, btempcxel;
++ int crow, ccol;
++
++ switch ( PNM_FORMAT_TYPE(format) )
++ {
++ case PPM_TYPE:
++ horizontal = TRUE;
++ crow = 0;
++ while ( horizontal && (crow < crows) )
++ {
++ ccol = 1;
++ rtempcxel = PPM_GETR(cxels[crow][0]);
++ gtempcxel = PPM_GETG(cxels[crow][0]);
++ btempcxel = PPM_GETB(cxels[crow][0]);
++ while ( horizontal && (ccol < ccols) )
++ {
++ if (( PPM_GETR(cxels[crow][ccol]) != rtempcxel ) |
++ ( PPM_GETG(cxels[crow][ccol]) != gtempcxel ) |
++ ( PPM_GETB(cxels[crow][ccol]) != btempcxel ))
++ horizontal = FALSE;
++ ++ccol;
++ }
++ ++crow;
++ }
++
++ vertical = TRUE;
++ ccol = 0;
++ while ( vertical && (ccol < ccols) )
++ {
++ crow = 1;
++ rtempcxel = PPM_GETR(cxels[0][ccol]);
++ gtempcxel = PPM_GETG(cxels[0][ccol]);
++ btempcxel = PPM_GETB(cxels[0][ccol]);
++ while ( vertical && (crow < crows) )
++ {
++ if (( PPM_GETR(cxels[crow][ccol]) != rtempcxel ) |
++ ( PPM_GETG(cxels[crow][ccol]) != gtempcxel ) |
++ ( PPM_GETB(cxels[crow][ccol]) != btempcxel ))
++ vertical = FALSE;
++ ++crow;
++ }
++ ++ccol;
++ }
++ break;
++
++ default:
++ horizontal = TRUE;
++ crow = 0;
++ while ( horizontal && (crow < crows) )
++ {
++ ccol = 1;
++ tempcxel = PNM_GET1(cxels[crow][0]);
++ while ( horizontal && (ccol < ccols) )
++ {
++ if ( PNM_GET1(cxels[crow][ccol]) != tempcxel )
++ horizontal = FALSE;
++ ++ccol;
++ }
++ ++crow;
++ }
++
++ vertical = TRUE;
++ ccol = 0;
++ while ( vertical && (ccol < ccols) )
++ {
++ crow = 1;
++ tempcxel = PNM_GET1(cxels[0][ccol]);
++ while ( vertical && (crow < crows) )
++ {
++ if ( PNM_GET1(cxels[crow][ccol]) != tempcxel )
++ vertical = FALSE;
++ ++crow;
++ }
++ ++ccol;
++ }
++ break;
++ }
++
++ /* Which type do we have? */
++ if ( horizontal && vertical )
++ convolve_type = MEAN_CONVOLVE;
++ else if ( horizontal )
++ convolve_type = HORIZONTAL_CONVOLVE;
++ else if ( vertical )
++ convolve_type = VERTICAL_CONVOLVE;
++ else
++ convolve_type = GENERAL_CONVOLVE;
++
++ return (convolve_type);
++ }
++
++
++
++
++/* General PGM Convolution
++**
++** No useful redundancy in convolution matrix.
++*/
++
++static void
++pgm_general_convolve()
++ {
++ register int ccol, col;
++ xel** xelbuf;
++ xel* outputrow;
++ xel x, y;
++ xelval g;
++ int row, crow;
++ float gsum;
++ xel **rowptr, *temprptr;
++ int toprow, temprow;
++ int i, irow;
++ int leftcol;
++ long tempgsum;
++
+ /* Allocate space for one convolution-matrix's worth of rows, plus
+ ** a row output buffer. */
+ xelbuf = pnm_allocarray( cols, crows );
+ outputrow = pnm_allocrow( cols );
+
++ /* Allocate array of pointers to xelbuf */
++ rowptr = (xel **) pnm_allocarray( 1, crows );
++
+ pnm_writepnminit( stdout, cols, rows, maxval, newformat, 0 );
+
+ /* Read in one convolution-matrix's worth of image, less one row. */
+@@ -155,65 +435,1470 @@
+ */
+ for ( ; row < rows; ++row )
+ {
+- pnm_readpnmrow( ifp, xelbuf[row % crows], cols, maxval, format );
++ toprow = row + 1;
++ temprow = row % crows;
++ pnm_readpnmrow( ifp, xelbuf[temprow], cols, maxval, format );
+ if ( PNM_FORMAT_TYPE(format) != newformat )
+ pnm_promoteformatrow(
+- xelbuf[row % crows], cols, maxval, format, maxval, newformat );
++ xelbuf[temprow], cols, maxval, format, maxval, newformat );
++
++ /* Arrange rowptr to eliminate the use of mod function to determine
++ ** which row of xelbuf is 0...crows. Mod function can be very costly.
++ */
++ temprow = toprow % crows;
++ i = 0;
++ for (irow = temprow; irow < crows; ++i, ++irow)
++ rowptr[i] = xelbuf[irow];
++ for (irow = 0; irow < temprow; ++irow, ++i)
++ rowptr[i] = xelbuf[irow];
+
+ for ( col = 0; col < cols; ++col )
++ {
+ if ( col < ccolso2 || col >= cols - ccolso2 )
+- outputrow[col] = xelbuf[(row - crowso2) % crows][col];
++ outputrow[col] = rowptr[crowso2][col];
+ else
+ {
+- switch ( PNM_FORMAT_TYPE(format) )
+- {
+- case PPM_TYPE:
+- rsum = gsum = bsum = 0.0;
+- for ( crow = 0; crow < crows; ++crow )
+- for ( ccol = 0; ccol < ccols; ++ccol )
+- {
+- x = xelbuf[(row+1+crow) % crows][col-ccolso2+ccol];
+- rsum += PPM_GETR( x ) * rweights[crow][ccol];
+- gsum += PPM_GETG( x ) * gweights[crow][ccol];
+- bsum += PPM_GETB( x ) * bweights[crow][ccol];
+- }
+- if ( rsum < 0.0 ) r = 0;
+- else if ( rsum > maxval ) r = maxval;
+- else r = rsum + 0.5;
+- if ( gsum < 0.0 ) g = 0;
+- else if ( gsum > maxval ) g = maxval;
+- else g = gsum + 0.5;
+- if ( bsum < 0.0 ) b = 0;
+- else if ( bsum > maxval ) b = maxval;
+- else b = bsum + 0.5;
+- PPM_ASSIGN( outputrow[col], r, g, b );
+- break;
+-
+- default:
+- gsum = 0.0;
+- for ( crow = 0; crow < crows; ++crow )
+- for ( ccol = 0; ccol < ccols; ++ccol )
+- {
+- x = xelbuf[(row+1+crow) % crows][col-ccolso2+ccol];
+- gsum += PNM_GET1( x ) * gweights[crow][ccol];
+- }
+- if ( gsum < 0.0 ) g = 0;
+- else if ( gsum > maxval ) g = maxval;
+- else g = gsum + 0.5;
++ leftcol = col - ccolso2;
++ gsum = 0.0;
++ for ( crow = 0; crow < crows; ++crow )
++ {
++ temprptr = rowptr[crow] + leftcol;
++ for ( ccol = 0; ccol < ccols; ++ccol )
++ gsum += PNM_GET1( *(temprptr + ccol) )
++ * gweights[crow][ccol];
++ }
++ tempgsum = gsum + 0.5;
++ CHECK_GRAY;
+ PNM_ASSIGN1( outputrow[col], g );
+- break;
+- }
+ }
++ }
++ pnm_writepnmrow( stdout, outputrow, cols, maxval, newformat, 0 );
++ }
++
++ /* Now write out the remaining unconvolved rows in xelbuf. */
++ for ( irow = crowso2 + 1; irow < crows; ++irow )
++ pnm_writepnmrow(
++ stdout, rowptr[irow], cols, maxval, newformat, 0 );
++
++ pm_close( stdout );
++ }
++
++
++/* PGM Mean Convolution
++**
++** This is the common case where you just want the target pixel replaced with
++** the average value of its neighbors. This can work much faster than the
++** general case because you can reduce the number of floating point operations
++** that are required since all the weights are the same. You will only need
++** to multiply by the weight once, not for every pixel in the convolution
++** matrix.
++**
++** This algorithm works by creating sums for each column of crows height for
++** the whole width of the image. Then add ccols column sums together to obtain
++** the total sum of the neighbors and multiply that sum by the weight. As you
++** move right to left to calculate the next pixel, take the total sum you just
++** generated, add in the value of the next column and subtract the value of the
++** leftmost column. Multiply that by the weight and that's it. As you move
++** down a row, calculate new column sums by using previous sum for that column
++** and adding in pixel on current row and subtracting pixel in top row.
++**
++*/
++
++
++static void
++pgm_mean_convolve()
++ {
++ register int ccol, col;
++ xel** xelbuf;
++ xel* outputrow;
++ xelval g;
++ int row, crow;
++ xel **rowptr, *temprptr;
++ int leftcol;
++ int i, irow;
++ int toprow, temprow;
++ int subrow, addrow;
++ int subcol, addcol;
++ long gisum;
++ int tempcol, crowsp1;
++ long tempgsum;
++ long *gcolumnsum;
++
++ /* Allocate space for one convolution-matrix's worth of rows, plus
++ ** a row output buffer. MEAN uses an extra row. */
++ xelbuf = pnm_allocarray( cols, crows + 1 );
++ outputrow = pnm_allocrow( cols );
++
++ /* Allocate array of pointers to xelbuf. MEAN uses an extra row. */
++ rowptr = (xel **) pnm_allocarray( 1, crows + 1);
++
++ /* Allocate space for intermediate column sums */
++ gcolumnsum = (long *) pm_allocrow( cols, sizeof(long) );
++ for ( col = 0; col < cols; ++col )
++ gcolumnsum[col] = 0L;
++
++ pnm_writepnminit( stdout, cols, rows, maxval, newformat, 0 );
++
++ /* Read in one convolution-matrix's worth of image, less one row. */
++ for ( row = 0; row < crows - 1; ++row )
++ {
++ pnm_readpnmrow( ifp, xelbuf[row], cols, maxval, format );
++ if ( PNM_FORMAT_TYPE(format) != newformat )
++ pnm_promoteformatrow(
++ xelbuf[row], cols, maxval, format, maxval, newformat );
++ /* Write out just the part we're not going to convolve. */
++ if ( row < crowso2 )
++ pnm_writepnmrow( stdout, xelbuf[row], cols, maxval, newformat, 0 );
++ }
++
++ /* Do first real row only */
++ subrow = crows;
++ addrow = crows - 1;
++ toprow = row + 1;
++ temprow = row % crows;
++ pnm_readpnmrow( ifp, xelbuf[temprow], cols, maxval, format );
++ if ( PNM_FORMAT_TYPE(format) != newformat )
++ pnm_promoteformatrow(
++ xelbuf[temprow], cols, maxval, format, maxval, newformat );
++
++ temprow = toprow % crows;
++ i = 0;
++ for (irow = temprow; irow < crows; ++i, ++irow)
++ rowptr[i] = xelbuf[irow];
++ for (irow = 0; irow < temprow; ++irow, ++i)
++ rowptr[i] = xelbuf[irow];
++
++ gisum = 0L;
++ for ( col = 0; col < cols; ++col )
++ {
++ if ( col < ccolso2 || col >= cols - ccolso2 )
++ outputrow[col] = rowptr[crowso2][col];
++ else if ( col == ccolso2 )
++ {
++ leftcol = col - ccolso2;
++ for ( crow = 0; crow < crows; ++crow )
++ {
++ temprptr = rowptr[crow] + leftcol;
++ for ( ccol = 0; ccol < ccols; ++ccol )
++ gcolumnsum[leftcol + ccol] +=
++ PNM_GET1( *(temprptr + ccol) );
++ }
++ for ( ccol = 0; ccol < ccols; ++ccol)
++ gisum += gcolumnsum[leftcol + ccol];
++ tempgsum = (float) gisum * gmeanweight + 0.5;
++ CHECK_GRAY;
++ PNM_ASSIGN1( outputrow[col], g );
++ }
++ else
++ {
++ /* Column numbers to subtract or add to isum */
++ subcol = col - ccolso2 - 1;
++ addcol = col + ccolso2;
++ for ( crow = 0; crow < crows; ++crow )
++ gcolumnsum[addcol] += PNM_GET1( rowptr[crow][addcol] );
++ gisum = gisum - gcolumnsum[subcol] + gcolumnsum[addcol];
++ tempgsum = (float) gisum * gmeanweight + 0.5;
++ CHECK_GRAY;
++ PNM_ASSIGN1( outputrow[col], g );
++ }
++ }
++ pnm_writepnmrow( stdout, outputrow, cols, maxval, newformat, 0 );
+
++ ++row;
++ /* For all subsequent rows do it this way as the columnsums have been
++ ** generated. Now we can use them to reduce further calculations.
++ */
++ crowsp1 = crows + 1;
++ for ( ; row < rows; ++row )
++ {
++ toprow = row + 1;
++ temprow = row % (crows + 1);
++ pnm_readpnmrow( ifp, xelbuf[temprow], cols, maxval, format );
++ if ( PNM_FORMAT_TYPE(format) != newformat )
++ pnm_promoteformatrow(
++ xelbuf[temprow], cols, maxval, format, maxval, newformat );
++
++ /* This rearrangement using crows+1 rowptrs and xelbufs will cause
++ ** rowptr[0..crows-1] to always hold active xelbufs and for
++ ** rowptr[crows] to always hold the oldest (top most) xelbuf.
++ */
++ temprow = (toprow + 1) % crowsp1;
++ i = 0;
++ for (irow = temprow; irow < crowsp1; ++i, ++irow)
++ rowptr[i] = xelbuf[irow];
++ for (irow = 0; irow < temprow; ++irow, ++i)
++ rowptr[i] = xelbuf[irow];
++
++ gisum = 0L;
++ for ( col = 0; col < cols; ++col )
++ {
++ if ( col < ccolso2 || col >= cols - ccolso2 )
++ outputrow[col] = rowptr[crowso2][col];
++ else if ( col == ccolso2 )
++ {
++ leftcol = col - ccolso2;
++ for ( ccol = 0; ccol < ccols; ++ccol )
++ {
++ tempcol = leftcol + ccol;
++ gcolumnsum[tempcol] = gcolumnsum[tempcol]
++ - PNM_GET1( rowptr[subrow][ccol] )
++ + PNM_GET1( rowptr[addrow][ccol] );
++ gisum += gcolumnsum[tempcol];
++ }
++ tempgsum = (float) gisum * gmeanweight + 0.5;
++ CHECK_GRAY;
++ PNM_ASSIGN1( outputrow[col], g );
++ }
++ else
++ {
++ /* Column numbers to subtract or add to isum */
++ subcol = col - ccolso2 - 1;
++ addcol = col + ccolso2;
++ gcolumnsum[addcol] = gcolumnsum[addcol]
++ - PNM_GET1( rowptr[subrow][addcol] )
++ + PNM_GET1( rowptr[addrow][addcol] );
++ gisum = gisum - gcolumnsum[subcol] + gcolumnsum[addcol];
++ tempgsum = (float) gisum * gmeanweight + 0.5;
++ CHECK_GRAY;
++ PNM_ASSIGN1( outputrow[col], g );
++ }
++ }
+ pnm_writepnmrow( stdout, outputrow, cols, maxval, newformat, 0 );
+ }
+- pm_close( ifp );
+
+ /* Now write out the remaining unconvolved rows in xelbuf. */
+- for ( ; row < rows + crowso2; ++row )
++ for ( irow = crowso2 + 1; irow < crows; ++irow )
+ pnm_writepnmrow(
+- stdout, xelbuf[(row-crowso2) % crows], cols, maxval, newformat, 0 );
++ stdout, rowptr[irow], cols, maxval, newformat, 0 );
++
++ pm_close( stdout );
++ }
++
++
++/* PGM Horizontal Convolution
++**
++** Similar idea to using columnsums of the Mean and Vertical convolution,
++** but uses temporary sums of row values. Need to multiply by weights crows
++** number of times. Each time a new line is started, must recalculate the
++** initials rowsums for the newest row only. Uses queue to still access
++** previous row sums.
++**
++*/
++
++static void
++pgm_horizontal_convolve()
++ {
++ register int ccol, col;
++ xel** xelbuf;
++ xel* outputrow;
++ xel x;
++ xelval g;
++ int row, crow;
++ xel **rowptr, *temprptr;
++ int leftcol;
++ int i, irow;
++ int temprow;
++ int subcol, addcol;
++ float gsum;
++ int addrow, subrow;
++ long **growsum, **growsumptr;
++ int crowsp1;
++ long tempgsum;
++
++ /* Allocate space for one convolution-matrix's worth of rows, plus
++ ** a row output buffer. */
++ xelbuf = pnm_allocarray( cols, crows + 1 );
++ outputrow = pnm_allocrow( cols );
++
++ /* Allocate array of pointers to xelbuf */
++ rowptr = (xel **) pnm_allocarray( 1, crows + 1);
++
++ /* Allocate intermediate row sums. HORIZONTAL uses an extra row. */
++ /* crows current rows and 1 extra for newest added row. */
++ growsum = (long **) pm_allocarray( cols, crows + 1, sizeof(long) );
++ growsumptr = (long **) pnm_allocarray( 1, crows + 1);
++
++ pnm_writepnminit( stdout, cols, rows, maxval, newformat, 0 );
++
++ /* Read in one convolution-matrix's worth of image, less one row. */
++ for ( row = 0; row < crows - 1; ++row )
++ {
++ pnm_readpnmrow( ifp, xelbuf[row], cols, maxval, format );
++ if ( PNM_FORMAT_TYPE(format) != newformat )
++ pnm_promoteformatrow(
++ xelbuf[row], cols, maxval, format, maxval, newformat );
++ /* Write out just the part we're not going to convolve. */
++ if ( row < crowso2 )
++ pnm_writepnmrow( stdout, xelbuf[row], cols, maxval, newformat, 0 );
++ }
++
++ /* First row only */
++ temprow = row % crows;
++ pnm_readpnmrow( ifp, xelbuf[temprow], cols, maxval, format );
++ if ( PNM_FORMAT_TYPE(format) != newformat )
++ pnm_promoteformatrow(
++ xelbuf[temprow], cols, maxval, format, maxval, newformat );
++
++ temprow = (row + 1) % crows;
++ i = 0;
++ for (irow = temprow; irow < crows; ++i, ++irow)
++ rowptr[i] = xelbuf[irow];
++ for (irow = 0; irow < temprow; ++irow, ++i)
++ rowptr[i] = xelbuf[irow];
++
++ for ( crow = 0; crow < crows; ++crow )
++ growsumptr[crow] = growsum[crow];
++
++ for ( col = 0; col < cols; ++col )
++ {
++ if ( col < ccolso2 || col >= cols - ccolso2 )
++ outputrow[col] = rowptr[crowso2][col];
++ else if ( col == ccolso2 )
++ {
++ leftcol = col - ccolso2;
++ gsum = 0.0;
++ for ( crow = 0; crow < crows; ++crow )
++ {
++ temprptr = rowptr[crow] + leftcol;
++ growsumptr[crow][leftcol] = 0L;
++ for ( ccol = 0; ccol < ccols; ++ccol )
++ growsumptr[crow][leftcol] +=
++ PNM_GET1( *(temprptr + ccol) );
++ gsum += growsumptr[crow][leftcol] * gweights[crow][0];
++ }
++ tempgsum = gsum + 0.5;
++ CHECK_GRAY;
++ PNM_ASSIGN1( outputrow[col], g );
++ }
++ else
++ {
++ gsum = 0.0;
++ leftcol = col - ccolso2;
++ subcol = col - ccolso2 - 1;
++ addcol = col + ccolso2;
++ for ( crow = 0; crow < crows; ++crow )
++ {
++ growsumptr[crow][leftcol] = growsumptr[crow][subcol]
++ - PNM_GET1( rowptr[crow][subcol] )
++ + PNM_GET1( rowptr[crow][addcol] );
++ gsum += growsumptr[crow][leftcol] * gweights[crow][0];
++ }
++ tempgsum = gsum + 0.5;
++ CHECK_GRAY;
++ PNM_ASSIGN1( outputrow[col], g );
++ }
++ }
++ pnm_writepnmrow( stdout, outputrow, cols, maxval, newformat, 0 );
++
++
++ /* For all subsequent rows */
++
++ subrow = crows;
++ addrow = crows - 1;
++ crowsp1 = crows + 1;
++ ++row;
++ for ( ; row < rows; ++row )
++ {
++ temprow = row % crowsp1;
++ pnm_readpnmrow( ifp, xelbuf[temprow], cols, maxval, format );
++ if ( PNM_FORMAT_TYPE(format) != newformat )
++ pnm_promoteformatrow(
++ xelbuf[temprow], cols, maxval, format, maxval, newformat );
++
++ temprow = (row + 2) % crowsp1;
++ i = 0;
++ for (irow = temprow; irow < crowsp1; ++i, ++irow)
++ {
++ rowptr[i] = xelbuf[irow];
++ growsumptr[i] = growsum[irow];
++ }
++ for (irow = 0; irow < temprow; ++irow, ++i)
++ {
++ rowptr[i] = xelbuf[irow];
++ growsumptr[i] = growsum[irow];
++ }
++
++ for ( col = 0; col < cols; ++col )
++ {
++ if ( col < ccolso2 || col >= cols - ccolso2 )
++ outputrow[col] = rowptr[crowso2][col];
++ else if ( col == ccolso2 )
++ {
++ gsum = 0.0;
++ leftcol = col - ccolso2;
++ growsumptr[addrow][leftcol] = 0L;
++ for ( ccol = 0; ccol < ccols; ++ccol )
++ growsumptr[addrow][leftcol] +=
++ PNM_GET1( rowptr[addrow][leftcol + ccol] );
++ for ( crow = 0; crow < crows; ++crow )
++ gsum += growsumptr[crow][leftcol] * gweights[crow][0];
++ tempgsum = gsum + 0.5;
++ CHECK_GRAY;
++ PNM_ASSIGN1( outputrow[col], g );
++ }
++ else
++ {
++ gsum = 0.0;
++ leftcol = col - ccolso2;
++ subcol = col - ccolso2 - 1;
++ addcol = col + ccolso2;
++ growsumptr[addrow][leftcol] = growsumptr[addrow][subcol]
++ - PNM_GET1( rowptr[addrow][subcol] )
++ + PNM_GET1( rowptr[addrow][addcol] );
++ for ( crow = 0; crow < crows; ++crow )
++ gsum += growsumptr[crow][leftcol] * gweights[crow][0];
++ tempgsum = gsum + 0.5;
++ CHECK_GRAY;
++ PNM_ASSIGN1( outputrow[col], g );
++ }
++ }
++ pnm_writepnmrow( stdout, outputrow, cols, maxval, newformat, 0 );
++ }
++
++ /* Now write out the remaining unconvolved rows in xelbuf. */
++ for ( irow = crowso2 + 1; irow < crows; ++irow )
++ pnm_writepnmrow(
++ stdout, rowptr[irow], cols, maxval, newformat, 0 );
++
++ pm_close( stdout );
++ }
++
++
++/* PGM Vertical Convolution
++**
++** Uses column sums as in Mean Convolution.
++**
++*/
++
++
++static void
++pgm_vertical_convolve()
++ {
++ register int ccol, col;
++ xel** xelbuf;
++ xel* outputrow;
++ xelval g;
++ int row, crow;
++ xel **rowptr, *temprptr;
++ int leftcol;
++ int i, irow;
++ int toprow, temprow;
++ int subrow, addrow;
++ int tempcol;
++ float gsum;
++ long *gcolumnsum;
++ int crowsp1;
++ int addcol;
++ long tempgsum;
++
++ /* Allocate space for one convolution-matrix's worth of rows, plus
++ ** a row output buffer. VERTICAL uses an extra row. */
++ xelbuf = pnm_allocarray( cols, crows + 1 );
++ outputrow = pnm_allocrow( cols );
++
++ /* Allocate array of pointers to xelbuf */
++ rowptr = (xel **) pnm_allocarray( 1, crows + 1 );
++
++ /* Allocate space for intermediate column sums */
++ gcolumnsum = (long *) pm_allocrow( cols, sizeof(long) );
++ for ( col = 0; col < cols; ++col )
++ gcolumnsum[col] = 0L;
++
++ pnm_writepnminit( stdout, cols, rows, maxval, newformat, 0 );
++
++ /* Read in one convolution-matrix's worth of image, less one row. */
++ for ( row = 0; row < crows - 1; ++row )
++ {
++ pnm_readpnmrow( ifp, xelbuf[row], cols, maxval, format );
++ if ( PNM_FORMAT_TYPE(format) != newformat )
++ pnm_promoteformatrow(
++ xelbuf[row], cols, maxval, format, maxval, newformat );
++ /* Write out just the part we're not going to convolve. */
++ if ( row < crowso2 )
++ pnm_writepnmrow( stdout, xelbuf[row], cols, maxval, newformat, 0 );
++ }
++
++ /* Now the rest of the image - read in the row at the end of
++ ** xelbuf, and convolve and write out the row in the middle.
++ */
++ /* For first row only */
++
++ toprow = row + 1;
++ temprow = row % crows;
++ pnm_readpnmrow( ifp, xelbuf[temprow], cols, maxval, format );
++ if ( PNM_FORMAT_TYPE(format) != newformat )
++ pnm_promoteformatrow(
++ xelbuf[temprow], cols, maxval, format, maxval, newformat );
++
++ /* Arrange rowptr to eliminate the use of mod function to determine
++ ** which row of xelbuf is 0...crows. Mod function can be very costly.
++ */
++ temprow = toprow % crows;
++ i = 0;
++ for (irow = temprow; irow < crows; ++i, ++irow)
++ rowptr[i] = xelbuf[irow];
++ for (irow = 0; irow < temprow; ++irow, ++i)
++ rowptr[i] = xelbuf[irow];
++
++ for ( col = 0; col < cols; ++col )
++ {
++ if ( col < ccolso2 || col >= cols - ccolso2 )
++ outputrow[col] = rowptr[crowso2][col];
++ else if ( col == ccolso2 )
++ {
++ gsum = 0.0;
++ leftcol = col - ccolso2;
++ for ( crow = 0; crow < crows; ++crow )
++ {
++ temprptr = rowptr[crow] + leftcol;
++ for ( ccol = 0; ccol < ccols; ++ccol )
++ gcolumnsum[leftcol + ccol] +=
++ PNM_GET1( *(temprptr + ccol) );
++ }
++ for ( ccol = 0; ccol < ccols; ++ccol)
++ gsum += gcolumnsum[leftcol + ccol] * gweights[0][ccol];
++ tempgsum = gsum + 0.5;
++ CHECK_GRAY;
++ PNM_ASSIGN1( outputrow[col], g );
++ }
++ else
++ {
++ gsum = 0.0;
++ leftcol = col - ccolso2;
++ addcol = col + ccolso2;
++ for ( crow = 0; crow < crows; ++crow )
++ gcolumnsum[addcol] += PNM_GET1( rowptr[crow][addcol] );
++ for ( ccol = 0; ccol < ccols; ++ccol )
++ gsum += gcolumnsum[leftcol + ccol] * gweights[0][ccol];
++ tempgsum = gsum + 0.5;
++ CHECK_GRAY;
++ PNM_ASSIGN1( outputrow[col], g );
++ }
++ }
++ pnm_writepnmrow( stdout, outputrow, cols, maxval, newformat, 0 );
++
++ /* For all subsequent rows */
++ subrow = crows;
++ addrow = crows - 1;
++ crowsp1 = crows + 1;
++ ++row;
++ for ( ; row < rows; ++row )
++ {
++ toprow = row + 1;
++ temprow = row % (crows +1);
++ pnm_readpnmrow( ifp, xelbuf[temprow], cols, maxval, format );
++ if ( PNM_FORMAT_TYPE(format) != newformat )
++ pnm_promoteformatrow(
++ xelbuf[temprow], cols, maxval, format, maxval, newformat );
++
++ /* Arrange rowptr to eliminate the use of mod function to determine
++ ** which row of xelbuf is 0...crows. Mod function can be very costly.
++ */
++ temprow = (toprow + 1) % crowsp1;
++ i = 0;
++ for (irow = temprow; irow < crowsp1; ++i, ++irow)
++ rowptr[i] = xelbuf[irow];
++ for (irow = 0; irow < temprow; ++irow, ++i)
++ rowptr[i] = xelbuf[irow];
++
++ for ( col = 0; col < cols; ++col )
++ {
++ if ( col < ccolso2 || col >= cols - ccolso2 )
++ outputrow[col] = rowptr[crowso2][col];
++ else if ( col == ccolso2 )
++ {
++ gsum = 0.0;
++ leftcol = col - ccolso2;
++ for ( ccol = 0; ccol < ccols; ++ccol )
++ {
++ tempcol = leftcol + ccol;
++ gcolumnsum[tempcol] = gcolumnsum[tempcol]
++ - PNM_GET1( rowptr[subrow][ccol] )
++ + PNM_GET1( rowptr[addrow][ccol] );
++ gsum = gsum + gcolumnsum[tempcol] * gweights[0][ccol];
++ }
++ tempgsum = gsum + 0.5;
++ CHECK_GRAY;
++ PNM_ASSIGN1( outputrow[col], g );
++ }
++ else
++ {
++ gsum = 0.0;
++ leftcol = col - ccolso2;
++ addcol = col + ccolso2;
++ gcolumnsum[addcol] = gcolumnsum[addcol]
++ - PNM_GET1( rowptr[subrow][addcol] )
++ + PNM_GET1( rowptr[addrow][addcol] );
++ for ( ccol = 0; ccol < ccols; ++ccol )
++ gsum += gcolumnsum[leftcol + ccol] * gweights[0][ccol];
++ tempgsum = gsum + 0.5;
++ CHECK_GRAY;
++ PNM_ASSIGN1( outputrow[col], g );
++ }
++ }
++ pnm_writepnmrow( stdout, outputrow, cols, maxval, newformat, 0 );
++ }
++
++ /* Now write out the remaining unconvolved rows in xelbuf. */
++ for ( irow = crowso2 + 1; irow < crows; ++irow )
++ pnm_writepnmrow(
++ stdout, rowptr[irow], cols, maxval, newformat, 0 );
++
++ pm_close( stdout );
++ }
++
++
++
++
++/* PPM General Convolution Algorithm
++**
++** No redundancy in convolution matrix. Just use brute force.
++** See pgm_general_convolve() for more details.
++*/
++
++static void
++ppm_general_convolve()
++ {
++ register int ccol, col;
++ xel** xelbuf;
++ xel* outputrow;
++ xel x, y;
++ xelval r, g, b;
++ int row, crow;
++ float rsum, gsum, bsum;
++ xel **rowptr, *temprptr;
++ int toprow, temprow;
++ int i, irow;
++ int leftcol;
++ long temprsum, tempgsum, tempbsum;
++
++ /* Allocate space for one convolution-matrix's worth of rows, plus
++ ** a row output buffer. */
++ xelbuf = pnm_allocarray( cols, crows );
++ outputrow = pnm_allocrow( cols );
++
++ /* Allocate array of pointers to xelbuf */
++ rowptr = (xel **) pnm_allocarray( 1, crows );
++
++ pnm_writepnminit( stdout, cols, rows, maxval, newformat, 0 );
++
++ /* Read in one convolution-matrix's worth of image, less one row. */
++ for ( row = 0; row < crows - 1; ++row )
++ {
++ pnm_readpnmrow( ifp, xelbuf[row], cols, maxval, format );
++ if ( PNM_FORMAT_TYPE(format) != newformat )
++ pnm_promoteformatrow(
++ xelbuf[row], cols, maxval, format, maxval, newformat );
++ /* Write out just the part we're not going to convolve. */
++ if ( row < crowso2 )
++ pnm_writepnmrow( stdout, xelbuf[row], cols, maxval, newformat, 0 );
++ }
++
++ /* Now the rest of the image - read in the row at the end of
++ ** xelbuf, and convolve and write out the row in the middle.
++ */
++ for ( ; row < rows; ++row )
++ {
++ toprow = row + 1;
++ temprow = row % crows;
++ pnm_readpnmrow( ifp, xelbuf[temprow], cols, maxval, format );
++ if ( PNM_FORMAT_TYPE(format) != newformat )
++ pnm_promoteformatrow(
++ xelbuf[temprow], cols, maxval, format, maxval, newformat );
++
++ /* Arrange rowptr to eliminate the use of mod function to determine
++ ** which row of xelbuf is 0...crows. Mod function can be very costly.
++ */
++ temprow = toprow % crows;
++ i = 0;
++ for (irow = temprow; irow < crows; ++i, ++irow)
++ rowptr[i] = xelbuf[irow];
++ for (irow = 0; irow < temprow; ++irow, ++i)
++ rowptr[i] = xelbuf[irow];
++
++ for ( col = 0; col < cols; ++col )
++ {
++ if ( col < ccolso2 || col >= cols - ccolso2 )
++ outputrow[col] = rowptr[crowso2][col];
++ else
++ {
++ leftcol = col - ccolso2;
++ rsum = gsum = bsum = 0.0;
++ for ( crow = 0; crow < crows; ++crow )
++ {
++ temprptr = rowptr[crow] + leftcol;
++ for ( ccol = 0; ccol < ccols; ++ccol )
++ {
++ rsum += PPM_GETR( *(temprptr + ccol) )
++ * rweights[crow][ccol];
++ gsum += PPM_GETG( *(temprptr + ccol) )
++ * gweights[crow][ccol];
++ bsum += PPM_GETB( *(temprptr + ccol) )
++ * bweights[crow][ccol];
++ }
++ }
++ temprsum = rsum + 0.5;
++ tempgsum = gsum + 0.5;
++ tempbsum = bsum + 0.5;
++ CHECK_RED;
++ CHECK_GREEN;
++ CHECK_BLUE;
++ PPM_ASSIGN( outputrow[col], r, g, b );
++ }
++ }
++ pnm_writepnmrow( stdout, outputrow, cols, maxval, newformat, 0 );
++ }
++
++ /* Now write out the remaining unconvolved rows in xelbuf. */
++ for ( irow = crowso2 + 1; irow < crows; ++irow )
++ pnm_writepnmrow(
++ stdout, rowptr[irow], cols, maxval, newformat, 0 );
++
++ pm_close( stdout );
++ }
++
++
++/* PPM Mean Convolution
++**
++** Same as pgm_mean_convolve() but for PPM.
++**
++*/
++
++static void
++ppm_mean_convolve()
++ {
++ register int ccol, col;
++ xel** xelbuf;
++ xel* outputrow;
++ xelval r, g, b;
++ int row, crow;
++ xel **rowptr, *temprptr;
++ int leftcol;
++ int i, irow;
++ int toprow, temprow;
++ int subrow, addrow;
++ int subcol, addcol;
++ long risum, gisum, bisum;
++ float rsum, gsum, bsum;
++ long temprsum, tempgsum, tempbsum;
++ int tempcol, crowsp1;
++ long *rcolumnsum, *gcolumnsum, *bcolumnsum;
++
++ /* Allocate space for one convolution-matrix's worth of rows, plus
++ ** a row output buffer. MEAN uses an extra row. */
++ xelbuf = pnm_allocarray( cols, crows + 1 );
++ outputrow = pnm_allocrow( cols );
++
++ /* Allocate array of pointers to xelbuf. MEAN uses an extra row. */
++ rowptr = (xel **) pnm_allocarray( 1, crows + 1);
++
++ /* Allocate space for intermediate column sums */
++ rcolumnsum = (long *) pm_allocrow( cols, sizeof(long) );
++ gcolumnsum = (long *) pm_allocrow( cols, sizeof(long) );
++ bcolumnsum = (long *) pm_allocrow( cols, sizeof(long) );
++ for ( col = 0; col < cols; ++col )
++ {
++ rcolumnsum[col] = 0L;
++ gcolumnsum[col] = 0L;
++ bcolumnsum[col] = 0L;
++ }
++
++ pnm_writepnminit( stdout, cols, rows, maxval, newformat, 0 );
++
++ /* Read in one convolution-matrix's worth of image, less one row. */
++ for ( row = 0; row < crows - 1; ++row )
++ {
++ pnm_readpnmrow( ifp, xelbuf[row], cols, maxval, format );
++ if ( PNM_FORMAT_TYPE(format) != newformat )
++ pnm_promoteformatrow(
++ xelbuf[row], cols, maxval, format, maxval, newformat );
++ /* Write out just the part we're not going to convolve. */
++ if ( row < crowso2 )
++ pnm_writepnmrow( stdout, xelbuf[row], cols, maxval, newformat, 0 );
++ }
++
++ /* Do first real row only */
++ subrow = crows;
++ addrow = crows - 1;
++ toprow = row + 1;
++ temprow = row % crows;
++ pnm_readpnmrow( ifp, xelbuf[temprow], cols, maxval, format );
++ if ( PNM_FORMAT_TYPE(format) != newformat )
++ pnm_promoteformatrow(
++ xelbuf[temprow], cols, maxval, format, maxval, newformat );
++
++ temprow = toprow % crows;
++ i = 0;
++ for (irow = temprow; irow < crows; ++i, ++irow)
++ rowptr[i] = xelbuf[irow];
++ for (irow = 0; irow < temprow; ++irow, ++i)
++ rowptr[i] = xelbuf[irow];
++
++ risum = 0L;
++ gisum = 0L;
++ bisum = 0L;
++ for ( col = 0; col < cols; ++col )
++ {
++ if ( col < ccolso2 || col >= cols - ccolso2 )
++ outputrow[col] = rowptr[crowso2][col];
++ else if ( col == ccolso2 )
++ {
++ leftcol = col - ccolso2;
++ for ( crow = 0; crow < crows; ++crow )
++ {
++ temprptr = rowptr[crow] + leftcol;
++ for ( ccol = 0; ccol < ccols; ++ccol )
++ {
++ rcolumnsum[leftcol + ccol] +=
++ PPM_GETR( *(temprptr + ccol) );
++ gcolumnsum[leftcol + ccol] +=
++ PPM_GETG( *(temprptr + ccol) );
++ bcolumnsum[leftcol + ccol] +=
++ PPM_GETB( *(temprptr + ccol) );
++ }
++ }
++ for ( ccol = 0; ccol < ccols; ++ccol)
++ {
++ risum += rcolumnsum[leftcol + ccol];
++ gisum += gcolumnsum[leftcol + ccol];
++ bisum += bcolumnsum[leftcol + ccol];
++ }
++ temprsum = (float) risum * rmeanweight + 0.5;
++ tempgsum = (float) gisum * gmeanweight + 0.5;
++ tempbsum = (float) bisum * bmeanweight + 0.5;
++ CHECK_RED;
++ CHECK_GREEN;
++ CHECK_BLUE;
++ PPM_ASSIGN( outputrow[col], r, g, b );
++ }
++ else
++ {
++ /* Column numbers to subtract or add to isum */
++ subcol = col - ccolso2 - 1;
++ addcol = col + ccolso2;
++ for ( crow = 0; crow < crows; ++crow )
++ {
++ rcolumnsum[addcol] += PPM_GETR( rowptr[crow][addcol] );
++ gcolumnsum[addcol] += PPM_GETG( rowptr[crow][addcol] );
++ bcolumnsum[addcol] += PPM_GETB( rowptr[crow][addcol] );
++ }
++ risum = risum - rcolumnsum[subcol] + rcolumnsum[addcol];
++ gisum = gisum - gcolumnsum[subcol] + gcolumnsum[addcol];
++ bisum = bisum - bcolumnsum[subcol] + bcolumnsum[addcol];
++ temprsum = (float) risum * rmeanweight + 0.5;
++ tempgsum = (float) gisum * gmeanweight + 0.5;
++ tempbsum = (float) bisum * bmeanweight + 0.5;
++ CHECK_RED;
++ CHECK_GREEN;
++ CHECK_BLUE;
++ PPM_ASSIGN( outputrow[col], r, g, b );
++ }
++ }
++ pnm_writepnmrow( stdout, outputrow, cols, maxval, newformat, 0 );
++
++ ++row;
++ /* For all subsequent rows do it this way as the columnsums have been
++ ** generated. Now we can use them to reduce further calculations.
++ */
++ crowsp1 = crows + 1;
++ for ( ; row < rows; ++row )
++ {
++ toprow = row + 1;
++ temprow = row % (crows + 1);
++ pnm_readpnmrow( ifp, xelbuf[temprow], cols, maxval, format );
++ if ( PNM_FORMAT_TYPE(format) != newformat )
++ pnm_promoteformatrow(
++ xelbuf[temprow], cols, maxval, format, maxval, newformat );
++
++ /* This rearrangement using crows+1 rowptrs and xelbufs will cause
++ ** rowptr[0..crows-1] to always hold active xelbufs and for
++ ** rowptr[crows] to always hold the oldest (top most) xelbuf.
++ */
++ temprow = (toprow + 1) % crowsp1;
++ i = 0;
++ for (irow = temprow; irow < crowsp1; ++i, ++irow)
++ rowptr[i] = xelbuf[irow];
++ for (irow = 0; irow < temprow; ++irow, ++i)
++ rowptr[i] = xelbuf[irow];
++
++ risum = 0L;
++ gisum = 0L;
++ bisum = 0L;
++ for ( col = 0; col < cols; ++col )
++ {
++ if ( col < ccolso2 || col >= cols - ccolso2 )
++ outputrow[col] = rowptr[crowso2][col];
++ else if ( col == ccolso2 )
++ {
++ leftcol = col - ccolso2;
++ for ( ccol = 0; ccol < ccols; ++ccol )
++ {
++ tempcol = leftcol + ccol;
++ rcolumnsum[tempcol] = rcolumnsum[tempcol]
++ - PPM_GETR( rowptr[subrow][ccol] )
++ + PPM_GETR( rowptr[addrow][ccol] );
++ risum += rcolumnsum[tempcol];
++ gcolumnsum[tempcol] = gcolumnsum[tempcol]
++ - PPM_GETG( rowptr[subrow][ccol] )
++ + PPM_GETG( rowptr[addrow][ccol] );
++ gisum += gcolumnsum[tempcol];
++ bcolumnsum[tempcol] = bcolumnsum[tempcol]
++ - PPM_GETB( rowptr[subrow][ccol] )
++ + PPM_GETB( rowptr[addrow][ccol] );
++ bisum += bcolumnsum[tempcol];
++ }
++ temprsum = (float) risum * rmeanweight + 0.5;
++ tempgsum = (float) gisum * gmeanweight + 0.5;
++ tempbsum = (float) bisum * bmeanweight + 0.5;
++ CHECK_RED;
++ CHECK_GREEN;
++ CHECK_BLUE;
++ PPM_ASSIGN( outputrow[col], r, g, b );
++ }
++ else
++ {
++ /* Column numbers to subtract or add to isum */
++ subcol = col - ccolso2 - 1;
++ addcol = col + ccolso2;
++ rcolumnsum[addcol] = rcolumnsum[addcol]
++ - PPM_GETR( rowptr[subrow][addcol] )
++ + PPM_GETR( rowptr[addrow][addcol] );
++ risum = risum - rcolumnsum[subcol] + rcolumnsum[addcol];
++ gcolumnsum[addcol] = gcolumnsum[addcol]
++ - PPM_GETG( rowptr[subrow][addcol] )
++ + PPM_GETG( rowptr[addrow][addcol] );
++ gisum = gisum - gcolumnsum[subcol] + gcolumnsum[addcol];
++ bcolumnsum[addcol] = bcolumnsum[addcol]
++ - PPM_GETB( rowptr[subrow][addcol] )
++ + PPM_GETB( rowptr[addrow][addcol] );
++ bisum = bisum - bcolumnsum[subcol] + bcolumnsum[addcol];
++ temprsum = (float) risum * rmeanweight + 0.5;
++ tempgsum = (float) gisum * gmeanweight + 0.5;
++ tempbsum = (float) bisum * bmeanweight + 0.5;
++ CHECK_RED;
++ CHECK_GREEN;
++ CHECK_BLUE;
++ PPM_ASSIGN( outputrow[col], r, g, b );
++ }
++ }
++ pnm_writepnmrow( stdout, outputrow, cols, maxval, newformat, 0 );
++ }
++
++ /* Now write out the remaining unconvolved rows in xelbuf. */
++ for ( irow = crowso2 + 1; irow < crows; ++irow )
++ pnm_writepnmrow(
++ stdout, rowptr[irow], cols, maxval, newformat, 0 );
++
++ pm_close( stdout );
++ }
++
++
++/* PPM Horizontal Convolution
++**
++** Same as pgm_horizontal_convolve()
++**
++**/
++
++static void
++ppm_horizontal_convolve()
++ {
++ register int ccol, col;
++ xel** xelbuf;
++ xel* outputrow;
++ xel x;
++ xelval r, g, b;
++ int row, crow;
++ xel **rowptr, *temprptr;
++ int leftcol;
++ int i, irow;
++ int temprow;
++ int subcol, addcol;
++ float rsum, gsum, bsum;
++ int addrow, subrow;
++ long **rrowsum, **rrowsumptr;
++ long **growsum, **growsumptr;
++ long **browsum, **browsumptr;
++ int crowsp1;
++ long temprsum, tempgsum, tempbsum;
++
++ /* Allocate space for one convolution-matrix's worth of rows, plus
++ ** a row output buffer. */
++ xelbuf = pnm_allocarray( cols, crows + 1 );
++ outputrow = pnm_allocrow( cols );
++
++ /* Allocate array of pointers to xelbuf */
++ rowptr = (xel **) pnm_allocarray( 1, crows + 1);
++
++ /* Allocate intermediate row sums. HORIZONTAL uses an extra row */
++ rrowsum = (long **) pm_allocarray( cols, crows + 1, sizeof(long) );
++ rrowsumptr = (long **) pnm_allocarray( 1, crows + 1);
++ growsum = (long **) pm_allocarray( cols, crows + 1, sizeof(long) );
++ growsumptr = (long **) pnm_allocarray( 1, crows + 1);
++ browsum = (long **) pm_allocarray( cols, crows + 1, sizeof(long) );
++ browsumptr = (long **) pnm_allocarray( 1, crows + 1);
++
++ pnm_writepnminit( stdout, cols, rows, maxval, newformat, 0 );
++
++ /* Read in one convolution-matrix's worth of image, less one row. */
++ for ( row = 0; row < crows - 1; ++row )
++ {
++ pnm_readpnmrow( ifp, xelbuf[row], cols, maxval, format );
++ if ( PNM_FORMAT_TYPE(format) != newformat )
++ pnm_promoteformatrow(
++ xelbuf[row], cols, maxval, format, maxval, newformat );
++ /* Write out just the part we're not going to convolve. */
++ if ( row < crowso2 )
++ pnm_writepnmrow( stdout, xelbuf[row], cols, maxval, newformat, 0 );
++ }
++
++ /* First row only */
++ temprow = row % crows;
++ pnm_readpnmrow( ifp, xelbuf[temprow], cols, maxval, format );
++ if ( PNM_FORMAT_TYPE(format) != newformat )
++ pnm_promoteformatrow(
++ xelbuf[temprow], cols, maxval, format, maxval, newformat );
++
++ temprow = (row + 1) % crows;
++ i = 0;
++ for (irow = temprow; irow < crows; ++i, ++irow)
++ rowptr[i] = xelbuf[irow];
++ for (irow = 0; irow < temprow; ++irow, ++i)
++ rowptr[i] = xelbuf[irow];
++
++ for ( crow = 0; crow < crows; ++crow )
++ {
++ rrowsumptr[crow] = rrowsum[crow];
++ growsumptr[crow] = growsum[crow];
++ browsumptr[crow] = browsum[crow];
++ }
++
++ for ( col = 0; col < cols; ++col )
++ {
++ if ( col < ccolso2 || col >= cols - ccolso2 )
++ outputrow[col] = rowptr[crowso2][col];
++ else if ( col == ccolso2 )
++ {
++ leftcol = col - ccolso2;
++ rsum = 0.0;
++ gsum = 0.0;
++ bsum = 0.0;
++ for ( crow = 0; crow < crows; ++crow )
++ {
++ temprptr = rowptr[crow] + leftcol;
++ rrowsumptr[crow][leftcol] = 0L;
++ growsumptr[crow][leftcol] = 0L;
++ browsumptr[crow][leftcol] = 0L;
++ for ( ccol = 0; ccol < ccols; ++ccol )
++ {
++ rrowsumptr[crow][leftcol] +=
++ PPM_GETR( *(temprptr + ccol) );
++ growsumptr[crow][leftcol] +=
++ PPM_GETG( *(temprptr + ccol) );
++ browsumptr[crow][leftcol] +=
++ PPM_GETB( *(temprptr + ccol) );
++ }
++ rsum += rrowsumptr[crow][leftcol] * rweights[crow][0];
++ gsum += growsumptr[crow][leftcol] * gweights[crow][0];
++ bsum += browsumptr[crow][leftcol] * bweights[crow][0];
++ }
++ temprsum = rsum + 0.5;
++ tempgsum = gsum + 0.5;
++ tempbsum = bsum + 0.5;
++ CHECK_RED;
++ CHECK_GREEN;
++ CHECK_BLUE;
++ PPM_ASSIGN( outputrow[col], r, g, b );
++ }
++ else
++ {
++ rsum = 0.0;
++ gsum = 0.0;
++ bsum = 0.0;
++ leftcol = col - ccolso2;
++ subcol = col - ccolso2 - 1;
++ addcol = col + ccolso2;
++ for ( crow = 0; crow < crows; ++crow )
++ {
++ rrowsumptr[crow][leftcol] = rrowsumptr[crow][subcol]
++ - PPM_GETR( rowptr[crow][subcol] )
++ + PPM_GETR( rowptr[crow][addcol] );
++ rsum += rrowsumptr[crow][leftcol] * rweights[crow][0];
++ growsumptr[crow][leftcol] = growsumptr[crow][subcol]
++ - PPM_GETG( rowptr[crow][subcol] )
++ + PPM_GETG( rowptr[crow][addcol] );
++ gsum += growsumptr[crow][leftcol] * gweights[crow][0];
++ browsumptr[crow][leftcol] = browsumptr[crow][subcol]
++ - PPM_GETB( rowptr[crow][subcol] )
++ + PPM_GETB( rowptr[crow][addcol] );
++ bsum += browsumptr[crow][leftcol] * bweights[crow][0];
++ }
++ temprsum = rsum + 0.5;
++ tempgsum = gsum + 0.5;
++ tempbsum = bsum + 0.5;
++ CHECK_RED;
++ CHECK_GREEN;
++ CHECK_BLUE;
++ PPM_ASSIGN( outputrow[col], r, g, b );
++ }
++ }
++ pnm_writepnmrow( stdout, outputrow, cols, maxval, newformat, 0 );
++
++
++ /* For all subsequent rows */
++
++ subrow = crows;
++ addrow = crows - 1;
++ crowsp1 = crows + 1;
++ ++row;
++ for ( ; row < rows; ++row )
++ {
++ temprow = row % crowsp1;
++ pnm_readpnmrow( ifp, xelbuf[temprow], cols, maxval, format );
++ if ( PNM_FORMAT_TYPE(format) != newformat )
++ pnm_promoteformatrow(
++ xelbuf[temprow], cols, maxval, format, maxval, newformat );
++
++ temprow = (row + 2) % crowsp1;
++ i = 0;
++ for (irow = temprow; irow < crowsp1; ++i, ++irow)
++ {
++ rowptr[i] = xelbuf[irow];
++ rrowsumptr[i] = rrowsum[irow];
++ growsumptr[i] = growsum[irow];
++ browsumptr[i] = browsum[irow];
++ }
++ for (irow = 0; irow < temprow; ++irow, ++i)
++ {
++ rowptr[i] = xelbuf[irow];
++ rrowsumptr[i] = rrowsum[irow];
++ growsumptr[i] = growsum[irow];
++ browsumptr[i] = browsum[irow];
++ }
++
++ for ( col = 0; col < cols; ++col )
++ {
++ if ( col < ccolso2 || col >= cols - ccolso2 )
++ outputrow[col] = rowptr[crowso2][col];
++ else if ( col == ccolso2 )
++ {
++ rsum = 0.0;
++ gsum = 0.0;
++ bsum = 0.0;
++ leftcol = col - ccolso2;
++ rrowsumptr[addrow][leftcol] = 0L;
++ growsumptr[addrow][leftcol] = 0L;
++ browsumptr[addrow][leftcol] = 0L;
++ for ( ccol = 0; ccol < ccols; ++ccol )
++ {
++ rrowsumptr[addrow][leftcol] +=
++ PPM_GETR( rowptr[addrow][leftcol + ccol] );
++ growsumptr[addrow][leftcol] +=
++ PPM_GETG( rowptr[addrow][leftcol + ccol] );
++ browsumptr[addrow][leftcol] +=
++ PPM_GETB( rowptr[addrow][leftcol + ccol] );
++ }
++ for ( crow = 0; crow < crows; ++crow )
++ {
++ rsum += rrowsumptr[crow][leftcol] * rweights[crow][0];
++ gsum += growsumptr[crow][leftcol] * gweights[crow][0];
++ bsum += browsumptr[crow][leftcol] * bweights[crow][0];
++ }
++ temprsum = rsum + 0.5;
++ tempgsum = gsum + 0.5;
++ tempbsum = bsum + 0.5;
++ CHECK_RED;
++ CHECK_GREEN;
++ CHECK_BLUE;
++ PPM_ASSIGN( outputrow[col], r, g, b );
++ }
++ else
++ {
++ rsum = 0.0;
++ gsum = 0.0;
++ bsum = 0.0;
++ leftcol = col - ccolso2;
++ subcol = col - ccolso2 - 1;
++ addcol = col + ccolso2;
++ rrowsumptr[addrow][leftcol] = rrowsumptr[addrow][subcol]
++ - PPM_GETR( rowptr[addrow][subcol] )
++ + PPM_GETR( rowptr[addrow][addcol] );
++ growsumptr[addrow][leftcol] = growsumptr[addrow][subcol]
++ - PPM_GETG( rowptr[addrow][subcol] )
++ + PPM_GETG( rowptr[addrow][addcol] );
++ browsumptr[addrow][leftcol] = browsumptr[addrow][subcol]
++ - PPM_GETB( rowptr[addrow][subcol] )
++ + PPM_GETB( rowptr[addrow][addcol] );
++ for ( crow = 0; crow < crows; ++crow )
++ {
++ rsum += rrowsumptr[crow][leftcol] * rweights[crow][0];
++ gsum += growsumptr[crow][leftcol] * gweights[crow][0];
++ bsum += browsumptr[crow][leftcol] * bweights[crow][0];
++ }
++ temprsum = rsum + 0.5;
++ tempgsum = gsum + 0.5;
++ tempbsum = bsum + 0.5;
++ CHECK_RED;
++ CHECK_GREEN;
++ CHECK_BLUE;
++ PPM_ASSIGN( outputrow[col], r, g, b );
++ }
++ }
++ pnm_writepnmrow( stdout, outputrow, cols, maxval, newformat, 0 );
++ }
++
++ /* Now write out the remaining unconvolved rows in xelbuf. */
++ for ( irow = crowso2 + 1; irow < crows; ++irow )
++ pnm_writepnmrow(
++ stdout, rowptr[irow], cols, maxval, newformat, 0 );
++
++ pm_close( stdout );
++ }
++
++
++/* PPM Vertical Convolution
++**
++** Same as pgm_vertical_convolve()
++**
++*/
++
++static void
++ppm_vertical_convolve()
++ {
++ register int ccol, col;
++ xel** xelbuf;
++ xel* outputrow;
++ xelval r, g, b;
++ int row, crow;
++ xel **rowptr, *temprptr;
++ int leftcol;
++ int i, irow;
++ int toprow, temprow;
++ int subrow, addrow;
++ int tempcol;
++ float rsum, gsum, bsum;
++ long *rcolumnsum, *gcolumnsum, *bcolumnsum;
++ int crowsp1;
++ int addcol;
++ long temprsum, tempgsum, tempbsum;
++
++ /* Allocate space for one convolution-matrix's worth of rows, plus
++ ** a row output buffer. VERTICAL uses an extra row. */
++ xelbuf = pnm_allocarray( cols, crows + 1 );
++ outputrow = pnm_allocrow( cols );
++
++ /* Allocate array of pointers to xelbuf */
++ rowptr = (xel **) pnm_allocarray( 1, crows + 1 );
++
++ /* Allocate space for intermediate column sums */
++ rcolumnsum = (long *) pm_allocrow( cols, sizeof(long) );
++ gcolumnsum = (long *) pm_allocrow( cols, sizeof(long) );
++ bcolumnsum = (long *) pm_allocrow( cols, sizeof(long) );
++ for ( col = 0; col < cols; ++col )
++ {
++ rcolumnsum[col] = 0L;
++ gcolumnsum[col] = 0L;
++ bcolumnsum[col] = 0L;
++ }
++
++ pnm_writepnminit( stdout, cols, rows, maxval, newformat, 0 );
++
++ /* Read in one convolution-matrix's worth of image, less one row. */
++ for ( row = 0; row < crows - 1; ++row )
++ {
++ pnm_readpnmrow( ifp, xelbuf[row], cols, maxval, format );
++ if ( PNM_FORMAT_TYPE(format) != newformat )
++ pnm_promoteformatrow(
++ xelbuf[row], cols, maxval, format, maxval, newformat );
++ /* Write out just the part we're not going to convolve. */
++ if ( row < crowso2 )
++ pnm_writepnmrow( stdout, xelbuf[row], cols, maxval, newformat, 0 );
++ }
++
++ /* Now the rest of the image - read in the row at the end of
++ ** xelbuf, and convolve and write out the row in the middle.
++ */
++ /* For first row only */
++
++ toprow = row + 1;
++ temprow = row % crows;
++ pnm_readpnmrow( ifp, xelbuf[temprow], cols, maxval, format );
++ if ( PNM_FORMAT_TYPE(format) != newformat )
++ pnm_promoteformatrow(
++ xelbuf[temprow], cols, maxval, format, maxval, newformat );
++
++ /* Arrange rowptr to eliminate the use of mod function to determine
++ ** which row of xelbuf is 0...crows. Mod function can be very costly.
++ */
++ temprow = toprow % crows;
++ i = 0;
++ for (irow = temprow; irow < crows; ++i, ++irow)
++ rowptr[i] = xelbuf[irow];
++ for (irow = 0; irow < temprow; ++irow, ++i)
++ rowptr[i] = xelbuf[irow];
++
++ for ( col = 0; col < cols; ++col )
++ {
++ if ( col < ccolso2 || col >= cols - ccolso2 )
++ outputrow[col] = rowptr[crowso2][col];
++ else if ( col == ccolso2 )
++ {
++ rsum = 0.0;
++ gsum = 0.0;
++ bsum = 0.0;
++ leftcol = col - ccolso2;
++ for ( crow = 0; crow < crows; ++crow )
++ {
++ temprptr = rowptr[crow] + leftcol;
++ for ( ccol = 0; ccol < ccols; ++ccol )
++ {
++ rcolumnsum[leftcol + ccol] +=
++ PPM_GETR( *(temprptr + ccol) );
++ gcolumnsum[leftcol + ccol] +=
++ PPM_GETG( *(temprptr + ccol) );
++ bcolumnsum[leftcol + ccol] +=
++ PPM_GETB( *(temprptr + ccol) );
++ }
++ }
++ for ( ccol = 0; ccol < ccols; ++ccol)
++ {
++ rsum += rcolumnsum[leftcol + ccol] * rweights[0][ccol];
++ gsum += gcolumnsum[leftcol + ccol] * gweights[0][ccol];
++ bsum += bcolumnsum[leftcol + ccol] * bweights[0][ccol];
++ }
++ temprsum = rsum + 0.5;
++ tempgsum = gsum + 0.5;
++ tempbsum = bsum + 0.5;
++ CHECK_RED;
++ CHECK_GREEN;
++ CHECK_BLUE;
++ PPM_ASSIGN( outputrow[col], r, g, b );
++ }
++ else
++ {
++ rsum = 0.0;
++ gsum = 0.0;
++ bsum = 0.0;
++ leftcol = col - ccolso2;
++ addcol = col + ccolso2;
++ for ( crow = 0; crow < crows; ++crow )
++ {
++ rcolumnsum[addcol] += PPM_GETR( rowptr[crow][addcol] );
++ gcolumnsum[addcol] += PPM_GETG( rowptr[crow][addcol] );
++ bcolumnsum[addcol] += PPM_GETB( rowptr[crow][addcol] );
++ }
++ for ( ccol = 0; ccol < ccols; ++ccol )
++ {
++ rsum += rcolumnsum[leftcol + ccol] * rweights[0][ccol];
++ gsum += gcolumnsum[leftcol + ccol] * gweights[0][ccol];
++ bsum += bcolumnsum[leftcol + ccol] * bweights[0][ccol];
++ }
++ temprsum = rsum + 0.5;
++ tempgsum = gsum + 0.5;
++ tempbsum = bsum + 0.5;
++ CHECK_RED;
++ CHECK_GREEN;
++ CHECK_BLUE;
++ PPM_ASSIGN( outputrow[col], r, g, b );
++ }
++ }
++ pnm_writepnmrow( stdout, outputrow, cols, maxval, newformat, 0 );
++
++ /* For all subsequent rows */
++ subrow = crows;
++ addrow = crows - 1;
++ crowsp1 = crows + 1;
++ ++row;
++ for ( ; row < rows; ++row )
++ {
++ toprow = row + 1;
++ temprow = row % (crows +1);
++ pnm_readpnmrow( ifp, xelbuf[temprow], cols, maxval, format );
++ if ( PNM_FORMAT_TYPE(format) != newformat )
++ pnm_promoteformatrow(
++ xelbuf[temprow], cols, maxval, format, maxval, newformat );
++
++ /* Arrange rowptr to eliminate the use of mod function to determine
++ ** which row of xelbuf is 0...crows. Mod function can be very costly.
++ */
++ temprow = (toprow + 1) % crowsp1;
++ i = 0;
++ for (irow = temprow; irow < crowsp1; ++i, ++irow)
++ rowptr[i] = xelbuf[irow];
++ for (irow = 0; irow < temprow; ++irow, ++i)
++ rowptr[i] = xelbuf[irow];
++
++ for ( col = 0; col < cols; ++col )
++ {
++ if ( col < ccolso2 || col >= cols - ccolso2 )
++ outputrow[col] = rowptr[crowso2][col];
++ else if ( col == ccolso2 )
++ {
++ rsum = 0.0;
++ gsum = 0.0;
++ bsum = 0.0;
++ leftcol = col - ccolso2;
++ for ( ccol = 0; ccol < ccols; ++ccol )
++ {
++ tempcol = leftcol + ccol;
++ rcolumnsum[tempcol] = rcolumnsum[tempcol]
++ - PPM_GETR( rowptr[subrow][ccol] )
++ + PPM_GETR( rowptr[addrow][ccol] );
++ rsum = rsum + rcolumnsum[tempcol] * rweights[0][ccol];
++ gcolumnsum[tempcol] = gcolumnsum[tempcol]
++ - PPM_GETG( rowptr[subrow][ccol] )
++ + PPM_GETG( rowptr[addrow][ccol] );
++ gsum = gsum + gcolumnsum[tempcol] * gweights[0][ccol];
++ bcolumnsum[tempcol] = bcolumnsum[tempcol]
++ - PPM_GETB( rowptr[subrow][ccol] )
++ + PPM_GETB( rowptr[addrow][ccol] );
++ bsum = bsum + bcolumnsum[tempcol] * bweights[0][ccol];
++ }
++ temprsum = rsum + 0.5;
++ tempgsum = gsum + 0.5;
++ tempbsum = bsum + 0.5;
++ CHECK_RED;
++ CHECK_GREEN;
++ CHECK_BLUE;
++ PPM_ASSIGN( outputrow[col], r, g, b );
++ }
++ else
++ {
++ rsum = 0.0;
++ gsum = 0.0;
++ bsum = 0.0;
++ leftcol = col - ccolso2;
++ addcol = col + ccolso2;
++ rcolumnsum[addcol] = rcolumnsum[addcol]
++ - PPM_GETR( rowptr[subrow][addcol] )
++ + PPM_GETR( rowptr[addrow][addcol] );
++ gcolumnsum[addcol] = gcolumnsum[addcol]
++ - PPM_GETG( rowptr[subrow][addcol] )
++ + PPM_GETG( rowptr[addrow][addcol] );
++ bcolumnsum[addcol] = bcolumnsum[addcol]
++ - PPM_GETB( rowptr[subrow][addcol] )
++ + PPM_GETB( rowptr[addrow][addcol] );
++ for ( ccol = 0; ccol < ccols; ++ccol )
++ {
++ rsum += rcolumnsum[leftcol + ccol] * rweights[0][ccol];
++ gsum += gcolumnsum[leftcol + ccol] * gweights[0][ccol];
++ bsum += bcolumnsum[leftcol + ccol] * bweights[0][ccol];
++ }
++ temprsum = rsum + 0.5;
++ tempgsum = gsum + 0.5;
++ tempbsum = bsum + 0.5;
++ CHECK_RED;
++ CHECK_GREEN;
++ CHECK_BLUE;
++ PPM_ASSIGN( outputrow[col], r, g, b );
++ }
++ }
++ pnm_writepnmrow( stdout, outputrow, cols, maxval, newformat, 0 );
++ }
++
++ /* Now write out the remaining unconvolved rows in xelbuf. */
++ for ( irow = crowso2 + 1; irow < crows; ++irow )
++ pnm_writepnmrow(
++ stdout, rowptr[irow], cols, maxval, newformat, 0 );
+
+ pm_close( stdout );
+- exit( 0 );
+ }
diff --git a/graphics/netpbm/patches/patch-bk b/graphics/netpbm/patches/patch-bk
new file mode 100644
index 00000000000..95d928e25c8
--- /dev/null
+++ b/graphics/netpbm/patches/patch-bk
@@ -0,0 +1,164 @@
+--- /dev/null Thu Oct 16 09:27:24 1997
++++ ./pnm/pnmhisteq.1 Sun Aug 13 00:13:48 1995
+@@ -0,0 +1,161 @@
++.TH pnmhisteq 1 "19 March 1995"
++.IX "pnmhisteq command"
++.IX histogram
++.SH NAME
++pnmhisteq \- histogram equalise a portable anymap
++.SH SYNOPSIS
++.na
++.B pnmhisteq
++'ti 15
++.RB [ \-gray ]
++.RB [ \-rmap
++.IR pgmfile ]
++.RB [ \-wmap
++.IR pgmfile ]
++.RB [ \-verbose ]
++.RI [ pnmfile ]
++.ad
++.SH DESCRIPTION
++.B pnmhisteq
++increases the contrast of a portable graymap or pixmap through the
++technique of
++.IR "histogram equalisation" [1].
++A histogram of the luminance of pixels in the map is computed, from
++which a transfer function is calculated which spreads out intensity levels
++around histogram peaks and compresses them at troughs. This has the
++effect of using the available levels of intensity more efficiently and
++thereby increases the detail visible in the image.
++.PP
++Mathematically, if
++.I N[i]
++is the number of pixels of luminosity
++.I i
++in the image and
++.I T
++is the total number of pixels, luminosity
++.I j
++is replaced by:
++.PP
++.NF
++.vs 9p
++ j
++ ---
++ \\
++ \> N[i] / T
++ \/
++ ---
++ i=0
++.vs
++.FI
++.PP
++If you're processing a related set of images, for example frames of an
++animation, it's generally best to apply the same intensity map to
++every frame, since otherwise you'll get distracting frame-to-frame
++changes in the brightness of objects.
++.BR pnmhisteq 's
++.B \-wmap
++option
++allows you to save, as a portable graymap, the luminosity map computed
++from an image (usually a composite of the images you intend
++to process created with
++.BR pnmcat ).
++Then, you can subsequently process each of the individual images using
++the luminosity map saved in the file, supplied with the
++.B \-rmap
++option.
++.SH OPTIONS
++.TP 10
++.B \-gray
++When processing a pixmap, only gray pixels (those with identical red,
++green, and blue values) are included in the histogram and modified
++in the output image. This is a special purpose option intended
++for images where the actual data are gray scale, with
++colour annotations you don't want modified. Weather
++satellite images that show continent outlines in colour are best
++processed using this option. The option has no effect when the input
++is a graymap.
++.TP
++.BI \-rmap " mapfile"
++Process the image using the luminosity map specified by the portable
++graymap
++.I mapfile.
++The graymap, usually created by an earlier run of
++.B pnmhisteq
++with the
++.B \-wmap
++option, contains a single row with number of columns equal to
++the
++.I maxval
++(greatest intensity) of the image. Each pixel in the image is
++transformed by looking up its luminosity in the corresponding
++column in the map file and changing it to the value
++given by that column.
++.TP
++.BI \-wmap " mapfile"
++Creates a portable graymap,
++.I mapfile,
++containing the luminosity map computed from the histogram of the
++input image. This map file can be read on subsequent runs of
++.B pnmhisteq
++with the
++.B \-rmap
++option, allowing a group of images to be processed with
++an identical map.
++.TP
++.B \-verbose
++Prints the histogram and luminosity map on standard error.
++.PP
++All flags can be abbreviated to their shortest unique prefix.
++.SH BUGS
++Histogram equalisation is effective for increasing the visible detail
++in scientific imagery and in some continuous-tone pictures. It is
++often too drastic, however, for scanned halftone images, where it
++does an excellent job of making halftone artifacts apparent. You
++might want to experiment with
++.BR pgnnorm ,
++.BR ppmnorm ,
++and
++.B pnmgamma
++for more subtle contrast enhancement.
++.PP
++The luminosity map file supplied by the
++.B \-rmap
++option must have the same
++.I maxval
++as the input image. This is always the case when the
++map file was created by the
++.B \-wmap
++option of
++.BR pnmhisteq .
++If this restriction causes a problem, simply adjust the
++.I maxval
++of the map with
++.B pnmdepth
++to agree with the input image.
++.PP
++If the input is a PBM file (on which histogram equalisation is an
++identity operation), the only effect of passing the file through
++.B pnmhisteq
++will be the passage of time.
++.SH "SEE ALSO"
++.PD
++.BR pgmnorm (1),
++.BR pnm (5),
++.BR pnmcat (1),
++.BR pnmdepth (1),
++.BR pnmgamma (1),
++.BR pnmnorm (1)
++.TP 5
++[1]
++Russ, John C. The Image Processing Handbook.
++Boca Raton: CRC Press, 1992. Pages 105-110.
++.ne 10
++.SH AUTHOR
++.ce 2
++Copyright (C) 1995 by John Walker (kelvin@fourmilab.ch).
++WWW home page: http://www.fourmilab.ch/
++.PP
++Permission to use, copy, modify, and distribute this software and its
++documentation for any purpose and without fee is hereby granted,
++without any conditions or restrictions. This software is provided ``as
++is'' without express or implied warranty.
diff --git a/graphics/netpbm/patches/patch-bl b/graphics/netpbm/patches/patch-bl
new file mode 100644
index 00000000000..0dbab9b0f1e
--- /dev/null
+++ b/graphics/netpbm/patches/patch-bl
@@ -0,0 +1,374 @@
+--- /dev/null Thu Oct 16 09:27:24 1997
++++ ./pnm/pnmhisteq.c Sun Aug 13 00:13:48 1995
+@@ -0,0 +1,371 @@
++/*
++ pnmhisteq.c
++
++ Equalise histogram for a PGM or PPM file
++
++ Options: -gray: modify gray pixels only; leave colours unchanged
++ -rmap fn: read luminosity map from PGM file fn
++ -wmap wn: write luminosity map to PGM file fn
++ -verbose: print histogram and luminosity map
++
++ Accepts PGM and PPM as input. PBM input is allowed, but histogram
++ equalisation does not modify a PBM file.
++
++ by John Walker (kelvin@fourmilab.ch) -- March MVM.
++ WWW home page: http://www.fourmilab.ch/
++
++ Copyright (C) 1995 by John Walker
++
++ Permission to use, copy, modify, and distribute this software and
++ its documentation for any purpose and without fee is hereby
++ granted, without any conditions or restrictions. This software is
++ provided "as is" without express or implied warranty.
++
++*/
++
++#include "pnm.h"
++
++/* Prototypes */
++
++static void hsv_rgb ARGS((double h, double s, double v,
++ double *r, double *g, double *b));
++static void rgb_hsv ARGS((double r, double g, double b,
++ double *h, double *s, double *v));
++
++/* HSV_RGB -- Convert HSV colour specification to RGB intensities.
++ Hue is specified as a real value from 0 to 360,
++ Saturation and Intensity as reals from 0 to 1. The
++ RGB components are returned as reals from 0 to 1. */
++
++static void hsv_rgb(h, s, v, r, g, b)
++ double h, s, v;
++ double *r, *g, *b;
++{
++ int i;
++ double f, p, q, t;
++
++ if (s == 0) {
++ *r = *g = *b = v;
++ } else {
++ if (h == 360.0) {
++ h = 0;
++ }
++ h /= 60.0;
++
++ i = h;
++ f = h - i;
++ p = v * (1.0 - s);
++ q = v * (1.0 - (s * f));
++ t = v * (1.0 - (s * (1.0 - f)));
++ switch (i) {
++
++ case 0:
++ *r = v;
++ *g = t;
++ *b = p;
++ break;
++
++ case 1:
++ *r = q;
++ *g = v;
++ *b = p;
++ break;
++
++ case 2:
++ *r = p;
++ *g = v;
++ *b = t;
++ break;
++
++ case 3:
++ *r = p;
++ *g = q;
++ *b = v;
++ break;
++
++ case 4:
++ *r = t;
++ *g = p;
++ *b = v;
++ break;
++
++ case 5:
++ *r = v;
++ *g = p;
++ *b = q;
++ break;
++ }
++ }
++}
++
++/* RGB_HSV -- Map R, G, B intensities in the range from 0 to 1 into
++ Hue, Saturation, and Value: Hue from 0 to 360,
++ Saturation from 0 to 1, and Value from 0 to 1.
++ Special case: if Saturation is 0 (it's a grey scale
++ tone), Hue is undefined and is returned as -1.
++
++ This follows Foley & van Dam, section 17.4.4. */
++
++static void rgb_hsv(r, g, b, h, s, v)
++ double r, g, b;
++ double *h, *s, *v;
++{
++ double imax = max(r, max(g, b)),
++ imin = min(r, min(g, b)),
++ rc, gc, bc;
++
++ *v = imax;
++ if (imax != 0) {
++ *s = (imax - imin) / imax;
++ } else {
++ *s = 0;
++ }
++
++ if (*s == 0) {
++ *h = -1;
++ } else {
++ rc = (imax - r) / (imax - imin);
++ gc = (imax - g) / (imax - imin);
++ bc = (imax - b) / (imax - imin);
++ if (r == imax) {
++ *h = bc - gc;
++ } else if (g == imax) {
++ *h = 2.0 + rc - bc;
++ } else {
++ *h = 4.0 + gc - rc;
++ }
++ *h *= 60.0;
++ if (*h < 0.0) {
++ *h += 360.0;
++ }
++ }
++}
++
++int main(argc, argv)
++ int argc;
++ char *argv[];
++{
++ FILE *ifp;
++ int argn = 1, i, j, verbose = 0, mono_only = 0;
++ gray lmin, lmax;
++ gray **lumamap; /* Luminosity map */
++ long *lumahist; /* Histogram of luminosity values */
++ int rows, hist_cols; /* Rows, columns of input image */
++ xelval maxval; /* Maxval of input image */
++ int format; /* Format indicator (PBM/PGM/PPM) */
++ xel** xels; /* Pixel array */
++ unsigned long pixels = 0, pixsum = 0, maxluma = 0;
++ double lscale;
++ xel *grayrow;
++ pixel *pixrow;
++ FILE *rmap = NULL, *wmap = NULL;
++ char *usage = "[-gray] [-verbose] [-rmap pgmfile] [-wmap pgmfile] [pnmfile]";
++
++ pnm_init(&argc, argv);
++
++ /* Check for flags. */
++
++ while (argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0') {
++ if (pm_keymatch(argv[argn], "-gray", 1)) {
++ mono_only = 1;
++ } else if (pm_keymatch(argv[argn], "-verbose", 1)) {
++ verbose = 1;
++ } else if (pm_keymatch(argv[argn], "-rmap", 1)) {
++ if (rmap != NULL) {
++ pm_error("already specified an input map");
++ }
++ argn++;
++ if (argn == argc || strcmp(argv[argn], "-") == 0) {
++ pm_usage(usage);
++ }
++ rmap = pm_openr(argv[argn]);
++ } else if (pm_keymatch(argv[argn], "-wmap", 1)) {
++ if (wmap != NULL) {
++ pm_error("already specified an output map");
++ }
++ argn++;
++ if (argn == argc) {
++ pm_usage(usage);
++ }
++ wmap = pm_openw(argv[argn]);
++ } else {
++ pm_usage(usage);
++ }
++ argn++;
++ }
++
++ if (--argc > argn) {
++ pm_usage(usage);
++ } else if (argc == argn) {
++ ifp = pm_openr(argv[argn]);
++ } else {
++ ifp = stdin;
++ }
++
++ xels = pnm_readpnm(ifp, &hist_cols, &rows, &maxval, &format);
++ pm_close(ifp);
++
++ /* Allocate histogram and luminosity map arrays. If the
++ user has specified an input map file, read it in at
++ this point. */
++
++ lumahist = (long *) pm_allocrow(maxval + 1, sizeof(long));
++ bzero((char *) lumahist, (maxval + 1) * sizeof(long));
++
++ if (rmap == NULL) {
++ lumamap = pgm_allocarray(maxval + 1, 1);
++ } else {
++ int rmcols, rmrows;
++ gray rmmaxv;
++
++ lumamap = pgm_readpgm(rmap, &rmcols, &rmrows, &rmmaxv);
++ if (rmmaxv != maxval) {
++ pm_error("maxval in map file (%d) different from input (%d)",
++ rmmaxv, maxval);
++ }
++ if (rmrows != 1 || rmcols != rmmaxv) {
++ pm_error("map size (%d by %d) wrong; must be (%d by 1)",
++ rmcols, rmrows, maxval);
++ }
++ }
++
++ /* Scan the image and build the luminosity histogram. If
++ the input is a PPM, we calculate the luminosity of each
++ pixel from its RGB components. */
++
++ lmin = maxval;
++ lmax = 0;
++ if (PNM_FORMAT_TYPE(format) == PGM_TYPE ||
++ PNM_FORMAT_TYPE(format) == PBM_TYPE) {
++
++ /* Compute intensity histogram */
++
++ pixels = ((unsigned long) rows) * ((unsigned long) hist_cols);
++ for (i = 0; i < rows; i++) {
++ xel *grayrow = xels[i];
++ for (j = 0; j < hist_cols; j++) {
++ gray l = PNM_GET1(grayrow[j]);
++ lmin = min(lmin, l);
++ lmax = max(lmax, l);
++ lumahist[l]++;
++ }
++ }
++ } else if (PNM_FORMAT_TYPE(format) == PPM_TYPE) {
++ for (i = 0; i < rows; i++) {
++ pixel *pixrow = (pixel *) xels[i];
++
++ for (j = 0; j < hist_cols; j++) {
++ if (!mono_only ||
++ ((PPM_GETR(pixrow[j]) == PPM_GETG(pixrow[j])) &&
++ (PPM_GETR(pixrow[j]) == PPM_GETB(pixrow[j])))) {
++ gray l = (gray) PPM_LUMIN(pixrow[j]);
++ lmin = min(lmin, l);
++ lmax = max(lmax, l);
++ lumahist[l]++;
++ pixels++;
++ }
++ }
++ }
++ } else {
++ pm_error("unknown input format");
++ }
++
++ /* The PGM and PPM branches rejoin here to calculate the
++ luminosity mapping table which gives the histogram-equalised
++ luminosity for each original luminosity. */
++
++ /* Calculate initial histogram equalisation curve. */
++
++ for (i = 0; i <= (int) maxval; i++) {
++
++ /* Yick. If PGM_BIGGRAYS is defined (I thought they were little
++ guys, about four foot, with funny eyes...) the following
++ calculation can overflow a 32 bit long. So, we do it in
++ floating point. Since this happens only maxval times, the
++ inefficiency is trivial compared to the every-pixel code above
++ and below. */
++
++ lumamap[0][i] = (gray) (((((double) pixsum * maxval)) / pixels) + 0.5);
++ if (lumahist[i] > 0) {
++ maxluma = i;
++ }
++ pixsum += lumahist[i];
++ }
++
++ /* Normalise so that the brightest pixels are set to
++ maxval. */
++
++ lscale = ((double) maxval) / ((lumahist[maxluma] > 0) ?
++ ((double) lumamap[0][maxluma]) : ((double) maxval));
++ for (i = 0; i <= (int) maxval; i++) {
++ lumamap[0][i] = (gray)
++ min(((long) maxval), ((long) (lumamap[0][i] * lscale + 0.5)));
++ }
++
++ /* If requested, print the luminosity map and original histogram. */
++
++ if (verbose) {
++ fprintf(stderr,
++ " Luminosity map Number of\n Original New Pixels\n");
++ for (i = 0; i <= (int) maxval; i++) {
++ if (lumahist[i] > 0) {
++ fprintf(stderr,"%6d -> %6d %8d\n", i,
++ lumamap[0][i], lumahist[i]);
++ }
++ }
++ }
++
++ switch (PNM_FORMAT_TYPE(format)) {
++ case PBM_TYPE:
++ case PPM_TYPE:
++ for (i = 0; i < rows; i++) {
++ pixrow = (pixel *) xels[i];
++ for (j = 0; j < hist_cols; j++) {
++ if (!mono_only ||
++ ((PPM_GETR(pixrow[j]) == PPM_GETG(pixrow[j])) &&
++ (PPM_GETR(pixrow[j]) == PPM_GETB(pixrow[j])))) {
++ double r, g, b, h, s, v;
++ int iv;
++
++ r = (double) PPM_GETR(pixrow[j]) / ((double) maxval);
++ g = (double) PPM_GETG(pixrow[j]) / ((double) maxval);
++ b = (double) PPM_GETB(pixrow[j]) / ((double) maxval);
++ rgb_hsv(r, g, b, &h, &s, &v);
++ iv = (int) ((v * maxval) + 0.5);
++
++ if (iv > ((int) maxval)) {
++ iv = maxval;
++ }
++ v = ((double) lumamap[0][iv]) / ((double) maxval);
++ if (v > 1.0) {
++ v = 1.0;
++ }
++ hsv_rgb(h, s, v, &r, &g, &b);
++ PPM_ASSIGN(pixrow[j], (int) (r * maxval),
++ (int) (g * maxval), (int) (b * maxval));
++ }
++ }
++ }
++ break;
++
++ case PGM_TYPE:
++ for (i = 0; i < rows; i++) {
++ grayrow = xels[i];
++ for (j = 0; j < hist_cols; j++) {
++ PNM_ASSIGN1(grayrow[j], lumamap[0][PNM_GET1(grayrow[j])]);
++ }
++ }
++ break;
++ }
++
++ pnm_writepnm(stdout, xels, hist_cols, rows, maxval, format, 0);
++
++ /* If requested, save the map as a PGM file. */
++
++ if (wmap != NULL) {
++ pgm_writepgm(wmap, lumamap, maxval, 1, maxval, 0);
++ fclose(wmap);
++ }
++
++ return 0;
++}
diff --git a/graphics/netpbm/patches/patch-bm b/graphics/netpbm/patches/patch-bm
new file mode 100644
index 00000000000..3cbd8d55541
--- /dev/null
+++ b/graphics/netpbm/patches/patch-bm
@@ -0,0 +1,29 @@
+--- ./pnm/pnmmerge.c.orig Mon Jan 31 06:31:47 1994
++++ ./pnm/pnmmerge.c Thu Oct 16 11:08:33 1997
+@@ -30,6 +30,10 @@
+ {
+ ++argv;
+ --argc;
++ if(!*argv) {
++ fprintf(stderr, "Usage: pnmmerge pnm_program_name [args ...]\n");
++ exit(1);
++ }
+ goto again;
+ }
+
+@@ -51,6 +55,7 @@
+ TRY("pnmgamma", pnmgamma_main);
+ TRY("pnminvert", pnminvert_main);
+ TRY("pnmhistmap", pnmhistmap_main);
++ TRY("pnmhisteq", pnmhisteq_main);
+ TRY("pnmnlfilt", pnmnlfilt_main);
+ TRY("pnmnoraw", pnmnoraw_main);
+ TRY("pnmpaste", pnmpaste_main);
+@@ -76,6 +81,7 @@
+ #endif /*LIBTIFF*/
+ TRY("xwdtopnm", xwdtopnm_main);
+ TRY("zeisstopnm", zeisstopnm_main);
++ TRY("pnmsmooth", pnmsmooth_main);
+
+ (void) fprintf(
+ stderr, "pnmmerge: \"%s\" is an unknown PNM program!\n", cp );
diff --git a/graphics/netpbm/patches/patch-bn b/graphics/netpbm/patches/patch-bn
new file mode 100644
index 00000000000..141ab4f26b9
--- /dev/null
+++ b/graphics/netpbm/patches/patch-bn
@@ -0,0 +1,52 @@
+--- ./pnm/pnmsmooth.1.orig Mon Oct 4 05:11:56 1993
++++ ./pnm/pnmsmooth.1 Sun Aug 13 00:21:28 1995
+@@ -1,25 +1,42 @@
+-.TH pnmsmooth 1 "13 January 1991"
++.TH pnmsmooth 1 "4 December 1994"
+ .IX pnmsmooth
+ .SH NAME
+ pnmsmooth - smooth out an image
+ .SH SYNOPSIS
+ .B pnmsmooth
++.RB [ -size
++.IR width
++.IR height ]
++.RB [ -dump
++.IR dumpfile ]
+ .RI [ pnmfile ]
+ .SH DESCRIPTION
+ Smooths out an image by replacing each pixel with the
+-average of its nine immediate neighbors.
++average of its width X height neighbors.
+ .IX smoothing
+ .IX anti-aliasing
+-It is implemented as a simple script using
++It is implemented as a C progam that generates a PGM convolution matrix
++and then invokes
+ .IR pnmconvol .
+ .IX pnmconvol
++.SH OPTIONS
++.TP
++.B -size width height
++Specifies the size of the convolution matrix.
++Default size is a 3x3 matrix.
++Width and height sizes must be odd.
++Maximum size of convolution matrix is limited by the maximum value for a
++pixel such that (width * height * 2) must not exceed the maximum pixel value.
++.TP
++.B -dump dumpfile
++Generates and saves the convolution file only.
++Use of this option does not invoke pnmconvol.
+ .SH "SEE ALSO"
+ pnmconvol(1), pnm(5)
+-.SH BUGS
+-It's a script.
+-Scripts are not portable to non-Unix environments.
+-.SH AUTHOR
++.SH AUTHORS
+ Copyright (C) 1989, 1991 by Jef Poskanzer.
++.br
++Converted from script to C program December 1994 by Mike Burns (burns@chem.psu.edu).
+ .\" 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
diff --git a/graphics/netpbm/patches/patch-bo b/graphics/netpbm/patches/patch-bo
new file mode 100644
index 00000000000..b016f05254f
--- /dev/null
+++ b/graphics/netpbm/patches/patch-bo
@@ -0,0 +1,24 @@
+--- /dev/null Thu Oct 16 09:27:24 1997
++++ ./pnm/pnmsmooth.README Sun Aug 13 00:21:28 1995
+@@ -0,0 +1,21 @@
++README for pnmsmooth.c 2.0
++
++This is a replacement for the pnmsmooth script that is distributed with
++pbmplus/netpbm. This version of pnmsmooth is written as a C program rather
++than a shell script. It accepts command line arguments to specify a size
++other than 3x3 for the convolution matrix and an argument for dumping the
++resultant convolution matrix as a PGM file. By default it uses the same 3x3
++matrix size as the pnmsmooth script and can be used as a direct replacement.
++
++Also included are an updated man page and a patch file to update the Imakefile
++in the pnm directory. You may want to apply the patches by hand if you have
++already modified the Imakefile to add other new programs. You will then
++have to remake the Makefiles and then type 'make all' in the pnm directory.
++
++- Mike
++
++----------------------------------------------------------------------------
++Mike Burns System Administrator
++burns@chem.psu.edu Department of Chemistry
++(814) 863-2123 The Pennsylvania State University
++
diff --git a/graphics/netpbm/patches/patch-bp b/graphics/netpbm/patches/patch-bp
new file mode 100644
index 00000000000..4d68010221b
--- /dev/null
+++ b/graphics/netpbm/patches/patch-bp
@@ -0,0 +1,174 @@
+--- /dev/null Thu Oct 16 09:27:24 1997
++++ ./pnm/pnmsmooth.c Sun Aug 13 00:21:29 1995
+@@ -0,0 +1,171 @@
++/* pnmsmooth.c - smooth out an image by replacing each pixel with the
++** average of its width x height neighbors.
++**
++** Version 2.0 December 5, 1994
++**
++** Copyright (C) 1994 by Mike Burns (burns@chem.psu.edu)
++**
++** 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.
++*/
++
++/* Version 2.0 - December 5, 1994
++** ------------------------------
++** Rewrote as a C program that accepts a few options instead of a shell
++** script with no options.
++**
++*/
++
++#include "pnm.h"
++#include <sys/wait.h>
++
++#define TRUE 1
++#define FALSE 0
++
++int
++main( argc, argv )
++ int argc;
++ char* argv[];
++ {
++ FILE *cofp;
++ char *tempfn;
++ char *pnmfn;
++ int argn;
++ int col, row;
++ int format, forceplain;
++ int cols, rows;
++ int newmaxval; /* normally xelval, but want int here */
++ xelval g;
++ xel *outputrow;
++ int pid, status;
++ int DUMPFLAG = FALSE;
++ char *usage = "[-size width height] [-dump dumpfile] [pnmfile]";
++
++ pnm_init( &argc, argv );
++
++ /* set up defaults */
++ cols = 3;
++ rows = 3;
++ format = PGM_FORMAT;
++ forceplain = 1;
++ pnmfn = (char *) 0; /* initialize to NULL just in case */
++
++ argn = 1;
++ while ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
++ {
++ if ( pm_keymatch( argv[argn], "-size", 2 ) )
++ {
++ ++argn;
++ if ( argn+1 >= argc )
++ {
++ pm_message( "incorrect number of arguments for -size option" );
++ pm_usage( usage );
++ }
++ else if ( argv[argn][0] == '-' || argv[argn+1][0] == '-' )
++ {
++ pm_message( "invalid arguments to -size option: %s %s",
++ argv[argn], argv[argn+1] );
++ pm_usage( usage );
++ }
++ if ( (cols = atoi(argv[argn])) == 0 )
++ pm_error( "invalid width size specification: %s", argv[argn] );
++ ++argn;
++ if ( (rows = atoi(argv[argn])) == 0 )
++ pm_error( "invalid height size specification: %s",argv[argn] );
++ if ( cols % 2 != 1 || rows % 2 != 1 )
++ pm_error( "the convolution matrix must have an odd number of rows and columns" );
++ }
++ else if ( pm_keymatch( argv[argn], "-dump", 2 ) )
++ {
++ ++argn;
++ if ( argn >= argc )
++ {
++ pm_message( "missing argument to -dump option" );
++ pm_usage( usage );
++ }
++ else if ( argv[argn][0] == '-' )
++ {
++ pm_message( "invalid argument to -dump option: %s",
++ argv[argn] );
++ pm_usage( usage );
++ }
++ cofp = pm_openw( argv[argn] );
++ DUMPFLAG = TRUE;
++ }
++ else
++ pm_usage( usage );
++ ++argn;
++ }
++
++ /* Only get file name if given on command line to pass through to
++ ** pnmconvol. If filename is coming from stdin, pnmconvol will read it.
++ */
++ if ( argn < argc )
++ {
++ pnmfn = argv[argn];
++ ++argn;
++ }
++
++ if ( argn != argc )
++ pm_usage( usage );
++
++
++ if ( !DUMPFLAG )
++ {
++ if ( (tempfn = tmpnam((char *) 0)) == NULL )
++ pm_error( "could not create temporary file name" );
++ if ( (cofp = pm_openw(tempfn)) == NULL )
++ pm_error( "could not create temporary convolution file" );
++ }
++
++ /* Generate mean value for all pixels in convolution matrix. */
++ g = rows * cols + 1;
++
++ /* Make sure newmaxval is not larger than PNM_MAXMAXVAL or else
++ ** newmaxval will overrun its defined data size and become garbage.
++ */
++ newmaxval = ( rows * cols ) * 2;
++ if ( newmaxval > PNM_MAXMAXVAL )
++ pm_error( "generated maxval is too large: %d", newmaxval );
++
++ pnm_writepnminit( cofp, cols, rows, newmaxval, format, forceplain );
++ outputrow = pnm_allocrow( cols );
++
++ for ( row = 0; row < rows; ++ row )
++ {
++ for ( col = 0; col < cols; ++col )
++ PNM_ASSIGN1( outputrow[col], g );
++ pnm_writepnmrow( cofp, outputrow, cols, newmaxval, format, forceplain );
++ }
++ pm_close( cofp );
++ pnm_freerow( outputrow );
++
++ /* If we're only going to dump the file, now is the time to stop. */
++ if ( DUMPFLAG )
++ exit( 0 );
++
++ /* fork a child process */
++ if ( (pid = fork()) < 0 )
++ pm_error( "fork" );
++
++ /* child process executes following code */
++ if ( pid == 0 )
++ {
++ /* If pnmfile name is not given on command line, then pnmfn will be
++ ** (char *) 0 and the arglist will terminate there.
++ */
++ execlp( "pnmconvol", "pnmconvol", tempfn, pnmfn, (char *) 0 );
++ pm_error( "error executing pnmconvol command" );
++ }
++
++ /* wait for child to finish */
++ while ( wait(&status) != pid )
++ ;
++
++ unlink( tempfn );
++ exit( 0 );
++ }
diff --git a/graphics/netpbm/patches/patch-bq b/graphics/netpbm/patches/patch-bq
new file mode 100644
index 00000000000..3a3481091de
--- /dev/null
+++ b/graphics/netpbm/patches/patch-bq
@@ -0,0 +1,23 @@
+--- /dev/null Thu Oct 16 09:27:24 1997
++++ ./pnm/pnmsmooth.orig Mon Oct 4 05:11:56 1993
+@@ -0,0 +1,20 @@
++#!/bin/sh
++#
++# pnmsmooth - smooth out an image by replacing each xel with the
++# average of its nine immediate neighbors
++
++tmp=/tmp/psm.$$
++rm -f $tmp
++
++cat > $tmp << MOO
++P2
++3 3
++18
++10 10 10
++10 10 10
++10 10 10
++MOO
++
++pnmconvol $tmp ${1+"$@"}
++
++rm -f $tmp
diff --git a/graphics/netpbm/patches/patch-br b/graphics/netpbm/patches/patch-br
new file mode 100644
index 00000000000..4274fcb0aff
--- /dev/null
+++ b/graphics/netpbm/patches/patch-br
@@ -0,0 +1,38 @@
+--- ./pnm/pnmtotiff.c.orig Sun Aug 13 00:32:57 1995
++++ ./pnm/pnmtotiff.c Sun Aug 13 00:34:21 1995
+@@ -196,6 +196,7 @@
+ samplesperpixel = 1;
+ bitspersample = pm_maxvaltobits( maxval );
+ photometric = PHOTOMETRIC_MINISBLACK;
++ i = 8 / bitspersample;
+ bytesperrow = ( cols + i - 1 ) / i;
+ }
+ else
+@@ -276,20 +277,20 @@
+ for ( col = 0, xP = xels[row], tP = buf;
+ col < cols; ++col, ++xP )
+ {
+- register unsigned char s;
++ register xelval s;
+
+ s = PPM_GETR( *xP );
+ if ( maxval != 255 )
+- s = (long) s * 255 / maxval;
+- *tP++ = s;
++ s = s * 255 / maxval;
++ *tP++ = (unsigned char)s;
+ s = PPM_GETG( *xP );
+ if ( maxval != 255 )
+- s = (long) s * 255 / maxval;
+- *tP++ = s;
++ s = s * 255 / maxval;
++ *tP++ = (unsigned char)s;
+ s = PPM_GETB( *xP );
+ if ( maxval != 255 )
+- s = (long) s * 255 / maxval;
+- *tP++ = s;
++ s = s * 255 / maxval;
++ *tP++ = (unsigned char)s;
+ }
+ }
+ else
diff --git a/graphics/netpbm/patches/patch-bs b/graphics/netpbm/patches/patch-bs
new file mode 100644
index 00000000000..62e93c308d8
--- /dev/null
+++ b/graphics/netpbm/patches/patch-bs
@@ -0,0 +1,11 @@
+--- ./ppm/ppm.5.orig Mon Oct 4 05:12:19 1993
++++ ./ppm/ppm.5 Sat Jul 20 21:53:06 1996
+@@ -73,7 +73,7 @@
+ it will automatically fall back on the slower but more general plain
+ format.
+ .SH "SEE ALSO"
+-giftoppm(1), gouldtoppm(1), ilbmtoppm(1), imgtoppm(1), mtvtoppm(1),
++giftopnm(1), gouldtoppm(1), ilbmtoppm(1), imgtoppm(1), mtvtoppm(1),
+ pcxtoppm(1), pgmtoppm(1), pi1toppm(1), picttoppm(1), pjtoppm(1), qrttoppm(1),
+ rawtoppm(1), rgb3toppm(1), sldtoppm(1), spctoppm(1), sputoppm(1), tgatoppm(1),
+ ximtoppm(1), xpmtoppm(1), yuvtoppm(1),
diff --git a/graphics/netpbm/patches/patch-bt b/graphics/netpbm/patches/patch-bt
new file mode 100644
index 00000000000..12abf41a78c
--- /dev/null
+++ b/graphics/netpbm/patches/patch-bt
@@ -0,0 +1,13 @@
+--- ./ppm/ppmmerge.c.orig Mon Jan 31 11:44:31 1994
++++ ./ppm/ppmmerge.c Sat Aug 12 23:51:35 1995
+@@ -29,6 +29,10 @@
+ {
+ ++argv;
+ --argc;
++ if(!*argv) {
++ fprintf(stderr, "Usage: ppmmerge ppm_program_name [args ...]\n");
++ exit(1);
++ }
+ goto again;
+ }
+
diff --git a/graphics/netpbm/patches/patch-bu b/graphics/netpbm/patches/patch-bu
new file mode 100644
index 00000000000..e95b5e6d187
--- /dev/null
+++ b/graphics/netpbm/patches/patch-bu
@@ -0,0 +1,11 @@
+--- ./ppm/ppmtogif.1.orig Fri Nov 12 04:18:30 1993
++++ ./ppm/ppmtogif.1 Sat Jul 20 21:54:02 1996
+@@ -54,7 +54,7 @@
+ .PP
+ All flags can be abbreviated to their shortest unique prefix.
+ .SH "SEE ALSO"
+-giftoppm(1), ppmquant(1), ppm(5)
++giftopnm(1), ppmquant(1), ppm(5)
+ .SH AUTHOR
+ Based on GIFENCOD by David Rowley <mgardi@watdcsu.waterloo.edu>.
+ Lempel-Ziv compression based on "compress".
diff --git a/graphics/netpbm/patches/patch-bv b/graphics/netpbm/patches/patch-bv
new file mode 100644
index 00000000000..412e7dc1d30
--- /dev/null
+++ b/graphics/netpbm/patches/patch-bv
@@ -0,0 +1,11 @@
+--- ./ppm/ppmtoicr.1.orig Mon Oct 4 05:12:38 1993
++++ ./ppm/ppmtoicr.1 Sat Jul 20 21:54:58 1996
+@@ -83,7 +83,7 @@
+ the displayed image by a factor of 2, and
+ run-length encode the data:
+ .nf
+- giftoppm giffile | ppmtoicr -w giffile -r -e 2
++ giftopnm giffile | ppmtoicr -w giffile -r -e 2
+ .fi
+ .SH BUGS
+ .PP
diff --git a/graphics/netpbm/patches/patch-bw b/graphics/netpbm/patches/patch-bw
new file mode 100644
index 00000000000..ab51edaeb59
--- /dev/null
+++ b/graphics/netpbm/patches/patch-bw
@@ -0,0 +1,27 @@
+--- ./ppm/ppmtoxpm.1.orig Mon Jan 31 06:49:48 1994
++++ ./ppm/ppmtoxpm.1 Fri Aug 18 05:30:35 1995
+@@ -8,20 +8,20 @@
+ Produces X11 pixmap (version 3) as output which
+ can be loaded directly by the XPM library.
+ .PP
+-The \fB-name\fP option allows one to specify the prefix string which is printed
++The \fB-name\f option allows one to specify the prefix string which is printed
+ in the resulting XPM output. If not specified, will default to the
+ filename (without extension) of the <ppmfile> argument.
+-If \fB-name\fP is not specified and <ppmfile>
++If \fB-name\f is not specified and <ppmfile>
+ is not specified (i.e. piped input), the prefix string will default to
+ the string "noname".
+ .PP
+-The \fB-rgb\fP option allows one to specify an X11 rgb text file for the
++The \fB-rgb\f option allows one to specify an X11 rgb text file for the
+ lookup of color name mnemonics. This rgb text file is typically the
+ /usr/lib/X11/rgb.txt of the MIT X11 distribution, but any file using the
+ same format may be used. When specified and
+ a RGB value from the ppm input matches a RGB value from the <rgb-textfile>,
+ then the corresponding color name mnemonic is printed in the XPM's colormap.
+-If \fB-rgb\fP is not specified, or if the RGB values don't match, then the color
++If \fB-rgb\f is not specified, or if the RGB values don't match, then the color
+ will be printed with the #RGB, #RRGGBB, #RRRGGGBBB, or #RRRRGGGGBBBB
+ hexadecimal format.
+ .PP
diff --git a/graphics/netpbm/patches/patch-bx b/graphics/netpbm/patches/patch-bx
new file mode 100644
index 00000000000..2a83b1f6268
--- /dev/null
+++ b/graphics/netpbm/patches/patch-bx
@@ -0,0 +1,211 @@
+--- ./ppm/ppmtoxpm.c.orig Mon Jan 31 02:44:41 1994
++++ ./ppm/ppmtoxpm.c Fri Aug 18 05:30:36 1995
+@@ -27,11 +27,25 @@
+ **
+ ** - lowercase conversion of RGB names def'ed out,
+ ** considered harmful.
++**
++** Michael Pall (pall@rz.uni-karlsruhe.de) - 29 Nov 93:
++** - Use the algorithm from xpm-lib for pixel encoding
++** (base 93 not base 28 -> saves a lot of space for colorful xpms)
+ */
+
++#include <stdio.h>
++#include <ctype.h>
+ #include "ppm.h"
+ #include "ppmcmap.h"
+
++#if defined(SYSV) || defined(SVR4)
++#include <string.h>
++#ifndef index
++#define index strchr
++#endif
++#else /* SYSV */
++#include <strings.h>
++#endif /* SYSV */
+
+ /* Max number of colors allowed in ppm input. */
+ #define MAXCOLORS 256
+@@ -39,15 +53,19 @@
+ /* Max number of rgb mnemonics allowed in rgb text file. */
+ #define MAX_RGBNAMES 1024
+
+-/* Lower bound and upper bound of character-pixels printed in XPM output.
+- Be careful, don't want the character '"' in this range. */
+-/*#define LOW_CHAR '#' <-- minimum ascii character allowed */
+-/*#define HIGH_CHAR '~' <-- maximum ascii character allowed */
+-#define LOW_CHAR '`'
+-#define HIGH_CHAR 'z'
++#define MAXPRINTABLE 92 /* number of printable ascii chars
++ * minus \ and " for string compat
++ * and ? to avoid ANSI trigraphs. */
++
++static char *printable =
++" .XoO+@#$%&*=-;:>,<1234567890qwertyuipasdfghjklzxcvbnmMNBVCZ\
++ASDFGHJKLPIUYTREWQ!~^/()_`'][{}|";
++
+
+ #define max(a,b) ((a) > (b) ? (a) : (b))
+
++void read_rgb_names(); /* forward reference */
++void gen_cmap(); /* forward reference */
+
+ typedef struct { /* rgb values and ascii names (from
+ * rgb text file) */
+@@ -62,17 +80,8 @@
+ * mnemonic or #rgb value */
+ } cixel_map;
+
+-
+-/* prototypes/forward reference */
+-static void read_rgb_names ARGS((char *, rgb_names *, int *));
+-static char * gen_numstr ARGS((int, int, int));
+-static void gen_cmap ARGS((colorhist_vector, int, pixval, int, rgb_names *, int, cixel_map *, int *));
+-
+-
+ pixel **pixels;
+
+-
+-int
+ main(argc, argv)
+ int argc;
+ char *argv[];
+@@ -88,11 +97,11 @@
+
+ /* Used for rgb value -> rgb mnemonic mapping */
+ int map_rgb_names = 0;
+- rgb_names *rgbn; /* rgb_names rgbn[MAX_RGBNAMES]; */
++ rgb_names rgbn[MAX_RGBNAMES];
+ int rgbn_max;
+
+ /* Used for rgb value -> character-pixel string mapping */
+- cixel_map *cmap; /* cixel_map cmap[MAXCOLORS]; */
++ cixel_map cmap[MAXCOLORS];
+ int charspp; /* chars per pixel */
+
+ char out_name[100], rgb_fname[100], *cp;
+@@ -188,17 +197,9 @@
+ * If a rgb text file was specified, read in the rgb mnemonics. Does not
+ * return if fatal error occurs.
+ */
+- rgbn = (rgb_names *) malloc(MAX_RGBNAMES * sizeof(rgb_names));
+- if (rgbn == (rgb_names *) NULL)
+- pm_error("out of memory");
+-
+ if (map_rgb_names)
+ read_rgb_names(rgb_fname, rgbn, &rgbn_max);
+
+- cmap = (cixel_map *)malloc(ncolors * sizeof(cixel_map));
+- if (cmap == (cixel_map *) NULL)
+- pm_error("out of memory");
+-
+ /* Now generate the character-pixel colormap table. */
+ gen_cmap(chv, ncolors, maxval, map_rgb_names, rgbn, rgbn_max,
+ cmap, &charspp);
+@@ -231,12 +232,12 @@
+ /* This routine reads a rgb text file. It stores the rgb values (0->65535)
+ and the rgb mnemonics (malloc'ed) into the "rgbn" array. Returns the
+ number of entries stored in "rgbn_max". */
+-static
+ void
+ read_rgb_names(rgb_fname, rgbn, rgbn_max)
+ char *rgb_fname;
+- rgb_names *rgbn;
+- int *rgbn_max;
++ rgb_names rgbn[MAX_RGBNAMES];
++int *rgbn_max;
++
+ {
+ FILE *rgbf;
+ int i, items, red, green, blue;
+@@ -303,16 +304,16 @@
+ } /* read_rgb_names */
+
+ /*---------------------------------------------------------------------------*/
+-/* Given a number and a base, (base == HIGH_CHAR-LOW_CHAR+1), this routine
++/* Given a number and a base (MAXPRINTABLE), this routine
+ prints the number into a malloc'ed string and returns it. The length of
+ the string is specified by "digits". The ascii characters of the printed
+- number range from LOW_CHAR to HIGH_CHAR. The string is LOW_CHAR filled,
+- (e.g. if LOW_CHAR==0, HIGH_CHAR==1, digits==5, i=3, routine would return
+- the malloc'ed string "00011"). */
+-static
++ number range from printable[0] to printable[MAXPRINTABLE]. The string is
++ printable[0] filled, (e.g. if printable[0]==0, printable[1]==1,
++ MAXPRINTABLE==2, digits==5, i=3, routine would return the malloc'ed
++ string "00011"). */
+ char *
+-gen_numstr(i, base, digits)
+- int i, base, digits;
++gen_numstr(i, digits)
++ int i, digits;
+ {
+ char *str, *p;
+ int d;
+@@ -325,9 +326,9 @@
+ p = str + digits;
+ *p-- = '\0'; /* nul terminate string */
+ while (p >= str) {
+- d = i % base;
+- i /= base;
+- *p-- = (char) ((int) LOW_CHAR + d);
++ d = i % MAXPRINTABLE;
++ i /= MAXPRINTABLE;
++ *p-- = printable[d];
+ }
+
+ return str;
+@@ -336,7 +337,6 @@
+
+ /*---------------------------------------------------------------------------*/
+ /* This routine generates the character-pixel colormap table. */
+-static
+ void
+ gen_cmap(chv, ncolors, maxval, map_rgb_names, rgbn, rgbn_max,
+ cmap, charspp)
+@@ -348,16 +348,16 @@
+ * == unsigned short) */
+ int map_rgb_names; /* == 1 if mapping rgb values to rgb
+ * mnemonics */
+- rgb_names *rgbn; /* rgb mnemonics from rgb text file */
++ rgb_names rgbn[MAX_RGBNAMES]; /* rgb mnemonics from rgb text file */
+ int rgbn_max; /* number of rgb mnemonics in table */
+
+ /* output: */
+-cixel_map *cmap; /* pixel strings and ascii rgb
++cixel_map cmap[MAXCOLORS]; /* pixel strings and ascii rgb
+ * colors */
+ int *charspp; /* characters per pixel */
+
+ {
+- int i, j, base, cpp, mval, red, green, blue, r, g, b, matched;
++ int i, j, cpp, mval, red, green, blue, r, g, b, matched;
+ char *str;
+
+ /*
+@@ -365,9 +365,8 @@
+ * to be forced to link with libm.a, so using a division loop rather
+ * than a log function.
+ */
+- base = (int) HIGH_CHAR - (int) LOW_CHAR + 1;
+ for (cpp = 0, j = ncolors; j; cpp++)
+- j /= base;
++ j /= MAXPRINTABLE;
+ *charspp = cpp;
+
+ /*
+@@ -392,10 +391,11 @@
+
+ /*
+ * The character-pixel string is simply a printed number in base
+- * "base" where the digits of the number range from LOW_CHAR to
+- * HIGH_CHAR and the printed length of the number is "cpp".
++ * MAXPRINTABLE where the digits of the number range from
++ * printable[0] .. printable[MAXPRINTABLE-1] and the printed length
++ * of the number is "cpp".
+ */
+- cmap[i].cixel = gen_numstr(i, base, cpp);
++ cmap[i].cixel = gen_numstr(i, cpp);
+
+ /* Fetch the rgb value of the current colormap entry. */
+ red = PPM_GETR(chv[i].color);
diff --git a/graphics/netpbm/patches/patch-by b/graphics/netpbm/patches/patch-by
new file mode 100644
index 00000000000..02c652f2a9e
--- /dev/null
+++ b/graphics/netpbm/patches/patch-by
@@ -0,0 +1,113 @@
+--- ./pnm/tifftopnm.c.orig Mon Oct 4 05:12:01 1993
++++ ./pnm/tifftopnm.c Sun Aug 13 00:35:55 1995
+@@ -54,7 +54,7 @@
+ int headerdump;
+ register u_char sample;
+ register int bitsleft;
+- unsigned short bps, spp, photomet;
++ unsigned short bps, spp, photomet, planarconfig;
+ unsigned short* redcolormap;
+ unsigned short* greencolormap;
+ unsigned short* bluecolormap;
+@@ -101,6 +101,13 @@
+ spp = 1;
+ if ( ! TIFFGetField( tif, TIFFTAG_PHOTOMETRIC, &photomet ) )
+ pm_error( "error getting photometric" );
++ if( spp > 1 ){
++ if ( ! TIFFGetField( tif, TIFFTAG_PLANARCONFIG, &planarconfig ) )
++ pm_error( "error getting planarconfig" );
++ }else{
++ planarconfig = PLANARCONFIG_CONTIG;
++ }
++
+
+ switch ( spp )
+ {
+@@ -114,6 +121,18 @@
+ "can only handle 1-channel gray scale or 1- or 3-channel color" );
+ }
+
++ switch( planarconfig )
++ {
++ case PLANARCONFIG_CONTIG:
++ break;
++ case PLANARCONFIG_SEPARATE:
++ if( photomet != PHOTOMETRIC_RGB )
++ pm_error( "can only handle separate planes with RGB data" );
++ break;
++ default:
++ pm_error("Unrecongnized PLANARCONFIG tag!\n");
++ }
++
+ (void) TIFFGetField( tif, TIFFTAG_IMAGEWIDTH, &cols );
+ (void) TIFFGetField( tif, TIFFTAG_IMAGELENGTH, &rows );
+
+@@ -259,20 +278,54 @@
+ break;
+
+ case PHOTOMETRIC_RGB:
+- for ( col = 0; col < cols; ++col, ++xP )
+- {
+- register xelval r, g, b;
+-
+- NEXTSAMPLE
+- r = sample;
+- NEXTSAMPLE
+- g = sample;
+- NEXTSAMPLE
+- b = sample;
+- if ( spp == 4 )
+- NEXTSAMPLE /* skip alpha channel */
+- PPM_ASSIGN( *xP, r, g, b );
+- }
++ if( planarconfig == PLANARCONFIG_CONTIG ){
++ for ( col = 0; col < cols; ++col, ++xP )
++ {
++ register xelval r, g, b;
++
++ NEXTSAMPLE
++ r = sample;
++ NEXTSAMPLE
++ g = sample;
++ NEXTSAMPLE
++ b = sample;
++ if ( spp == 4 )
++ NEXTSAMPLE /* skip alpha channel */
++ PPM_ASSIGN( *xP, r, g, b );
++ }
++ }else{
++ /* First clear the value and assign the reds */
++ for ( col = 0; col < cols; ++col, ++xP )
++ {
++ NEXTSAMPLE
++ PPM_ASSIGN( *xP, 0, 0, 0 );
++ PPM_PUTR( *xP, sample );
++ }
++
++ /* Next the greens */
++ if ( TIFFReadScanline( tif, buf, row, 1 ) < 0 )
++ pm_error( "bad data read on green line %d", row );
++ xP = xelrow;
++ inP = buf;
++ bitsleft = 8;
++ for ( col = 0; col < cols; ++col, ++xP )
++ {
++ NEXTSAMPLE
++ PPM_PUTG( *xP, sample );
++ }
++
++ /* And finally the blues */
++ if ( TIFFReadScanline( tif, buf, row, 2 ) < 0 )
++ pm_error( "bad data read on green line %d", row );
++ xP = xelrow;
++ inP = buf;
++ bitsleft = 8;
++ for ( col = 0; col < cols; ++col, ++xP )
++ {
++ NEXTSAMPLE
++ PPM_PUTB( *xP, sample );
++ }
++ }
+ break;
+
+ default:
diff --git a/graphics/netpbm/patches/patch-bz b/graphics/netpbm/patches/patch-bz
new file mode 100644
index 00000000000..d95829211b6
--- /dev/null
+++ b/graphics/netpbm/patches/patch-bz
@@ -0,0 +1,51 @@
+--- ./ppm/xpmtoppm.c.orig Mon Jan 31 02:42:05 1994
++++ ./ppm/xpmtoppm.c Fri Aug 18 05:30:36 1995
+@@ -30,9 +30,8 @@
+
+ #include "ppm.h"
+
+-static void ReadXPMFile ARGS((FILE *stream, int *widthP, int *heightP,
+- int *ncolorsP, int *chars_per_pixelP, pixel **colorsP, int **dataP));
+-static void getline ARGS((char *line, int size, FILE *stream));
++void ReadXPMFile();
++static void getline();
+
+ /* number of xpmColorKeys */
+ #define NKEYS 5
+@@ -46,7 +45,27 @@
+ "c", /* key #5: color visual */
+ };
+
+-int
++#ifdef NEED_STRSTR
++/* for systems which do not provide it */
++static char *
++strstr(s1, s2)
++ char *s1, *s2;
++{
++ int ls2 = strlen(s2);
++
++ if (ls2 == 0)
++ return (s1);
++ while (strlen(s1) >= ls2) {
++ if (strncmp(s1, s2, ls2) == 0)
++ return (s1);
++ s1++;
++ }
++ return (0);
++}
++
++#endif
++
++void
+ main(argc, argv)
+ int argc;
+ char *argv[];
+@@ -89,7 +108,6 @@
+
+ #define MAX_LINE 2048
+
+-static
+ void
+ ReadXPMFile(stream, widthP, heightP, ncolorsP,
+ chars_per_pixelP, colorsP, dataP)
diff --git a/graphics/netpbm/pkg/PLIST b/graphics/netpbm/pkg/PLIST
index 1327dd88426..935265ecc83 100644
--- a/graphics/netpbm/pkg/PLIST
+++ b/graphics/netpbm/pkg/PLIST
@@ -1,4 +1,4 @@
-@comment $NetBSD: PLIST,v 1.3 1997/12/31 03:34:57 hubertf Exp $
+@comment $NetBSD: PLIST,v 1.4 1998/07/15 19:52:58 tron Exp $
bin/anytopnm
bin/asciitopgm
bin/atktopbm
@@ -89,6 +89,7 @@ bin/pnmenlarge
bin/pnmfile
bin/pnmflip
bin/pnmgamma
+bin/pnmhisteq
bin/pnmhistmap
bin/pnmindex
bin/pnminvert
@@ -268,6 +269,7 @@ man/man1/pnmenlarge.1
man/man1/pnmfile.1
man/man1/pnmflip.1
man/man1/pnmgamma.1
+man/man1/pnmhisteq.1
man/man1/pnmhistmap.1
man/man1/pnmindex.1
man/man1/pnminvert.1