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 disgusting. */ 9 typedef void (*process_func)(struct stream *streams, size_t n_streams, size_t n); 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_streams, size_t n)\ 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); k < n; k += 4 * sizeof(TYPE))\ 39 P(j - 1, j, ALGO, TYPE);\ 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); k < n; k += 4 * sizeof(TYPE))\ 45 P(0, j, ALGO, TYPE);\ 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", streams->pixfmt); 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, "<stdout>", 1, process); 123 return 0; 124 }