blind-temporal-arithm.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-temporal-arithm.c (2413B)
---
1 /* See LICENSE file for copyright and license details. */
2 #include "common.h"
3
4 USAGE("operation")
5
6 /* Because the syntax for a function returning a function pointer is disgusting. */
7 typedef void (*process_func)(struct stream *stream, void *image);
8
9 #define LIST_OPERATORS(PIXFMT, TYPE)\
10 X(add, *img + *buf, PIXFMT, TYPE)\
11 X(mul, *img * *buf, PIXFMT, TYPE)\
12 X(min, MIN(*img, *buf), PIXFMT, TYPE)\
13 X(max, MAX(*img, *buf), PIXFMT, TYPE)
14
15 #define X(NAME, ALGO, PIXFMT, TYPE)\
16 static void\
17 process_##PIXFMT##_##NAME(struct stream *stream, void *image)\
18 {\
19 TYPE *buf, *img = image;\
20 size_t i, n, j = 0, m = stream->frame_size / sizeof(TYPE);\
21 do {\
22 n = stream->ptr / sizeof(TYPE);\
23 buf = (TYPE *)(stream->buf);\
24 for (i = 0; i < n; i++, buf++) {\
25 *img = ALGO;\
26 if (++j == m) {\
27 j = 0;\
28 img = image;\
29 } else {\
30 img++;\
31 }\
32 }\
33 n *= sizeof(TYPE);\
34 memmove(stream->buf, stream->buf + n, stream->ptr -= n);\
35 } while (eread_stream(stream, SIZE_MAX));\
36 }
37 LIST_OPERATORS(lf, double)
38 LIST_OPERATORS(f, float)
39 #undef X
40
41 static process_func
42 get_process_lf(const char *operation)
43 {
44 #define X(NAME, _ALGO, PIXFMT, TYPE)\
45 if (!strcmp(operation, #NAME)) return process_##PIXFMT##_##NAME;
46 LIST_OPERATORS(lf, double)
47 #undef X
48 eprintf("algorithm not recognised: %s\n", operation);
49 return NULL;
50 }
51
52 static process_func
53 get_process_f(const char *operation)
54 {
55 #define X(NAME, _ALGO, PIXFMT, TYPE)\
56 if (!strcmp(operation, #NAME)) return process_##PIXFMT##_##NAME;
57 LIST_OPERATORS(f, float)
58 #undef X
59 eprintf("algorithm not recognised: %s\n", operation);
60 return NULL;
61 }
62
63 int
64 main(int argc, char *argv[])
65 {
66 struct stream stream;
67 process_func process;
68 char *img;
69
70 UNOFLAGS(argc != 1);
71
72 eopen_stream(&stream, NULL);
73
74 if (stream.encoding == DOUBLE)
75 process = get_process_lf(argv[0]);
76 else if (stream.encoding == FLOAT)
77 process = get_process_f(argv[0]);
78 else
79 eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt);
80
81 echeck_dimensions(&stream, WIDTH | HEIGHT, NULL);
82 img = emalloc(stream.frame_size);
83 if (!eread_frame(&stream, img))
84 eprintf("video has no frames\n");
85
86 process(&stream, img);
87 if (stream.ptr)
88 eprintf("%s: incomplete frame\n", stream.file);
89
90 stream.frames = 1;
91 fprint_stream_head(stdout, &stream);
92 efflush(stdout, "<stdout>");
93 ewriteall(STDOUT_FILENO, img, stream.frame_size, "<stdout>");
94 free(img);
95 return 0;
96 }