about summary refs log tree commit diff
path: root/lib/libpamcolor.c
diff options
context:
space:
mode:
authorgiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2018-05-09 20:16:38 +0000
committergiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2018-05-09 20:16:38 +0000
commit7cdc87d40ebefe11322a91afdc3ea68b25965b3e (patch)
tree68c99acf515480246e1ee9fb08a86bb7332468b4 /lib/libpamcolor.c
parent81215f675d2156322f8139c55d43b2b8e2c20077 (diff)
downloadnetpbm-mirror-7cdc87d40ebefe11322a91afdc3ea68b25965b3e.tar.gz
netpbm-mirror-7cdc87d40ebefe11322a91afdc3ea68b25965b3e.tar.xz
netpbm-mirror-7cdc87d40ebefe11322a91afdc3ea68b25965b3e.zip
Add pnm_parsecolor2, make ppm_parsecolor2 use pnm_parsecolor2
git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@3247 9d0c8265-081b-0410-96cb-a4ca84ce46f8
Diffstat (limited to 'lib/libpamcolor.c')
-rw-r--r--lib/libpamcolor.c91
1 files changed, 87 insertions, 4 deletions
diff --git a/lib/libpamcolor.c b/lib/libpamcolor.c
index 95c9e18f..3cef5e2d 100644
--- a/lib/libpamcolor.c
+++ b/lib/libpamcolor.c
@@ -20,6 +20,7 @@
 
 #include <string.h>
 #include <limits.h>
+#include <math.h>
 
 #include "netpbm/pm_c_util.h"
 #include "netpbm/mallocvar.h"
@@ -155,6 +156,50 @@ parseNewDecX11(const char * const colorname,
 
 
 static void
+parseInteger(const char * const colorname,
+             tuplen       const color) {
+
+    unsigned int maxval;
+    unsigned int r, g, b;
+    int rc;
+
+    rc = sscanf(colorname, "rgb-%u:%u/%u/%u", &maxval, &r, &g, &b);
+
+    if (rc != 4)
+        pm_error("invalid color specifier '%s'.  "
+                 "If it starts with \"rgb-\", then it must have the format "
+                 "rgb-<MAXVAL>:<RED>:<GRN>:<BLU>, "
+                 "where <MAXVAL>, <RED>, <GRN>, and <BLU> are "
+                 "unsigned integers",
+                 colorname);
+
+    if (maxval < 1 || maxval > PNM_OVERALLMAXVAL)
+        pm_error("Maxval in color specification '%s' is %u, "
+                 "which is invalid because it is not between "
+                 "1 and %u, inclusive",
+                 colorname, maxval, PNM_OVERALLMAXVAL);
+
+    if (r > maxval)
+        pm_error("Red value in color specification '%s' is %u, "
+                 "whcih is invalid because the specified maxval is %u",
+                 colorname, r, maxval);
+    if (g > maxval)
+        pm_error("Green value in color specification '%s' is %u, "
+                 "whcih is invalid because the specified maxval is %u",
+                 colorname, g, maxval);
+    if (b > maxval)
+        pm_error("Blue value in color specification '%s' is %u, "
+                 "whcih is invalid because the specified maxval is %u",
+                 colorname, b, maxval);
+
+    color[PAM_RED_PLANE] = (float)r/maxval;
+    color[PAM_GRN_PLANE] = (float)g/maxval;
+    color[PAM_BLU_PLANE] = (float)b/maxval;
+}
+
+
+
+static void
 parseOldX11(const char * const colorname,
             tuplen       const color) {
 /*----------------------------------------------------------------------------
@@ -263,12 +308,15 @@ pnm_parsecolorn(const char * const colorname) {
 
     MALLOCARRAY_NOFAIL(retval, 3);
 
-    if (strncmp(colorname, "rgb:", 4) == 0)
+    if (strneq(colorname, "rgb:", 4))
         /* It's a new-X11-style hexadecimal rgb specifier. */
         parseNewHexX11(colorname, retval);
-    else if (strncmp(colorname, "rgbi:", 5) == 0)
+    else if (strneq(colorname, "rgbi:", 5))
         /* It's a new-X11-style decimal/float rgb specifier. */
         parseNewDecX11(colorname, retval);
+    else if (strneq(colorname, "rgb-", 4))
+        /* It's a Netpbm-native decimal integer rgb specifier */
+        parseInteger(colorname, retval);
     else if (colorname[0] == '#')
         /* It's an old-X11-style hexadecimal rgb specifier. */
         parseOldX11(colorname, retval);
@@ -285,9 +333,29 @@ pnm_parsecolorn(const char * const colorname) {
 
 
 
+static void
+warnIfNotExact(const char * const colorname,
+               tuple        const rounded,
+               tuplen       const exact,
+               sample       const maxval,
+               unsigned int const plane) {
+
+    float const epsilon = 1.0/65536.0;
+
+    if (fabs((float)(rounded[plane] / maxval) - exact[plane]) > epsilon) {
+        pm_message("WARNING: Component %u of color '%s' is %f, "
+                   "which cannot be represented precisely with maxval %lu.  "
+                   "Approximating as %lu.",
+                   plane, colorname, exact[plane], maxval, rounded[plane]);
+    }
+}
+
+
+
 tuple
-pnm_parsecolor(const char * const colorname,
-               sample       const maxval) {
+pnm_parsecolor2(const char * const colorname,
+                sample       const maxval,
+                int          const closeOk) {
 
     tuple retval;
     tuplen color;
@@ -306,6 +374,12 @@ pnm_parsecolor(const char * const colorname,
     retval[PAM_GRN_PLANE] = ROUNDU(color[PAM_GRN_PLANE] * maxval);
     retval[PAM_BLU_PLANE] = ROUNDU(color[PAM_BLU_PLANE] * maxval);
 
+    if (!closeOk) {
+        warnIfNotExact(colorname, retval, color, maxval, PAM_RED_PLANE);
+        warnIfNotExact(colorname, retval, color, maxval, PAM_GRN_PLANE);
+        warnIfNotExact(colorname, retval, color, maxval, PAM_BLU_PLANE);
+    }
+
     free(color);
 
     return retval;
@@ -313,6 +387,15 @@ pnm_parsecolor(const char * const colorname,
 
 
 
+tuple
+pnm_parsecolor(const char * const colorname,
+               sample       const maxval) {
+
+    return pnm_parsecolor2(colorname, maxval, true);
+}
+
+
+
 const char *
 pnm_colorname(struct pam * const pamP,
               tuple        const color,