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