diff options
Diffstat (limited to 'converter/other/pgmtoppm.c')
-rw-r--r-- | converter/other/pgmtoppm.c | 161 |
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; } + + + |