blind-spiral-gradient.c (3993B)
1 /* See LICENSE file for copyright and license details. */ 2 #ifndef TYPE 3 #include "common.h" 4 5 USAGE("[-s spirals | t] [-al] -w width -h height") 6 7 static int anticlockwise = 0; 8 static int logarithmic = 0; 9 static int angle = 0; 10 static double spirals = 1; 11 static size_t width = 0; 12 static size_t height = 0; 13 static int with_params; 14 static int with_vector; 15 16 #define FILE "blind-spiral-gradient.c" 17 #include "define-functions.h" 18 19 int 20 main(int argc, char *argv[]) 21 { 22 struct stream stream; 23 void (*process)(struct stream *stream); 24 25 ARGBEGIN { 26 case 'a': 27 anticlockwise = 1; 28 break; 29 case 'l': 30 logarithmic = 1; 31 break; 32 case 's': 33 spirals = etolf_flag('s', UARGF()); 34 if (!spirals) 35 eprintf("the value of -s must not be 0"); 36 break; 37 case 't': 38 angle = 1; 39 break; 40 case 'w': 41 width = etozu_flag('w', UARGF(), 1, SIZE_MAX); 42 break; 43 case 'h': 44 height = etozu_flag('h', UARGF(), 1, SIZE_MAX); 45 break; 46 default: 47 usage(); 48 } ARGEND; 49 50 if (!width || !height || argc || (spirals != 1 && angle)) 51 usage(); 52 53 eopen_stream(&stream, NULL); 54 55 SELECT_PROCESS_FUNCTION(&stream); 56 CHECK_N_CHAN(&stream, 4, 4); 57 58 if (stream.width > 5 || stream.height > 5 || 59 stream.width * stream.height < 2 || 60 stream.width * stream.height > 5) 61 eprintf("<stdin>: each frame must contain exactly 2, 3, 4, or 5 pixels\n"); 62 63 with_params = (stream.width * stream.height) & 1; 64 with_vector = stream.width * stream.height > 3; 65 66 stream.width = width; 67 stream.height = height; 68 fprint_stream_head(stdout, &stream); 69 efflush(stdout, "<stdout>"); 70 process(&stream); 71 return 0; 72 } 73 74 #else 75 76 static void 77 PROCESS(struct stream *stream) 78 { 79 typedef TYPE pixel_t[4]; 80 pixel_t buf[BUFSIZ / sizeof(pixel_t)]; 81 TYPE *params, x1, y1, x2, y2, b, r, u, v; 82 TYPE x, y, a = 0, e = 1, p = 1, k = 1, ep = 1; 83 TYPE x3 = 1, y3 = 0, rd = 1, P, R, Rx, Ry, Pe = 2, Re = 2, PRe = 0.5; 84 size_t i, ix, iy, ptr = 0; 85 for (;;) { 86 while (stream->ptr < stream->frame_size) { 87 if (!eread_stream(stream, stream->frame_size - stream->ptr)) { 88 ewriteall(STDOUT_FILENO, buf, ptr * sizeof(*buf), "<stdout>"); 89 return; 90 } 91 } 92 params = (TYPE *)stream->buf; 93 x1 = (params)[0]; 94 y1 = (params)[1]; 95 x2 = (params)[4]; 96 y2 = (params)[5]; 97 if (with_vector) { 98 x3 = (params)[8]; 99 y3 = (params)[9]; 100 Pe = (params)[12]; 101 Re = (params)[13]; 102 rd = (params)[14]; 103 PRe = 1 / sqrt(Pe * Re); 104 b = sqrt(x3 * x3 + y3 * y3); 105 x3 /= b; 106 y3 /= b; 107 } 108 if (with_params) { 109 a = (params)[with_vector ? 16 : 8]; 110 e = (params)[with_vector ? 17 : 9]; 111 p = (params)[with_vector ? 18 : 10]; 112 k = (params)[with_vector ? 19 : 11]; 113 ep = 1 / (e * p); 114 } 115 memmove(stream->buf, stream->buf + stream->frame_size, 116 stream->ptr -= stream->frame_size); 117 118 x2 -= x1; 119 y2 -= y1; 120 u = atan2(y2, x2); 121 b = sqrt(x2 * x2 + y2 * y2); 122 b *= (TYPE)spirals; 123 if (logarithmic) 124 b = log(b); 125 b /= pow(2 * (TYPE)M_PI, e); 126 127 for (iy = 0; iy < height; iy++) { 128 y = (TYPE)iy - y1; 129 for (ix = 0; ix < width; ix++) { 130 x = (TYPE)ix - x1; 131 if (!x && !y) { 132 v = 0; 133 } else { 134 v = atan2(y, x); 135 if (anticlockwise) 136 v = -v; 137 v -= u; 138 v += 4 * (TYPE)M_PI; 139 v = mod(v, 2 * (TYPE)M_PI); 140 } 141 if (!with_vector) { 142 r = sqrt(x * x + y * y); 143 } else { 144 P = x * x3 + y * y3; 145 Rx = x - P * x3; 146 Ry = y - P * y3; 147 R = sqrt(Rx * Rx + Ry * Ry) / rd; 148 P = pow(abs(P), Pe); 149 R = pow(abs(R), Re); 150 r = pow(P + R, PRe); 151 } 152 r -= a; 153 if (!logarithmic) { 154 r = pow(r / b, ep); 155 r = (r - v) / (2 * (TYPE)M_PI); 156 } else if (r) { 157 r = log(r / k); 158 r = pow(r / b, ep); 159 r = (r - v) / (2 * (TYPE)M_PI); 160 } 161 if (angle) 162 r = (TYPE)(int)(r + 1) + v / (2 * (TYPE)M_PI); 163 else 164 r = mod(r, 1 / (TYPE)spirals) * (TYPE)spirals + r - mod(r, (TYPE)1); 165 for (i = 0; i < stream->n_chan; i++) 166 buf[ptr][i] = r; 167 if (++ptr == ELEMENTSOF(buf)) { 168 ewriteall(STDOUT_FILENO, buf, sizeof(buf), "<stdout>"); 169 ptr = 0; 170 } 171 } 172 } 173 } 174 } 175 176 #endif