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