123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188 |
- /*-
- * convert.c
- *
- * Last changed in libpng 1.6.0 [February 14, 2013]
- *
- * COPYRIGHT: Written by John Cunningham Bowler, 2013.
- * To the extent possible under law, the author has waived all copyright and
- * related or neighboring rights to this work. This work is published from:
- * United States.
- *
- * Convert 8-bit sRGB or 16-bit linear values to another format.
- */
- #define _ISOC99_SOURCE 1
- #include <stdlib.h>
- #include <string.h>
- #include <math.h>
- #include <stdio.h>
- #include <fenv.h>
- #include "sRGB.h"
- static void
- usage(const char *prog)
- {
- fprintf(stderr,
- "%s: usage: %s [-linear|-sRGB] [-gray|-color] component{1,4}\n",
- prog, prog);
- exit(1);
- }
- unsigned long
- component(const char *prog, const char *arg, int issRGB)
- {
- char *ep;
- unsigned long c = strtoul(arg, &ep, 0);
- if (ep <= arg || *ep || c > 65535 || (issRGB && c > 255))
- {
- fprintf(stderr, "%s: %s: invalid component value (%lu)\n", prog, arg, c);
- usage(prog);
- }
- return c;
- }
- int
- main(int argc, const char **argv)
- {
- const char *prog = *argv++;
- int to_linear = 0, to_gray = 0, to_color = 0;
- int channels = 0;
- double c[4];
- /* FE_TONEAREST is the IEEE754 round to nearest, preferring even, mode; i.e.
- * everything rounds to the nearest value except that '.5' rounds to the
- * nearest even value.
- */
- fesetround(FE_TONEAREST);
- c[3] = c[2] = c[1] = c[0] = 0;
- while (--argc > 0 && **argv == '-')
- {
- const char *arg = 1+*argv++;
- if (strcmp(arg, "sRGB") == 0)
- to_linear = 0;
- else if (strcmp(arg, "linear") == 0)
- to_linear = 1;
- else if (strcmp(arg, "gray") == 0)
- to_gray = 1, to_color = 0;
- else if (strcmp(arg, "color") == 0)
- to_gray = 0, to_color = 1;
- else
- usage(prog);
- }
- switch (argc)
- {
- default:
- usage(prog);
- break;
- case 4:
- c[3] = component(prog, argv[3], to_linear);
- ++channels;
- case 3:
- c[2] = component(prog, argv[2], to_linear);
- ++channels;
- case 2:
- c[1] = component(prog, argv[1], to_linear);
- ++channels;
- case 1:
- c[0] = component(prog, argv[0], to_linear);
- ++channels;
- break;
- }
- if (to_linear)
- {
- int i;
- int components = channels;
- if ((components & 1) == 0)
- --components;
- for (i=0; i<components; ++i) c[i] = linear_from_sRGB(c[i] / 255);
- if (components < channels)
- c[components] = c[components] / 255;
- }
- else
- {
- int i;
- for (i=0; i<4; ++i) c[i] /= 65535;
- if ((channels & 1) == 0)
- {
- double alpha = c[channels-1];
- if (alpha > 0)
- for (i=0; i<channels-1; ++i) c[i] /= alpha;
- else
- for (i=0; i<channels-1; ++i) c[i] = 1;
- }
- }
- if (to_gray)
- {
- if (channels < 3)
- {
- fprintf(stderr, "%s: too few channels (%d) for -gray\n",
- prog, channels);
- usage(prog);
- }
- c[0] = YfromRGB(c[0], c[1], c[2]);
- channels -= 2;
- }
- if (to_color)
- {
- if (channels > 2)
- {
- fprintf(stderr, "%s: too many channels (%d) for -color\n",
- prog, channels);
- usage(prog);
- }
- c[3] = c[1]; /* alpha, if present */
- c[2] = c[1] = c[0];
- }
- if (to_linear)
- {
- int i;
- if ((channels & 1) == 0)
- {
- double alpha = c[channels-1];
- for (i=0; i<channels-1; ++i) c[i] *= alpha;
- }
- for (i=0; i<channels; ++i) c[i] = nearbyint(c[i] * 65535);
- }
- else /* to sRGB */
- {
- int i = (channels+1)&~1;
- while (--i >= 0)
- c[i] = sRGB_from_linear(c[i]);
- for (i=0; i<channels; ++i) c[i] = nearbyint(c[i] * 255);
- }
- {
- int i;
- for (i=0; i<channels; ++i) printf(" %g", c[i]);
- }
- printf("\n");
- return 0;
- }
|