about summary refs log tree commit diff
path: root/editor
diff options
context:
space:
mode:
authorgiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2011-03-03 03:16:21 +0000
committergiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2011-03-03 03:16:21 +0000
commit151b2a752e6c09e1a43c5cd855694332b9e154af (patch)
treeb1ede294ec6af6a03f6bea27524805061d90d4f2 /editor
parent425839275c283dc9979f0aae6e91b7de4ca64461 (diff)
downloadnetpbm-mirror-151b2a752e6c09e1a43c5cd855694332b9e154af.tar.gz
netpbm-mirror-151b2a752e6c09e1a43c5cd855694332b9e154af.tar.xz
netpbm-mirror-151b2a752e6c09e1a43c5cd855694332b9e154af.zip
cleanup
git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@1415 9d0c8265-081b-0410-96cb-a4ca84ce46f8
Diffstat (limited to 'editor')
-rw-r--r--editor/pamrubber.c823
1 files changed, 446 insertions, 377 deletions
diff --git a/editor/pamrubber.c b/editor/pamrubber.c
index 83d75613..02ada801 100644
--- a/editor/pamrubber.c
+++ b/editor/pamrubber.c
@@ -29,21 +29,8 @@
 #include "pam.h"
 #include "pamdraw.h"
 
-/*----------------------------------------------------------------------------*/
-
-
-struct cmdlineInfo {
-    const char * filename;
-    unsigned int quad;
-    unsigned int tri;
-    unsigned int frame;
-    unsigned int linear;
-    unsigned int verbose;
-};
 
 
-/*----------------------------------------------------------------------------*/
-
 typedef struct point {
   double x;
   double y;
@@ -61,11 +48,101 @@ typedef struct triangle {
 } triangle;
 
 
+struct cmdlineInfo {
+    unsigned int nCP;
+    point oldCP[4];
+    point newCP[4];
+    const char * filename;
+    unsigned int quad;
+    unsigned int tri;
+    unsigned int frame;
+    unsigned int linear;
+    unsigned int verbose;
+    unsigned int randseedSpec;
+    unsigned int randseed;
+};
+
+
+static void
+parseCmdline(int argc, const char ** argv,
+             struct cmdlineInfo * const cmdlineP) {
+
+/* parse all parameters from the command line */
+
+    unsigned int option_def_index;
+    char * endptr;
+    unsigned int i;
+    unsigned int nCP;
+
+    /* instructions to optParseOptions3 on how to parse our options. */
+    optEntry * option_def;
+    optStruct3 opt;
+    
+    MALLOCARRAY_NOFAIL(option_def, 100);
+
+    option_def_index = 0;   /* incremented by OPTENT3 */
+    OPTENT3(0, "quad",     OPT_FLAG, NULL, &cmdlineP->quad,     0);
+    OPTENT3(0, "tri",      OPT_FLAG, NULL, &cmdlineP->tri,      0);
+    OPTENT3(0, "frame",    OPT_FLAG, NULL, &cmdlineP->frame,    0);
+    OPTENT3(0, "linear",   OPT_FLAG, NULL, &cmdlineP->linear,   0);
+    OPTENT3(0, "verbose",  OPT_FLAG, NULL, &cmdlineP->verbose,  0);
+    OPTENT3(0, "randseed", OPT_UINT, &cmdlineP->randseed,
+            &cmdlineP->randseedSpec, 0);
+
+    opt.opt_table = option_def;
+    opt.short_allowed = FALSE;  /* we have no short (old-fashioned) options */
+    opt.allowNegNum = FALSE;   /* we have no parms that are negative numbers */
+
+    /* uses and sets argc, argv, and some of *cmdlineP and others. */
+    pm_optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0);
+
+    if (!cmdlineP->tri && !cmdlineP->quad)
+        pm_error("You must specify either -tri or -quad");
+
+    if (cmdlineP->tri && cmdlineP->quad)
+        pm_error("You may not specify both -tri and -quad");
+
+    /* Parameters are the control points (in qty of 4) and possibly a filename
+     */
+    nCP = (argc-1) / 4;
+
+    if (nCP > 4)
+        pm_error("Too many arguments: %u.  Arguments are "
+                 "control point coordinates and an optional file name, "
+                 "with a maximum of 4 control points", argc-1);
+
+    cmdlineP->nCP = nCP;
+
+    assert(nCP <= ARRAY_SIZE(cmdlineP->oldCP));
+    assert(nCP <= ARRAY_SIZE(cmdlineP->newCP));
+
+    for (i = 0; i < nCP; ++i) {
+        cmdlineP->oldCP[i].x = strtol(argv[i * 2 + 1], &endptr, 10);
+        cmdlineP->oldCP[i].y = strtol(argv[i * 2 + 2], &endptr, 10);
+        cmdlineP->newCP[i].x = strtol(argv[4 * nCP / 2 + i * 2 + 1],
+                                      &endptr, 10);
+        cmdlineP->newCP[i].y = strtol(argv[4 * nCP / 2 + i * 2 + 2],
+                                      &endptr, 10);
+    }
+
+    if (argc - 1 == 4 * nCP)
+        cmdlineP->filename = "-";
+    else if (argc - 2 == 4 * nCP)
+        cmdlineP->filename = argv[nCP * 4 + 1];
+    else
+        pm_error("Invalid number of arguments.  Arguments are "
+                 "control point coordinates and an optional file name, "
+                 "so there must be a multiple of 4 or a multiple of 4 "
+                 "plus 1.");
+}
+
+
+
 /* global variables */
 
 static int nCP;
-static point oldCP[4] = {{-1.0,-1.0},{-1.0,-1.0},{-1.0,-1.0},{-1.0,-1.0}};
-static point newCP[4] = {{-1.0,-1.0},{-1.0,-1.0},{-1.0,-1.0},{-1.0,-1.0}};
+static point oldCP[4];
+static point newCP[4];
 static int nTri;
 static triangle tri1s[10];
 static triangle tri2s[10];
@@ -75,13 +152,16 @@ static tuple black;
 
 /*----------------------------------------------------------------------------*/
 
