about summary refs log tree commit diff
path: root/converter/other/pgmtoppm.c
diff options
context:
space:
mode:
Diffstat (limited to 'converter/other/pgmtoppm.c')
-rw-r--r--converter/other/pgmtoppm.c161
1 files changed, 109 insertions, 52 deletions
diff --git a/converter/other/pgmtoppm.c b/converter/other/pgmtoppm.c
index c3a26594..822ddac7 100644
--- a/converter/other/pgmtoppm.c
+++ b/converter/other/pgmtoppm.c
@@ -17,27 +17,30 @@
 
 #include "pm_c_util.h"
 #include "mallocvar.h"
+#include "nstring.h"
 #include "shhopt.h"
 #include "ppm.h"
 
-struct cmdlineInfo {
+struct CmdlineInfo {
     /* All the information the user supplied in the command line,
        in a form easy for the program to use.
     */
     const char * inputFilename;  /* '-' if stdin */
     const char * map;
-    const char * colorBlack;
-    const char * colorWhite;
+    const char * colorBlack;  /* malloc'ed */
+        /* The color to which the user says to map black */
+    const char * colorWhite;  /* malloc'ed */
+        /* The color to which the user says to map white */
 };
 
 
 
 static void
-parseCommandLine(int argc, char ** argv,
-                 struct cmdlineInfo * const cmdlineP) {
+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.
@@ -45,18 +48,23 @@ parseCommandLine(int argc, char ** argv,
    Note that the strings we return are stored in the storage that
    was passed to us as the argv array.  We also trash *argv.
 -----------------------------------------------------------------------------*/
-    optEntry *option_def;
-        /* Instructions to pm_optParseOptions3 on how to parse our options.
-         */
+    optEntry * option_def;   /* Used by OPTENT3 */
     optStruct3 opt;
 
     unsigned int option_def_index;
 
-    unsigned int mapSpec;
+    unsigned int blackSpec, whiteSpec, mapSpec;
+
+    const char * blackOpt;
+    const char * whiteOpt;
 
     MALLOCARRAY_NOFAIL(option_def, 100);
 
     option_def_index = 0;   /* incremented by OPTENT3 */
+    OPTENT3(0, "black",          OPT_STRING,    &blackOpt,
+            &blackSpec,          0);
+    OPTENT3(0, "white",          OPT_STRING,    &whiteOpt,
+            &whiteSpec,          0);
     OPTENT3(0, "map",            OPT_STRING,    &cmdlineP->map,
             &mapSpec,            0);
 
@@ -64,13 +72,19 @@ 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);
-        /* Uses and sets argc, argv, and some of *cmdlineP and others. */
+    pm_optParseOptions4(&argc, argv, opt, sizeof(opt), 0);
 
     if (!mapSpec)
         cmdlineP->map = NULL;
 
     if (mapSpec) {
+        if (blackSpec || whiteSpec)
+            pm_error("You may not specify -black or -white "
+                     "together with -map");
+
+        cmdlineP->colorBlack = NULL;
+        cmdlineP->colorWhite = NULL;
+
         /* No color argument; only argument is file name */
         if (argc-1 < 1)
             cmdlineP->inputFilename = "-";
@@ -81,37 +95,77 @@ parseCommandLine(int argc, char ** argv,
                          "the file name.  You specified %u", argc-1);
         }
     } else {
-        /* Arguments are color or color range and file name */
-        if (argc-1 < 1) {
-            cmdlineP->colorBlack = "black";
-            cmdlineP->colorWhite = "white";
+        /* For default colors, we use "rgbi:..." instead of the simpler
+           "black" and "white" so that we don't have an unnecessary dependency
+           on a color dictionary being available.
+        */
+        if (blackSpec || whiteSpec) {
+            cmdlineP->colorBlack =
+                pm_strdup(blackSpec ? blackOpt : "rgbi:0/0/0");
+            cmdlineP->colorWhite =
+                pm_strdup(whiteSpec ? whiteOpt : "rgbi:1/1/1");
+
+            /* The only possibly argument is input file name */
+            if (argc-1 < 1)
+                cmdlineP->inputFilename = "-";
+            else {
+                cmdlineP->inputFilename = argv[1];
+                if (argc-1 > 1)
+                    pm_error("Whten you specify -black or -white, "
+                             "there can be at most one non-option arguments:  "
+                             "the file name.  "
+                             "You specified %u", argc-1);
+            }
         } else {
-            char * buffer = strdup(argv[1]);
-            char * hyphenPos = strchr(buffer, '-');
-            if (hyphenPos) {
-                *hyphenPos = '\0';
-                cmdlineP->colorBlack = buffer;
-                cmdlineP->colorWhite = hyphenPos+1;
+            /* Arguments are color or color range and optional file name */
+
+            if (argc-1 < 1) {
+                cmdlineP->colorBlack = pm_strdup("rgbi:0/0/0");
+                cmdlineP->colorWhite = pm_strdup("rgbi:1/1/1");
             } else {
-                cmdlineP->colorBlack = "black";
-                cmdlineP->colorWhite = buffer;
+                char * buffer = strdup(argv[1]);
+                if (!buffer)
+                    pm_error("Out of memory allocating tiny buffer");
+                char * hyphenPos = strchr(buffer, '-');
+                if (hyphenPos) {
+                    *hyphenPos = '\0';
+                    cmdlineP->colorBlack = pm_strdup(buffer);
+                    cmdlineP->colorWhite = pm_strdup(hyphenPos+1);
+                } else {
+                    cmdlineP->colorBlack = pm_strdup("rgbi:0/0/0");
+                    cmdlineP->colorWhite = pm_strdup(buffer);
+                }
+                free(buffer);
+            }
+
+            if (argc-1 < 2)
+                cmdlineP->inputFilename = "-";
+            else {
+                cmdlineP->inputFilename = argv[2];
+
+                if (argc-1 > 2)
+                    pm_error("Program takes at most 2 arguments:  "
+                             "color name/range and input file name.  "
+                             "You specified %u", argc-1);
             }
         }
-        if (argc-1 < 2)
-            cmdlineP->inputFilename = "-";
-        else
-            cmdlineP->inputFilename = argv[2];
-        
-        if (argc-1 > 2)
-            pm_error("Program takes at most 2 arguments:  "
-                     "color name/range and input file name.  "
-                     "You specified %u", argc-1);
     }
 }
 
 
 
 static void
+freeCommandLine(struct CmdlineInfo const cmdline) {
+
+    if (cmdline.colorBlack)
+        pm_strfree(cmdline.colorBlack);
+    if (cmdline.colorWhite)
+        pm_strfree(cmdline.colorWhite);
+}
+
+
+
+static void
 convertWithMap(FILE * const ifP,
                unsigned int const cols,
                unsigned int const rows,
@@ -128,7 +182,7 @@ convertWithMap(FILE * const ifP,
     pixval mapmaxval;
     pixel ** mappixels;
     unsigned int mapmaxcolor;
-    
+
     mapFileP = pm_openr(mapFileName);
     mappixels = ppm_readppm(mapFileP, &mapcols, &maprows, &mapmaxval);
     pm_close(mapFileP);
@@ -138,7 +192,7 @@ convertWithMap(FILE * const ifP,
 
     for (row = 0; row < rows; ++row) {
         unsigned int col;
-            
+
         pgm_readpgmrow(ifP, grayrow, cols, maxval, format);
 
         for (col = 0; col < cols; ++col) {
@@ -168,22 +222,20 @@ convertLinear(FILE * const ifP,
               gray *       const grayrow,
               pixel *      const pixelrow) {
 
-    pixel colorBlack, colorWhite;
-    pixval red0, grn0, blu0, red1, grn1, blu1;
+    pixel const colorBlack = ppm_parsecolor(colorNameBlack, maxval);
+    pixel const colorWhite = ppm_parsecolor(colorNameWhite, maxval);
+
+    pixval const red0 = PPM_GETR(colorBlack);
+    pixval const grn0 = PPM_GETG(colorBlack);
+    pixval const blu0 = PPM_GETB(colorBlack);
+    pixval const red1 = PPM_GETR(colorWhite);
+    pixval const grn1 = PPM_GETG(colorWhite);
+    pixval const blu1 = PPM_GETB(colorWhite);
+
     unsigned int row;
 
     ppm_writeppminit(ofP, cols, rows, maxval, 0);
 
-    colorBlack = ppm_parsecolor(colorNameBlack, maxval);
-    colorWhite = ppm_parsecolor(colorNameWhite, maxval);
- 
-    red0 = PPM_GETR(colorBlack);
-    grn0 = PPM_GETG(colorBlack);
-    blu0 = PPM_GETB(colorBlack);
-    red1 = PPM_GETR(colorWhite);
-    grn1 = PPM_GETG(colorWhite);
-    blu1 = PPM_GETB(colorWhite);
-
     for (row = 0; row < rows; ++row) {
         unsigned int col;
 
@@ -204,17 +256,17 @@ convertLinear(FILE * const ifP,
 
 
 int
-main(int    argc,
-     char * argv[]) {
+main(int          argc,
+     const char * argv[]) {
 
     FILE * ifP;
-    struct cmdlineInfo cmdline;
+    struct CmdlineInfo cmdline;
     gray * grayrow;
     pixel * pixelrow;
     int rows, cols, format;
     gray maxval;
 
-    ppm_init(&argc, argv);
+    pm_proginit(&argc, argv);
 
     parseCommandLine(argc, argv, &cmdline);
 
@@ -228,7 +280,7 @@ main(int    argc,
         convertWithMap(ifP, cols, rows, maxval, format, cmdline.map,
                        stdout, grayrow, pixelrow);
     else
-        convertLinear(ifP, cols, rows, maxval, format, 
+        convertLinear(ifP, cols, rows, maxval, format,
                       cmdline.colorBlack, cmdline.colorWhite, stdout,
                       grayrow, pixelrow);
 
@@ -236,8 +288,13 @@ main(int    argc,
     pgm_freerow(grayrow);
     pm_close(ifP);
 
+    freeCommandLine(cmdline);
+
     /* If the program failed, it previously aborted with nonzero completion
        code, via various function calls.
     */
     return 0;
 }
+
+
+