summaryrefslogtreecommitdiff
path: root/src/pnmcurve.c
diff options
context:
space:
mode:
authorJohannes Hofmann <Johannes.Hofmann@gmx.de>2008-01-15 17:33:47 +0100
committerJohannes Hofmann <Johannes.Hofmann@gmx.de>2008-01-15 17:33:47 +0100
commit3d0a45e0177b85efba5936f020e984224d04234d (patch)
tree5d5b09ed5c5bbf283955b77c0a534fef87355921 /src/pnmcurve.c
parentbe1fb05e4c4aab33045ab8d777c8980d418d97cc (diff)
remove flcurve; remove lcms dependency
Diffstat (limited to 'src/pnmcurve.c')
-rw-r--r--src/pnmcurve.c168
1 files changed, 168 insertions, 0 deletions
diff --git a/src/pnmcurve.c b/src/pnmcurve.c
new file mode 100644
index 0000000..e170f36
--- /dev/null
+++ b/src/pnmcurve.c
@@ -0,0 +1,168 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <math.h>
+
+#include <gsl/gsl_spline.h>
+
+#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;
+}