about summary refs log tree commit diff
diff options
context:
space:
mode:
authorgiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2018-05-12 20:00:11 +0000
committergiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2018-05-12 20:00:11 +0000
commit40a120115a9201d590d90d7a62f31dbcb006bdb0 (patch)
tree7dbc86bb2229397cab75e66bc3daa090ff87ca17
parent522a4d03e91ba0e45dd9246ee5cc657b28d51803 (diff)
downloadnetpbm-mirror-40a120115a9201d590d90d7a62f31dbcb006bdb0.tar.gz
netpbm-mirror-40a120115a9201d590d90d7a62f31dbcb006bdb0.tar.xz
netpbm-mirror-40a120115a9201d590d90d7a62f31dbcb006bdb0.zip
Add pnm_colorspec_*, pnm_parsecolor2, pnm_allocpamtuplen, pnm_freepamtuplen. Make normalized tuple functions respect pam.allocation_depth
git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@3250 9d0c8265-081b-0410-96cb-a4ca84ce46f8
-rw-r--r--doc/HISTORY15
-rw-r--r--lib/libpamcolor.c257
-rw-r--r--lib/libpamn.c42
-rw-r--r--lib/libppmcolor.c8
-rw-r--r--lib/pam.h28
5 files changed, 344 insertions, 6 deletions
diff --git a/doc/HISTORY b/doc/HISTORY
index e5ced971..4ef73227 100644
--- a/doc/HISTORY
+++ b/doc/HISTORY
@@ -8,6 +8,21 @@ not yet  BJH  Release 10.83.00
 
               Add pamlevels.  Thanks Anton Shepelev <anton.txt@gmail.com>.
 
+              Add rgb-<maxval>:r/g/b color specification format.
+
+              libnetpbm: Add pnm_colorspec_rgb_integer,
+              pnm_colorspec_rgb_norm, pnm_colorspec_rgb_x11,
+              pnm_colorspec_dict, pnm_colorspec_dict_close.
+
+              libnetpbm: Add pnm_parsecolor2.
+
+              libnetpbm: Add pnm_allocpamtuplen, pnm_freepamtuplen.
+              
+              libnetpbm: Make the normalized tuple functions respect the
+              allocation depth specified in struct pam (member
+              'allocation_depth') instead of using the actual tuple depth
+              (member 'depth').
+
               ilbmtoppm: Fix bug: may fail with bogus error message about an
               invalid CLUT chunk if image has a CLUT chunk.  Introduced after
               Netpbm 10.26 (January 2005) and at or before Netpbm 10.35
