blind

suckless command-line video editing utility
git clone git://git.suckless.org/blind
Log | Files | Refs | README | LICENSE

blind-radial-gradient.c (2874B)


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