about summary refs log tree commit diff
path: root/editor
diff options
context:
space:
mode:
authorgiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2018-09-29 03:18:57 +0000
committergiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2018-09-29 03:18:57 +0000
commite227331a6b5626e100705fcff3269fd8479ea988 (patch)
treefd51fff8ec8dc90185ce5ae457805a0f25a0ded6 /editor
parentcdd64d00181d5e5a6c8142cdb59f2215014ca82d (diff)
downloadnetpbm-mirror-e227331a6b5626e100705fcff3269fd8479ea988.tar.gz
netpbm-mirror-e227331a6b5626e100705fcff3269fd8479ea988.tar.xz
netpbm-mirror-e227331a6b5626e100705fcff3269fd8479ea988.zip
Promote current Development release as Advanced
git-svn-id: http://svn.code.sf.net/p/netpbm/code/advanced@3352 9d0c8265-081b-0410-96cb-a4ca84ce46f8
Diffstat (limited to 'editor')
-rw-r--r--editor/Makefile2
-rw-r--r--editor/pamaltsat.c535
-rw-r--r--editor/pamscale.c58
-rw-r--r--editor/ppmbrighten.c35
-rw-r--r--editor/ppmcolormask.c10
-rw-r--r--editor/ppmdraw.c68
6 files changed, 625 insertions, 83 deletions
diff --git a/editor/Makefile b/editor/Makefile
index d7d71bf6..159f8ea7 100644
--- a/editor/Makefile
+++ b/editor/Makefile
@@ -16,7 +16,7 @@ SUBDIRS = pamflip specialty
 # This package is so big, it's useful even when some parts won't 
 # build.
 
-PORTBINARIES = pamaddnoise pambackground pamcomp pamcut \
+PORTBINARIES = pamaddnoise pamaltsat pambackground pamcomp pamcut \
 	       pamdice pamditherbw pamedge \
 	       pamenlarge \
 	       pamfunc pamlevels pammasksharpen \
