diff options
author | giraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8> | 2017-06-28 22:04:00 +0000 |
---|---|---|
committer | giraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8> | 2017-06-28 22:04:00 +0000 |
commit | 04f0382f7f28e6456f23b150b60ce2b9fe7f0d98 (patch) | |
tree | 89241e451eef86014bc524db0a8630b3c033d5c8 /lib/libpamcolor.c | |
parent | 6f62629842614ba3cd807d9eaad722a7d7653969 (diff) | |
download | netpbm-mirror-04f0382f7f28e6456f23b150b60ce2b9fe7f0d98.tar.gz netpbm-mirror-04f0382f7f28e6456f23b150b60ce2b9fe7f0d98.tar.xz netpbm-mirror-04f0382f7f28e6456f23b150b60ce2b9fe7f0d98.zip |
Add pnm_parsecolorn
git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@3007 9d0c8265-081b-0410-96cb-a4ca84ce46f8
Diffstat (limited to 'lib/libpamcolor.c')
-rw-r--r-- | lib/libpamcolor.c | 281 |
1 files changed, 274 insertions, 7 deletions
diff --git a/lib/libpamcolor.c b/lib/libpamcolor.c index 06dd2493..120a82cf 100644 --- a/lib/libpamcolor.c +++ b/lib/libpamcolor.c @@ -22,9 +22,274 @@ #include <limits.h> #include "netpbm/pm_c_util.h" +#include "netpbm/mallocvar.h" +#include "netpbm/nstring.h" +#include "netpbm/colorname.h" + +#include "netpbm/pam.h" +#include "netpbm/ppm.h" + + + +static void +computeHexTable(int * const hexit) { + + unsigned int i; + + for (i = 0; i < 256; ++i) + hexit[i] = -1; + + hexit['0'] = 0; + hexit['1'] = 1; + hexit['2'] = 2; + hexit['3'] = 3; + hexit['4'] = 4; + hexit['5'] = 5; + hexit['6'] = 6; + hexit['7'] = 7; + hexit['8'] = 8; + hexit['9'] = 9; + hexit['a'] = hexit['A'] = 10; + hexit['b'] = hexit['B'] = 11; + hexit['c'] = hexit['C'] = 12; + hexit['d'] = hexit['D'] = 13; + hexit['e'] = hexit['E'] = 14; + hexit['f'] = hexit['F'] = 15; +} + + + +static void +parseHexDigits(const char * const string, + char const delim, + const int * const hexit, + samplen * const nP, + unsigned int * const digitCtP) { + + unsigned int digitCt; + unsigned long n; + unsigned long maxval; + + for (digitCt = 0, n = 0, maxval = 1; string[digitCt] != delim; ) { + char const digit = string[digitCt]; + if (digit == '\0') + pm_error("rgb: color spec ends prematurely"); + else { + int const hexval = hexit[(unsigned int)digit]; + if (hexval == -1) + pm_error("Invalid hex digit in rgb: color spec: 0x%02x", + digit); + n = n * 16 + hexval; + maxval *= 16; + ++digitCt; + } + } + *nP = (samplen) n / maxval; + *digitCtP = digitCt; +} + + + +static void +parseNewHexX11(char const colorname[], + tuplen const color) { +/*---------------------------------------------------------------------------- + Determine what color colorname[] specifies in the new style hex + color specification format (e.g. rgb:55/40/55). + + Return that color as *colorP. + + Assume colorname[] starts with "rgb:", but otherwise it might be + gibberish. +-----------------------------------------------------------------------------*/ + int hexit[256]; + + const char * cp; + unsigned int digitCt; + + computeHexTable(hexit); + + cp = &colorname[4]; + + parseHexDigits(cp, '/', hexit, &color[PAM_RED_PLANE], &digitCt); + + cp += digitCt; + ++cp; /* Skip the slash */ + + parseHexDigits(cp, '/', hexit, &color[PAM_GRN_PLANE], &digitCt); + + cp += digitCt; + ++cp; /* Skip the slash */ + + parseHexDigits(cp, '\0', hexit, &color[PAM_BLU_PLANE], &digitCt); +} + + + +static bool +isNormal(samplen const arg) { + + return arg >= 0.0 && arg <= 1.0; +} + + + +static void +parseNewDecX11(const char * const colorname, + tuplen const color) { -#include "pam.h" -#include "ppm.h" + int rc; + + rc = sscanf(colorname, "rgbi:%f/%f/%f", + &color[PAM_RED_PLANE], + &color[PAM_GRN_PLANE], + &color[PAM_BLU_PLANE]); + + if (rc != 3) + pm_error("invalid color specifier '%s'", colorname); + + if (!(isNormal(color[PAM_RED_PLANE]) && + isNormal(color[PAM_GRN_PLANE]) && + isNormal(color[PAM_BLU_PLANE]))) { + pm_error("invalid color specifier '%s' - " + "values must be between 0.0 and 1.0", colorname); + } +} + + + +static void +parseOldX11(const char * const colorname, + tuplen const color) { +/*---------------------------------------------------------------------------- + Return as *colorP the color specified by the old X11 style color + specififier colorname[] (e.g. #554055). +-----------------------------------------------------------------------------*/ + int hexit[256]; + + computeHexTable(hexit); + + if (!pm_strishex(&colorname[1])) + pm_error("Non-hexadecimal characters in #-type color specification"); + + switch (strlen(colorname) - 1 /* (Number of hex digits) */) { + case 3: + color[PAM_RED_PLANE] = (samplen)hexit[(unsigned int)colorname[1]]/15; + color[PAM_GRN_PLANE] = (samplen)hexit[(unsigned int)colorname[2]]/15; + color[PAM_BLU_PLANE] = (samplen)hexit[(unsigned int)colorname[3]]/15; + break; + + case 6: + color[PAM_RED_PLANE] = + ((samplen)(hexit[(unsigned int)colorname[1]] << 4) + + (samplen)(hexit[(unsigned int)colorname[2]] << 0)) + / 255; + color[PAM_GRN_PLANE] = + ((samplen)(hexit[(unsigned int)colorname[3]] << 4) + + (samplen)(hexit[(unsigned int)colorname[4]] << 0)) + / 255; + color[PAM_BLU_PLANE] = + ((samplen)(hexit[(unsigned int)colorname[5]] << 4) + + (samplen)(hexit[(unsigned int)colorname[6]] << 0)) + / 255; + break; + + case 9: + color[PAM_RED_PLANE] = + ((samplen)(hexit[(unsigned int)colorname[1]] << 8) + + (samplen)(hexit[(unsigned int)colorname[2]] << 4) + + (samplen)(hexit[(unsigned int)colorname[3]] << 0)) + / 4095; + color[PAM_GRN_PLANE] = + ((samplen)(hexit[(unsigned int)colorname[4]] << 8) + + (samplen)(hexit[(unsigned int)colorname[5]] << 4) + + (samplen)(hexit[(unsigned int)colorname[6]] << 0)) + / 4095; + color[PAM_BLU_PLANE] = + ((samplen)(hexit[(unsigned int)colorname[7]] << 8) + + (samplen)(hexit[(unsigned int)colorname[8]] << 4) + + (samplen)(hexit[(unsigned int)colorname[9]] << 0)) + / 4095; + break; + + case 12: + color[PAM_RED_PLANE] = + ((samplen)(hexit[(unsigned int)colorname[1]] << 12) + + (samplen)(hexit[(unsigned int)colorname[2]] << 8) + + (samplen)(hexit[(unsigned int)colorname[3]] << 4) + + (samplen)(hexit[(unsigned int)colorname[4]] << 0)) + / 65535; + color[PAM_GRN_PLANE] = + ((samplen)(hexit[(unsigned int)colorname[5]] << 12) + + (samplen)(hexit[(unsigned int)colorname[6]] << 8) + + (samplen)(hexit[(unsigned int)colorname[7]] << 4) + + (samplen)(hexit[(unsigned int)colorname[8]] << 0)) + / 65535; + color[PAM_BLU_PLANE] = + ((samplen)(hexit[(unsigned int)colorname[9]] << 12) + + (samplen)(hexit[(unsigned int)colorname[10]] << 8) + + (samplen)(hexit[(unsigned int)colorname[11]] << 4) + + (samplen)(hexit[(unsigned int)colorname[12]] << 0)) + / 65535; + break; + + default: + pm_error("invalid color specifier '%s'", colorname); + } +} + + + +static void +parseOldX11Dec(const char* const colorname, + tuplen const color) { + + int rc; + + rc = sscanf(colorname, "%f,%f,%f", + &color[PAM_RED_PLANE], + &color[PAM_GRN_PLANE], + &color[PAM_BLU_PLANE]); + + if (rc != 3) + pm_error("invalid color specifier '%s'", colorname); + + if (!(isNormal(color[PAM_RED_PLANE]) && + isNormal(color[PAM_GRN_PLANE]) && + isNormal(color[PAM_BLU_PLANE]))) { + pm_error("invalid color specifier '%s' - " + "values must be between 0.0 and 1.0", colorname); + } +} + + + +tuplen +pnm_parsecolorn(const char * const colorname) { + + tuplen retval; + + MALLOCARRAY_NOFAIL(retval, 3); + + if (strncmp(colorname, "rgb:", 4) == 0) + /* It's a new-X11-style hexadecimal rgb specifier. */ + parseNewHexX11(colorname, retval); + else if (strncmp(colorname, "rgbi:", 5) == 0) + /* It's a new-X11-style decimal/float rgb specifier. */ + parseNewDecX11(colorname, retval); + else if (colorname[0] == '#') + /* It's an old-X11-style hexadecimal rgb specifier. */ + parseOldX11(colorname, retval); + else if ((colorname[0] >= '0' && colorname[0] <= '9') || + colorname[0] == '.') + /* It's an old-style decimal/float rgb specifier. */ + parseOldX11Dec(colorname, retval); + else + /* Must be a name from the X-style rgb file. */ + pm_parse_dictionary_namen(colorname, retval); + + return retval; +} @@ -33,7 +298,7 @@ pnm_parsecolor(const char * const colorname, sample const maxval) { tuple retval; - pixel color; + tuplen color; struct pam pam; pam.len = PAM_STRUCT_SIZE(bytes_per_sample); @@ -43,11 +308,13 @@ pnm_parsecolor(const char * const colorname, retval = pnm_allocpamtuple(&pam); - color = ppm_parsecolor(colorname, maxval); + color = pnm_parsecolorn(colorname); + + retval[PAM_RED_PLANE] = ROUNDU(color[PAM_RED_PLANE] * maxval); + retval[PAM_GRN_PLANE] = ROUNDU(color[PAM_GRN_PLANE] * maxval); + retval[PAM_BLU_PLANE] = ROUNDU(color[PAM_BLU_PLANE] * maxval); - retval[PAM_RED_PLANE] = PPM_GETR(color); - retval[PAM_GRN_PLANE] = PPM_GETG(color); - retval[PAM_BLU_PLANE] = PPM_GETB(color); + free(color); return retval; } |