blind-spiral-gradient.c - blind - suckless command-line video editing utility | |
git clone git://git.suckless.org/blind | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
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, … | |
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 =… | |
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 - s… | |
88 ewriteall(STDOUT_FILENO, buf, ptr * size… | |
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 … | |
163 else | |
164 r = mod(r, 1 / (TYPE)spirals) * … | |
165 for (i = 0; i < stream->n_chan; i++) | |
166 buf[ptr][i] = r; | |
167 if (++ptr == ELEMENTSOF(buf)) { | |
168 ewriteall(STDOUT_FILENO, buf, si… | |
169 ptr = 0; | |
170 } | |
171 } | |
172 } | |
173 } | |
174 } | |
175 | |
176 #endif |