diff --git a/editor/pamaltsat.c b/editor/pamaltsat.c
new file mode 100644
index 00000000..6d9b91e0
--- /dev/null
+++ b/editor/pamaltsat.c
@@ -0,0 +1,535 @@
+#include <stdbool.h>
+#include <assert.h>
+#include <string.h>
+
+#include <pam.h>
+#include <pm_gamma.h>
+#include <nstring.h>
+
+#include "shhopt.h"
+#include "mallocvar.h"
+
+typedef unsigned int  uint;
+typedef unsigned char uchar;
+
+typedef enum {MLog,  MSpectrum } Method; /* method identifiers */
+
+typedef struct {
+    Method       method;
+    const char * name;
+} MethodTableEntry;
+
+MethodTableEntry methodTable[] = {
+    {MLog,      "log"},
+    {MSpectrum, "spectrum"}
+};
+
+/* Command-line arguments parsed: */
+typedef struct {
+    const char * inputFileName;
+        /* name of the input file. "-" for stdin */
+    float        strength;
+    uint         linear;
+    Method       method;
+} CmdlineInfo;
+
+
+
+
+static Method
+methodFmNm(const char * const methodNm) {
+/*----------------------------------------------------------------------------
+   The method of saturation whose name is 'methodNm'
+-----------------------------------------------------------------------------*/
+    uint  i;
+    bool found;
+    Method method;
+
+    for (i = 0, found = false; i < ARRAY_SIZE(methodTable) && !found; ++i) {
+        if (streq(methodNm, methodTable[i].name)) {
+            found = true;
+            method = methodTable[i].method;
+        }
+    }
+
+    if (!found) {
+        /* Issue error message and abort */
+        char * methodList;
+        uint   methodListLen;
+        uint   i;
+
+        /* Allocate a buffer to store the list of known saturation methods: */
+        for (i = 0, methodListLen = 0; i < ARRAY_SIZE(methodTable); ++i)
+            methodListLen += strlen(methodTable[i].name) + 2;
+
+        MALLOCARRAY(methodList, methodListLen);
+
+        if (!methodList)
+            pm_error("Failed to allocate memory for %lu saturation "
+                     "method names", (unsigned long)ARRAY_SIZE(methodTable));
+
+        /* Fill the list of methods: */
+        for (i = 0, methodList[0] = '\0'; i < ARRAY_SIZE(methodTable); ++i) {
+            if (i > 0)
+                strcat(methodList, ", ");
+            strcat(methodList, methodTable[i].name);
+        }
+
+        pm_error("Unknown saturation method: '%s'. Known methods are: %s",
+                 methodNm, methodList);
+
+        free(methodList);
+    }
+    return method;
+}
+
+
+
+static CmdlineInfo
+parsedCommandLine(int argc, const char ** argv) {
+
+    CmdlineInfo cmdline;
+    optStruct3 opt;
+
+    uint option_def_index;
+    uint methodSpec, strengthSpec, linearSpec;
+    const char * method;
+
+    optEntry * option_def;
+    MALLOCARRAY_NOFAIL(option_def, 100);
+
+    option_def_index = 0;   /* incremented by OPTENT3 */
+    OPTENT3(0, "method",   OPT_STRING, &method,            &methodSpec,   0);
+    OPTENT3(0, "strength", OPT_FLOAT,  &cmdline.strength,  &strengthSpec, 0);
+    OPTENT3(0, "linear",   OPT_FLAG,   &cmdline.linear,    &linearSpec,   0);
+
+    opt.opt_table     = option_def;
+    opt.short_allowed = 0;
+    opt.allowNegNum   = 0;
+
+    pm_optParseOptions3( &argc, (char **)argv, opt, sizeof(opt), 0);
+        /* Uses and sets argc, argv, and some of *cmdlineP and others. */
+
+    if (methodSpec)
+        cmdline.method = methodFmNm(method);
+    else
+        cmdline.method = MSpectrum;
+
+    if (!strengthSpec)
+        pm_error("You must specify -strength");
+
+    if (!linearSpec)
+        cmdline.linear = 0;
+
+    if (argc-1 < 1)
+        cmdline.inputFileName = "-";
+    else {
+        cmdline.inputFileName = argv[1];
+        if (argc-1 > 1)
+            pm_error("Program takes at most one argument:  file name");
+    }
+
+    free(option_def);
+
+    return cmdline;
+}
+
+
+
+typedef struct {
+    double _[3];
+} TupleD;
+
+typedef struct {
+/*----------------------------------------------------------------------------
+  Information about a color sample in linear format
+-----------------------------------------------------------------------------*/
+    TupleD sample;    /* layer intensities                        */
+    double maxval;    /* the highest layer intensity              */
+    uint   maxl;      /* index of that layer                      */
+    uint   minl;      /* index of the layer with lowest intensity */
+    double intensity; /* total sample intensity                   */
+} LinSampleInfo;
+
+/* ---------------------------- Binary search ------------------------------ */
+/*                    ( a minimal drop-in implementation )                   */
+
+/* Function to search, where <data> is an arbitrary user-supplied parameter */
+typedef double (binsearchFunc)(double       const x,
+                               const void * const data);
+
+/* The binary-search function. Returns such <x> from [<min>, <max>] that
+   monotonically increasing function func(x, data) equals <value> within
+   precision <prec>. <dataP> is an arbitary parameter to <func>. */
+static double
+binsearch(binsearchFunc       func,
+          const void  * const dataP,
+          double        const prec,
+          double        const minArg,
+          double        const maxArg,
+          double        const value
+         ) {
+    double x;
+    double min, max;
+    bool found;
+
+    for (min = minArg, max = maxArg, found = false; !found;) {
+
+        x = (min + max) / 2;
+        {
+            double const f = func(x, dataP);
+
+            if ((fabs(f - value)) < prec)
+                found = true;
+            else {
+                assert(f != value);
+
+                if (f > value) max = x;
+                else           min = x;
+            }
+        }
+    }
+    return x;
+}
+
+/* ------------- Utilities not specific to saturation methods -------------- */
+
+/* Y chromaticities in Rec.709: R       G       B  */
+static double const yCoeffs[3]  = {0.3333, 0.6061, 0.0606};
+
+static void
+applyRatio(TupleD * const tupP,
+           double   const ratio) {
+/*----------------------------------------------------------------------------
+  Multiply the components of tuple *tupP by coefficient 'ratio'.
+-----------------------------------------------------------------------------*/
+    uint c;
+
+    for (c = 0; c < 3; ++c)
+        tupP->_[c] = tupP->_[c] * ratio;
+}
+
+
+
+static void
+getTupInfo(tuplen          const tup,
+           bool            const linear,
+           LinSampleInfo * const siP) {
+/*----------------------------------------------------------------------------
+  Convert PBM tuple <tup> into linear form with double precision siP->sample
+  and obtain also additional information required for further processing.
+  Return the result as *siP.
+-----------------------------------------------------------------------------*/
+    uint i;
+    double minval;
+
+    minval         = 1.1;
+    siP->intensity = 0;
+    siP->maxval    = 0.0;
+    siP->maxl      = 0;
+
+    for (i = 0; i < 3; ++i) {
+        double linval;
+        if (!linear)
+            linval = pm_ungamma709(tup[i]);
+        else
+            linval = tup[i];
+
+        siP->sample._[i] = linval;
+
+        if (linval > siP->maxval) {
+            siP->maxval = linval;
+            siP->maxl   = i;
+        }
+        if (linval < minval) {
+           siP->minl = i;
+           minval    = linval;
+        }
+        siP->intensity += linval * yCoeffs[i];
+    }
+}
+
+/* ------------------------ Logarithmic saturation ------------------------- */
+
+/* Method and algorithm by Anton Shepelev.  */
+
+static void
+tryLogSat(double          const sat,
+          LinSampleInfo * const siP,
+          TupleD *        const tupsatP,
+          double *        const intRatioP,
+          double *        const highestP) {
+/*----------------------------------------------------------------------------
+  Try to increase the saturation of siP->sample by a factor 'sat' and return
+  the result as *tupsatP.
+
+  Also return as *intRatioP the ratio of intensities of 'tupin' and
+  siP->sample.
+
+  Return as *highestP the highest component the saturated color would have if
+  normalized to intensity siP->intensity.
+
+  If the return value exceeds unity saturation cannot be properly increased by
+  the required factor.
+-----------------------------------------------------------------------------*/
+    uint   c;
+    double intSat;
+
+    for (c = 0, intSat = 0.0; c < 3; ++c) {
+        tupsatP->_[c] = pow(siP->sample._[c], sat);
+        intSat       = intSat + tupsatP->_[c] * yCoeffs[c];
+    }
+
+    {
+        double const intRatio = siP->intensity / intSat;
+
+        double const maxComp = tupsatP->_[siP->maxl] * intRatio;
+
+        *intRatioP = intRatio;
+        *highestP = maxComp;
+    }
+}
+
+
+
+/* Structure for the binary search of maximum saturation: */
+typedef struct {
+    LinSampleInfo * siP;
+        /* original color with precalculated information  */
+    TupleD *        tupsatP;
+        /* saturated color                            */
+    double *        intRatioP;
+        /* ratio of orignal and saturated intensities */
+} MaxLogSatInfo;
+
+
+
+static binsearchFunc binsearchMaxLogSat;
+
+static double
+binsearchMaxLogSat(double       const x,
+                   const void * const dataP) {
+/*----------------------------------------------------------------------------
+  Target function for the generic binary search routine, for the finding
+  of the maximum possible saturation of a given color. 'dataP' shall point
+  to a MaxSatInfo structure.
+-----------------------------------------------------------------------------*/
+    const MaxLogSatInfo * const infoP = dataP;
+
+    double highest;
+
+    tryLogSat(x, infoP->siP, infoP->tupsatP, infoP->intRatioP, &highest);
+
+    return highest;
+}
+
+
+
+static void
+getMaxLogSat(LinSampleInfo * const siP,
+             TupleD        * const tupsatP,
+             double        * const intRatioP,
+             double          const upperLimit
+          ) {
+/*  Saturates the color <siP->sample> as much as possible and stores the result
+    in <tupsatP>, which must be multiplied by <*intRatioP> in order to restore
+    the intensity of the original color. The range of saturation search is
+    [1.0..<upperlimit>]. */
+    const double PREC = 0.00001; /* precision of binary search */
+
+    MaxLogSatInfo info;
+
+    info.siP       = siP;
+    info.tupsatP   = tupsatP;
+    info.intRatioP = intRatioP;
+
+/*  Discarding return value (maximum saturation) because upon completion of
+    binsearch() info.tupsatP will contain the saturated color. The target value
+    of maximum channel intensity is decreased by PREC in order to avoid
+    overlow. */
+    binsearch(binsearchMaxLogSat, &info, PREC, 1.0, upperLimit, 1.0 - PREC);
+}
+
+
+
+static void
+saturateLog(LinSampleInfo* const siP,
+            double         const sat,
+            TupleD*        const tupsatP) {
+/*----------------------------------------------------------------------------
+  Saturate linear tuple *siP using the logarithmic saturation method.
+-----------------------------------------------------------------------------*/
+    double intRatio;
+        /* ratio of original and saturated intensities */
+    double maxlValSat;
+        /* maximum component intensity in the saturated sample */
+
+    tryLogSat(sat, siP, tupsatP, &intRatio, &maxlValSat);
+
+    /* if we cannot saturate siP->sample by 'sat', use the maximum possible
+       saturation
+    */
+    if (maxlValSat > 1.0)
+        getMaxLogSat(siP, tupsatP, &intRatio, sat);
+
+    /* restore the original intensity: */
+    applyRatio(tupsatP, intRatio);
+}
+
+
+
+/* ------------------------- Spectrum saturation --------------------------- */
+
+/* Method and algorithm by Anton Shepelev.  */
+
+static void
+saturateSpectrum(LinSampleInfo * const siP,
+                 double          const sat,
+                 TupleD *        const tupsatP) {
+/*----------------------------------------------------------------------------
+  Saturate linear tuple *siP using the Spectrum saturation method.
+-----------------------------------------------------------------------------*/
+    double k;
+    double * sample;
+
+    sample = siP->sample._; /* short-cut to the input sample data */
+
+    if (sample[siP->minl] == sample[siP->maxl])
+        k = 1.0; /* Cannot saturate a neutral sample */
+    else {
+        double const km1 =
+            (1.0 - siP->intensity)/(siP->maxval - siP->intensity);
+            /* Maximum saturation factor that keeps maximum layer intesity
+               within range
+            */
+        double const km2 = siP->intensity/(siP->intensity - sample[siP->minl]);
+            /* Maximum saturation factor  that keeps minimum layer intesity
+               within range
+            */
+
+        /* To satisfy both constraints, choose the strictest: */
+        double const km = km1 > km2 ? km2 : km1;
+
+        /* Ensure the saturation factor does not exceed the maximum
+           possible value:
+        */
+        k = sat < km ? sat : km;
+    }
+
+    {
+        /* Initialize the resulting sample with the input value */
+        uint i;
+        for (i = 0; i < 3; ++i)
+            tupsatP->_[i] = sample[i];
+    }
+
+    applyRatio(tupsatP, k); /* apply the saturation factor */
+
+    {
+         /* restore the original intensity */
+        uint i;
+        for (i = 0; i < 3; ++i)
+            tupsatP->_[i] = tupsatP->_[i] - siP->intensity * (k - 1.0);
+    }
+}
+
+
+
+/* --------------------- General saturation algorithm ---------------------- */
+
+static void
+saturateTup(Method const method,
+            double const sat,
+            bool   const linear,
+            tuplen const tup) {
+/*----------------------------------------------------------------------------
+  Saturate black and white tuple 'tup'
+-----------------------------------------------------------------------------*/
+    LinSampleInfo si;
+
+    getTupInfo(tup, linear, &si);
+
+    if (sat < 1.0 ||  /* saturation can always be decresed */
+        si.maxval < 1.0 ) { /* there is room for increase        */
+
+        TupleD tupsat;
+
+        /* Dispatch saturation methods:
+           (There seems too little benefit in using a table of
+           function pointers, so a manual switch should suffice)
+        */
+        switch (method) {
+            case MLog:      saturateLog     (&si, sat, &tupsat); break;
+            case MSpectrum: saturateSpectrum(&si, sat, &tupsat); break;
+        }
+
+        /* Put the processed tuple back in the tuple row, gamma-adjusting it
+           if required.
+        */
+        {
+            uint i;
+
+            for (i = 0; i < 3; ++i)
+                tup[i] = linear ? tupsat._[i] : pm_gamma709(tupsat._[i]);
+        }
+    }
+}
+
+
+
+static void
+pamaltsat(CmdlineInfo const cmdline,
+          FILE *      const ofP) {
+
+    struct pam inPam, outPam;
+    tuplen *   tuplerown;
+    FILE *     ifP;
+    uint       row;
+
+    ifP = pm_openr(cmdline.inputFileName);
+
+    pnm_readpaminit(ifP, &inPam, PAM_STRUCT_SIZE(tuple_type));
+
+    outPam = inPam;
+    outPam.file = ofP;
+
+    tuplerown = pnm_allocpamrown(&inPam);
+
+    pnm_writepaminit(&outPam);
+
+    for (row = 0; row < inPam.height; ++row) {
+        pnm_readpamrown(&inPam, tuplerown);
+
+        if (inPam.depth >= 3) {
+            uint col;
+
+            for (col = 0; col < inPam.width; ++col)
+                saturateTup(cmdline.method, cmdline.strength, cmdline.linear,
+                            tuplerown[col]);
+        }
+
+        pnm_writepamrown(&outPam, tuplerown);
+    }
+
+    pnm_freepamrown(tuplerown);
+    pm_close(ifP);
+}
+
+
+
+int
+main(int argc, const char ** argv) {
+
+    CmdlineInfo cmdline;
+
+    pm_proginit(&argc, argv);
+
+    cmdline = parsedCommandLine(argc, argv);
+
+    pamaltsat(cmdline, stdout);
+
+    return 0;
+}
+
+
+
diff --git a/editor/pamscale.c b/editor/pamscale.c
index 433d5cee..27902dbf 100644
--- a/editor/pamscale.c
+++ b/editor/pamscale.c
@@ -24,6 +24,7 @@
 
 #define _XOPEN_SOURCE 500  /* get M_PI in math.h */
 
