about summary refs log tree commit diff
path: root/editor/pnmremap.c
diff options
context:
space:
mode:
authorgiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2009-05-04 01:03:24 +0000
committergiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2009-05-04 01:03:24 +0000
commitb2f780d9e1249f8595c5d1ba39a529fc0c0e9893 (patch)
tree189b290dac41a88a215287415ee6462348bc0679 /editor/pnmremap.c
parent35dea34710a2750d9aa1b04a6d6e112baf5ca6cf (diff)
downloadnetpbm-mirror-b2f780d9e1249f8595c5d1ba39a529fc0c0e9893.tar.gz
netpbm-mirror-b2f780d9e1249f8595c5d1ba39a529fc0c0e9893.tar.xz
netpbm-mirror-b2f780d9e1249f8595c5d1ba39a529fc0c0e9893.zip
Fix -missing, -firstisdefault
git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@914 9d0c8265-081b-0410-96cb-a4ca84ce46f8
Diffstat (limited to 'editor/pnmremap.c')
-rw-r--r--editor/pnmremap.c167
1 files changed, 111 insertions, 56 deletions
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);