| blind-arithm.c - blind - suckless command-line video editing utility | |
| git clone git://git.suckless.org/blind | |
| Log | |
| Files | |
| Refs | |
| README | |
| LICENSE | |
| --- | |
| blind-arithm.c (3393B) | |
| --- | |
| 1 /* See LICENSE file for copyright and license details. */ | |
| 2 #include "common.h" | |
| 3 | |
| 4 USAGE("[-axyz] operation right-hand-stream ...") | |
| 5 | |
| 6 static int skip_ch[4] = {0, 0, 0, 0}; | |
| 7 | |
| 8 /* Because the syntax for a function returning a function pointer is dis… | |
| 9 typedef void (*process_func)(struct stream *streams, size_t n_streams, s… | |
| 10 | |
| 11 #define LIST_OPERATORS(PIXFMT, TYPE)\ | |
| 12 X(add, 0, *lh += rh, PIXFMT, TYPE)\ | |
| 13 X(sub, 0, *lh -= rh, PIXFMT, TYPE)\ | |
| 14 X(mul, 0, *lh *= rh, PIXFMT, TYPE)\ | |
| 15 X(div, 0, *lh /= rh, PIXFMT, TYPE)\ | |
| 16 X(mod, 0, *lh = posmod(*lh, rh), PIXFMT, TYPE)\ | |
| 17 X(exp, 1, *lh = pow(*lh, rh), PIXFMT, TYPE)\ | |
| 18 X(log, 0, *lh = log2(*lh) / log2(rh), PIXFMT, TYPE)\ | |
| 19 X(min, 0, *lh = MIN(*lh, rh), PIXFMT, TYPE)\ | |
| 20 X(max, 0, *lh = MAX(*lh, rh), PIXFMT, TYPE)\ | |
| 21 X(abs, 0, *lh = abs(*lh - rh) + rh, PIXFMT, TYPE) | |
| 22 | |
| 23 #define P(L, R, ALGO, TYPE)\ | |
| 24 (lh = (TYPE *)(streams[L].buf + k),\ | |
| 25 rh = *((TYPE *)(streams[R].buf + k)),\ | |
| 26 (ALGO)) | |
| 27 | |
| 28 #define X(NAME, RTL, ALGO, PIXFMT, TYPE)\ | |
| 29 static void\ | |
| 30 process_##PIXFMT##_##NAME(struct stream *streams, size_t n_strea… | |
| 31 {\ | |
| 32 size_t i, j, k;\ | |
| 33 TYPE *lh, rh;\ | |
| 34 if (RTL) {\ | |
| 35 for (i = 0; i < streams->n_chan; i++)\ | |
| 36 if (!skip_ch[i])\ | |
| 37 for (j = n_streams; --j;)\ | |
| 38 for (k = i * sizeof(TYPE… | |
| 39 P(j - 1, j, ALGO… | |
| 40 } else {\ | |
| 41 for (i = 0; i < streams->n_chan; i++)\ | |
| 42 if (!skip_ch[i])\ | |
| 43 for (j = 1; j < n_streams; j++)\ | |
| 44 for (k = i * sizeof(TYPE… | |
| 45 P(0, j, ALGO, TY… | |
| 46 }\ | |
| 47 } | |
| 48 LIST_OPERATORS(lf, double) | |
| 49 LIST_OPERATORS(f, float) | |
| 50 #undef X | |
| 51 | |
| 52 static process_func | |
| 53 get_process_lf(const char *operation) | |
| 54 { | |
| 55 #define X(NAME, _RTL, _ALGO, PIXFMT, _TYPE)\ | |
| 56 if (!strcmp(operation, #NAME)) return process_##PIXFMT##_##NAME; | |
| 57 LIST_OPERATORS(lf, double) | |
| 58 #undef X | |
| 59 eprintf("algorithm not recognised: %s\n", operation); | |
| 60 return NULL; | |
| 61 } | |
| 62 | |
| 63 static process_func | |
| 64 get_process_f(const char *operation) | |
| 65 { | |
| 66 #define X(NAME, _RTL, _ALGO, PIXFMT, _TYPE)\ | |
| 67 if (!strcmp(operation, #NAME)) return process_##PIXFMT##_##NAME; | |
| 68 LIST_OPERATORS(f, float) | |
| 69 #undef X | |
| 70 eprintf("algorithm not recognised: %s\n", operation); | |
| 71 return NULL; | |
| 72 } | |
| 73 | |
| 74 int | |
| 75 main(int argc, char *argv[]) | |
| 76 { | |
| 77 struct stream *streams; | |
| 78 process_func process; | |
| 79 const char *operation; | |
| 80 size_t frames = SIZE_MAX, tmp; | |
| 81 int i; | |
| 82 | |
| 83 ARGBEGIN { | |
| 84 case 'a': | |
| 85 skip_ch[3] = 1; | |
| 86 break; | |
| 87 case 'x': | |
| 88 case 'y': | |
| 89 case 'z': | |
| 90 skip_ch[ARGC() - 'x'] = 1; | |
| 91 break; | |
| 92 default: | |
| 93 usage(); | |
| 94 } ARGEND; | |
| 95 | |
| 96 if (argc < 2) | |
| 97 usage(); | |
| 98 | |
| 99 operation = *argv; | |
| 100 streams = alloca((size_t)argc * sizeof(*streams)); | |
| 101 *argv = NULL; | |
| 102 for (i = 0; i < argc; i++) { | |
| 103 eopen_stream(streams + i, argv[i]); | |
| 104 if (streams[i].frames && streams[i].frames < frames) | |
| 105 frames = streams[i].frames; | |
| 106 } | |
| 107 | |
| 108 if (streams->alpha) | |
| 109 CHECK_ALPHA(streams); | |
| 110 CHECK_N_CHAN(streams, 1, 3 + !!streams->alpha); | |
| 111 if (streams->encoding == DOUBLE) | |
| 112 process = get_process_lf(operation); | |
| 113 else if (streams->encoding == FLOAT) | |
| 114 process = get_process_f(operation); | |
| 115 else | |
| 116 eprintf("pixel format %s is not supported, try xyza\n", … | |
| 117 | |
| 118 tmp = streams->frames, streams->frames = frames; | |
| 119 fprint_stream_head(stdout, streams); | |
| 120 efflush(stdout, "<stdout>"); | |
| 121 streams->frames = tmp; | |
| 122 process_multiple_streams(streams, (size_t)argc, STDOUT_FILENO, "… | |
| 123 return 0; | |
| 124 } |