diff --git a/lib/libpamcolor.c b/lib/libpamcolor.c
index 3cef5e2d..b6a09d26 100644
--- a/lib/libpamcolor.c
+++ b/lib/libpamcolor.c
@@ -424,6 +424,263 @@ pnm_colorname(struct pam * const pamP,
 
 
 
+static tuple
+scaledRgb(struct pam * const pamP,
+          tuple        const color,
+          sample       const maxval) {
+
+    tuple scaledColor;
+
+    struct pam pam;
+
+    pam.size             = sizeof(pam);
+    pam.len              = PAM_STRUCT_SIZE(allocation_depth);
+    pam.maxval           = pamP->maxval;
+    pam.depth            = pamP->depth;
+    pam.allocation_depth = 3;
+
+    scaledColor = pnm_allocpamtuple(&pam);
+
+    pnm_scaletuple(&pam, scaledColor, color, maxval);
+
+    pnm_maketuplergb(&pam, scaledColor);
+
+    return scaledColor;
+}
+
+
+
+const char *
+pnm_colorspec_rgb_integer(struct pam * const pamP,
+                          tuple        const color,
+                          sample       const maxval) {
+
+    const char * retval;
+
+    tuple scaledColor = scaledRgb(pamP, color, maxval);
+
+    pm_asprintf(&retval, "rgb-%lu:%lu/%lu/%lu",
+                maxval,
+                scaledColor[PAM_RED_PLANE],
+                scaledColor[PAM_GRN_PLANE],
+                scaledColor[PAM_BLU_PLANE]
+        );
+
+    pnm_freepamtuple(scaledColor);
+
+    return retval;
+}
+
+
+
+const char *
+pnm_colorspec_rgb_norm(struct pam * const pamP,
+                       tuple        const color,
+                       unsigned int const digitCt) {
+
+    const char * retval;
+
+    tuple rgbColor;
+
+    tuplen normColor;
+
+    struct pam rgbPam;
+
+    rgbPam.size             = sizeof(rgbPam);
+    rgbPam.len              = PAM_STRUCT_SIZE(allocation_depth);
+    rgbPam.maxval           = pamP->maxval;
+    rgbPam.depth            = pamP->depth;
+    rgbPam.allocation_depth = 3;
+
+    rgbColor = pnm_allocpamtuple(&rgbPam);
+
+    pnm_assigntuple(&rgbPam, rgbColor, color);  /* initial value */
+
+    pnm_maketuplergb(&rgbPam, rgbColor);
+
+    normColor = pnm_allocpamtuplen(&rgbPam);
+
+    rgbPam.depth = 3;
+
+    pnm_normalizetuple(&rgbPam, rgbColor, normColor);
+
+    {
+        const char * format;
+        pm_asprintf(&format, "rgbi:%%.%uf/%%.%uf/%%.%uf",
+                    digitCt, digitCt, digitCt);
+
+        pm_asprintf(&retval, format,
+                    normColor[PAM_RED_PLANE],
+                    normColor[PAM_GRN_PLANE],
+                    normColor[PAM_BLU_PLANE]
+            );
+    }
+
+    pnm_freepamtuplen(normColor);
+    pnm_freepamtuple(rgbColor);
+
+    return retval;
+}
+
+
+
+const char *
+pnm_colorspec_rgb_x11(struct pam * const pamP,
+                      tuple        const color,
+                      unsigned int const hexDigitCt) {
+
+    const char * retval;
+
+    sample maxval;
+    const char * format;
+
+    switch(hexDigitCt) {
+    case 1:
+        maxval =    15;
+        format = "rgb:%01x:%01x:%01x";
+        break;
+    case 2:
+        maxval =   255;
+        format = "rgb:%02x:%02x:%02x";
+        break;
+    case 3:
+        maxval =  4095;
+        format = "rgb:%03x:%03x:%03x";
+        break;
+    case 4:
+        maxval = 65535;
+        format = "rgb:%04x:%04x:%04x";
+        break;
+    default:
+        pm_error("Invalid number of hex digits "
+                 "for X11 color specification: %u.  "
+                 "Must be 1, 2, 3, or 4", hexDigitCt);
+    }
+
+    {
+        tuple const scaledColor = scaledRgb(pamP, color, maxval);
+
+        pm_asprintf(&retval, format,
+                    scaledColor[PAM_RED_PLANE],
+                    scaledColor[PAM_GRN_PLANE],
+                    scaledColor[PAM_BLU_PLANE]
+            );
+
+        pnm_freepamtuple(scaledColor);
+    }
+    return retval;
+}
+
+
+
+const char *
+pnm_colorspec_dict(struct pam * const pamP,
+                   tuple        const color) {
+/*----------------------------------------------------------------------------
+   Return the name from the color dictionary of color 'color'.
+
+   Return it in newly allocated pm_strdrup storage.
+
+   If the color is not in the dictionary, or the dictionary doesn't even
+   exist (file not found in any of the possible places), return NULL.
+
+   The color dictionary uses maxval 255, so we match to that precision.
+   E.g. if a component of 'color' is 1000 out of maxval 65535 (which would be
+   3.9 out of maxval 255), we consider it a match to a component value of 4
+   in the color dictionary.
+-----------------------------------------------------------------------------*/
+    tuple scaledColor = scaledRgb(pamP, color, PAM_COLORFILE_MAXVAL);
+
+    FILE * dictFileP;
+    const char * colorname;
+
+    dictFileP = pm_openColornameFile(NULL, false);
+
+    if (dictFileP) {
+        bool eof;
+        for (colorname = NULL, eof = false; !colorname && !eof; ) {
+            struct colorfile_entry const ce = pm_colorget(dictFileP);
+
+            if (ce.colorname)  {
+                if (scaledColor[PAM_RED_PLANE] == (sample)ce.r &&
+                    scaledColor[PAM_GRN_PLANE] == (sample)ce.g &&
+                    scaledColor[PAM_BLU_PLANE] == (sample)ce.b) {
+                    colorname = pm_strdup(ce.colorname);
+                }
+            } else
+                eof = TRUE;
+        }
+
+        fclose(dictFileP);
+    } else
+        colorname = NULL;
+
+    pnm_freepamtuple(scaledColor);
+
+    return colorname;
+}
+
+
+
+const char *
+pnm_colorspec_dict_close(struct pam * const pamP,
+                         tuple        const color) {
+/*----------------------------------------------------------------------------
+   Return the name from the color dictionary of the color closst to 'color'.
+
+   Return it in newly allocated pm_strdrup storage.
+
+   If the color dictionary is empty, or the dictionary doesn't even exist
+   (file not found in any of the possible places), return a null string.
+   This is the only case in which we would return a null string, as the
+   color dictionary cannot define a null string color name.
+-----------------------------------------------------------------------------*/
+    tuple scaledColor = scaledRgb(pamP, color, PAM_COLORFILE_MAXVAL);
+
+    FILE * dictFileP;
+    static char colorname[200];
+
+    dictFileP = pm_openColornameFile(NULL, false);
+
+    if (dictFileP) {
+        unsigned int bestDiff;
+        bool eof;
+
+        for (bestDiff = 32767, eof = FALSE; !eof && bestDiff > 0; ) {
+            struct colorfile_entry const ce = pm_colorget(dictFileP);
+
+            if (ce.colorname)  {
+                unsigned int const thisDiff =
+                    abs((int)scaledColor[PAM_RED_PLANE] - (int)ce.r) +
+                    abs((int)scaledColor[PAM_GRN_PLANE] - (int)ce.g) +
+                    abs((int)scaledColor[PAM_BLU_PLANE] - (int)ce.b);
+
+                if (thisDiff < bestDiff) {
+                    bestDiff = thisDiff;
+                    STRSCPY(colorname, ce.colorname);
+                }
+            } else
+                eof = TRUE;
+        }
+
+        fclose(dictFileP);
+
+        if (bestDiff == 32767) {
+            /* Color file contain no entries, so we can't even pick a close
+               one
+            */
+            STRSCPY(colorname, "");
+        }
+    } else
+        STRSCPY(colorname, "");
+
+    pnm_freepamtuple(scaledColor);
+
+    return pm_strdup(colorname);
+}
+
+
+
 double pnm_lumin_factor[3] = {PPM_LUMINR, PPM_LUMING, PPM_LUMINB};
 
 void
diff --git a/lib/libpamn.c b/lib/libpamn.c
index ce844c7f..65c8979f 100644
--- a/lib/libpamn.c
+++ b/lib/libpamn.c
@@ -23,6 +23,43 @@
 
 
 
+static unsigned int
+allocationDepth(const struct pam * const pamP) {
+
+    unsigned int retval;
+
+    if (pamP->len >= PAM_STRUCT_SIZE(allocation_depth)) {
+        if (pamP->allocation_depth == 0)
+            retval = pamP->depth;
+        else {
+            if (pamP->depth > pamP->allocation_depth)
+                pm_error("'allocationDepth' (%u) is smaller than 'depth' (%u)",
+                         pamP->allocation_depth, pamP->depth);
+            retval = pamP->allocation_depth;
+        }
+    } else
+        retval = pamP->depth;
+    return retval;
+}
+
+
+
+tuplen
+pnm_allocpamtuplen(const struct pam * const pamP) {
+
+    tuplen retval;
+
+    retval = malloc(allocationDepth(pamP) * sizeof(retval[0]));
+
+    if (retval == NULL)
+        pm_error("Out of memory allocating %u-plane normalized tuple",
+                 allocationDepth(pamP));
+
+    return retval;
+}
+
+
+
 static void
 allocpamrown(const struct pam * const pamP,
              tuplen **          const tuplerownP,
@@ -32,7 +69,7 @@ allocpamrown(const struct pam * const pamP,
    overflow will not occur in our calculations.  NOTE: pnm_readpaminit()
    ensures this assumption is valid.
 -----------------------------------------------------------------------------*/
-    int const bytes_per_tuple = pamP->depth * sizeof(samplen);
+    int const bytes_per_tuple = allocationDepth(pamP) * sizeof(samplen);
 
     tuplen * tuplerown;
     const char * error;
@@ -47,7 +84,8 @@ allocpamrown(const struct pam * const pamP,
         pm_asprintf(&error, "Out of memory allocating space for a tuple row of"
                     "%u tuples by %u samples per tuple "
                     "by %u bytes per sample.",
-                    pamP->width, pamP->depth, (unsigned)sizeof(samplen));
+                    pamP->width, allocationDepth(pamP),
+                    (unsigned)sizeof(samplen));
     else {
         /* Now we initialize the pointers to the individual tuples to make this
            a regulation C two dimensional array.
diff --git a/lib/libppmcolor.c b/lib/libppmcolor.c
index df9e5295..27340d5f 100644
--- a/lib/libppmcolor.c
+++ b/lib/libppmcolor.c
@@ -78,7 +78,7 @@ ppm_colorname(const pixel * const colorP,
     f = pm_openColornameFile(NULL, !hexok);
 
     if (!f)
-        strcpy(colorname, "");
+        STRSCPY(colorname, "");
     else {
         int bestDiff;
         bool eof;
@@ -94,7 +94,7 @@ ppm_colorname(const pixel * const colorP,
 
                 if (thisDiff < bestDiff) {
                     bestDiff = thisDiff;
-                    strcpy(colorname, ce.colorname);
+                    STRSCPY(colorname, ce.colorname);
                 }
             } else
                 eof = TRUE;
@@ -105,12 +105,12 @@ ppm_colorname(const pixel * const colorP,
             /* Color file contain no entries, so we can't even pick a close
                one
             */
-            strcpy(colorname, "");
+            STRSCPY(colorname, "");
         } else if (bestDiff > 0 && hexok) {
             /* We didn't find an exact match and user is willing to accept
                hex, so we don't have to use an approximate match.
             */
-            strcpy(colorname, "");
+            STRSCPY(colorname, "");
         }
     }
 
diff --git a/lib/pam.h b/lib/pam.h
index 9f999e93..c2cfb4c7 100644
--- a/lib/pam.h
+++ b/lib/pam.h
@@ -401,6 +401,11 @@ typedef float samplen;
 typedef samplen *tuplen;
     /* Same as 'tuple', except using normalized samples. */
 
+tuplen
+pnm_allocpamtuplen(const struct pam * const pamP);
+
+#define pnm_freepamtuplen(tuplen) pm_freerow((char*) tuplen)
+
 tuplen *
 pnm_allocpamrown(const struct pam * const pamP);
 
@@ -506,6 +511,29 @@ pnm_colorname(struct pam * const pamP,
               tuple        const color,
               int          const hexok);
 
+const char *
+pnm_colorspec_rgb_integer(struct pam * const pamP,
+                          tuple        const color,
+                          sample       const maxval);
+
+const char *
+pnm_colorspec_rgb_norm(struct pam * const pamP,
+                       tuple        const color,
+                       unsigned int const digitCt);
+
+const char *
+pnm_colorspec_rgb_x11(struct pam * const pamP,
+                      tuple        const color,
+                      unsigned int const hexDigitCt);
+
+const char *
+pnm_colorspec_dict(struct pam * const pamP,
+                   tuple        const color);
+
+const char *
+pnm_colorspec_dict_close(struct pam * const pamP,
+                         tuple        const color);
+
 extern double
 pnm_lumin_factor[3];