blind-stack.c (2685B)
1 /* See LICENSE file for copyright and license details. */ 2 #include "common.h" 3 4 USAGE("[-bs] bottom-stream ... top-stream") 5 6 #define PROCESS(TYPE, BLEND)\ 7 do {\ 8 TYPE x1, y1, z1, a1;\ 9 TYPE x2, y2, z2, a2;\ 10 size_t i, j;\ 11 for (i = 0; i < n; i += streams->pixel_size) {\ 12 x1 = ((TYPE *)(streams[0].buf + i))[0];\ 13 y1 = ((TYPE *)(streams[0].buf + i))[1];\ 14 z1 = ((TYPE *)(streams[0].buf + i))[2];\ 15 a1 = ((TYPE *)(streams[0].buf + i))[3];\ 16 for (j = 1; j < n_streams; j++) {\ 17 x2 = ((TYPE *)(streams[j].buf + i))[0];\ 18 y2 = ((TYPE *)(streams[j].buf + i))[1];\ 19 z2 = ((TYPE *)(streams[j].buf + i))[2];\ 20 a2 = ((TYPE *)(streams[j].buf + i))[3];\ 21 if (BLEND)\ 22 a2 /= (TYPE)(j + 1);\ 23 a1 *= 1 - a2;\ 24 x1 = x1 * a1 + x2 * a2;\ 25 y1 = y1 * a1 + y2 * a2;\ 26 z1 = z1 * a1 + z2 * a2;\ 27 a1 += a2;\ 28 }\ 29 ((TYPE *)(streams[0].buf + i))[0] = x1;\ 30 ((TYPE *)(streams[0].buf + i))[1] = y1;\ 31 ((TYPE *)(streams[0].buf + i))[2] = z1;\ 32 ((TYPE *)(streams[0].buf + i))[3] = a1;\ 33 }\ 34 } while (0) 35 36 static void process_lf (struct stream *streams, size_t n_streams, size_t n) { PROCESS(double, 0); } 37 static void process_lf_b(struct stream *streams, size_t n_streams, size_t n) { PROCESS(double, 1); } 38 static void process_f (struct stream *streams, size_t n_streams, size_t n) { PROCESS(float, 0); } 39 static void process_f_b (struct stream *streams, size_t n_streams, size_t n) { PROCESS(float, 1); } 40 41 int 42 main(int argc, char *argv[]) 43 { 44 struct stream *streams; 45 size_t n_streams, i, frames = 0, tmp; 46 int blend = 0, shortest = 0; 47 void (*process)(struct stream *streams, size_t n_streams, size_t n); 48 49 ARGBEGIN { 50 case 'b': 51 blend = 1; 52 break; 53 case 's': 54 shortest = 1; 55 frames = SIZE_MAX; 56 break; 57 default: 58 usage(); 59 } ARGEND; 60 61 if (argc < 2) 62 usage(); 63 64 n_streams = (size_t)argc; 65 streams = ecalloc(n_streams, sizeof(*streams)); 66 67 for (i = 0; i < n_streams; i++) { 68 eopen_stream(streams + i, argv[i]); 69 if (shortest ? 70 (streams[i].frames && streams[i].frames < frames) : 71 (streams[i].frames || streams[i].frames > frames)) 72 frames = streams[i].frames; 73 } 74 75 if (streams->encoding == DOUBLE) 76 process = blend ? process_lf_b :process_lf; 77 else if (streams->encoding == FLOAT) 78 process = blend ? process_f_b : process_f; 79 else 80 eprintf("pixel format %s is not supported, try xyza\n", streams->pixfmt); 81 CHECK_ALPHA_CHAN(streams); 82 CHECK_N_CHAN(streams, 4, 4); 83 84 tmp = streams->frames, streams->frames = frames; 85 fprint_stream_head(stdout, streams); 86 efflush(stdout, "<stdout>"); 87 streams->frames = tmp; 88 process_multiple_streams(streams, n_streams, STDOUT_FILENO, "<stdout>", shortest, process); 89 90 free(streams); 91 return 0; 92 }