blind-set-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-set-luma.c (3592B)
---
1 /* See LICENSE file for copyright and license details. */
2 #ifndef TYPE
3 #include "common.h"
4
5 USAGE("luma-stream")
6
7 #define FILE "blind-set-luma.c"
8 #include "define-functions.h"
9
10 int
11 main(int argc, char *argv[])
12 {
13 struct stream colour, luma;
14 void (*process)(struct stream *colour, struct stream *luma, size_t n);
15
16 UNOFLAGS(argc != 1);
17
18 eopen_stream(&colour, NULL);
19 eopen_stream(&luma, argv[0]);
20
21 SELECT_PROCESS_FUNCTION(&colour);
22 CHECK_CHANS(&colour, == 3, == 1);
23 CHECK_COLOUR_SPACE(&colour, CIEXYZ);
24
25 fprint_stream_head(stdout, &colour);
26 efflush(stdout, "<stdout>");
27 process_two_streams(&colour, &luma, STDOUT_FILENO, "<stdout>", process);
28 return 0;
29 }
30
31 #else
32
33 static void
34 PROCESS(struct stream *colour, struct stream *luma, size_t n)
35 {\
36 size_t i;
37 TYPE a, y;
38 for (i = 0; i < n; i += colour->pixel_size) {
39 a = ((TYPE *)(luma->buf + i))[1];
40 a *= ((TYPE *)(luma->buf + i))[3];
41 y = ((TYPE *)(colour->buf + i))[1];
42 ((TYPE *)(colour->buf + i))[0] += y * a - y;
43 ((TYPE *)(colour->buf + i))[1] = y * a;
44 ((TYPE *)(colour->buf + i))[2] += y * a - y;
45 /*
46 * Note, this changes the luma only, not the saturation,
47 * so the result may look a bit weird. To change both
48 * you can use `blind-arithm mul`.
49 *
50 * Explaination of algorithm:
51 *
52 * Y is the luma, but (X, Z) is not the chroma,
53 * but in CIELAB, L* is the luma and (a*, *b) is
54 * the chroma. Multiplying
55 *
56 * ⎛0 1 0⎞
57 * ⎜1 −1 0⎟
58 * ⎝0 1 −1⎠
59 *
60 * (X Y Z)' gives a colour model similar to
61 * CIE L*a*b*: a model where each parameter is
62 * a linear transformation of the corresponding
63 * parameter in CIE L*a*b*. The inverse of that
64 * matrix is
65 *
66 * ⎛1 1 0⎞
67 * ⎜1 0 0⎟
68 * ⎝0 0 −1⎠
69 *
70 * and
71 *
72 * ⎛1 1 0⎞⎛a 0 0⎞⎛0 1 0⎞ ⎛1 a−1 0⎞
73 * ⎜1 0 0⎟⎜0 1 0⎟⎜1 −1 0⎟ = ⎜0 a 0⎟.
74 * ⎝0 0 −1⎠⎝0 0 1⎠⎝0 1 −1⎠ ⎝0 a−1 1⎠
75 *
76 * Explanation of why changing only the luma looks weird:
77 *
78 * Consider when you are workings with colours,
79 * when you want to change the brightness of a
80 * colour, you multiply all parameters: red, green,
81 * and blue, with the same value (this is however
82 * only an approximation in most cases, since you
83 * are usually usally working with colours that
84 * have the sRGB transfer function applied to their
85 * parameters). This action is the same in all
86 * colour models and colour spaces that are a
87 * linear transformation of the sRGB colour spaces
88 * (sans transfer function); this is simply because
89 * of the properties of linear transformations.
90 *
91 * The reason you change brightness this way can
92 * be explained by how objects reflect colour.
93 * Objects can only reject colours that are present
94 * in the light source. A ideal white object will look
95 * pure red if the light sources is ideal red, and a
96 * a ideal blue object will pure black in the same
97 * light source. An object can also not reflect
98 * colours brighter than the source. When the brightness
99 * of a light source is changed, the intensity of all
100 * colours (by wavelength) it emits is multiplied by
101 * one value. Therefore, when changing the brightness
102 * it looks most natural when all primaries (red, green,
103 * and blue) are multiplied by one value, or all
104 * parameters of the used colour spaces is a linear
105 * transformation of sRGB, such as CIE XYZ.
106 */
107 }
108 }
109
110 #endif