From b2f780d9e1249f8595c5d1ba39a529fc0c0e9893 Mon Sep 17 00:00:00 2001 From: giraffedata Date: Mon, 4 May 2009 01:03:24 +0000 Subject: Fix -missing, -firstisdefault git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@914 9d0c8265-081b-0410-96cb-a4ca84ce46f8 --- editor/pnmremap.c | 167 ++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 111 insertions(+), 56 deletions(-) (limited to 'editor/pnmremap.c') diff --git a/editor/pnmremap.c b/editor/pnmremap.c index 7301fa35..5de82a60 100644 --- a/editor/pnmremap.c +++ b/editor/pnmremap.c @@ -745,7 +745,6 @@ lookupThroughHash(struct pam * const pamP, static void mapTuple(struct pam * const pamP, tuple const inTuple, - enum missingMethod const missingMethod, tuple const defaultColor, tupletable const colormap, struct colormapFinder * const colorFinderP, @@ -759,22 +758,15 @@ mapTuple(struct pam * const pamP, there is no usable color in the color map. */ - lookupThroughHash(pamP, inTuple, - missingMethod != MISSING_CLOSE, colorFinderP, + lookupThroughHash(pamP, inTuple, !!defaultColor, colorFinderP, colorhash, &colormapIndex, usehashP); if (colormapIndex == -1) { *missingP = TRUE; - switch (missingMethod) { - case MISSING_SPECIFIED: - pnm_assigntuple(pamP, outTuple, defaultColor); - break; - case MISSING_FIRST: - pnm_assigntuple(pamP, outTuple, colormap[0]->tuple); - break; - default: - pm_error("Internal error: invalid value of missingMethod"); - } + + assert(defaultColor); // Otherwise, lookup would have succeeded + + pnm_assigntuple(pamP, outTuple, defaultColor); } else { *missingP = FALSE; pnm_assigntuple(pamP, outTuple, colormap[colormapIndex]->tuple); @@ -792,7 +784,6 @@ convertRowStraight(struct pam * const inpamP, struct colormapFinder * const colorFinderP, tuplehash const colorhash, bool * const usehashP, - enum missingMethod const missingMethod, tuple const defaultColor, tuple outrow[], unsigned int * const missingCountP) { @@ -822,7 +813,7 @@ convertRowStraight(struct pam * const inpamP, for (col = 0; col < outpamP->width; ++col) { bool missing; - mapTuple(outpamP, outrow[col], missingMethod, defaultColor, + mapTuple(outpamP, outrow[col], defaultColor, colormap, colorFinderP, colorhash, usehashP, outrow[col], &missing); @@ -844,7 +835,6 @@ convertRowDither(struct pam * const inpamP, struct colormapFinder * const colorFinderP, tuplehash const colorhash, bool * const usehashP, - enum missingMethod const missingMethod, tuple const defaultColor, struct fserr * const fserrP, tuple outrow[], @@ -883,7 +873,7 @@ convertRowDither(struct pam * const inpamP, pnm_scaletuple(inpamP, normTuple, ditheredTuple, outpamP->maxval); adjustDepthTuple(normTuple, depthAdjustment); - mapTuple(outpamP, normTuple, missingMethod, defaultColor, + mapTuple(outpamP, normTuple, defaultColor, colormap, colorFinderP, colorhash, usehashP, outrow[col], &missing); @@ -919,7 +909,6 @@ convertRow(struct pam * const inpamP, tuplehash const colorhash, bool * const usehashP, bool const floyd, - enum missingMethod const missingMethod, tuple const defaultColor, struct fserr * const fserrP, tuple outrow[], @@ -945,14 +934,12 @@ convertRow(struct pam * const inpamP, if (floyd) convertRowDither(inpamP, outpamP, inrow, depthAdjustment, colormap, colorFinderP, colorhash, - usehashP, - missingMethod, defaultColor, + usehashP, defaultColor, fserrP, outrow, missingCountP); else convertRowStraight(inpamP, outpamP, inrow, depthAdjustment, colormap, colorFinderP, colorhash, - usehashP, - missingMethod, defaultColor, + usehashP, defaultColor, outrow, missingCountP); } @@ -965,7 +952,6 @@ copyRaster(struct pam * const inpamP, unsigned int const colormapSize, bool const floyd, bool const randomize, - enum missingMethod const missingMethod, tuple const defaultColor, unsigned int * const missingCountP) { @@ -994,7 +980,7 @@ copyRaster(struct pam * const inpamP, inrow = pnm_allocpamrow(inpamP); outrow = pnm_allocpamrow(&workpam); - if (outpamP->maxval != inpamP->maxval && missingMethod != MISSING_CLOSE) + if (outpamP->maxval != inpamP->maxval && defaultColor) pm_error("The maxval of the colormap (%u) is not equal to the " "maxval of the input image (%u). This is allowable only " "if you are doing an approximate mapping (i.e. you don't " @@ -1019,8 +1005,7 @@ copyRaster(struct pam * const inpamP, convertRow(inpamP, &workpam, inrow, depthAdjustment, colormap, colorFinderP, colorhash, - &usehash, - floyd, missingMethod, defaultColor, + &usehash, floyd, defaultColor, &fserr, outrow, &missingCount); *missingCountP += missingCount; @@ -1036,23 +1021,34 @@ copyRaster(struct pam * const inpamP, static void -remap(FILE * const ifP, +remap(FILE * const ifP, const struct pam * const outpamCommonP, tupletable const colormap, unsigned int const colormapSize, bool const floyd, bool const randomize, - enum missingMethod const missingMethod, tuple const defaultColor, bool const verbose) { +/*---------------------------------------------------------------------------- + Remap the pixels from the raster on *ifP to the 'colormapSize' colors in + 'colormap'. + Where the input pixel's color is in the map, just use that for the output. + Where it isn't, use 'defaultColor', except if that is NULL, use the + closest color in the map to the input color. + + But if 'floyd' is true and 'defaultColor' is NULL, also do Floyd-Steinberg + dithering on the output so the aggregate color of a region is about the + same as that of the input even though the individual pixels have different + colors. +-----------------------------------------------------------------------------*/ bool eof; eof = FALSE; while (!eof) { struct pam inpam, outpam; unsigned int missingCount; - /* Number of pixels that were not matched in the color map (where - missingMethod is MISSING_CLOSE, this is always zero). + /* Number of pixels that were mapped to 'defaultColor' because + they weren't present in the color map. */ pnm_readpaminit(ifP, &inpam, PAM_STRUCT_SIZE(allocation_depth)); @@ -1069,7 +1065,7 @@ remap(FILE * const ifP, pnm_setminallocationdepth(&inpam, outpam.depth); copyRaster(&inpam, &outpam, colormap, colormapSize, floyd, - randomize, missingMethod, defaultColor, &missingCount); + randomize, defaultColor, &missingCount); if (verbose) pm_message("%u pixels not matched in color map", missingCount); @@ -1080,6 +1076,64 @@ remap(FILE * const ifP, +static void +processMapFile(const char * const mapFileName, + struct pam * const outpamCommonP, + tupletable * const colormapP, + unsigned int * const colormapSizeP, + tuple * const firstColorP) { + + FILE * mapfile; + struct pam mappam; + tuple ** maptuples; + tuple firstColor; + + mapfile = pm_openr(mapFileName); + maptuples = pnm_readpam(mapfile, &mappam, PAM_STRUCT_SIZE(tuple_type)); + pm_close(mapfile); + + computeColorMapFromMap(&mappam, maptuples, colormapP, colormapSizeP); + + firstColor = pnm_allocpamtuple(&mappam); + pnm_assigntuple(&mappam, firstColor, maptuples[0][0]); + *firstColorP = firstColor; + + pnm_freepamarray(maptuples, &mappam); + + *outpamCommonP = mappam; + outpamCommonP->file = stdout; +} + + + +static void +getSpecifiedMissingColor(struct pam * const pamP, + const char * const colorName, + tuple * const specColorP) { + + tuple specColor; + + specColor = pnm_allocpamtuple(pamP); + + if (colorName) { + pixel const color = ppm_parsecolor(colorName, pamP->maxval); + if (pamP->depth == 3) { + specColor[PAM_RED_PLANE] = PPM_GETR(color); + specColor[PAM_GRN_PLANE] = PPM_GETG(color); + specColor[PAM_BLU_PLANE] = PPM_GETB(color); + } else if (pamP->depth == 1) { + specColor[0] = PPM_LUMIN(color); + } else { + pm_error("You may not use -missing with a colormap that is not " + "of depth 1 or 3. Yours has depth %u", + pamP->depth); + } + } + *specColorP = specColor; +} + + + int main(int argc, char * argv[] ) { @@ -1093,9 +1147,17 @@ main(int argc, char * argv[] ) { */ tupletable colormap; unsigned int colormapSize; + tuple specColor; + /* A tuple of the color the user specified to use for input colors + that are not in the colormap. Arbitrary tuple if he didn't + specify any. + */ + tuple firstColor; + /* A tuple of the first color present in the map file */ tuple defaultColor; - /* A tuple of the color that should replace any input color that is - not in the colormap, if we're doing MISSING_SPECIFIED. + /* The color to which we will map an input color that is not in the + colormap. NULL if we are not to map such a color to a particular + color (i.e. we'll choose an approximate match from the map). */ pnm_init(&argc, argv); @@ -1103,37 +1165,30 @@ main(int argc, char * argv[] ) { parseCommandLine(argc, argv, &cmdline); ifP = pm_openr(cmdline.inputFilespec); - { - FILE * mapfile; - struct pam mappam; - tuple ** maptuples; - - mapfile = pm_openr(cmdline.mapFilespec); - maptuples = pnm_readpam(mapfile, &mappam, PAM_STRUCT_SIZE(tuple_type)); - pm_close(mapfile); - computeColorMapFromMap(&mappam, maptuples, &colormap, &colormapSize); - pnm_freepamarray(maptuples, &mappam); + processMapFile(cmdline.mapFilespec, &outpamCommon, + &colormap, &colormapSize, &firstColor); - outpamCommon = mappam; - outpamCommon.file = stdout; - } + getSpecifiedMissingColor(&outpamCommon, cmdline.missingcolor, &specColor); - defaultColor = pnm_allocpamtuple(&outpamCommon); - if (cmdline.missingcolor && outpamCommon.depth == 3) { - pixel const color = - ppm_parsecolor(cmdline.missingcolor, outpamCommon.maxval); - defaultColor[PAM_RED_PLANE] = PPM_GETR(color); - defaultColor[PAM_GRN_PLANE] = PPM_GETG(color); - defaultColor[PAM_BLU_PLANE] = PPM_GETB(color); + switch (cmdline.missingMethod) { + case MISSING_CLOSE: + defaultColor = NULL; + break; + case MISSING_FIRST: + defaultColor = firstColor; + break; + case MISSING_SPECIFIED: + defaultColor = specColor; + break; } remap(ifP, &outpamCommon, colormap, colormapSize, - cmdline.floyd, !cmdline.norandom, cmdline.missingMethod, - defaultColor, + cmdline.floyd, !cmdline.norandom, defaultColor, cmdline.verbose); - pnm_freepamtuple(defaultColor); + pnm_freepamtuple(firstColor); + pnm_freepamtuple(specColor); pm_close(stdout); -- cgit 1.4.1