blind-invert-luma.c - blind - suckless command-line video editing utility
(HTM) git clone git://git.suckless.org/blind
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) README
(DIR) LICENSE
---
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 }