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, 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