about summary refs log tree commit diff
path: root/converter/other/pnmtojpeg.c
diff options
context:
space:
mode:
Diffstat (limited to 'converter/other/pnmtojpeg.c')
-rw-r--r--converter/other/pnmtojpeg.c1036
1 files changed, 585 insertions, 451 deletions
diff --git a/converter/other/pnmtojpeg.c b/converter/other/pnmtojpeg.c
index e3458319..b80860e7 100644
--- a/converter/other/pnmtojpeg.c
+++ b/converter/other/pnmtojpeg.c
@@ -20,7 +20,8 @@
 #define _BSD_SOURCE 1      /* Make sure strdup() is in string.h */
 #define _XOPEN_SOURCE 500  /* Make sure strdup() is in string.h */
 
-#include <ctype.h>		/* to declare isdigit(), etc. */
+#include <ctype.h>              /* to declare isdigit(), etc. */
+#include <stdbool.h>
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
@@ -39,11 +40,11 @@
 
 #define EXIT_WARNING 2   /* Goes with EXIT_SUCCESS, EXIT_FAILURE in stdlib.h */
 
-enum restart_unit {RESTART_MCU, RESTART_ROW, RESTART_NONE};
-enum density_unit {DEN_UNSPECIFIED, DEN_DOTS_PER_INCH, DEN_DOTS_PER_CM};
+enum RestartUnit {RESTART_MCU, RESTART_ROW, RESTART_NONE};
+enum DensityUnit {DEN_UNSPECIFIED, DEN_DOTS_PER_INCH, DEN_DOTS_PER_CM};
 
