blind-invert-luma.c (3065B)
1 /* See LICENSE file for copyright and license details. */ 2 #include "common.h" 3 4 USAGE("[-iw] mask-stream") 5 6 #define PROCESS(TYPE, INV)\ 7 do {\ 8 size_t i;\ 9 TYPE w, y, yo;\ 10 for (i = 0; i < n; i += colour->pixel_size) {\ 11 w = INV ((TYPE *)(mask->buf + i))[1];\ 12 w *= ((TYPE *)(mask->buf + i))[3];\ 13 yo = ((TYPE *)(colour->buf + i))[1];\ 14 y = (1 - yo) * w + yo * (1 - w);\ 15 ((TYPE *)(colour->buf + i))[0] += (y - yo) * (TYPE)D65_XYZ_X;\ 16 ((TYPE *)(colour->buf + i))[1] = y;\ 17 ((TYPE *)(colour->buf + i))[2] += (y - yo) * (TYPE)D65_XYZ_Z;\ 18 /* 19 * Explaination: 20 * Y is the luma and ((X / Xn - Y / Yn), (Z / Zn - Y / Yn)) 21 * is the chroma (according to CIELAB), where (Xn, Yn, Zn) 22 * is the white point. 23 */\ 24 }\ 25 } while (0) 26 27 #define PROCESS_W(TYPE, INV)\ 28 do {\ 29 size_t i;\ 30 TYPE w, y, yo, X, Z;\ 31 for (i = 0; i < n; i += colour->pixel_size) {\ 32 X = ((TYPE *)(mask->buf + i))[0];\ 33 Z = ((TYPE *)(mask->buf + i))[2];\ 34 w = INV ((TYPE *)(mask->buf + i))[1];\ 35 w *= ((TYPE *)(mask->buf + i))[3];\ 36 yo = ((TYPE *)(colour->buf + i))[1];\ 37 y = (1 - yo) * w + yo * (1 - w);\ 38 ((TYPE *)(colour->buf + i))[0] += (y - yo) * X;\ 39 ((TYPE *)(colour->buf + i))[1] = y;\ 40 ((TYPE *)(colour->buf + i))[2] += (y - yo) * Z;\ 41 }\ 42 } while (0) 43 44 static void process_lf (struct stream *colour, struct stream *mask, size_t n) {PROCESS(double,);} 45 static void process_lf_i (struct stream *colour, struct stream *mask, size_t n) {PROCESS(double, 1 -);} 46 static void process_lf_w (struct stream *colour, struct stream *mask, size_t n) {PROCESS_W(double,);} 47 static void process_lf_iw(struct stream *colour, struct stream *mask, size_t n) {PROCESS_W(double, 1 -);} 48 static void process_f (struct stream *colour, struct stream *mask, size_t n) {PROCESS(float,);} 49 static void process_f_i (struct stream *colour, struct stream *mask, size_t n) {PROCESS(float, 1 -);} 50 static void process_f_w (struct stream *colour, struct stream *mask, size_t n) {PROCESS_W(float,);} 51 static void process_f_iw (struct stream *colour, struct stream *mask, size_t n) {PROCESS_W(float, 1 -);} 52 53 int 54 main(int argc, char *argv[]) 55 { 56 int invert = 0, whitepoint = 0; 57 struct stream colour, mask; 58 void (*process)(struct stream *colour, struct stream *mask, size_t n); 59 60 ARGBEGIN { 61 case 'i': 62 invert = 1; 63 break; 64 case 'w': 65 whitepoint = 1; 66 break; 67 default: 68 usage(); 69 } ARGEND; 70 71 if (argc != 1) 72 usage(); 73 74 eopen_stream(&colour, NULL); 75 eopen_stream(&mask, argv[0]); 76 77 CHECK_ALPHA(&colour); 78 CHECK_COLOUR_SPACE(&colour, CIEXYZ); 79 if (colour.encoding == DOUBLE) 80 process = invert ? whitepoint ? process_lf_iw : process_lf_i 81 : whitepoint ? process_lf_w : process_lf; 82 else if (colour.encoding == FLOAT) 83 process = invert ? whitepoint ? process_f_iw : process_f_i 84 : whitepoint ? process_f_w : process_f; 85 else 86 eprintf("pixel format %s is not supported, try xyza\n", colour.pixfmt); 87 88 fprint_stream_head(stdout, &colour); 89 efflush(stdout, "<stdout>"); 90 process_two_streams(&colour, &mask, STDOUT_FILENO, "<stdout>", process); 91 return 0; 92 }