+#include <stdbool.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <math.h>
@@ -359,23 +360,23 @@ typedef struct {
 
 
 static filter Filters[] = {
-    { "point",     filter_box,       radius_point,     FALSE },
-    { "box",       filter_box,       radius_box,       FALSE },
-    { "triangle",  filter_triangle,  radius_triangle,  FALSE },
-    { "quadratic", filter_quadratic, radius_quadratic, FALSE },
-    { "cubic",     filter_cubic,     radius_cubic,     FALSE },
-    { "catrom",    filter_catrom,    radius_catrom,    FALSE },
-    { "mitchell",  filter_mitchell,  radius_mitchell,  FALSE },
-    { "gauss",     filter_gauss,     radius_gauss,     FALSE },
-    { "sinc",      filter_sinc,      radius_sinc,      TRUE  },
-    { "bessel",    filter_bessel,    radius_bessel,    TRUE  },
-    { "hanning",   filter_hanning,   radius_hanning,   FALSE },
-    { "hamming",   filter_hamming,   radius_hamming,   FALSE },
-    { "blackman",  filter_blackman,  radius_blackman,  FALSE },
-    { "kaiser",    filter_kaiser,    radius_kaiser,    FALSE },
-    { "normal",    filter_normal,    radius_normal,    FALSE },
-    { "hermite",   filter_hermite,   radius_hermite,   FALSE },
-    { "lanczos",   filter_lanczos,   radius_lanczos,   FALSE },
+    { "point",     filter_box,       radius_point,     false },
+    { "box",       filter_box,       radius_box,       false },
+    { "triangle",  filter_triangle,  radius_triangle,  false },
+    { "quadratic", filter_quadratic, radius_quadratic, false },
+    { "cubic",     filter_cubic,     radius_cubic,     false },
+    { "catrom",    filter_catrom,    radius_catrom,    false },
+    { "mitchell",  filter_mitchell,  radius_mitchell,  false },
+    { "gauss",     filter_gauss,     radius_gauss,     false },
+    { "sinc",      filter_sinc,      radius_sinc,      true  },
+    { "bessel",    filter_bessel,    radius_bessel,    true  },
+    { "hanning",   filter_hanning,   radius_hanning,   false },
+    { "hamming",   filter_hamming,   radius_hamming,   false },
+    { "blackman",  filter_blackman,  radius_blackman,  false },
+    { "kaiser",    filter_kaiser,    radius_kaiser,    false },
+    { "normal",    filter_normal,    radius_normal,    false },
+    { "hermite",   filter_hermite,   radius_hermite,   false },
+    { "lanczos",   filter_lanczos,   radius_lanczos,   false },
    { NULL },
 };
 
@@ -452,12 +453,12 @@ lookupFilterByName(const char * const filtername,
     unsigned int i;
     bool found;
 
-    found = FALSE;  /* initial assumption */
+    found = false;  /* initial assumption */
 
     for (i=0; Filters[i].name; ++i) {
         if (strcmp(filtername, Filters[i].name) == 0) {
             *filterP = Filters[i];
-            found = TRUE;
+            found = true;
         }
     }
     if (!found) {
@@ -641,7 +642,8 @@ parseCommandLine(int argc,
     int xsize, ysize, pixels;
     int reduce;
     float xscale, yscale;
-    const char *filterOpt, *window;
+    const char * filterOpt;
+    const char * window;
     unsigned int filterSpec, windowSpec;
     unsigned int xscaleSpec, yscaleSpec, xsizeSpec, ysizeSpec;
     unsigned int pixelsSpec, reduceSpec;
@@ -667,8 +669,8 @@ parseCommandLine(int argc,
     OPTENT3(0, "linear",    OPT_FLAG,    NULL,       &cmdlineP->linear,    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 */
+    opt.short_allowed = false;  /* We have no short (old-fashioned) options */
+    opt.allowNegNum = false;   /* We have no parms that are negative numbers */
 
     pm_optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0);
     /* Uses and sets argc, argv, and some of *cmdlineP and others. */
@@ -1440,7 +1442,7 @@ static bool
 scanbufContainsTheRows(SCAN  const scanbuf,
                        WLIST const rowWeights) {
 /*----------------------------------------------------------------------------
-   Return TRUE iff scanbuf 'scanbuf' contains every row mentioned in
+   Return true iff scanbuf 'scanbuf' contains every row mentioned in
    'rowWeights'.
 
    It might contain additional rows besides.
@@ -1448,7 +1450,7 @@ scanbufContainsTheRows(SCAN  const scanbuf,
     bool missingRow;
     unsigned int i;
 
-    for (i = 0, missingRow = FALSE;
+    for (i = 0, missingRow = false;
          i < rowWeights.nWeight && !missingRow;
         ++i) {
         unsigned int const inputRow = rowWeights.Weight[i].position;
@@ -1461,7 +1463,7 @@ scanbufContainsTheRows(SCAN  const scanbuf,
             /* Nope, this slot has some other row or no row at all.
                So the row we're looking for isn't in the scanbuf.
             */
-            missingRow = TRUE;
+            missingRow = true;
         }
     }
     return !missingRow;
@@ -1569,7 +1571,7 @@ resample(struct pam *     const inpamP,
         /* Output all the rows we can make out of the current contents of
            the scanbuf.  Might be none.
         */
-        needMoreInput = FALSE;  /* initial assumption */
+        needMoreInput = false;  /* initial assumption */
         while (outputRow < outpamP->height && !needMoreInput) {
             WLIST const rowWeights = vertWeight[outputRow];
                 /* The description of what makes up our current output row;
@@ -1583,7 +1585,7 @@ resample(struct pam *     const inpamP,
                                       horizWeight, line, weight);
                 ++outputRow;
             } else
-                needMoreInput = TRUE;
+                needMoreInput = true;
         }
     }
 
@@ -2213,7 +2215,7 @@ main(int argc, const char **argv ) {
 
     ifP = pm_openr(cmdline.inputFileName);
 
-    eof = FALSE;
+    eof = false;
     while (!eof) {
         pamscale(ifP, stdout, cmdline);
         pnm_nextimage(ifP, &eof);
diff --git a/editor/ppmbrighten.c b/editor/ppmbrighten.c
index a7aba2e7..6ee6897b 100644
--- a/editor/ppmbrighten.c
+++ b/editor/ppmbrighten.c
@@ -31,11 +31,11 @@ struct cmdlineInfo {
 
 
 static void
-parseCommandLine(int argc, char ** argv,
+parseCommandLine(int argc, const char ** argv,
                  struct cmdlineInfo * const cmdlineP) {
 /*----------------------------------------------------------------------------
    parse program command line described in Unix standard form by argc
-   and argv.  Return the information in the options as *cmdlineP.  
+   and argv.  Return the information in the options as *cmdlineP.
 
    If command line is internally inconsistent (invalid options, etc.),
    issue error message to stderr and abort program.
@@ -68,9 +68,9 @@ parseCommandLine(int argc, char ** argv,
     opt.short_allowed = FALSE;  /* We have no short (old-fashioned) options */
     opt.allowNegNum = FALSE;  /* We have no parms that are negative numbers */
 
-    pm_optParseOptions3( &argc, argv, opt, sizeof(opt), 0);
+    pm_optParseOptions3( &argc, (char **)argv, opt, sizeof(opt), 0);
         /* Uses and sets argc, argv, and some of *cmdlineP and others. */
-    
+
     if (saturationSpec) {
         if (saturationOpt < -100)
             pm_error("Saturation reduction cannot be more than 100%%.  "
@@ -106,17 +106,17 @@ mod(int const dividend, unsigned int const divisor) {
 
     if (remainder < 0)
         return divisor + remainder;
-    else 
+    else
         return (unsigned int) remainder;
 }
 
 
 
-static void 
+static void
 RGBtoHSV(pixel          const color,
          pixval         const maxval,
-         unsigned int * const hP, 
-         unsigned int * const sP, 
+         unsigned int * const hP,
+         unsigned int * const sP,
          unsigned int * const vP) {
 
     unsigned int const R = (MULTI * PPM_GETR(color) + maxval - 1) / maxval;
@@ -161,12 +161,12 @@ RGBtoHSV(pixel          const color,
 
 
 static void
-HSVtoRGB(unsigned int   const h, 
-         unsigned int   const s, 
-         unsigned int   const v, 
+HSVtoRGB(unsigned int   const h,
+         unsigned int   const s,
+         unsigned int   const v,
          pixval         const maxval,
          pixel *        const colorP) {
-    
+
     unsigned int R, G, B;
 
     if (s == 0) {
@@ -222,7 +222,7 @@ HSVtoRGB(unsigned int   const h,
             pm_error("Invalid H value passed to HSVtoRGB: %u/%u", h, MULTI);
         }
     }
-    PPM_ASSIGN(*colorP, 
+    PPM_ASSIGN(*colorP,
                (R * maxval) / MULTI,
                (G * maxval) / MULTI,
                (B * maxval) / MULTI);
@@ -267,7 +267,7 @@ getMinMax(FILE *         const ifP,
 
 
 int
-main(int argc, char * argv[]) {
+main(int argc, const char ** argv) {
 
     struct cmdlineInfo cmdline;
     FILE * ifP;
@@ -276,7 +276,7 @@ main(int argc, char * argv[]) {
     pixval maxval;
     int rows, cols, format, row;
 
-    ppm_init(&argc, argv);
+    pm_proginit(&argc, argv);
 
     parseCommandLine(argc, argv, &cmdline);
 
@@ -311,7 +311,7 @@ main(int argc, char * argv[]) {
             unsigned int H, S, V;
 
             RGBtoHSV(pixelrow[col], maxval, &H, &S, &V);
-            
+
             if (cmdline.normalize) {
                 V -= minValue;
                 V = (V * MULTI) /
@@ -335,3 +335,6 @@ main(int argc, char * argv[]) {
     */
     return 0;
 }
+
+
+
diff --git a/editor/ppmcolormask.c b/editor/ppmcolormask.c
index d9f68b68..3812ac86 100644
--- a/editor/ppmcolormask.c
+++ b/editor/ppmcolormask.c
@@ -66,10 +66,10 @@ parseColorOpt(const char *         const colorOpt,
     char * colorOptWork;
     char * cursor;
     bool eol;
-    
+
     colorOptWork = strdup(colorOpt);
     cursor = &colorOptWork[0];
-    
+
     eol = FALSE;    /* initial value */
     colorCt = 0;    /* initial value */
     while (!eol && colorCt < ARRAY_SIZE(cmdlineP->maskColor)) {
@@ -150,7 +150,7 @@ parseCommandLine(int argc, const char ** argv,
                 cmdlineP->inputFilename = "-";  /* he wants stdin */
             else if (argc-1 == 2)
                 cmdlineP->inputFilename = argv[2];
-            else 
+            else
                 pm_error("Too many arguments.  The only arguments accepted "
                          "are the mask color and optional input file name");
         }
@@ -191,7 +191,7 @@ isBkColor(tuple        const comparator,
     /* TODO: keep a cache of the bk color for each color in
        a colorhash_table.
     */
-    
+
     assert(pamP->depth >= 3);
 
     PPM_ASSIGN(comparatorPixel,
@@ -281,7 +281,7 @@ main(int argc, const char *argv[]) {
                 if (colorIsInSet(inputRow[col], &inPam, cmdline)) {
                     maskRow[col][0] = PAM_BLACK;
                     ++numPixelsMasked;
-                } else 
+                } else
                     maskRow[col][0] = PAM_BW_WHITE;
             }
             pnm_writepamrow(&outPam, maskRow);
diff --git a/editor/ppmdraw.c b/editor/ppmdraw.c
index b2ed39ca..c76489c9 100644
--- a/editor/ppmdraw.c
+++ b/editor/ppmdraw.c
@@ -1,5 +1,5 @@
 #define _DEFAULT_SOURCE /* New name for SVID & BSD source defines */
-#define _XOPEN_SOURCE 500 
+#define _XOPEN_SOURCE 500
    /* Make sure M_PI is in math.h, strdup is in string.h */
 #define _BSD_SOURCE      /* Make sure strdup is in string.h (alternate) */
 
@@ -50,7 +50,7 @@ parseCommandLine (int argc, const char ** argv,
                   struct cmdlineInfo * const cmdlineP) {
 /*----------------------------------------------------------------------------
    parse program command line described in Unix standard form by argc
-   and argv.  Return the information in the options as *cmdlineP.  
+   and argv.  Return the information in the options as *cmdlineP.
 
    If command line is internally inconsistent (invalid options, etc.),
    issue error message to stderr and abort program.
@@ -84,7 +84,7 @@ parseCommandLine (int argc, const char ** argv,
 
     pm_optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0);
         /* Uses and sets argc, argv, and some of *cmdlineP and others. */
-    
+
     if (!scriptSpec && !scriptfileSpec)
         pm_error("You must specify either -script or -scriptfile");
 
@@ -282,7 +282,7 @@ struct drawCommand {
 
 static void
 freeDrawCommand(const struct drawCommand * const commandP) {
-    
+
     switch (commandP->verb) {
     case VERB_SETPOS:
         break;
@@ -313,7 +313,7 @@ freeDrawCommand(const struct drawCommand * const commandP) {
         pm_strfree(commandP->u.textArg.text);
         break;
     }
-    
+
 
     free((void *) commandP);
 }
@@ -361,21 +361,21 @@ doFilledCircle(pixel **                   const pixels,
     struct fillobj * fhP;
 
     fhP = ppmd_fill_create();
-            
+
     ppmd_circle(pixels, cols, rows, maxval,
                 commandP->u.circleArg.cx,
                 commandP->u.circleArg.cy,
                 commandP->u.circleArg.radius,
                 ppmd_fill_drawproc,
                 fhP);
-            
+
     ppmd_fill(pixels, cols, rows, maxval,
               fhP,
               PPMD_NULLDRAWPROC,
               &drawStateP->color);
 
     ppmd_fill_destroy(fhP);
-} 
+}
 
 
 
@@ -386,7 +386,7 @@ doTextHere(pixel **                   const pixels,
            pixval                     const maxval,
            const struct drawCommand * const commandP,
            struct drawState *         const drawStateP) {
-    
+
     ppmd_text(pixels, cols, rows, maxval,
               drawStateP->currentPos.x,
               drawStateP->currentPos.y,
@@ -395,14 +395,14 @@ doTextHere(pixel **                   const pixels,
               commandP->u.textArg.text,
               PPMD_NULLDRAWPROC,
               &drawStateP->color);
-    
+
     {
         int left, top, right, bottom;
-        
+
         ppmd_text_box(commandP->u.textArg.height, 0,
                       commandP->u.textArg.text,
                       &left, &top, &right, &bottom);
-        
+
 
         drawStateP->currentPos.x +=
             ROUND((right-left) * cosdeg(commandP->u.textArg.angle));
@@ -529,10 +529,10 @@ executeScript(struct script * const scriptP,
 
 
 struct tokenSet {
-    
+
     const char * token[10];
     unsigned int count;
-    
+
 };
 
 
@@ -571,7 +571,7 @@ parseDrawCommand(struct tokenSet             const commandTokens,
                 if (streq(typeArg, "normal"))
                     drawCommandP->u.setlinetypeArg.type = PPMD_LINETYPE_NORMAL;
                 else if (streq(typeArg, "normal"))
-                    drawCommandP->u.setlinetypeArg.type = 
+                    drawCommandP->u.setlinetypeArg.type =
                         PPMD_LINETYPE_NODIAGS;
                 else
                     pm_error("Invalid type");
@@ -610,7 +610,7 @@ parseDrawCommand(struct tokenSet             const commandTokens,
                 drawCommandP->u.lineArg.y0 = atoi(commandTokens.token[2]);
                 drawCommandP->u.lineArg.x1 = atoi(commandTokens.token[3]);
                 drawCommandP->u.lineArg.y1 = atoi(commandTokens.token[4]);
-            } 
+            }
         } else if (streq(verb, "line_here")) {
             drawCommandP->verb = VERB_LINE_HERE;
             if (commandTokens.count < 3)
@@ -621,7 +621,7 @@ parseDrawCommand(struct tokenSet             const commandTokens,
                     &drawCommandP->u.lineHereArg;
                 argP->right = atoi(commandTokens.token[1]);
                 argP->down = atoi(commandTokens.token[2]);
-            } 
+            }
        } else if (streq(verb, "spline3")) {
             drawCommandP->verb = VERB_SPLINE3;
             if (commandTokens.count < 7)
@@ -636,7 +636,7 @@ parseDrawCommand(struct tokenSet             const commandTokens,
                 argP->y1 = atoi(commandTokens.token[4]);
                 argP->x2 = atoi(commandTokens.token[5]);
                 argP->y2 = atoi(commandTokens.token[6]);
-            } 
+            }
         } else if (streq(verb, "circle")) {
             drawCommandP->verb = VERB_CIRCLE;
             if (commandTokens.count < 4)
@@ -647,7 +647,7 @@ parseDrawCommand(struct tokenSet             const commandTokens,
                 argP->cx     = atoi(commandTokens.token[1]);
                 argP->cy     = atoi(commandTokens.token[2]);
                 argP->radius = atoi(commandTokens.token[3]);
-            } 
+            }
         } else if (streq(verb, "filledcircle")) {
             drawCommandP->verb = VERB_FILLEDCIRCLE;
             if (commandTokens.count < 4)
@@ -658,7 +658,7 @@ parseDrawCommand(struct tokenSet             const commandTokens,
                 argP->cx     = atoi(commandTokens.token[1]);
                 argP->cy     = atoi(commandTokens.token[2]);
                 argP->radius = atoi(commandTokens.token[3]);
-            } 
+            }
         } else if (streq(verb, "filledrectangle")) {
             drawCommandP->verb = VERB_FILLEDRECTANGLE;
             if (commandTokens.count < 5)
@@ -671,7 +671,7 @@ parseDrawCommand(struct tokenSet             const commandTokens,
                 argP->y      = atoi(commandTokens.token[2]);
                 argP->width  = atoi(commandTokens.token[3]);
                 argP->height = atoi(commandTokens.token[4]);
-            } 
+            }
         } else if (streq(verb, "text")) {
             drawCommandP->verb = VERB_TEXT;
             if (commandTokens.count < 6)
@@ -713,9 +713,9 @@ disposeOfCommandTokens(struct tokenSet * const tokenSetP,
     /* We've got a whole command in 'tokenSet'.  Parse it into *scriptP
        and reset tokenSet to empty.
     */
-    
+
     struct commandListElt * commandListEltP;
-    
+
     MALLOCVAR(commandListEltP);
     if (commandListEltP == NULL)
         pm_error("Out of memory allocating command list element frame");
@@ -747,12 +747,14 @@ processToken(const char *      const scriptText,
              struct script *   const scriptP,
              struct tokenSet * const tokenSetP) {
 
-    char * token;
     unsigned int const tokenLength = cursor - tokenStart;
+
+    char * token;
+
     MALLOCARRAY_NOFAIL(token, tokenLength + 1);
     memcpy(token, &scriptText[tokenStart], tokenLength);
     token[tokenLength] = '\0';
-    
+
     if (streq(token, ";")) {
         disposeOfCommandTokens(tokenSetP, scriptP);
         free(token);
@@ -779,7 +781,7 @@ parseScript(const char *     const scriptText,
         */
     bool quotedToken;
         /* Current token is a quoted string.  Meaningless if 'intoken'
-           is false 
+           is false
         */
     struct tokenSet tokenSet;
 
@@ -803,7 +805,7 @@ parseScript(const char *     const scriptText,
 
     while (scriptText[cursor] != '\0') {
         char const scriptChar = scriptText[cursor];
-        
+
         if (intoken) {
             if ((quotedToken && scriptChar == '"') ||
                 (!quotedToken && (isspace(scriptChar) || scriptChar == ';'))) {
@@ -835,7 +837,7 @@ parseScript(const char *     const scriptText,
                 }
             }
             ++cursor;
-        }            
+        }
     }
 
     if (intoken) {
@@ -879,7 +881,7 @@ getScript(struct cmdlineInfo const cmdline,
     pm_strfree(scriptText);
 }
 
-          
+
 
 static void
 doOneImage(FILE *          const ifP,
@@ -888,13 +890,13 @@ doOneImage(FILE *          const ifP,
     pixel ** pixels;
     pixval maxval;
     int rows, cols;
-    
+
     pixels = ppm_readppm(ifP, &cols, &rows, &maxval);
-    
+
     executeScript(scriptP, pixels, cols, rows, maxval);
-    
+
     ppm_writeppm(stdout, pixels, cols, rows, maxval, 0);
-    
+
     ppm_freearray(pixels, rows);
 }