diff options
Diffstat (limited to 'src/pnmlcms.c')
| -rw-r--r-- | src/pnmlcms.c | 78 |
1 files changed, 75 insertions, 3 deletions
diff --git a/src/pnmlcms.c b/src/pnmlcms.c index 0a8fdac..800af08 100644 --- a/src/pnmlcms.c +++ b/src/pnmlcms.c @@ -1,4 +1,5 @@ #include <lcms.h> +#include <gsl/gsl_spline.h> #include "pnm.h" @@ -6,10 +7,14 @@ static int pam_transform(FILE *in_fp, FILE *out_fp, const struct pnm *in_pnm, cmsHTRANSFORM *hTransform); +static LPGAMMATABLE +buildGammaCurve(const char *ctrl_points, int resolution); + int main(int argc, char **argv) { int c, i, nProf = 0; char *in_prof = NULL, *out_prof = NULL; + char *curve = NULL; double gamma = 0.0, bright = 0.0, contrast = 1.0, hue = 0.0; double saturation = 0.0; int tempSrc = 5000, tempDst = 5000; @@ -18,7 +23,7 @@ main(int argc, char **argv) { DWORD type; struct pnm in_pnm; - while ((c = getopt(argc, argv, "i:o:g:b:c:h:s:S:D:")) != EOF) { + while ((c = getopt(argc, argv, "i:o:g:b:c:h:s:S:D:C:")) != EOF) { switch (c) { case 'i': in_prof = optarg; @@ -46,18 +51,21 @@ main(int argc, char **argv) { break; case 'D': tempDst = atoi(optarg); + case 'C': + curve = optarg; break; default: break; } } - +#if 0 if (in_prof) { profiles[nProf++] = cmsOpenProfileFromFile(in_prof, "r"); } else { profiles[nProf++] = cmsCreate_sRGBProfile(); } +#endif if (gamma) { LPGAMMATABLE gTable[3]; @@ -70,8 +78,19 @@ main(int argc, char **argv) { gTable); } + if (curve) { + LPGAMMATABLE gTable[3]; + + gTable[0] = gTable[1] = gTable[2] = buildGammaCurve(curve, 256); + + profiles[nProf++] = cmsCreateLinearizationDeviceLink( + icSigLabData, + gTable); + } + +#if 0 profiles[nProf++] = cmsCreateBCHSWabstractProfile( - 10, + 5, bright, contrast, hue, @@ -84,6 +103,7 @@ main(int argc, char **argv) { } else { profiles[nProf++] = cmsCreate_sRGBProfile(); } +#endif if (readPnmHeader(stdin, &in_pnm) != 0) { exit(1); @@ -139,3 +159,55 @@ pam_transform(FILE *in_fp, FILE *out_fp, return 0; } +#define MAX_CTRL 256 + +static LPGAMMATABLE +buildGammaCurve(const char *ctrl_points, int resolution) { + LPGAMMATABLE table; + char *pstr, *buf = strdup(ctrl_points); + int i, n = 0; + double X[MAX_CTRL], Y[MAX_CTRL]; + gsl_interp_accel *acc; + gsl_spline *spline; + + while (pstr = strsep(&buf, ";")) { + if (n == MAX_CTRL) { + fprintf(stderr, "Maximum number of control points (%d) reached.\n", + MAX_CTRL); + break; + } + + if (sscanf(pstr, "%lf,%lf", &X[n], &Y[n]) != 2 || + X[n] < 0.0 || X[n] > 1.0 || Y[n] < 0.0 || Y[n] > 1.0) { + fprintf(stderr, "Could not parse control point %s.\n", pstr); + free(buf); + return NULL; + } + + n++; + } + + free(buf); + + table = (LPGAMMATABLE) calloc(resolution, sizeof(GAMMATABLE)); + table->nEntries = resolution; + + acc = gsl_interp_accel_alloc(); + spline = gsl_spline_alloc(gsl_interp_cspline, n); + gsl_spline_init (spline, X, Y, n); + + for (i = 0; i < resolution; i++) { + double _x = (double) i / (resolution - 1); + double _y = gsl_spline_eval(spline, _x, acc); + double dval = _y * 65535.0 + .5; + if (dval > 65535.) dval = 65535.0; + if (dval < 0) dval = 0; + + table->GammaTable[i] = (WORD) floor(dval); + } + + gsl_spline_free(spline); + gsl_interp_accel_free(acc); + + return table; +} |