-static void
-makepoint(point * const p1P,
-          double  const x,
-          double  const y) {
+static point
+makepoint(double const x,
+          double const y) {
+
+    point retval;
+
+    retval.x = x;
+    retval.y = y;
 
-    p1P->x = x;
-    p1P->y = y;
+    return retval;
 }
 
 
@@ -100,38 +180,38 @@ static double
 distance(point * const p1P,
          point * const p2P) {
 
-    return sqrt((p1P->x - p2P->x) * (p1P->x - p2P->x) + 
-                (p1P->y - p2P->y) * (p1P->y - p2P->y));
+    return sqrt(SQR(p1P->x - p2P->x) + SQR(p1P->y - p2P->y));
 }
 
 
 
-static void
-makeline(line *  const lP,
-         point * const p1P,
-         point * const p2P) {
+static line
+makeline(point const p1,
+         point const p2) {
+
+    line retval;
 
-    lP->p1.x = p1P->x;
-    lP->p1.y = p1P->y;
-    lP->p2.x = p2P->x;
-    lP->p2.y = p2P->y;
+    retval.p1 = p1;
+    retval.p2 = p2;
+
+    return retval;
 }
 
 
 
-static int
+static bool
 intersect(line *  const l1P,
           line *  const l2P,
           point * const pP) {
 
-    int cross;
-    double ua, ub;
-
-    cross = 0;  /* initial value */
+    bool cross;
 
     if (((l2P->p2.y - l2P->p1.y) * (l1P->p2.x - l1P->p1.x) -
          (l2P->p2.x - l2P->p1.x) * (l1P->p2.y - l1P->p1.y)) == 0) {
         /* parallel lines */
+
+        cross = false;
+
         if ((l1P->p1.x == l1P->p2.x) && (l2P->p1.x == l2P->p2.x)) {
             /* two vertical lines */
             pP->x = (l1P->p1.x + l2P->p1.x) / 2.0;
@@ -155,12 +235,14 @@ intersect(line *  const l1P,
         }
     } else {
         /* intersecting lines */
-        ua = ((l2P->p2.x - l2P->p1.x) * (l1P->p1.y - l2P->p1.y)
+        double const ua =
+            ((l2P->p2.x - l2P->p1.x) * (l1P->p1.y - l2P->p1.y)
               - (l2P->p2.y - l2P->p1.y) * (l1P->p1.x - l2P->p1.x))
             / ((l2P->p2.y - l2P->p1.y)
                * (l1P->p2.x - l1P->p1.x) - (l2P->p2.x - l2P->p1.x)
                * (l1P->p2.y - l1P->p1.y));
-        ub = ((l1P->p2.x - l1P->p1.x) * (l1P->p1.y - l2P->p1.y)
+        double const ub =
+            ((l1P->p2.x - l1P->p1.x) * (l1P->p1.y - l2P->p1.y)
               - (l1P->p2.y - l1P->p1.y) * (l1P->p1.x - l2P->p1.x))
             / ((l2P->p2.y - l2P->p1.y)
                * (l1P->p2.x - l1P->p1.x) - (l2P->p2.x - l2P->p1.x)
@@ -170,7 +252,9 @@ intersect(line *  const l1P,
         pP->y = l1P->p1.y + ua * (l1P->p2.y - l1P->p1.y);
 
         if ((ua >= 0.0) && (ua <= 1.0) && (ub >= 0.0) && (ub <= 1.0))
-            cross = 1;
+            cross = true;
+        else
+            cross = false;
     }
 
     return cross;
@@ -228,30 +312,30 @@ insidetri(triangle * const triP,
 
 
 
-static int
+static bool
 windtriangle(triangle * const tP,
              point *    const p1P,
              point *    const p2P,
              point *    const p3P) {
     point f, c;
     line le, lv;
-    int cw;
+    bool cw;
 
     /* find cross of vertical through p3 and the edge p1-p2 */
     f.x = p3P->x;
     f.y = -1.0;
-    makeline (&lv, p3P, &f);
-    makeline (&le, p1P, p2P);
-    intersect (&le, &lv, &c);
+    lv = makeline(*p3P, f);
+    le = makeline(*p1P, *p2P);
+    intersect(&le, &lv, &c);
 
     /* check for clockwise winding triangle */
     if (((p1P->x > p2P->x) && (p3P->y < c.y)) ||
         ((p1P->x < p2P->x) && (p3P->y > c.y))) {
         maketriangle(tP, p1P, p2P, p3P);
-        cw = 1;
+        cw = true;
     } else { /* p1/2/3 were counter clockwise */
         maketriangle (tP, p1P, p3P, p2P);
-        cw = 0;
+        cw = false;
     }
 
     return cw;
@@ -284,16 +368,12 @@ angle(point * const p1P,
 
 
 
-/*----------------------------------------------------------------------------*/
-
-
-
 #define TL 0
 #define TR 1
 #define BL 2
 #define BR 3
 
-/*----------------------------------------------------------------------------*/
+
 
 #define SIDETRIANGLE(N,TRIG1,P11,P12,P13,P14,R11,R12,TRIG2,P21,P22,P23,P24,R21,R22) { \
   if (fabs (R11.x - R12.x) < 1.0) { /* vertical edge */ \
@@ -359,13 +439,21 @@ angle(point * const p1P,
     } \
 }
 
-#define QUAD_RECT(QUAD,LFT,RGT,TOP,BOT) { \
-  makepoint (&QUAD[0], LFT, TOP); \
-  makepoint (&QUAD[1], RGT, TOP); \
-  makepoint (&QUAD[2], LFT, BOT); \
-  makepoint (&QUAD[3], RGT, BOT); \
+static void
+quadRect(point * const quad,
+         double  const lft,
+         double  const rgt,
+         double  const top,
+         double  const bot) {
+
+    quad[0] = makepoint(lft, top);
+    quad[1] = makepoint(rgt, top);
+    quad[2] = makepoint(lft, bot);
+    quad[3] = makepoint(rgt, bot);
 }
 
+
+
 #define QUAD_CORNER(QUAD,P0,P1,P2,P3,MID,TRI) { \
 /* P0-P1 and P2-P3 are the diagonals */ \
   if (fabs(P0.x - P1.x) + fabs(P0.y - P1.y) >= fabs(P2.x - P3.x) + fabs(P2.y - P3.y)) { \
@@ -529,65 +617,6 @@ static void drawClippedTriangle(const struct pam * const pamP,
 
 
 
-/*----------------------------------------------------------------------------*/
-
-static void
-parseCmdline(int argc, const char ** argv,
-             struct cmdlineInfo * const pCmdline) {
-
-/* parse all parameters from the command line */
-
-    unsigned int option_def_index;
-    char * endptr;
-    int i;
-
-    /* instructions to optParseOptions3 on how to parse our options. */
-    optEntry * option_def;
-    optStruct3 opt;
-
-    MALLOCARRAY_NOFAIL(option_def, 100);
-
-    option_def_index = 0;   /* incremented by OPTENT3 */
-    OPTENT3(0, "quad", OPT_FLAG, NULL, &pCmdline->quad, 0);
-    OPTENT3(0, "tri", OPT_FLAG, NULL, &pCmdline->tri, 0);
-    OPTENT3(0, "frame", OPT_FLAG, NULL, &pCmdline->frame, 0);
-    OPTENT3(0, "linear", OPT_FLAG, NULL, &pCmdline->linear, 0);
-    OPTENT3(0, "verbose", OPT_FLAG, NULL, &pCmdline->verbose, 0);
-
-    opt.opt_table = option_def;
-    opt.short_allowed = FALSE;  /* we have no short (old-fashioned) options */
-    opt.allowNegNum = FALSE;    /* we have no parms that are negative numbers */
-
-    /* uses and sets argc, argv, and some of *pCmdline and others. */
-    pm_optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0);
-
-    /* check if one of -tri and -quad are given */
-    if (pCmdline->tri == pCmdline->quad) {
-        pm_error ("Either '-tri' or '-quad' are required.");
-    }
-
-    /* remaining are the control points (in qty of 4) and possibly a filename */
-    nCP = (argc - 1) / 4;
-    for (i = 0; i < nCP; i++) {
-      oldCP[i].x = strtol(argv[i * 2 + 1], &endptr, 10);
-      oldCP[i].y = strtol(argv[i * 2 + 2], &endptr, 10);
-      newCP[i].x = strtol(argv[4 * nCP / 2 + i * 2 + 1], &endptr, 10);
-      newCP[i].y = strtol(argv[4 * nCP / 2 + i * 2 + 2], &endptr, 10);
-    }
-
-    /* only parameter allowed is optional filespec */
-    if (argc - 1 == 4 * nCP) {
-        pCmdline->filename = "-";
-    } else
-    if (argc - 2 == 4 * nCP) {
-        pCmdline->filename = argv[nCP * 4 + 1];
-    } else {
-        pm_error ("Incorrect number of coordinates.");
-    }
-}
-
-
-
 static void
 prepTrig(int const wd,
          int const ht) {
@@ -601,19 +630,19 @@ prepTrig(int const wd,
   line l1, l2;
   point p0;
 
-  makepoint (&rtl1, 0.0 + tiny(), 0.0 + tiny());
-  makepoint (&rtr1, (double) wd - 1.0 + tiny(), 0.0 + tiny());
-  makepoint (&rbl1, 0.0 + tiny(), (double) ht - 1.0 + tiny());
-  makepoint (&rbr1, (double) wd - 1.0 + tiny(), (double) ht - 1.0 + tiny());
+  rtl1 = makepoint(0.0 + tiny(),               0.0 + tiny());
+  rtr1 = makepoint((double) wd - 1.0 + tiny(), 0.0 + tiny());
+  rbl1 = makepoint(0.0 + tiny(),               (double) ht - 1.0 + tiny());
+  rbr1 = makepoint((double) wd - 1.0 + tiny(), (double) ht - 1.0 + tiny());
 
-  makepoint (&rtl2, 0.0 + tiny(), 0.0 + tiny());
-  makepoint (&rtr2, (double) wd - 1.0 + tiny(), 0.0 + tiny());
-  makepoint (&rbl2, 0.0 + tiny(), (double) ht - 1.0 + tiny());
-  makepoint (&rbr2, (double) wd - 1.0 + tiny(), (double) ht - 1.0 + tiny());
+  rtl2 = makepoint(0.0 + tiny(),               0.0 + tiny());
+  rtr2 = makepoint((double) wd - 1.0 + tiny(), 0.0 + tiny());
+  rbl2 = makepoint(0.0 + tiny(),               (double) ht - 1.0 + tiny());
+  rbr2 = makepoint((double) wd - 1.0 + tiny(), (double) ht - 1.0 + tiny());
 
   if (nCP == 1) {
-    copypoint (&c1p1, &oldCP[0]);
-    copypoint (&c2p1, &newCP[0]);
+      c1p1 = oldCP[0];
+      c2p1 = newCP[0];
 
     /* connect control point to all corners to get 4 triangles */
     SIDETRIANGLE(nCP,tri1s[0],c1p1,p0,p0,p0,rbl1,rtl1,tri2s[0],c2p1,p0,p0,p0,rbl2,rtl2); /* left side triangle */
@@ -625,10 +654,10 @@ prepTrig(int const wd,
   } else
 
   if (nCP == 2) {
-    copypoint (&c1p1, &oldCP[0]);
-    copypoint (&c1p2, &oldCP[1]);
-    copypoint (&c2p1, &newCP[0]);
-    copypoint (&c2p2, &newCP[1]);
+    c1p1 = oldCP[0];
+    c1p2 = oldCP[1];
+    c2p1 = newCP[0];
+    c2p2 = newCP[1];
 
     /* check for hor/ver edges */
     angle (&c1p1, &c1p2);
@@ -648,13 +677,13 @@ prepTrig(int const wd,
   } else
 
   if (nCP == 3) {
-    copypoint (&c1p1, &oldCP[0]);
-    copypoint (&c1p2, &oldCP[1]);
-    copypoint (&c1p3, &oldCP[2]);
-
-    copypoint (&c2p1, &newCP[0]);
-    copypoint (&c2p2, &newCP[1]);
-    copypoint (&c2p3, &newCP[2]);
+    c1p1 = oldCP[0];
+    c1p2 = oldCP[1];
+    c1p3 = oldCP[2];
+         
+    c2p1 = newCP[0];
+    c2p2 = newCP[1];
+    c2p3 = newCP[2];
 
     /* check for hor/ver edges */
     angle (&c1p1, &c1p2);
@@ -671,13 +700,13 @@ prepTrig(int const wd,
         maketriangle (&tri2s[0], &c2p1, &c2p3, &c2p2);
     }
 
-    copypoint (&c1p1, &tri1s[0].p1);
-    copypoint (&c1p2, &tri1s[0].p2);
-    copypoint (&c1p3, &tri1s[0].p3);
-
-    copypoint (&c2p1, &tri2s[0].p1);
-    copypoint (&c2p2, &tri2s[0].p2);
-    copypoint (&c2p3, &tri2s[0].p3);
+    c1p1 = tri1s[0].p1;
+    c1p2 = tri1s[0].p2;
+    c1p3 = tri1s[0].p3;
+         
+    c2p1 = tri2s[0].p1;
+    c2p2 = tri2s[0].p2;
+    c2p3 = tri2s[0].p3;
 
     /* point to side triangles */
     SIDETRIANGLE(nCP,tri1s[1],c1p1,c1p2,c1p3,p0,rbl1,rtl1,tri2s[1],c2p1,c2p2,c2p3,p0,rbl2,rtl2); /* left side */
@@ -694,15 +723,15 @@ prepTrig(int const wd,
   } else
 
   if (nCP == 4) {
-    copypoint (&c1p1, &oldCP[0]);
-    copypoint (&c1p2, &oldCP[1]);
-    copypoint (&c1p3, &oldCP[2]);
-    copypoint (&c1p4, &oldCP[3]);
-
-    copypoint (&c2p1, &newCP[0]);
-    copypoint (&c2p2, &newCP[1]);
-    copypoint (&c2p3, &newCP[2]);
-    copypoint (&c2p4, &newCP[3]);
+    c1p1 = oldCP[0];
+    c1p2 = oldCP[1];
+    c1p3 = oldCP[2];
+    c1p4 = oldCP[3];
+         
+    c2p1 = newCP[0];
+    c2p2 = newCP[1];
+    c2p3 = newCP[2];
+    c2p4 = newCP[3];
 
     /* check for hor/ver edges */
     angle (&c1p1, &c1p2);
@@ -727,8 +756,8 @@ prepTrig(int const wd,
     /*--------------------------------------------------------------------*/
 
     /* center two triangles */
-    makeline (&l1, &c1p1, &c1p4);
-    makeline (&l2, &c1p2, &c1p3);
+    l1 = makeline(c1p1, c1p4);
+    l2 = makeline(c1p2, c1p3);
     if (intersect(&l1, &l2, &p0)) {
       if (windtriangle (&tri1s[0], &c1p1, &c1p2, &c1p3)) {
         maketriangle (&tri1s[1], &c1p4, &c1p3, &c1p2);
@@ -740,8 +769,8 @@ prepTrig(int const wd,
         maketriangle (&tri2s[1], &c2p4, &c2p2, &c2p3);
       }
     }
-    makeline (&l1, &c1p1, &c1p3);
-    makeline (&l2, &c1p2, &c1p4);
+    l1 = makeline(c1p1, c1p3);
+    l2 = makeline(c1p2, c1p4);
     if (intersect(&l1, &l2, &p0)) {
       if (windtriangle (&tri1s[0], &c1p1, &c1p2, &c1p4)) {
         maketriangle (&tri1s[1], &c1p3, &c1p4, &c1p2);
@@ -753,8 +782,8 @@ prepTrig(int const wd,
         maketriangle (&tri2s[1], &c2p3, &c2p2, &c2p4);
       }
     }
-    makeline (&l1, &c1p1, &c1p2);
-    makeline (&l2, &c1p3, &c1p4);
+    l1 = makeline(c1p1, c1p2);
+    l2 = makeline(c1p3, c1p4);
     if (intersect(&l1, &l2, &p0)) {
       if (windtriangle (&tri1s[0], &c1p1, &c1p3, &c1p4)) {
         maketriangle (&tri1s[1], &c1p2, &c1p4, &c1p3);
@@ -768,14 +797,14 @@ prepTrig(int const wd,
     }
 
     /* control points in correct orientation */
-    copypoint (&c1p1, &tri1s[0].p1);
-    copypoint (&c1p2, &tri1s[0].p2);
-    copypoint (&c1p3, &tri1s[0].p3);
-    copypoint (&c1p4, &tri1s[1].p1);
-    copypoint (&c2p1, &tri2s[0].p1);
-    copypoint (&c2p2, &tri2s[0].p2);
-    copypoint (&c2p3, &tri2s[0].p3);
-    copypoint (&c2p4, &tri2s[1].p1);
+    c1p1 = tri1s[0].p1;
+    c1p2 = tri1s[0].p2;
+    c1p3 = tri1s[0].p3;
+    c1p4 = tri1s[1].p1;
+    c2p1 = tri2s[0].p1;
+    c2p2 = tri2s[0].p2;
+    c2p3 = tri2s[0].p3;
+    c2p4 = tri2s[1].p1;
 
     /* triangle from triangle point to side of image */
     SIDETRIANGLE(nCP,tri1s[2],c1p1,c1p2,c1p3,c1p4,rbl1,rtl1,tri2s[2],c2p1,c2p2,c2p3,c2p4,rbl2,rtl2); /* left side triangle */
@@ -815,40 +844,35 @@ prepQuad(void) {
   triangle tri;
 
   if (nCP == 1) {
-
     /* create a rectangle from top-left corner of image and control point */
-    QUAD_RECT(quad1,0.0,oldCP[0].x,0.0,oldCP[0].y);
-    QUAD_RECT(quad2,0.0,newCP[0].x,0.0,newCP[0].y);
-
-  } else
-
-  if (nCP == 2) {
-
+      quadRect(quad1, 0.0, oldCP[0].x, 0.0, oldCP[0].y);
+      quadRect(quad2, 0.0, newCP[0].x, 0.0, newCP[0].y);
+  } else if (nCP == 2) {
     /* create a rectangle with the two points as opposite corners */
     if ((oldCP[0].x < oldCP[1].x) && (oldCP[0].y < oldCP[1].y)) { /* top-left and bottom-right */
-      QUAD_RECT(quad1,oldCP[0].x,oldCP[1].x,oldCP[0].y,oldCP[1].y);
+      quadRect(quad1,oldCP[0].x,oldCP[1].x,oldCP[0].y,oldCP[1].y);
     } else
     if ((oldCP[0].x > oldCP[1].x) && (oldCP[0].y < oldCP[1].y)) { /* top-right and bottom-left */
-      QUAD_RECT(quad1,oldCP[1].x,oldCP[0].x,oldCP[0].y,oldCP[1].y);
+      quadRect(quad1,oldCP[1].x,oldCP[0].x,oldCP[0].y,oldCP[1].y);
     } else
     if ((oldCP[0].x < oldCP[1].x) && (oldCP[0].y < oldCP[1].y)) { /* bottom-left and top-right */
-      QUAD_RECT(quad1,oldCP[0].x,oldCP[1].x,oldCP[1].y,oldCP[0].y);
+      quadRect(quad1,oldCP[0].x,oldCP[1].x,oldCP[1].y,oldCP[0].y);
     } else
     if ((oldCP[0].x > oldCP[1].x) && (oldCP[0].y < oldCP[1].y)) { /* bottom-right and top-left */
-      QUAD_RECT(quad1,oldCP[1].x,oldCP[0].x,oldCP[1].y,oldCP[0].y);
+      quadRect(quad1,oldCP[1].x,oldCP[0].x,oldCP[1].y,oldCP[0].y);
     }
 
     if ((newCP[0].x < newCP[1].x) && (newCP[0].y < newCP[1].y)) { /* top-left and bottom-right */
-      QUAD_RECT(quad2,newCP[0].x,newCP[1].x,newCP[0].y,newCP[1].y);
+      quadRect(quad2,newCP[0].x,newCP[1].x,newCP[0].y,newCP[1].y);
     } else
     if ((newCP[0].x > newCP[1].x) && (newCP[0].y < newCP[1].y)) { /* top-right and bottom-left */
-      QUAD_RECT(quad2,newCP[1].x,newCP[0].x,newCP[0].y,newCP[1].y);
+      quadRect(quad2,newCP[1].x,newCP[0].x,newCP[0].y,newCP[1].y);
     } else
     if ((newCP[0].x < newCP[1].x) && (newCP[0].y < newCP[1].y)) { /* bottom-left and top-right */
-      QUAD_RECT(quad2,newCP[0].x,newCP[1].x,newCP[1].y,newCP[0].y);
+      quadRect(quad2,newCP[0].x,newCP[1].x,newCP[1].y,newCP[0].y);
     } else
     if ((newCP[0].x > newCP[1].x) && (newCP[0].y < newCP[1].y)) { /* bottom-right and top-left */
-      QUAD_RECT(quad2,newCP[1].x,newCP[0].x,newCP[1].y,newCP[0].y);
+      quadRect(quad2,newCP[1].x,newCP[0].x,newCP[1].y,newCP[0].y);
     }
 
   } else {
@@ -891,50 +915,47 @@ prepQuad(void) {
     /* nCP = 3 or 4 */
 
     /* find the intersection of the diagonals */
-    makeline (&l1, &oldCP[0], &oldCP[1]);
-    makeline (&l2, &oldCP[2], &oldCP[3]);
+    l1 = makeline(oldCP[0], oldCP[1]);
+    l2 = makeline(oldCP[2], oldCP[3]);
     if (intersect(&l1, &l2, &mid)) {
       QUAD_CORNER(quad1,oldCP[0],oldCP[1],oldCP[2],oldCP[3],mid,tri);
-    }
-    else {
-      makeline (&l1, &oldCP[0], &oldCP[2]);
-      makeline (&l2, &oldCP[1], &oldCP[3]);
+    } else {
+      l1 = makeline(oldCP[0], oldCP[2]);
+      l2 = makeline(oldCP[1], oldCP[3]);
       if (intersect(&l1, &l2, &mid)) {
         QUAD_CORNER(quad1,oldCP[0],oldCP[2],oldCP[1],oldCP[3],mid,tri);
       }
       else {
-        makeline (&l1, &oldCP[0], &oldCP[3]);
-        makeline (&l2, &oldCP[1], &oldCP[2]);
+        l1 = makeline(oldCP[0], oldCP[3]);
+        l2 = makeline(oldCP[1], oldCP[2]);
         if (intersect(&l1, &l2, &mid)) {
           QUAD_CORNER(quad1,oldCP[0],oldCP[3],oldCP[1],oldCP[2],mid,tri);
         }
-        else {
-          pm_error ("pamrubber: The four old control points don't seem to be corners.");
-        }
+        else
+          pm_error("The four old control points don't seem to be corners.");
       }
     }
 
     /* repeat for the "to-be" control points */
-    makeline (&l1, &newCP[0], &newCP[1]);
-    makeline (&l2, &newCP[2], &newCP[3]);
+    l1 = makeline(newCP[0], newCP[1]);
+    l2 = makeline(newCP[2], newCP[3]);
     if (intersect(&l1, &l2, &mid)) {
       QUAD_CORNER(quad2,newCP[0],newCP[1],newCP[2],newCP[3],mid,tri);
     }
     else {
-      makeline (&l1, &newCP[0], &newCP[2]);
-      makeline (&l2, &newCP[1], &newCP[3]);
+      l1 = makeline(newCP[0], newCP[2]);
+      l2 = makeline(newCP[1], newCP[3]);
       if (intersect(&l1, &l2, &mid)) {
         QUAD_CORNER(quad2,newCP[0],newCP[2],newCP[1],newCP[3],mid,tri);
       }
       else {
-        makeline (&l1, &newCP[0], &newCP[3]);
-        makeline (&l2, &newCP[1], &newCP[2]);
+        l1 = makeline(newCP[0], newCP[3]);
+        l2 = makeline(newCP[1], newCP[2]);
         if (intersect(&l1, &l2, &mid)) {
           QUAD_CORNER(quad2,newCP[0],newCP[3],newCP[1],newCP[2],mid,tri);
         }
-        else {
-          pm_error ("pamrubber: The four new control points don't seem to be corners.");
-        }
+        else
+          pm_error("The four new control points don't seem to be corners.");
       }
     }
   }
@@ -943,78 +964,86 @@ prepQuad(void) {
 
 
 static void
-warpTrig(point * const p2,
-         point * const p1) {
+warpTrig(point * const p2P,
+         point * const p1P) {
 
 /* map target to source by triangulation */
 
-  point e1p1, e1p2, e1p3;
-  point e2p1, e2p2, e2p3;
-  line lp, le;
-  line l1, l2, l3;
-  double d1, d2, d3;
-  int i;
-
-  /* find in which triangle p2 lies */
-  for (i = 0; i < nTri; i++) {
-    if (insidetri (&tri2s[i], p2))
-      break;
-  }
-
-  if (i == nTri) {
-    p1->x = 0.0;
-    p1->y = 0.0;
-    return;
-  }
-
-  /* where in triangle is point */
-  d1 = fabs (p2->x - tri2s[i].p1.x) + fabs (p2->y - tri2s[i].p1.y);
-  d2 = fabs (p2->x - tri2s[i].p2.x) + fabs (p2->y - tri2s[i].p2.y);
-  d3 = fabs (p2->x - tri2s[i].p3.x) + fabs (p2->y - tri2s[i].p3.y);
-
-  /* line through p1 and p intersecting with edge p2-p3 */
-  makeline (&lp, &tri2s[i].p1, p2);
-  makeline (&le, &tri2s[i].p2, &tri2s[i].p3);
-  intersect (&lp, &le, &e2p1);
-
-  /* line through p2 and p intersecting with edge p3-p1 */
-  makeline (&lp, &tri2s[i].p2, p2);
-  makeline (&le, &tri2s[i].p3, &tri2s[i].p1);
-  intersect (&lp, &le, &e2p2);
-
-  /* line through p3 and p intersecting with edge p1-p2 */
-  makeline (&lp, &tri2s[i].p3, p2);
-  makeline (&le, &tri2s[i].p1, &tri2s[i].p2);
-  intersect (&lp, &le, &e2p3);
-
-  /* map target control points to source control points */
-  e1p1.x = tri1s[i].p2.x + (e2p1.x - tri2s[i].p2.x)/(tri2s[i].p3.x - tri2s[i].p2.x) * (tri1s[i].p3.x - tri1s[i].p2.x);
-  e1p1.y = tri1s[i].p2.y + (e2p1.y - tri2s[i].p2.y)/(tri2s[i].p3.y - tri2s[i].p2.y) * (tri1s[i].p3.y - tri1s[i].p2.y);
-  e1p2.x = tri1s[i].p3.x + (e2p2.x - tri2s[i].p3.x)/(tri2s[i].p1.x - tri2s[i].p3.x) * (tri1s[i].p1.x - tri1s[i].p3.x);
-  e1p2.y = tri1s[i].p3.y + (e2p2.y - tri2s[i].p3.y)/(tri2s[i].p1.y - tri2s[i].p3.y) * (tri1s[i].p1.y - tri1s[i].p3.y);
-  e1p3.x = tri1s[i].p1.x + (e2p3.x - tri2s[i].p1.x)/(tri2s[i].p2.x - tri2s[i].p1.x) * (tri1s[i].p2.x - tri1s[i].p1.x);
-  e1p3.y = tri1s[i].p1.y + (e2p3.y - tri2s[i].p1.y)/(tri2s[i].p2.y - tri2s[i].p1.y) * (tri1s[i].p2.y - tri1s[i].p1.y);
+    point e1p1, e1p2, e1p3;
+    point e2p1, e2p2, e2p3;
+    line lp, le;
+    line l1, l2, l3;
+    double d1, d2, d3;
+    int i;
 
-  /* intersect grid lines in source */
-  makeline (&l1, &tri1s[i].p1, &e1p1);
-  makeline (&l2, &tri1s[i].p2, &e1p2);
-  makeline (&l3, &tri1s[i].p3, &e1p3);
+    /* find in which triangle p2 lies */
+    for (i = 0; i < nTri; i++) {
+        if (insidetri (&tri2s[i], p2P))
+            break;
+    }
 
-  if ((d1 < d2) && (d1 < d3)) {
-    intersect (&l2, &l3, p1);
-  } else
-  if (d2 < d3) {
-    intersect (&l1, &l3, p1);
-  } else {
-    intersect (&l1, &l2, p1);
-  }
+    if (i == nTri)
+        *p1P = makepoint(0.0, 0.0);
+    else {
+        /* where in triangle is point */
+        d1 = fabs (p2P->x - tri2s[i].p1.x) + fabs (p2P->y - tri2s[i].p1.y);
+        d2 = fabs (p2P->x - tri2s[i].p2.x) + fabs (p2P->y - tri2s[i].p2.y);
+        d3 = fabs (p2P->x - tri2s[i].p3.x) + fabs (p2P->y - tri2s[i].p3.y);
+
+        /* line through p1 and p intersecting with edge p2-p3 */
+        lp = makeline(tri2s[i].p1, *p2P);
+        le = makeline(tri2s[i].p2, tri2s[i].p3);
+        intersect (&lp, &le, &e2p1);
+
+        /* line through p2 and p intersecting with edge p3-p1 */
+        lp = makeline(tri2s[i].p2, *p2P);
+        le = makeline(tri2s[i].p3, tri2s[i].p1);
+        intersect (&lp, &le, &e2p2);
+
+        /* line through p3 and p intersecting with edge p1-p2 */
+        lp = makeline(tri2s[i].p3, *p2P);
+        le = makeline(tri2s[i].p1, tri2s[i].p2);
+        intersect (&lp, &le, &e2p3);
+
+        /* map target control points to source control points */
+        e1p1.x = tri1s[i].p2.x
+            + (e2p1.x - tri2s[i].p2.x)/(tri2s[i].p3.x - tri2s[i].p2.x) 
+            * (tri1s[i].p3.x - tri1s[i].p2.x);
+        e1p1.y = tri1s[i].p2.y
+            + (e2p1.y - tri2s[i].p2.y)/(tri2s[i].p3.y - tri2s[i].p2.y)
+            * (tri1s[i].p3.y - tri1s[i].p2.y);
+        e1p2.x = tri1s[i].p3.x
+            + (e2p2.x - tri2s[i].p3.x)/(tri2s[i].p1.x - tri2s[i].p3.x)
+            * (tri1s[i].p1.x - tri1s[i].p3.x);
+        e1p2.y = tri1s[i].p3.y
+            + (e2p2.y - tri2s[i].p3.y)/(tri2s[i].p1.y - tri2s[i].p3.y)
+            * (tri1s[i].p1.y - tri1s[i].p3.y);
+        e1p3.x = tri1s[i].p1.x
+            + (e2p3.x - tri2s[i].p1.x)/(tri2s[i].p2.x - tri2s[i].p1.x)
+            * (tri1s[i].p2.x - tri1s[i].p1.x);
+        e1p3.y = tri1s[i].p1.y
+            + (e2p3.y - tri2s[i].p1.y)/(tri2s[i].p2.y - tri2s[i].p1.y)
+            * (tri1s[i].p2.y - tri1s[i].p1.y);
+
+        /* intersect grid lines in source */
+        l1 = makeline(tri1s[i].p1, e1p1);
+        l2 = makeline(tri1s[i].p2, e1p2);
+        l3 = makeline(tri1s[i].p3, e1p3);
+
+        if ((d1 < d2) && (d1 < d3))
+            intersect (&l2, &l3, p1P);
+        else if (d2 < d3)
+            intersect (&l1, &l3, p1P);
+        else
+            intersect (&l1, &l2, p1P);
+    }
 }
 
 
 
 static void
-warpQuad(point * const p2,
-         point * const p1) {
+warpQuad(point * const p2P,
+         point * const p1P) {
 
 /* map target to source for quad control points */
 
@@ -1026,31 +1055,31 @@ warpQuad(point * const p2,
   line l2t, l2b, l2l, l2r;
   line lh, lv;
 
-  copypoint (&c1tl, &quad1[TL]);
-  copypoint (&c1tr, &quad1[TR]);
-  copypoint (&c1bl, &quad1[BL]);
-  copypoint (&c1br, &quad1[BR]);
-
-  copypoint (&c2tl, &quad2[TL]);
-  copypoint (&c2tr, &quad2[TR]);
-  copypoint (&c2bl, &quad2[BL]);
-  copypoint (&c2br, &quad2[BR]);
-
-  makeline (&l2t, &c2tl, &c2tr);
-  makeline (&l2b, &c2bl, &c2br);
-  makeline (&l2l, &c2tl, &c2bl);
-  makeline (&l2r, &c2tr, &c2br);
+  c1tl = quad1[TL];
+  c1tr = quad1[TR];
+  c1bl = quad1[BL];
+  c1br = quad1[BR];
+       
+  c2tl = quad2[TL];
+  c2tr = quad2[TR];
+  c2bl = quad2[BL];
+  c2br = quad2[BR];
+
+  l2t = makeline(c2tl, c2tr);
+  l2b = makeline(c2bl, c2br);
+  l2l = makeline(c2tl, c2bl);
+  l2r = makeline(c2tr, c2br);
 
   /* find intersections of lines through control points */
   intersect (&l2t, &l2b, &h2);
   intersect (&l2l, &l2r, &v2);
 
   /* find intersections of axes through P with control point box */
-  makeline (&lv, p2, &v2);
+  lv = makeline(*p2P, v2);
   intersect (&l2t, &lv, &e2t);
   intersect (&l2b, &lv, &e2b);
 
-  makeline (&lh, p2, &h2);
+  lh = makeline(*p2P, h2);
   intersect (&l2l, &lh, &e2l);
   intersect (&l2r, &lh, &e2r);
 
@@ -1080,9 +1109,44 @@ warpQuad(point * const p2,
   e1r.y = c1tr.y + (e2r.y - c2tr.y)/(c2br.y - c2tr.y) * (c1br.y - c1tr.y);
 
   /* intersect grid lines in source */
-  makeline (&lv, &e1t, &e1b);
-  makeline (&lh, &e1l, &e1r);
-  intersect (&lh, &lv, p1);
+  lv = makeline(e1t, e1b);
+  lh = makeline(e1l, e1r);
+  intersect (&lh, &lv, p1P);
+}
+
+
+
+static void
+setGlobalCP(struct cmdlineInfo const cmdline) {
+
+    unsigned int i;
+
+    for (i = 0; i < cmdline.nCP; ++i) {
+        oldCP[i] = cmdline.oldCP[i];
+        newCP[i] = cmdline.newCP[i];
+    }
+    nCP = cmdline.nCP;
+    for (i = nCP; i < ARRAY_SIZE(oldCP); ++i)
+        oldCP[i] = makepoint(-1.0, -1.0);
+    for (i = nCP; i < ARRAY_SIZE(newCP); ++i)
+        newCP[i] = makepoint(-1.0, -1.0);
+}
+
+
+
+static void
+createWhiteTuple(const struct pam * const pamP,
+                 tuple *            const tupleP) {
+
+    tuple white;
+    unsigned int plane;
+
+    white = pnm_allocpamtuple(pamP);
+
+    for (plane = 0; plane < pamP->depth; ++plane)
+        white[plane] = pamP->maxval;
+
+    *tupleP = white;
 }
 
 
@@ -1090,116 +1154,121 @@ warpQuad(point * const p2,
 int
 main(int argc, const char ** const argv) {
 
-  struct cmdlineInfo cmdline;
-  FILE * rdFile;
-  struct pam inpam, outpam;
-  tuple ** rdTuples;
-  tuple ** wrTuples;
-  tuple white;
-  int row, col;
+    struct cmdlineInfo cmdline;
+    FILE * rdFileP;
+    struct pam inpam, outpam;
+    tuple ** rdTuples;
+    tuple ** wrTuples;
+    tuple white;
+    unsigned int row;
 
-  point p1, p2;
-  int p2x, p2y;
-  double rx, ry;
-  double pix;
-  int i;
+    point p1, p2;
+    int p2x, p2y;
+    double rx, ry;
+    double pix;
+  
+    pm_proginit(&argc, argv);
 
-  /* initialize random generator */
-  srand ( time(NULL) );
+    parseCmdline(argc, argv, &cmdline);
 
-  /* get parameters, open input file, read header */
-  pm_proginit(&argc, argv);
-  parseCmdline(argc, argv, &cmdline);
+    setGlobalCP(cmdline);
 
-  rdFile = pm_openr(cmdline.filename);
+    srand(cmdline.randseedSpec ? cmdline.randseed : time(NULL));
 
-  rdTuples = pnm_readpam (rdFile, &inpam, PAM_STRUCT_SIZE(tuple_type));
-  if (rdTuples == NULL) {
-    pm_error ("Out of memory.");
-  }
-  outpam = inpam;  /* initial value */
-  outpam.file = stdout;
-
-  if (cmdline.verbose) {
-    fprintf (stderr, "type = %s\n", inpam.tuple_type);
-    fprintf (stderr, "width = %d\n", inpam.width);
-    fprintf (stderr, "height = %d\n", inpam.height);
-    fprintf (stderr, "depth = %d\n", inpam.depth);
-    fprintf (stderr, "maxval = %d\n", (int) inpam.maxval);
-  }
+    rdFileP = pm_openr(cmdline.filename);
 
-  wrTuples = pnm_allocpamarray(&outpam);
+    rdTuples = pnm_readpam (rdFileP, &inpam, PAM_STRUCT_SIZE(tuple_type));
 
-  white = pnm_allocpamtuple(&outpam);
-  for (i = 0; i < inpam.depth; i++)
-    white[i] = outpam.maxval;
-  for (row = 0; row < inpam.height; row++)  {
-    for (col = 0; col < inpam.width; col++)  {
-      pnm_assigntuple(&outpam, wrTuples[row][col], white);
-    }
-  }
+    outpam = inpam;  /* initial value */
+    outpam.file = stdout;
 
-  if (cmdline.tri)
-    prepTrig(inpam.width, inpam.height);
-  if (cmdline.quad)
-    prepQuad();
+    wrTuples = pnm_allocpamarray(&outpam);
 
-  for (p2y = 0; p2y < inpam.height; p2y++)
-  {
-    for (p2x = 0; p2x < inpam.width; p2x++)
-    {
-      makepoint (&p2, (double) p2x, (double) p2y);
-      if (cmdline.quad)
-        warpQuad (&p2, &p1);
-      if (cmdline.tri)
-        warpTrig (&p2, &p1);
-
-      p1.x += 1E-3;
-      p1.y += 1E-3;
-      if ((p1.x >= 0.0) && (p1.x < (double) inpam.width - 0.5) &&
-          (p1.y >= 0.0) && (p1.y < (double) inpam.height - 0.5))
-      {
-        for (i = 0; i < inpam.depth; i++) {
-          if (!cmdline.linear) {
-            pix = rdTuples[(int) floor(p1.y + 0.5)][(int) floor(p1.x + 0.5)][i];
-          } else {
-            rx = p1.x - floor(p1.x);
-            ry = p1.y - floor(p1.y);
-            pix = 0.0;
-            pix += (1.0 - rx) * (1.0 - ry) * rdTuples[(int) floor(p1.y)][(int) floor(p1.x)][i];
-            pix += rx * (1.0 - ry) * rdTuples[(int) floor(p1.y)][(int) floor(p1.x) + 1][i];
-            pix += (1.0 - rx) * ry * rdTuples[(int) floor(p1.y) + 1][(int) floor(p1.x)][i];
-            pix += rx * ry * rdTuples[(int) floor(p1.y) + 1][(int) floor(p1.x) + 1][i];
-          }
-          wrTuples[p2y][p2x][i] = (int) floor(pix);
-        } /* end for */
-      }
+    pnm_createBlackTuple(&outpam, &black);
+    createWhiteTuple(&outpam, &white);
+
+    for (row = 0; row < inpam.height; ++row)  {
+        unsigned int col;
+        for (col = 0; col < inpam.width; ++col)
+            pnm_assigntuple(&outpam, wrTuples[row][col], white);
     }
-  }
 
-  pnm_createBlackTuple(&outpam, &black);
+    if (cmdline.tri)
+        prepTrig(inpam.width, inpam.height);
+    if (cmdline.quad)
+        prepQuad();
 
-  if (cmdline.frame) {
-    if (cmdline.quad) {
-        drawExtendedLine(&outpam, wrTuples, quad2[0], quad2[1]);
-        drawExtendedLine(&outpam, wrTuples, quad2[2], quad2[3]);
-        drawExtendedLine(&outpam, wrTuples, quad2[0], quad2[2]);
-        drawExtendedLine(&outpam, wrTuples, quad2[1], quad2[3]);
+    for (p2y = 0; p2y < inpam.height; p2y++)
+    {
+        for (p2x = 0; p2x < inpam.width; p2x++)
+        {
+            p2 = makepoint(p2x, p2y);
+            if (cmdline.quad)
+                warpQuad (&p2, &p1);
+            if (cmdline.tri)
+                warpTrig (&p2, &p1);
+
+            p1.x += 1E-3;
+            p1.y += 1E-3;
+            if ((p1.x >= 0.0) && (p1.x < (double) inpam.width - 0.5) &&
+                (p1.y >= 0.0) && (p1.y < (double) inpam.height - 0.5)) {
+                unsigned int i;
+                for (i = 0; i < inpam.depth; ++i) {
+                    if (!cmdline.linear) {
+                        pix = rdTuples
+                            [(int) floor(p1.y + 0.5)]
+                            [(int) floor(p1.x + 0.5)][i];
+                    } else {
+                        rx = p1.x - floor(p1.x);
+                        ry = p1.y - floor(p1.y);
+                        pix = 0.0;
+                        pix += (1.0 - rx) * (1.0 - ry)
+                            * rdTuples
+                            [(int) floor(p1.y)]
+                            [(int) floor(p1.x)][i];
+                        pix += rx * (1.0 - ry)
+                            * rdTuples
+                            [(int) floor(p1.y)]
+                            [(int) floor(p1.x) + 1][i];
+                        pix += (1.0 - rx) * ry 
+                            * rdTuples
+                            [(int) floor(p1.y) + 1]
+                            [(int) floor(p1.x)][i];
+                        pix += rx * ry
+                            * rdTuples
+                            [(int) floor(p1.y) + 1]
+                            [(int) floor(p1.x) + 1][i];
+                    }
+                    wrTuples[p2y][p2x][i] = (int) floor(pix);
+                } /* end for */
+            }
+        }
     }
-    if (cmdline.tri) {
-        unsigned int i;
-        for (i = 0; i < nTri; ++i) {
-            drawClippedTriangle(&outpam, wrTuples, tri2s[i]);
+
+    if (cmdline.frame) {
+        if (cmdline.quad) {
+            drawExtendedLine(&outpam, wrTuples, quad2[0], quad2[1]);
+            drawExtendedLine(&outpam, wrTuples, quad2[2], quad2[3]);
+            drawExtendedLine(&outpam, wrTuples, quad2[0], quad2[2]);
+            drawExtendedLine(&outpam, wrTuples, quad2[1], quad2[3]);
+        }
+        if (cmdline.tri) {
+            unsigned int i;
+            for (i = 0; i < nTri; ++i) {
+                drawClippedTriangle(&outpam, wrTuples, tri2s[i]);
+            }
         }
     }
-  }
 
-  pnm_writepam( &outpam, wrTuples );
-  pnm_freepamarray(wrTuples, &outpam);
-  pnm_freepamarray(rdTuples, &inpam);
+    pnm_writepam(&outpam, wrTuples);
+
+    pnm_freepamtuple(white);
+    pnm_freepamtuple(black);
+    pnm_freepamarray(wrTuples, &outpam);
+    pnm_freepamarray(rdTuples, &inpam);
 
-  pm_close( inpam.file );
-  pm_close( outpam.file );
+    pm_close(rdFileP);
+    pm_close(stdout);
 
-  return 0;
+    return 0;
 }