3 * COPYRIGHT: Written by John Cunningham Bowler, 2013.
4 * To the extent possible under law, the author has waived all copyright and
5 * related or neighboring rights to this work. This work is published from:
8 * Convert 8-bit sRGB or 16-bit linear values to another format.
11 #define _ISOC99_SOURCE 1
23 usage(const char *prog)
26 "%s: usage: %s [-linear|-sRGB] [-gray|-color] component{1,4}\n",
32 component(const char *prog, const char *arg, int issRGB)
35 unsigned long c = strtoul(arg, &ep, 0);
37 if (ep <= arg || *ep || c > 65535 || (issRGB && c > 255))
39 fprintf(stderr, "%s: %s: invalid component value (%lu)\n", prog, arg, c);
47 main(int argc, const char **argv)
49 const char *prog = *argv++;
50 int to_linear = 0, to_gray = 0, to_color = 0;
54 /* FE_TONEAREST is the IEEE754 round to nearest, preferring even, mode; i.e.
55 * everything rounds to the nearest value except that '.5' rounds to the
58 fesetround(FE_TONEAREST);
60 c[3] = c[2] = c[1] = c[0] = 0;
62 while (--argc > 0 && **argv == '-')
64 const char *arg = 1+*argv++;
66 if (strcmp(arg, "sRGB") == 0)
69 else if (strcmp(arg, "linear") == 0)
72 else if (strcmp(arg, "gray") == 0)
73 to_gray = 1, to_color = 0;
75 else if (strcmp(arg, "color") == 0)
76 to_gray = 0, to_color = 1;
89 c[3] = component(prog, argv[3], to_linear);
92 c[2] = component(prog, argv[2], to_linear);
95 c[1] = component(prog, argv[1], to_linear);
98 c[0] = component(prog, argv[0], to_linear);
106 int components = channels;
108 if ((components & 1) == 0)
111 for (i=0; i<components; ++i) c[i] = linear_from_sRGB(c[i] / 255);
112 if (components < channels)
113 c[components] = c[components] / 255;
119 for (i=0; i<4; ++i) c[i] /= 65535;
121 if ((channels & 1) == 0)
123 double alpha = c[channels-1];
126 for (i=0; i<channels-1; ++i) c[i] /= alpha;
128 for (i=0; i<channels-1; ++i) c[i] = 1;
136 fprintf(stderr, "%s: too few channels (%d) for -gray\n",
141 c[0] = YfromRGB(c[0], c[1], c[2]);
149 fprintf(stderr, "%s: too many channels (%d) for -color\n",
154 c[3] = c[1]; /* alpha, if present */
161 if ((channels & 1) == 0)
163 double alpha = c[channels-1];
164 for (i=0; i<channels-1; ++i) c[i] *= alpha;
167 for (i=0; i<channels; ++i) c[i] = nearbyint(c[i] * 65535);
172 int i = (channels+1)&~1;
174 c[i] = sRGB_from_linear(c[i]);
176 for (i=0; i<channels; ++i) c[i] = nearbyint(c[i] * 255);
181 for (i=0; i<channels; ++i) printf(" %g", c[i]);