-struct density {
-    enum density_unit unit;
+struct Density {
+    enum DensityUnit unit;
         /* The units of density for 'horiz', 'vert' */
     unsigned short horiz;  /* Not 0 */
         /* Horizontal density, in units specified by 'unit' */
@@ -51,92 +52,93 @@ struct density {
         /* Same as 'horiz', but vertical */
 };
 
-struct cmdlineInfo {
+struct CmdlineInfo {
     /* All the information the user supplied in the command line,
        in a form easy for the program to use.
      */
-    char *input_filespec;
-    unsigned int verbose;
-    unsigned int quality;
-    unsigned int force_baseline;
-    unsigned int progressive;
-    unsigned int arith_code;
-    J_DCT_METHOD dct_method;
-    unsigned int grayscale;
-    unsigned int rgb;
-    long int max_memory_to_use;
-    unsigned int trace_level;
-    char *qslots;
-    char *qtablefile;
-    char *sample;
-    char *scans;
-    int smoothing_factor;
-    unsigned int optimize;
-    unsigned int restart_value;
-    enum restart_unit restart_unit;
-    char *restart;
-    char *comment;              /* NULL if none */
-    const char *exif_filespec;  /* NULL if none */
-    unsigned int density_spec;
+    char *           inputFileNm;
+    unsigned int     verbose;
+    unsigned int     quality;
+    unsigned int     baseline;
+    unsigned int     progressive;
+    unsigned int     arithmetic;
+    J_DCT_METHOD     dctMethod;
+    unsigned int     grayscale;
+    unsigned int     rgb;
+    long int         maxMemoryToUse;
+    unsigned int     tracelevel;
+    char *           qslots;
+    char *           qtablefile;
+    char *           sample;
+    char *           scans;
+    int              smooth;
+    unsigned int     optimize;
+    unsigned int     restartValue;
+    enum RestartUnit restartUnit;
+    char *           restart;
+    char *           comment;            /* NULL if none */
+    const char *     exif;               /* NULL if none */
+    unsigned int     densitySpec;
         /* boolean: JFIF should specify a density.  If false, 'density'
            is undefined.
         */
-    struct density density;
+    struct Density density;
 };
 
 static void
-interpret_maxmemory (const char * const maxmemory,
-                     long int * const max_memory_to_use_p) {
+interpretMaxmemory (const char * const maxmemory,
+                    long int *   const maxMemoryToUseP) {
     long int lval;
     char ch;
 
     if (maxmemory == NULL) {
-        *max_memory_to_use_p = -1;  /* unspecified */
+        *maxMemoryToUseP = -1;  /* unspecified */
     } else if (sscanf(maxmemory, "%ld%c", &lval, &ch) < 1) {
         pm_error("Invalid value for --maxmemory option: '%s'.", maxmemory);
         exit(EXIT_FAILURE);
     } else {
         if (ch == 'm' || ch == 'M') lval *= 1000L;
-        *max_memory_to_use_p = lval * 1000L;
+        *maxMemoryToUseP = lval * 1000L;
     }
 }
 
 
 
 static void
-interpret_restart(const char * const restart,
-                  unsigned int * const restart_value_p,
-                  enum restart_unit * const restart_unit_p) {
+interpretRestart(const char *       const restartOpt,
+                 unsigned int *     const restartValueP,
+                 enum RestartUnit * const restartUnitP) {
 /*----------------------------------------------------------------------------
    Interpret the restart command line option.  Return values suitable
    for plugging into a jpeg_compress_struct to control compression.
 -----------------------------------------------------------------------------*/
-    if (restart == NULL) {
+    if (restartOpt == NULL) {
         /* No --restart option.  Set default */
-        *restart_unit_p = RESTART_NONE;
+        *restartUnitP = RESTART_NONE;
     } else {
         /* Restart interval in MCU rows (or in MCUs with 'b'). */
         long lval;
         char ch;
         unsigned int matches;
 
-        matches= sscanf(restart, "%ld%c", &lval, &ch);
+        matches= sscanf(restartOpt, "%ld%c", &lval, &ch);
         if (matches == 0)
             pm_error("Invalid value for the --restart option : '%s'.",
-                     restart);
+                     restartOpt);
         else {
             if (lval < 0 || lval > 65535L) {
                 pm_error("--restart value %ld is out of range.", lval);
                 exit(EXIT_FAILURE);
             } else {
                 if (matches == 1) {
-                    *restart_value_p = lval;
-                    *restart_unit_p = RESTART_ROW;
+                    *restartValueP = lval;
+                    *restartUnitP  = RESTART_ROW;
                 } else {
                     if (ch == 'b' || ch == 'B') {
-                        *restart_value_p = lval;
-                        *restart_unit_p = RESTART_MCU;
-                    } else pm_error("Invalid --restart value '%s'.", restart);
+                        *restartValueP = lval;
+                        *restartUnitP  = RESTART_MCU;
+                    } else
+                        pm_error("Invalid --restart value '%s'.", restartOpt);
                 }
             }
         }
@@ -145,10 +147,9 @@ interpret_restart(const char * const restart,
 
 
 
-
 static void
-interpret_density(const char *        const densityString,
-                  struct density *    const densityP) {
+interpretDensity(const char *     const densityString,
+                 struct Density * const densityP) {
 /*----------------------------------------------------------------------------
    Interpret the value of the "-density" option.
 -----------------------------------------------------------------------------*/
@@ -200,8 +201,8 @@ interpret_density(const char *        const densityString,
 
 
 static void
-parseCommandLine(const int argc, char ** argv,
-                   struct cmdlineInfo *cmdlineP) {
+parseCommandLine(const int argc, const char ** argv,
+                 struct CmdlineInfo * const cmdlineP) {
 /*----------------------------------------------------------------------------
    Note that many of the strings that this function returns in the
    *cmdlineP structure are actually in the supplied argv array.  And
@@ -211,140 +212,141 @@ parseCommandLine(const int argc, char ** argv,
    On the other hand, unlike other option processing functions, we do
    not change argv at all.
 -----------------------------------------------------------------------------*/
-    optEntry *option_def = malloc(100*sizeof(optEntry));
-        /* Instructions to OptParseOptions3 on how to parse our options.
-         */
+    optEntry * option_def;   /* Used by OPTENT3 */
     optStruct3 opt;
 
     int i;  /* local loop variable */
 
-    const char *dctval;
-    const char *maxmemory;
-    const char *restart;
-    const char *density;
+    const char * dctval;
+    const char * maxmemory;
+    const char * restart;
+    const char * density;
 
     unsigned int qualitySpec, smoothSpec;
 
     unsigned int option_def_index;
 
-    int argc_parse;       /* argc, except we modify it as we parse */
-    char ** argv_parse;
+    int argcParse;       /* argc, except we modify it as we parse */
+    const char ** argvParse;
         /* argv, except we modify it as we parse */
 
-    MALLOCARRAY(argv_parse, argc + 1);  /* +1 for the terminating null ptr */
+    MALLOCARRAY_NOFAIL(option_def, 100);
+
+    MALLOCARRAY(argvParse, argc + 1);  /* +1 for the terminating null ptr */
 
     option_def_index = 0;   /* incremented by OPTENTRY */
     OPTENT3(0, "verbose",     OPT_FLAG,   NULL, &cmdlineP->verbose,        0);
     OPTENT3(0, "quality",     OPT_UINT,   &cmdlineP->quality,
             &qualitySpec,        0);
-    OPTENT3(0, "baseline",    OPT_FLAG,   NULL, &cmdlineP->force_baseline, 0);
+    OPTENT3(0, "baseline",    OPT_FLAG,   NULL, &cmdlineP->baseline,       0);
     OPTENT3(0, "progressive", OPT_FLAG,   NULL, &cmdlineP->progressive,    0);
-    OPTENT3(0, "arithmetic",  OPT_FLAG,   NULL, &cmdlineP->arith_code,     0);
-    OPTENT3(0, "dct",         OPT_STRING, &dctval, NULL,                    0);
+    OPTENT3(0, "arithmetic",  OPT_FLAG,   NULL, &cmdlineP->arithmetic,     0);
+    OPTENT3(0, "dct",         OPT_STRING, &dctval, NULL,                   0);
     OPTENT3(0, "grayscale",   OPT_FLAG,   NULL, &cmdlineP->grayscale,      0);
     OPTENT3(0, "greyscale",   OPT_FLAG,   NULL, &cmdlineP->grayscale,      0);
     OPTENT3(0, "rgb",         OPT_FLAG,   NULL, &cmdlineP->rgb,            0);
-    OPTENT3(0, "maxmemory",   OPT_STRING, &maxmemory, NULL,                 0);
-    OPTENT3(0, "tracelevel",  OPT_UINT,   &cmdlineP->trace_level, NULL,    0);
+    OPTENT3(0, "maxmemory",   OPT_STRING, &maxmemory, NULL,                0);
+    OPTENT3(0, "tracelevel",  OPT_UINT,   &cmdlineP->tracelevel, NULL,    0);
     OPTENT3(0, "qslots",      OPT_STRING, &cmdlineP->qslots,      NULL,    0);
     OPTENT3(0, "qtables",     OPT_STRING, &cmdlineP->qtablefile,  NULL,    0);
     OPTENT3(0, "sample",      OPT_STRING, &cmdlineP->sample,      NULL,    0);
     OPTENT3(0, "scans",       OPT_STRING, &cmdlineP->scans,       NULL,    0);
-    OPTENT3(0, "smooth",      OPT_UINT,   &cmdlineP->smoothing_factor,
+    OPTENT3(0, "smooth",      OPT_UINT,   &cmdlineP->smooth,
             &smoothSpec,  0);
     OPTENT3(0, "optimize",    OPT_FLAG,   NULL, &cmdlineP->optimize,       0);
     OPTENT3(0, "optimise",    OPT_FLAG,   NULL, &cmdlineP->optimize,       0);
     OPTENT3(0, "restart",     OPT_STRING, &restart, NULL,                   0);
     OPTENT3(0, "comment",     OPT_STRING, &cmdlineP->comment, NULL,        0);
-    OPTENT3(0, "exif",        OPT_STRING, &cmdlineP->exif_filespec, NULL,  0);
+    OPTENT3(0, "exif",        OPT_STRING, &cmdlineP->exif, NULL,  0);
     OPTENT3(0, "density",     OPT_STRING, &density,
-            &cmdlineP->density_spec, 0);
+            &cmdlineP->densitySpec, 0);
+
 
     /* Set the defaults */
     dctval = NULL;
     maxmemory = NULL;
-    cmdlineP->trace_level = 0;
+    cmdlineP->tracelevel = 0;
     cmdlineP->qslots = NULL;
     cmdlineP->qtablefile = NULL;
     cmdlineP->sample = NULL;
     cmdlineP->scans = NULL;
     restart = NULL;
     cmdlineP->comment = NULL;
-    cmdlineP->exif_filespec = NULL;
+    cmdlineP->exif = NULL;
 
     /* Make private copy of arguments for pm_optParseOptions to corrupt */
-    argc_parse = argc;
-    for (i=0; i < argc+1; i++) argv_parse[i] = argv[i];
+    argcParse = argc;
+    for (i = 0; i < argc+1; ++i)
+        argvParse[i] = argv[i];
 
     opt.opt_table = option_def;
     opt.short_allowed = FALSE;  /* We have no short (old-fashioned) options */
     opt.allowNegNum = FALSE;  /* We have no parms that are negative numbers */
 
-    pm_optParseOptions3(&argc_parse, argv_parse, opt, sizeof(opt), 0);
+    pm_optParseOptions4(&argcParse, argvParse, opt, sizeof(opt), 0);
 
     if (!qualitySpec)
         cmdlineP->quality = -1;  /* unspecified */
 
     if (!smoothSpec)
-        cmdlineP->smoothing_factor = -1;
+        cmdlineP->smooth = -1;
 
     if (cmdlineP->rgb && cmdlineP->grayscale)
         pm_error("You can't specify both -rgb and -grayscale");
 
-    if (argc_parse - 1 == 0)
-        cmdlineP->input_filespec = strdup("-");  /* he wants stdin */
-    else if (argc_parse - 1 == 1)
-        cmdlineP->input_filespec = strdup(argv_parse[1]);
+    if (argcParse - 1 == 0)
+        cmdlineP->inputFileNm = strdup("-");  /* he wants stdin */
+    else if (argcParse - 1 == 1)
+        cmdlineP->inputFileNm = strdup(argvParse[1]);
     else
         pm_error("Too many arguments.  The only argument accepted "
                  "is the input file specification.");
     if (dctval == NULL)
-        cmdlineP->dct_method = JDCT_DEFAULT;
+        cmdlineP->dctMethod = JDCT_DEFAULT;
     else {
         if (streq(dctval, "int"))
-            cmdlineP->dct_method = JDCT_ISLOW;
+            cmdlineP->dctMethod = JDCT_ISLOW;
         else if (streq(dctval, "fast"))
-            cmdlineP->dct_method = JDCT_IFAST;
+            cmdlineP->dctMethod = JDCT_IFAST;
         else if (streq(dctval, "float"))
-            cmdlineP->dct_method = JDCT_FLOAT;
+            cmdlineP->dctMethod = JDCT_FLOAT;
         else
             pm_error("Invalid value for the --dct option: '%s'.", dctval);
     }
 
-    interpret_maxmemory(maxmemory, &cmdlineP->max_memory_to_use);
-    interpret_restart(restart, &cmdlineP->restart_value,
-                      &cmdlineP->restart_unit);
-    if (cmdlineP->density_spec)
-        interpret_density(density, &cmdlineP->density);
+    interpretMaxmemory(maxmemory, &cmdlineP->maxMemoryToUse);
+    interpretRestart(restart, &cmdlineP->restartValue,
+                      &cmdlineP->restartUnit);
+    if (cmdlineP->densitySpec)
+        interpretDensity(density, &cmdlineP->density);
 
-    if (cmdlineP->smoothing_factor > 100)
+    if (cmdlineP->smooth > 100)
         pm_error("Smoothing factor %d is greater than 100 (%%).",
-                 cmdlineP->smoothing_factor);
+                 cmdlineP->smooth);
 
-    if (streq(cmdlineP->input_filespec, "=") &&
-        cmdlineP->exif_filespec &&
-        streq(cmdlineP->exif_filespec, "-"))
+    if (streq(cmdlineP->inputFileNm, "=") &&
+        cmdlineP->exif && streq(cmdlineP->exif, "-"))
 
         pm_error("Cannot have both input image and exif header be from "
                  "Standard Input.");
 
 
-    free(argv_parse);
+    free(argvParse);
 }
 
 
 
 static void
-report_compressor(const struct jpeg_compress_struct cinfo) {
+reportCompressor(const struct jpeg_compress_struct cinfo) {
 
     if (cinfo.scan_info == NULL)
         pm_message("No scan script is being used");
     else {
-        int i;
+        unsigned int i;
         pm_message("A scan script with %d entries is being used:",
                    cinfo.num_scans);
-        for (i = 0; i < cinfo.num_scans; i++) {
-            int j;
+        for (i = 0; i < cinfo.num_scans; ++i) {
+            unsigned int j;
             pm_message("    Scan %2d: Ss=%2d Se=%2d Ah=%2d Al=%2d  "
                        "%d components",
                        i,
@@ -354,7 +356,7 @@ report_compressor(const struct jpeg_compress_struct cinfo) {
                        cinfo.scan_info[i].Al,
                        cinfo.scan_info[i].comps_in_scan
                        );
-            for (j = 0; j < cinfo.scan_info[i].comps_in_scan; j++)
+            for (j = 0; j < cinfo.scan_info[i].comps_in_scan; ++j)
                 pm_message("        Color component %d index: %d", j,
                            cinfo.scan_info[i].component_index[j]);
         }
@@ -364,14 +366,14 @@ report_compressor(const struct jpeg_compress_struct cinfo) {
 
 
 static void
-setup_jpeg_source_parameters(struct jpeg_compress_struct * const cinfoP,
-                             int const width, int const height,
-                             int const format) {
+setupJpegSourceParameters(struct jpeg_compress_struct * const cinfoP,
+                          unsigned int                  const width,
+                          unsigned int                  const height,
+                          int                           const format) {
 /*----------------------------------------------------------------------------
    Set up in the compressor descriptor *cinfoP the description of the
    source image as required by the compressor.
 -----------------------------------------------------------------------------*/
-
     switch PNM_FORMAT_TYPE(format) {
     case PBM_TYPE:
     case PGM_TYPE:
@@ -391,8 +393,8 @@ setup_jpeg_source_parameters(struct jpeg_compress_struct * const cinfoP,
 
 
 static void
-setup_jpeg_density(struct jpeg_compress_struct * const cinfoP,
-                   struct density                const density) {
+setupJpegDensity(struct jpeg_compress_struct * const cinfoP,
+                 struct Density                const density) {
 /*----------------------------------------------------------------------------
    Set up in the compressor descriptor *cinfoP the density information
    'density'.
@@ -421,24 +423,28 @@ setup_jpeg_density(struct jpeg_compress_struct * const cinfoP,
 -----------------------------------------------------------------------------*/
 
 static int
-text_getc (FILE * file)
-/* Read next char, skipping over any comments (# to end of line) */
-/* A comment/newline sequence is returned as a newline */
-{
-    register int ch;
+textGetc (FILE * fileP) {
+/*----------------------------------------------------------------------------
+  Read next char, skipping over any comments (# to end of line).
 
-    ch = getc(file);
+  Return a comment/newline sequence as a newline.
+-----------------------------------------------------------------------------*/
+    int ch;
+
+    ch = getc(fileP);
     if (ch == '#') {
         do {
-            ch = getc(file);
+            ch = getc(fileP);
         } while (ch != '\n' && ch != EOF);
     }
     return ch;
 }
 
 
-static boolean
+
+static void
 readTextInteger(FILE * const fileP,
+                bool * const gotOneP,
                 long * const resultP,
                 int *  const termcharP) {
 /*----------------------------------------------------------------------------
@@ -450,234 +456,335 @@ readTextInteger(FILE * const fileP,
    If there is no character after the integer, return *termcharP == EOF.
 
    Iff the next thing in the file is not a valid unsigned decimal integer,
-   return FALSE.
+   return *gotOneP false.
 -----------------------------------------------------------------------------*/
     int ch;
-    boolean retval;
 
     /* Skip any leading whitespace, detect EOF */
     do {
-        ch = text_getc(fileP);
+        ch = textGetc(fileP);
     } while (isspace(ch));
 
     if (!isdigit(ch))
-        retval = FALSE;
+        *gotOneP = false;
     else {
         long val;
         val = ch - '0';  /* initial value */
-        while ((ch = text_getc(fileP)) != EOF) {
+        while ((ch = textGetc(fileP)) != EOF) {
             if (! isdigit(ch))
                 break;
             val *= 10;
             val += ch - '0';
         }
         *resultP = val;
-        retval = TRUE;
+        *gotOneP = true;
     }
     *termcharP = ch;
-    return retval;
 }
 
 
-static boolean
-read_scan_integer (FILE * file, long * result, int * termchar)
-/* Variant of readTextInteger that always looks for a non-space termchar;
- * this simplifies parsing of punctuation in scan scripts.
- */
-{
-    register int ch;
-
-    if (! readTextInteger(file, result, termchar))
-        return FALSE;
-    ch = *termchar;
-    while (ch != EOF && isspace(ch))
-        ch = text_getc(file);
-    if (isdigit(ch)) {		/* oops, put it back */
-        if (ungetc(ch, file) == EOF)
-            return FALSE;
-        ch = ' ';
-    } else {
-        /* Any separators other than ';' and ':' are ignored;
-         * this allows user to insert commas, etc, if desired.
-         */
-        if (ch != EOF && ch != ';' && ch != ':')
+
+static void
+readScanInteger(FILE * const fileP,
+                bool * const gotOneP,
+                long * const resultP,
+                int *  const termcharP) {
+/*----------------------------------------------------------------------------
+  Variant of readTextInteger that always looks for a non-space termchar.
+  this simplifies parsing of punctuation in scan scripts.
+-----------------------------------------------------------------------------*/
+    readTextInteger(fileP, gotOneP, resultP, termcharP);
+
+    if (*gotOneP) {
+        int ch;
+
+        ch = *termcharP;  /* initial value */
+
+        while (ch != EOF && isspace(ch))
+            ch = textGetc(fileP);
+
+        if (isdigit(ch)) {              /* oops, put it back */
+            if (ungetc(ch, fileP) == EOF)
+                pm_error("Unexpected failure of ungetc");
             ch = ' ';
+        } else {
+            /* Any separators other than ';' and ':' are ignored;
+             * this allows user to insert commas, etc, if desired.
+             */
+            if (ch != EOF && ch != ';' && ch != ':')
+                ch = ' ';
+        }
+        *termcharP = ch;
     }
-    *termchar = ch;
-    return TRUE;
 }
 
 
 
-static boolean
-read_scan_script(j_compress_ptr const cinfo,
-                 const char *   const filename) {
+static void
+readScanScriptComponents(FILE *           const fP,
+                         jpeg_scan_info * const scanP,
+                         int *            const termcharP,
+                         long *           const valP,
+                         const char **    const errorP) {
+/*----------------------------------------------------------------------------
+   Set component table in *scanP, i.e. scanP->component_index and
+   scanP->comps_in_scan.
+
+   *termcharP and *valP at entry are for the value we already read from the
+   file; at exit, they are the value beyond the component table.
+-----------------------------------------------------------------------------*/
+    unsigned int compCt;
+
+    *errorP = NULL;  /* initial value */
+
+    /* First component is value we already read: */
+    scanP->component_index[0] = (int) *valP;
+    compCt = 1;
+
+    /* Rest of components follow, until termchar other than ' ': */
+    while (*termcharP == ' ' && !*errorP) {
+        bool gotOne;
+        if (compCt >= MAX_COMPS_IN_SCAN) {
+            pm_asprintf(errorP, "Too many components in one scan "
+                        "(Max allowed is %u)", MAX_COMPS_IN_SCAN);
+        }
+        readScanInteger(fP, &gotOne, valP, termcharP);
+        if (!gotOne)
+            pm_asprintf(errorP, "Invalid scan entry format");
+        else
+            scanP->component_index[compCt++] = (int) *valP;
+    }
+    scanP->comps_in_scan = compCt;
+}
+
+
+
+static void
+readScanScriptProg(FILE *           const fP,
+                   jpeg_scan_info * const scanP,
+                   int *            const termcharP,
+                   long *           const valP,
+                   const char **    const errorP) {
+
+    bool gotOne;
+    readScanInteger(fP, &gotOne, valP, termcharP);
+    if (!gotOne || *termcharP != ' ')
+        pm_asprintf(errorP, "Error in Ss");
+    else {
+        bool gotOne;
+        scanP->Ss = (int) *valP;
+        readScanInteger(fP, &gotOne, valP, termcharP);
+        if (!gotOne || *termcharP != ' ')
+            pm_asprintf(errorP, "Error in Se");
+        else {
+            bool gotOne;
+            scanP->Se = (int) *valP;
+            readScanInteger(fP, &gotOne, valP, termcharP);
+            if (!gotOne || *termcharP != ' ')
+                pm_asprintf(errorP, "Error in Ah");
+            else {
+                bool gotOne;
+                scanP->Ah = (int) *valP;
+                readScanInteger(fP, &gotOne, valP, termcharP);
+                if (!gotOne)
+                    pm_asprintf(errorP, "Error in Al");
+                else {
+                    scanP->Al = (int) *valP;
+                    *errorP = NULL;
+                }
+            }
+        }
+    }
+}
+
+
+
+static void
+setScanScriptNonProgressive(jpeg_scan_info * const scanP) {
+
+    scanP->Ss = 0;
+    scanP->Se = DCTSIZE2-1;
+    scanP->Ah = 0;
+    scanP->Al = 0;
+}
+
+
+
+static void
+readScanScript1(FILE *           const fP,
+                jpeg_scan_info * const scanP,
+                int *            const termcharP,
+                long *           const valP,
+                const char **    const errorP) {
+
+    const char * error;
+
+    readScanScriptComponents(fP, scanP, termcharP, valP, &error);
+
+    if (error) {
+        pm_asprintf(errorP, "Error in component table.  %s", error);
+        pm_strfree(error);
+    } else {
+        if (*termcharP == ':') {
+            const char * error;
+
+            readScanScriptProg(fP, scanP, termcharP, valP, &error);
+
+            if (error) {
+                pm_asprintf(errorP, "Invalid progressive parameters.  %s",
+                            error);
+                pm_strfree(error);
+            }
+        } else
+            setScanScriptNonProgressive(scanP);
+
+        if (*termcharP != ';' && *termcharP != EOF) {
+            pm_asprintf(errorP, "Expected ';' or EOF");
+        }
+    }
+}
+
+
+
+static void
+readScanScript(j_compress_ptr const cinfoP,
+               const char *   const fileNm,
+               const char **  const errorP) {
 /*----------------------------------------------------------------------------
   Read a scan script from the specified text file.
+
   Each entry in the file defines one scan to be emitted.
+
   Entries are separated by semicolons ';'.
-  An entry contains one to four component indexes,
-  optionally followed by a colon ':' and four progressive-JPEG parameters.
-  The component indexes denote which component(s) are to be transmitted
-  in the current scan.  The first component has index 0.
+
+  An entry contains one to four component indexes, optionally followed by a
+  colon ':' and four progressive-JPEG parameters.  The indexes and parameters
+  are separated by spaces.
+
+  The component indexes identify the color components to be transmitted in the
+  current scan.  The first component has index 0.
+
   Sequential JPEG is used if the progressive-JPEG parameters are omitted.
-  The file is free format text: any whitespace may appear between numbers
-  and the ':' and ';' punctuation marks.  Also, other punctuation (such
-  as commas or dashes) can be placed between numbers if desired.
+
+  Any whitespace may appear between numbers and the ':' and ';' punctuation
+  marks.  Also, other punctuation (such as commas or dashes) may be placed
+  between numbers.
+
   Comments preceded by '#' may be included in the file.
-  Note: we do very little validity checking here;
-  jcmaster.c will validate the script parameters.
+
+  Note: we do very little validity checking here; libjpeg will validate the
+  script parameters.
+
+  The data goes into newly malloc'ed memory pointed to by cinfo->scan_info,
+  with its size as cinfo->num_scans.  If there isn't any scan script,
+  cinfo->scan_info is null.
 -----------------------------------------------------------------------------*/
-    FILE * fp;
-    unsigned int nscans;
-    unsigned int ncomps;
-    int termchar;
-    long val;
-#define MAX_SCANS  100      /* quite arbitrary limit */
-    jpeg_scan_info scans[MAX_SCANS];
+    FILE * fP;
 
-    fp = fopen(filename, "r");
-    if (fp == NULL) {
-        pm_message("Can't open scan definition file %s", filename);
-        return FALSE;
-    }
-    nscans = 0;
-
-    while (read_scan_integer(fp, &val, &termchar)) {
-        ++nscans;  /* We got another scan */
-        if (nscans > MAX_SCANS) {
-            pm_message("Too many scans defined in file %s", filename);
-            fclose(fp);
-            return FALSE;
-        }
-        scans[nscans-1].component_index[0] = (int) val;
-        ncomps = 1;
-        while (termchar == ' ') {
-            if (ncomps >= MAX_COMPS_IN_SCAN) {
-                pm_message("Too many components in one scan in file %s",
-                           filename);
-                fclose(fp);
-                return FALSE;
+    fP = fopen(fileNm, "r");
+    if (!fP)
+        pm_asprintf(errorP, "Can't open file");
+    else {
+        bool notEof;
+        unsigned int scanCt;
+        int termchar;
+        long val;
+        jpeg_scan_info * scan;  /* malloc'ed array */
+            /* Index 0 in this array is called "Entry 1" by libjpeg messages */
+
+        for (notEof = true, *errorP = NULL, scanCt = 0, scan = NULL;
+             notEof && !*errorP;
+            ) {
+            readScanInteger(fP, &notEof, &val, &termchar);
+            if (notEof && !*errorP) {
+                ++scanCt;  /* We got another scan */
+
+                REALLOCARRAY(scan, scanCt);
+
+                if (!scan)
+                    pm_error("Unable to allocate memory for scan table");
+
+                readScanScript1(fP, &scan[scanCt-1], &termchar, &val, errorP);
             }
-            if (! read_scan_integer(fp, &val, &termchar))
-                goto bogus;
-            scans[nscans-1].component_index[ncomps] = (int) val;
-            ++ncomps;
         }
-        scans[nscans-1].comps_in_scan = ncomps;
-        if (termchar == ':') {
-            if (! read_scan_integer(fp, &val, &termchar) || termchar != ' ')
-                goto bogus;
-            scans[nscans-1].Ss = (int) val;
-            if (! read_scan_integer(fp, &val, &termchar) || termchar != ' ')
-                goto bogus;
-            scans[nscans-1].Se = (int) val;
-            if (! read_scan_integer(fp, &val, &termchar) || termchar != ' ')
-                goto bogus;
-            scans[nscans-1].Ah = (int) val;
-            if (! read_scan_integer(fp, &val, &termchar))
-                goto bogus;
-            scans[nscans-1].Al = (int) val;
+        if (!*errorP && termchar != EOF)
+            pm_asprintf(errorP, "Non-numeric data in file '%s'", fileNm);
+
+        if (*errorP) {
+            if (scan)
+                free(scan);
+            cinfoP->scan_info = NULL;
         } else {
-            /* set non-progressive parameters */
-            scans[nscans-1].Ss = 0;
-            scans[nscans-1].Se = DCTSIZE2-1;
-            scans[nscans-1].Ah = 0;
-            scans[nscans-1].Al = 0;
-        }
-        if (termchar != ';' && termchar != EOF) {
-        bogus:
-            pm_message("Invalid scan entry format in file %s", filename);
-            fclose(fp);
-            return FALSE;
+            cinfoP->scan_info = scanCt > 0 ? scan : NULL;
+            cinfoP->num_scans = scanCt;
         }
+        fclose(fP);
     }
-
-    if (termchar != EOF) {
-        pm_message("Non-numeric data in file %s", filename);
-        fclose(fp);
-        return FALSE;
-    }
-
-    if (nscans > 0) {
-        /* Stash completed scan list in cinfo structure.  NOTE: in
-           this program, JPOOL_IMAGE is the right lifetime for this
-           data, but if you want to compress multiple images you'd
-           want JPOOL_PERMANENT.
-        */
-        const unsigned int scan_info_size = nscans * sizeof(jpeg_scan_info);
-        jpeg_scan_info * const scan_info =
-            (jpeg_scan_info *)
-            (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
-                                        scan_info_size);
-        memcpy(scan_info, scans, scan_info_size);
-        cinfo->scan_info = scan_info;
-        cinfo->num_scans = nscans;
-    }
-
-    fclose(fp);
-    return TRUE;
 }
 
 
 
-static boolean
-read_quant_tables (j_compress_ptr cinfo, char * filename,
-                   int scale_factor, boolean force_baseline)
-/* Read a set of quantization tables from the specified file.
- * The file is plain ASCII text: decimal numbers with whitespace between.
- * Comments preceded by '#' may be included in the file.
- * There may be one to NUM_QUANT_TBLS tables in the file, each of 64 values.
- * The tables are implicitly numbered 0,1,etc.
- * NOTE: does not affect the qslots mapping, which will default to selecting
- * table 0 for luminance (or primary) components, 1 for chrominance components.
- * You must use -qslots if you want a different component->table mapping.
- */
-{
+static bool
+readQuantTables(j_compress_ptr const cinfo,
+                const char *   const fileNm,
+                int            const scaleFactor,
+                bool           const forceBaseline) {
+/*----------------------------------------------------------------------------
+  Read a set of quantization tables from the specified file.
+  The file is plain ASCII text: decimal numbers with whitespace between.
+  Comments preceded by '#' may be included in the file.
+  There may be one to NUM_QUANT_TBLS tables in the file, each of 64 values.
+  The tables are implicitly numbered 0,1,etc.
+  NOTE: does not affect the qslots mapping, which will default to selecting
+  table 0 for luminance (or primary) components, 1 for chrominance components.
+  You must use -qslots if you want a different component->table mapping.
+-----------------------------------------------------------------------------*/
     FILE * fp;
-    boolean retval;
+    bool retval;
 
-    fp = fopen(filename, "rb");
+    fp = fopen(fileNm, "rb");
     if (fp == NULL) {
-        pm_message("Can't open table file %s", filename);
-        retval = FALSE;
+        pm_message("Can't open table file '%s'", fileNm);
+        retval = false;
     } else {
         boolean eof, error;
         unsigned int tblno;
 
-        for (tblno = 0, eof = FALSE, error = FALSE; !eof && !error; ++tblno) {
+        for (tblno = 0, eof = false, error = false; !eof && !error; ++tblno) {
             long val;
             int termchar;
-            boolean gotOne;
+            bool gotOne;
 
-            gotOne = readTextInteger(fp, &val, &termchar);
+            readTextInteger(fp, &gotOne, &val, &termchar);
             if (gotOne) {
                 /* read 1st element of table */
                 if (tblno >= NUM_QUANT_TBLS) {
-                    pm_message("Too many tables in file %s", filename);
-                    error = TRUE;
+                    pm_message("Too many tables in file '%s'", fileNm);
+                    error = true;
                 } else {
                     unsigned int table[DCTSIZE2];
                     unsigned int i;
 
                     table[0] = (unsigned int) val;
                     for (i = 1; i < DCTSIZE2 && !error; ++i) {
-                        if (! readTextInteger(fp, &val, &termchar)) {
-                            pm_message("Invalid table data in file %s",
-                                       filename);
-                            error = TRUE;
+                        bool gotOne;
+                        readTextInteger(fp, &gotOne, &val, &termchar);
+                        if (!gotOne) {
+                            pm_message("Invalid table data in file '%s'",
+                                       fileNm);
+                            error = true;
                         } else
                             table[i] = (unsigned int) val;
                     }
                     if (!error)
                         jpeg_add_quant_table(
-                            cinfo, tblno, table, scale_factor, force_baseline);
+                            cinfo, tblno, table, scaleFactor, forceBaseline);
                 }
             } else {
                 if (termchar == EOF)
                     eof = TRUE;
                 else {
-                    pm_message("Non-numeric data in file %s", filename);
+                    pm_message("Non-numeric data in file '%s'", fileNm);
                     error = TRUE;
                 }
             }
@@ -692,75 +799,88 @@ read_quant_tables (j_compress_ptr cinfo, char * filename,
 
 
 
-static boolean
-set_quant_slots (j_compress_ptr cinfo, char *arg)
-/* Process a quantization-table-selectors parameter string, of the form
- *     N[,N,...]
- * If there are more components than parameters, the last value is replicated.
- */
-{
-    int val = 0;			/* default table # */
+static bool
+setQuantSlots(j_compress_ptr const cinfo,
+              const char *   const arg) {
+/*----------------------------------------------------------------------------
+  Process a quantization-table-selectors parameter string, of the form
+  N[,N,...]
+
+  If there are more components than parameters, the last value is replicated.
+-----------------------------------------------------------------------------*/
+    int val;
     int ci;
     char ch;
+    unsigned int i;
+
+    val = 0; /* initial value - default table */
 
-    for (ci = 0; ci < MAX_COMPONENTS; ci++) {
-        if (*arg) {
-            ch = ',';			/* if not set by sscanf, will be ',' */
-            if (sscanf(arg, "%d%c", &val, &ch) < 1)
-                return FALSE;
-            if (ch != ',')		/* syntax check */
-                return FALSE;
+    for (ci = 0, i = 0; ci < MAX_COMPONENTS; ++ci) {
+        if (arg[i]) {
+            ch = ',';                   /* if not set by sscanf, will be ',' */
+            if (sscanf(&arg[i], "%d%c", &val, &ch) < 1)
+                return false;
+            if (ch != ',')              /* syntax check */
+                return false;
             if (val < 0 || val >= NUM_QUANT_TBLS) {
                 pm_message("Invalid quantization table number: %d.  "
                            "JPEG quantization tables are numbered 0..%d",
                            val, NUM_QUANT_TBLS - 1);
-                return FALSE;
+                return false;
             }
             cinfo->comp_info[ci].quant_tbl_no = val;
-            while (*arg && *arg++ != ',')
+            while (arg[i] && arg[i] != ',') {
+                ++i;
                 /* advance to next segment of arg string */
-                ;
+            }
         } else {
             /* reached end of parameter, set remaining components to last tbl*/
             cinfo->comp_info[ci].quant_tbl_no = val;
         }
     }
-    return TRUE;
+    return true;
 }
 
 
-static boolean
-set_sample_factors (j_compress_ptr cinfo, char *arg)
-/* Process a sample-factors parameter string, of the form
- *     HxV[,HxV,...]
- * If there are more components than parameters, "1x1" is assumed for the rest.
- */
-{
-    int ci, val1, val2;
-    char ch1, ch2;
 
-    for (ci = 0; ci < MAX_COMPONENTS; ci++) {
-        if (*arg) {
-            ch2 = ',';		/* if not set by sscanf, will be ',' */
-            if (sscanf(arg, "%d%c%d%c", &val1, &ch1, &val2, &ch2) < 3)
-                return FALSE;
+static bool
+setSampleFactors (j_compress_ptr const cinfo,
+                  const char *   const arg) {
+/*----------------------------------------------------------------------------
+  Process a sample-factors parameter string, of the form
+  HxV[,HxV,...]
+
+  If there are more components than parameters, "1x1" is assumed for the rest.
+-----------------------------------------------------------------------------*/
+    int val1, val2;
+    char ch1, ch2;
+    unsigned int i;
+    unsigned int ci;
+
+    for (ci = 0, i = 0; ci < MAX_COMPONENTS; ++ci) {
+        if (arg[i]) {
+            ch2 = ',';          /* if not set by sscanf, will be ',' */
+            if (sscanf(&arg[i], "%d%c%d%c", &val1, &ch1, &val2, &ch2) < 3)
+                return false;
             if ((ch1 != 'x' && ch1 != 'X') || ch2 != ',') /* syntax check */
-                return FALSE;
+                return false;
             if (val1 <= 0 || val1 > 4) {
                 pm_message("Invalid sampling factor: %d.  "
                            "JPEG sampling factors must be 1..4", val1);
-                return FALSE;
+                return false;
             }
             if (val2 <= 0 || val2 > 4) {
                 pm_message("Invalid sampling factor: %d.  "
                            "JPEG sampling factors must be 1..4", val2);
-                return FALSE;
+                return false;
             }
             cinfo->comp_info[ci].h_samp_factor = val1;
             cinfo->comp_info[ci].v_samp_factor = val2;
-            while (*arg && *arg++ != ',')
+
+            while (arg[i] && arg[i] != ',') {
                 /* advance to next segment of arg string */
-                ;
+                ++i;
+            }
         } else {
             /* reached end of parameter, set remaining components
                to 1x1 sampling */
@@ -768,42 +888,42 @@ set_sample_factors (j_compress_ptr cinfo, char *arg)
             cinfo->comp_info[ci].v_samp_factor = 1;
         }
     }
-    return TRUE;
+    return true;
 }
 
 
 
 static void
-setup_jpeg(struct jpeg_compress_struct * const cinfoP,
-           struct jpeg_error_mgr       * const jerrP,
-           struct cmdlineInfo            const cmdline,
-           int                           const width,
-           int                           const height,
-           pixval                        const maxval,
-           int                           const input_fmt,
-           FILE *                        const output_file) {
+setupJpeg(struct jpeg_compress_struct * const cinfoP,
+          struct jpeg_error_mgr       * const jerrP,
+          struct CmdlineInfo            const cmdline,
+          unsigned int                  const width,
+          unsigned int                  const height,
+          pixval                        const maxval,
+          int                           const inputFmt,
+          FILE *                        const ofP) {
 
     int quality;
-    int q_scale_factor;
+    int qScaleFactor;
 
     /* Initialize the JPEG compression object with default error handling. */
     cinfoP->err = jpeg_std_error(jerrP);
     jpeg_create_compress(cinfoP);
 
-    setup_jpeg_source_parameters(cinfoP, width, height, input_fmt);
+    setupJpegSourceParameters(cinfoP, width, height, inputFmt);
 
     jpeg_set_defaults(cinfoP);
 
     cinfoP->data_precision = BITS_IN_JSAMPLE;
         /* we always rescale data to this */
-    cinfoP->image_width = (unsigned int) width;
-    cinfoP->image_height = (unsigned int) height;
+    cinfoP->image_width = width;
+    cinfoP->image_height = height;
 
-    cinfoP->arith_code = cmdline.arith_code;
-    cinfoP->dct_method = cmdline.dct_method;
-    if (cmdline.trace_level == 0 && cmdline.verbose)
+    cinfoP->arith_code = cmdline.arithmetic;
+    cinfoP->dct_method = cmdline.dctMethod;
+    if (cmdline.tracelevel == 0 && cmdline.verbose)
         cinfoP->err->trace_level = 1;
-    else cinfoP->err->trace_level = cmdline.trace_level;
+    else cinfoP->err->trace_level = cmdline.tracelevel;
     if (cmdline.grayscale)
         jpeg_set_colorspace(cinfoP, JCS_GRAYSCALE);
     else if (cmdline.rgb)
@@ -812,38 +932,38 @@ setup_jpeg(struct jpeg_compress_struct * const cinfoP,
     else
         /* This default will be based on the in_color_space set above */
         jpeg_default_colorspace(cinfoP);
-    if (cmdline.max_memory_to_use != -1)
-        cinfoP->mem->max_memory_to_use = cmdline.max_memory_to_use;
+    if (cmdline.maxMemoryToUse != -1)
+        cinfoP->mem->max_memory_to_use = cmdline.maxMemoryToUse;
     cinfoP->optimize_coding = cmdline.optimize;
     if (cmdline.quality == -1) {
         quality = 75;
-        q_scale_factor = 100;
+        qScaleFactor = 100;
     } else {
         quality = cmdline.quality;
-        q_scale_factor = jpeg_quality_scaling(cmdline.quality);
+        qScaleFactor = jpeg_quality_scaling(cmdline.quality);
     }
-    if (cmdline.smoothing_factor != -1)
-        cinfoP->smoothing_factor = cmdline.smoothing_factor;
+    if (cmdline.smooth != -1)
+        cinfoP->smoothing_factor = cmdline.smooth;
 
     /* Set quantization tables for selected quality. */
     /* Some or all may be overridden if user specified --qtables. */
-    jpeg_set_quality(cinfoP, quality, cmdline.force_baseline);
+    jpeg_set_quality(cinfoP, quality, cmdline.baseline);
 
     if (cmdline.qtablefile != NULL) {
-        if (! read_quant_tables(cinfoP, cmdline.qtablefile,
-                                q_scale_factor, cmdline.force_baseline))
+        if (! readQuantTables(cinfoP, cmdline.qtablefile,
+                              qScaleFactor, cmdline.baseline))
             pm_error("Can't use quantization table file '%s'.",
                      cmdline.qtablefile);
     }
 
     if (cmdline.qslots != NULL) {
-        if (! set_quant_slots(cinfoP, cmdline.qslots))
+        if (! setQuantSlots(cinfoP, cmdline.qslots))
             pm_error("Bad quantization-table-selectors parameter string '%s'.",
                      cmdline.qslots);
     }
 
     if (cmdline.sample != NULL) {
-        if (! set_sample_factors(cinfoP, cmdline.sample))
+        if (! setSampleFactors(cinfoP, cmdline.sample))
             pm_error("Bad sample-factors parameters string '%s'.",
                      cmdline.sample);
     }
@@ -851,19 +971,24 @@ setup_jpeg(struct jpeg_compress_struct * const cinfoP,
     if (cmdline.progressive)
         jpeg_simple_progression(cinfoP);
 
-    if (cmdline.density_spec)
-        setup_jpeg_density(cinfoP, cmdline.density);
+    if (cmdline.densitySpec)
+        setupJpegDensity(cinfoP, cmdline.density);
 
     if (cmdline.scans != NULL) {
-        if (! read_scan_script(cinfoP, cmdline.scans)) {
-            pm_message("Error in scan script '%s'.", cmdline.scans);
+        const char * error;
+        readScanScript(cinfoP, cmdline.scans, &error);
+        if (error) {
+            pm_message("Error in scan script '%s'.  %s", cmdline.scans, error);
+            pm_strfree(error);
         }
-    }
+    } else
+        cinfoP->scan_info = NULL;
 
     /* Specify data destination for compression */
-    jpeg_stdio_dest(cinfoP, output_file);
+    jpeg_stdio_dest(cinfoP, ofP);
 
-    if (cmdline.verbose) report_compressor(*cinfoP);
+    if (cmdline.verbose)
+        reportCompressor(*cinfoP);
 
     /* Start compressor */
     jpeg_start_compress(cinfoP, TRUE);
@@ -873,115 +998,122 @@ setup_jpeg(struct jpeg_compress_struct * const cinfoP,
 
 
 static void
-write_exif_header(struct jpeg_compress_struct * const cinfoP,
-                  const char * const exif_filespec) {
+writeExifHeader(struct jpeg_compress_struct * const cinfoP,
+                const char *                  const exifFileNm) {
 /*----------------------------------------------------------------------------
    Generate an APP1 marker in the JFIF output that is an Exif header.
 
    The contents of the Exif header are in the file with filespec
-   'exif_filespec' (file spec and contents are not validated).
+   'exifFileNm' (file spec and contents are not validated).
 
-   exif_filespec = "-" means Standard Input.
+   exifFileNm = "-" means Standard Input.
 
    If the file contains just two bytes of zero, don't write any marker
    but don't recognize any error either.
 -----------------------------------------------------------------------------*/
-    FILE * exif_file;
+    FILE * exifFp;
     unsigned short length;
 
-    exif_file = pm_openr(exif_filespec);
+    exifFp = pm_openr(exifFileNm);
 
-    pm_readbigshort(exif_file, (short*)&length);
+    pm_readbigshort(exifFp, (short*)&length);
 
     if (length == 0) {
         /* Special value meaning "no header" */
     } else if (length < 3)
         pm_error("Invalid length %u at start of exif file", length);
     else {
-        unsigned char * exif_data;
-        size_t rc;
-        size_t const data_length = length - 2;
+        unsigned char * exifData;
+        size_t const dataLength = length - 2;
             /* Subtract 2 byte length field*/
+        size_t rc;
 
-        assert(data_length > 0);
+        assert(dataLength > 0);
 
-        exif_data = malloc(data_length);
-        if (exif_data == NULL)
+        MALLOCARRAY(exifData, dataLength);
+        if (!exifData)
             pm_error("Unable to allocate %u bytes for exif header buffer",
-                     (unsigned)data_length);
+                     (unsigned)dataLength);
 
-        rc = fread(exif_data, 1, data_length, exif_file);
+        rc = fread(exifData, 1, dataLength, exifFp);
 
-        if (rc != data_length)
+        if (rc != dataLength)
             pm_error("Premature end of file on exif header file.  Should be "
                      "%u bytes of data, read only %u",
-                     (unsigned)data_length, (unsigned)rc);
+                     (unsigned)dataLength, (unsigned)rc);
 
         jpeg_write_marker(cinfoP, JPEG_APP0+1,
-                          (const JOCTET *) exif_data, data_length);
+                          (const JOCTET *) exifData, dataLength);
 
-        free(exif_data);
+        free(exifData);
     }
 
-    pm_close(exif_file);
+    pm_close(exifFp);
 }
 
 
 
 static void
-compute_rescaling_array(JSAMPLE ** const rescale_p, const pixval maxval,
-                        const struct jpeg_compress_struct cinfo) {
+computeRescalingArray(JSAMPLE **                  const rescaleP,
+                      pixval                      const maxval,
+                      struct jpeg_compress_struct const cinfo) {
 /*----------------------------------------------------------------------------
    Compute the rescaling array for a maximum pixval of 'maxval'.
    Allocate the memory for it too.
 -----------------------------------------------------------------------------*/
-  const long half_maxval = maxval / 2;
-  long val;
-
-  *rescale_p = (JSAMPLE *)
-    (cinfo.mem->alloc_small) ((j_common_ptr) &cinfo, JPOOL_IMAGE,
-                              (size_t) (((long) maxval + 1L) *
-                                        sizeof(JSAMPLE)));
-  for (val = 0; val <= maxval; val++) {
-    /* The multiplication here must be done in 32 bits to avoid overflow */
-    (*rescale_p)[val] = (JSAMPLE) ((val*MAXJSAMPLE + half_maxval)/maxval);
-  }
+    long const halfMaxval = maxval / 2;
+
+    JSAMPLE * rescale;
+    long val;
+
+    MALLOCARRAY(rescale, maxval + 1);
+
+    if (!rescale)
+        pm_error("Failed to get memory for map of %u possible sample values",
+                 maxval + 1);
+
+    for (val = 0; val <= maxval; ++val) {
+        /* The multiplication here must be done in 32 bits to avoid overflow */
+        rescale[val] = (JSAMPLE) ((val*MAXJSAMPLE + halfMaxval)/maxval);
+    }
+
+    *rescaleP = rescale;
 }
 
 
 
 static void
-translate_row(const pixel pnm_buffer[],
-              JSAMPLE jpeg_buffer[],
-              int const width,
-              int const input_components,
-              const JSAMPLE translate[]) {
+translateRow(pixel        const pnm_buffer[],
+             unsigned int const width,
+             unsigned int const inputComponentCt,
+             JSAMPLE      const translate[],
+             JSAMPLE *    const jpegBuffer) {
 /*----------------------------------------------------------------------------
    Convert the input row, in pnm format, to an output row in JPEG compressor
    input format.
 
    This is a byte for byte copy, translated through the array 'translate'.
 -----------------------------------------------------------------------------*/
-  unsigned int column;
+  unsigned int col;
   /* I'm not sure why the JPEG library data structures don't have some kind
      of pixel data structure (such that a row buffer is an array of pixels,
      rather than an array of samples).  But because of this, we have to
      index jpeg_buffer the old fashioned way.
      */
 
-  switch (input_components) {
+  switch (inputComponentCt) {
   case 1:
-      for (column = 0; column < width; column++)
-          jpeg_buffer[column] = translate[(int)PNM_GET1(pnm_buffer[column])];
+      for (col = 0; col < width; ++col)
+          jpegBuffer[col] = translate[(int)PNM_GET1(pnm_buffer[col])];
       break;
   case 3:
-      for (column = 0; column < width; column++) {
-          jpeg_buffer[column*3+0] =
-              translate[(int)PPM_GETR(pnm_buffer[column])];
-          jpeg_buffer[column*3+1] =
-              translate[(int)PPM_GETG(pnm_buffer[column])];
-          jpeg_buffer[column*3+2] =
-              translate[(int)PPM_GETB(pnm_buffer[column])];
+      for (col = 0; col < width; ++col) {
+          jpegBuffer[col * 3 + 0] =
+              translate[(int)PPM_GETR(pnm_buffer[col])];
+          jpegBuffer[col * 3 + 1] =
+              translate[(int)PPM_GETG(pnm_buffer[col])];
+          jpegBuffer[col * 3 + 2] =
+              translate[(int)PPM_GETB(pnm_buffer[col])];
       }
       break;
   default:
@@ -994,72 +1126,69 @@ translate_row(const pixel pnm_buffer[],
 
 
 static void
-convert_scanlines(struct jpeg_compress_struct * const cinfo_p,
-                  FILE *                        const input_file,
-                  pixval                        const maxval,
-                  int                           const input_fmt,
-                  JSAMPLE                             xlate_table[]){
+convertScanLines(struct jpeg_compress_struct * const cinfoP,
+                 FILE *                        const inputFileNm,
+                 pixval                        const maxval,
+                 int                           const inputFmt,
+                 const JSAMPLE *               const xlateTable){
 /*----------------------------------------------------------------------------
-   Read scan lines from the input file, which is already opened in the
-   netpbm library sense and ready for reading, and write them to the
-   output JPEG object.  Translate the pnm sample values to JPEG sample
-   values through the thable xlate_table[].
+  Read scan lines from the input file, which is already opened in the
+  netpbm library sense and ready for reading, and write them to the
+  output JPEG object.  Translate the pnm sample values to JPEG sample
+  values through the table xlateTable[].
 -----------------------------------------------------------------------------*/
-  xel * pnm_buffer;
-    /* contains the row of the input image currently being processed,
-       in pnm_readpnmrow format
-    */
-  JSAMPARRAY buffer;
-    /* Row 0 of this array contains the row of the output image currently
-       being processed, in JPEG compressor input format.  The array only
-       has that one row.
-    */
+    xel * pnmBuffer;
+        /* This malloc'ed array contains the row of the input image currently
+           being processed, in pnm_readpnmrow format.
+        */
+    JSAMPLE * jpegBuffer;
+        /* This malloc'ed array contains the row of the output image currently
+           being processed, in JPEG compressor input format.
+        */
 
-  /* Allocate the libpnm output and compressor input buffers */
-  buffer = (*cinfo_p->mem->alloc_sarray)
-    ((j_common_ptr) cinfo_p, JPOOL_IMAGE,
-     (unsigned int) cinfo_p->image_width * cinfo_p->input_components,
-     (unsigned int) 1);
-
-  pnm_buffer = pnm_allocrow(cinfo_p->image_width);
-
-  while (cinfo_p->next_scanline < cinfo_p->image_height) {
-    if (cinfo_p->err->trace_level > 1)
-        pm_message("Converting Row %d...", cinfo_p->next_scanline);
-    pnm_readpnmrow(input_file, pnm_buffer, cinfo_p->image_width,
-                   maxval, input_fmt);
-    translate_row(pnm_buffer, buffer[0],
-                  cinfo_p->image_width, cinfo_p->input_components,
-                  xlate_table);
-    jpeg_write_scanlines(cinfo_p, buffer, 1);
-    if (cinfo_p->err->trace_level > 1)
-        pm_message("Done.");
-  }
+    MALLOCARRAY(jpegBuffer, cinfoP->image_width * cinfoP->input_components);
+    if (!jpegBuffer)
+        pm_error("Unable to allocate buffer for a row of %u pixels, "
+                 "%u samples each",
+                 cinfoP->image_width, cinfoP->input_components);
+
+    pnmBuffer = pnm_allocrow(cinfoP->image_width);
+
+    while (cinfoP->next_scanline < cinfoP->image_height) {
+        if (cinfoP->err->trace_level > 1)
+            pm_message("Converting Row %d...", cinfoP->next_scanline);
+        pnm_readpnmrow(inputFileNm, pnmBuffer, cinfoP->image_width,
+                       maxval, inputFmt);
+        translateRow(pnmBuffer,
+                     cinfoP->image_width, cinfoP->input_components,
+                     xlateTable,  jpegBuffer);
+        jpeg_write_scanlines(cinfoP, &jpegBuffer, 1);
+        if (cinfoP->err->trace_level > 1)
+            pm_message("Done.");
+    }
 
-  pnm_freerow(pnm_buffer);
-  /* Don't worry about the compressor input buffer; it gets freed
-     automatically
-  */
+    pnm_freerow(pnmBuffer);
+    free(jpegBuffer);
 }
 
 
 
 int
-main(int     argc,
-     char ** argv) {
+main(int           argc,
+     const char ** argv) {
 
-    struct cmdlineInfo cmdline;
+    struct CmdlineInfo cmdline;
     struct jpeg_compress_struct cinfo;
     struct jpeg_error_mgr jerr;
-    FILE * input_file;
-    FILE * output_file;
+    FILE * ifP;
+    FILE * ofP;
     int height;
         /* height of the input image in rows, as specified by its header */
     int width;
         /* width of the input image in columns, as specified by its header */
     pixval maxval;
         /* maximum value of an input pixel component, as specified by header */
-    int input_fmt;
+    int inputFmt;
         /* The input format, as determined by its header.  */
     JSAMPLE *rescale;         /* => maxval-remapping array, or NULL */
         /* This is an array that maps each possible pixval in the input to
@@ -1067,48 +1196,53 @@ main(int     argc,
            0 .. maxval, the range of the output values is 0 .. MAXJSAMPLE.
         */
 
-    pnm_init(&argc, argv);
+    pm_proginit(&argc, argv);
 
     parseCommandLine(argc, argv, &cmdline);
 
-    input_file = pm_openr(cmdline.input_filespec);
-    free(cmdline.input_filespec);
+    ifP = pm_openr(cmdline.inputFileNm);
 
-    output_file = stdout;
+    ofP = stdout;
 
     /* Open the pnm input */
-    pnm_readpnminit(input_file, &width, &height, &maxval, &input_fmt);
+    pnm_readpnminit(ifP, &width, &height, &maxval, &inputFmt);
     if (cmdline.verbose) {
         pm_message("Input file has format %c%c.\n"
                    "It has %d rows of %d columns of pixels "
                    "with max sample value of %d.",
-                   (char) (input_fmt/256), (char) (input_fmt % 256),
+                   (char) (inputFmt/256), (char) (inputFmt % 256),
                    height, width, maxval);
     }
 
-    setup_jpeg(&cinfo, &jerr, cmdline, width, height, maxval, input_fmt,
-               output_file);
+    setupJpeg(&cinfo, &jerr, cmdline, width, height, maxval, inputFmt, ofP);
 
-    compute_rescaling_array(&rescale, maxval, cinfo);
+    computeRescalingArray(&rescale, maxval, cinfo);
 
     if (cmdline.comment)
         jpeg_write_marker(&cinfo, JPEG_COM, (const JOCTET *) cmdline.comment,
                           strlen(cmdline.comment));
 
-    if (cmdline.exif_filespec)
-        write_exif_header(&cinfo, cmdline.exif_filespec);
+    if (cmdline.exif)
+        writeExifHeader(&cinfo, cmdline.exif);
 
     /* Translate and copy over the actual scanlines */
-    convert_scanlines(&cinfo, input_file, maxval, input_fmt, rescale);
+    convertScanLines(&cinfo, ifP, maxval, inputFmt, rescale);
 
     /* Finish compression and release memory */
     jpeg_finish_compress(&cinfo);
     jpeg_destroy_compress(&cinfo);
 
+    if (cinfo.scan_info) {
+        free((void*)cinfo.scan_info);
+        cinfo.scan_info = NULL;
+    }
+    free(rescale);
+
     /* Close files, if we opened them */
-    if (input_file != stdin)
-        pm_close(input_file);
+    if (ifP != stdin)
+        pm_close(ifP);
 
+    free(cmdline.inputFileNm);
     /* Program may have exited with non-zero completion code via
        various function calls above.
     */