blind-cone-gradient.c (2630B)
1 /* See LICENSE file for copyright and license details. */ 2 #ifndef TYPE 3 #include "common.h" 4 5 USAGE("[-a | -s] -w width -h height") 6 7 static int anticlockwise = 0; 8 static int symmetric = 0; 9 static size_t width = 0; 10 static size_t height = 0; 11 static int with_multiplier = 0; 12 13 #define FILE "blind-cone-gradient.c" 14 #include "define-functions.h" 15 16 int 17 main(int argc, char *argv[]) 18 { 19 struct stream stream; 20 void (*process)(struct stream *stream); 21 22 ARGBEGIN { 23 case 'a': 24 anticlockwise = 1; 25 break; 26 case 's': 27 symmetric = 1; 28 break; 29 case 'w': 30 width = etozu_flag('w', UARGF(), 1, SIZE_MAX); 31 break; 32 case 'h': 33 height = etozu_flag('h', UARGF(), 1, SIZE_MAX); 34 break; 35 default: 36 usage(); 37 } ARGEND; 38 39 if (!width || !height || (symmetric && anticlockwise) || argc) 40 usage(); 41 42 eopen_stream(&stream, NULL); 43 44 SELECT_PROCESS_FUNCTION(&stream); 45 CHECK_N_CHAN(&stream, 4, 4); 46 47 if (stream.width > 3 || stream.height > 3 || 48 stream.width * stream.height < 2 || 49 stream.width * stream.height > 3) 50 eprintf("<stdin>: each frame must contain exactly 2 or 3 pixels\n"); 51 52 with_multiplier = stream.width * stream.height == 3; 53 54 stream.width = width; 55 stream.height = height; 56 fprint_stream_head(stdout, &stream); 57 efflush(stdout, "<stdout>"); 58 process(&stream); 59 return 0; 60 } 61 62 #else 63 64 static void 65 PROCESS(struct stream *stream) 66 { 67 typedef TYPE pixel_t[4]; 68 pixel_t buf[BUFSIZ / sizeof(pixel_t)]; 69 TYPE *params, x1, y1, x2, y2; 70 TYPE x, y, u, v, m = 1; 71 size_t i, ix, iy, ptr = 0; 72 73 for (;;) { 74 while (stream->ptr < stream->frame_size) { 75 if (!eread_stream(stream, stream->frame_size - stream->ptr)) { 76 ewriteall(STDOUT_FILENO, buf, ptr * sizeof(*buf), "<stdout>"); 77 return; 78 } 79 } 80 params = (TYPE *)stream->buf; 81 x1 = (params)[0]; 82 y1 = (params)[1]; 83 x2 = (params)[4]; 84 y2 = (params)[5]; 85 if (with_multiplier) 86 m = (params)[9]; 87 memmove(stream->buf, stream->buf + stream->frame_size, 88 stream->ptr -= stream->frame_size); 89 90 x2 -= x1; 91 y2 -= y1; 92 u = atan2(y2, x2); 93 94 for (iy = 0; iy < height; iy++) { 95 y = (TYPE)iy - y1; 96 for (ix = 0; ix < width; ix++) { 97 x = (TYPE)ix - x1; 98 if (!x && !y) { 99 v = 0.5; 100 } else { 101 v = atan2(y, x); 102 v -= u; 103 v += 2 * (TYPE)M_PI; 104 v = mod(v, 2 * (TYPE)M_PI); 105 v /= 2 * (TYPE)M_PI; 106 if (anticlockwise) 107 v = 1 - v; 108 v *= m; 109 if (symmetric) { 110 v = mod(2 * v, (TYPE)2); 111 if (v > 1) 112 v = 2 - v; 113 } 114 } 115 for (i = 0; i < stream->n_chan; i++) 116 buf[ptr][i] = v; 117 if (++ptr == ELEMENTSOF(buf)) { 118 ewriteall(STDOUT_FILENO, buf, sizeof(buf), "<stdout>"); 119 ptr = 0; 120 } 121 } 122 } 123 } 124 } 125 126 #endif