#include #include #include #include #include #include "pnm.h" typedef struct { int n; short value[1]; } table_t; static int pam_transform(FILE *in_fp, FILE *out_fp, const struct pnm *in_pnm, table_t **tables); static table_t* buildCurve(const char *ctrl_points, int resolution); #define RED 0x1 #define GREEN 0x2 #define BLUE 0x4 int main(int argc, char **argv) { int c, i; char *curve = NULL; struct pnm in_pnm; int channels = 0; table_t *gTable[3]; while ((c = getopt(argc, argv, "rgbC:h")) != EOF) { switch (c) { case 'r': channels |= RED; break; case 'g': channels |= GREEN; break; case 'b': channels |= BLUE; break; case 'C': curve = optarg; break; default: break; } } if (readPnmHeader(stdin, &in_pnm) != 0) { exit(1); } if (in_pnm.maxval == 255) { } else if (in_pnm.maxval == 65535) { } else { fprintf(stderr, "unsupported PNM maxval %d\n", in_pnm.maxval); exit(1); } if (curve) { table_t *table; if (channels == 0) channels = RED | GREEN | BLUE; table = buildCurve(curve, 256); gTable[0] = channels & RED?table:NULL; gTable[1] = channels & GREEN?table:NULL; gTable[2] = channels & BLUE?table:NULL; } writePnmHeader(stdout, &in_pnm); pam_transform(stdin, stdout, &in_pnm, gTable); return 0; } static int pam_transform(FILE *in_fp, FILE *out_fp, const struct pnm *in_pnm, table_t **tables) { int row, col; int nbytes = in_pnm->maxval == 65535?2:1; char *buf = malloc(in_pnm->width * nbytes * 3); for (row = 0; row < in_pnm->height; row++) { fread(buf, in_pnm->width, nbytes * 3, in_fp); for (i = 0; i < in_pnm->width; i++) { for (c = 0; c < in_pnm->depth; c++) { if (tables[c]) { int val = (unsigned char) buf[(i * in_pnm->depth + c) * nbytes]; if (nbytes == 2) { val = (val << 8) | (uchar) buf[(i * in_pnm->depth + c) * nbytes + 1]; } bud } } } fwrite(buf, in_pnm->width, nbytes * 3, out_fp); } free(buf); return 0; } #define MAX_CTRL 256 static table_t* buildCurve(const char *ctrl_points, int resolution) { table_t *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 = (table_t*) malloc(sizeof(table_t) + resolution * sizeof(short)); table->n = 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->value[i] = (short) floor(dval); } gsl_spline_free(spline); gsl_interp_accel_free(acc); return table; }