blind-chroma-key.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-chroma-key.c (2289B)
---
1 /* See LICENSE file for copyright and license details. */
2 #ifndef TYPE
3 #include "common.h"
4
5 USAGE("key-stream")
6
7 #define FILE "blind-chroma-key.c"
8 #include "define-functions.h"
9
10 int
11 main(int argc, char *argv[])
12 {
13 struct stream stream, key;
14 void (*process)(struct stream *stream, struct stream *key);
15
16 UNOFLAGS(argc != 1);
17
18 eopen_stream(&stream, NULL);
19 eopen_stream(&key, argv[0]);
20
21 SELECT_PROCESS_FUNCTION(&stream);
22 CHECK_ALPHA_CHAN(&stream);
23 CHECK_N_CHAN(&stream, 4, 4);
24 if (strcmp(stream.pixfmt, key.pixfmt))
25 eprintf("videos use incompatible pixel formats\n");
26
27 if (key.width > 2 || key.height > 2 || key.width * key.height != 2)
28 eprintf("%s: each frame must contain exactly 2 pixels\n", key.file);
29
30 fprint_stream_head(stdout, &stream);
31 efflush(stdout, "<stdout>");
32 process(&stream, &key);
33 return 0;
34 }
35
36 #else
37
38 static void
39 PROCESS(struct stream *stream, struct stream *key)
40 {
41 size_t i, n, m = 0;
42 TYPE x1, y1, z1, a1, a2, variance2, *keyxyza;
43 TYPE x, y, z, d;
44 do {
45 if (!m) {
46 m = stream->frame_size;
47 while (key->ptr < key->frame_size)
48 if (!eread_stream(key, key->frame_size - key->ptr))
49 return;
50 keyxyza = (TYPE *)(key->buf);
51 x1 = keyxyza[0];
52 y1 = keyxyza[1];
53 z1 = keyxyza[2];
54 a1 = keyxyza[3];
55 x = x1 - keyxyza[4];
56 y = y1 - keyxyza[5];
57 z = z1 - keyxyza[6];
58 a2 = keyxyza[7];
59 variance2 = x * x + y * y + z * z;
60 /* TODO add more formulae: https://en.wikipedia.org/wiki/Color_difference */
61 if (a2 > a1) {
62 a1 = 1 - a1;
63 a2 = 1 - a2;
64 }
65 memmove(key->buf, key->buf + key->frame_size,
66 key->ptr -= key->frame_size);
67 }
68 n = MIN(stream->ptr, m) / stream->pixel_size;
69 for (i = 0; i < n; i++) {
70 x = ((TYPE *)(stream->buf))[4 * i + 0] - x1;
71 y = ((TYPE *)(stream->buf))[4 * i + 1] - y1;
72 z = ((TYPE *)(stream->buf))[4 * i + 2] - z1;
73 d = x * x + y * y + z * z;
74 if (d <= variance2) {
75 if (a1 == a2)
76 d = 0;
77 else
78 d = sqrt(d / variance2) * (a1 - a2) + a2;
79 ((TYPE *)(stream->buf))[4 * i + 3] *= d;
80 }
81 }
82 n *= stream->pixel_size;
83 m -= n;
84 ewriteall(STDOUT_FILENO, stream->buf, n, "<stdout>");
85 memmove(stream->buf, stream->buf + n, stream->ptr -= n);
86 } while (eread_stream(stream, SIZE_MAX));
87 if (stream->ptr)
88 eprintf("%s: incomplete frame\n", stream->file);
89 }
90
91 #endif