blind

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

blind-spatial-arithm.c (2546B)


      1 /* See LICENSE file for copyright and license details. */
      2 #include "common.h"
      3 
      4 USAGE("operation")
      5 
      6 /* Because the syntax for a function returning a function pointer is disgusting. */
      7 typedef void (*process_func)(struct stream *stream);
      8 
      9 #define LIST_OPERATORS(PIXFMT, TYPE)\
     10 	X(add, img[j & 3] + *buf,     PIXFMT, TYPE)\
     11 	X(mul, img[j & 3] * *buf,     PIXFMT, TYPE)\
     12 	X(min, MIN(img[j & 3], *buf), PIXFMT, TYPE)\
     13 	X(max, MAX(img[j & 3], *buf), PIXFMT, TYPE)
     14 
     15 #define X(NAME, ALGO, PIXFMT, TYPE)\
     16 	static void\
     17 	process_##PIXFMT##_##NAME(struct stream *stream)\
     18 	{\
     19 		TYPE img[4], *buf;\
     20 		size_t i, n, j = 0, m = stream->frame_size / sizeof(*img);\
     21 		int first = 1;\
     22 		do {\
     23 			n = stream->ptr / stream->pixel_size * stream->n_chan;\
     24 			buf = (TYPE *)(stream->buf);\
     25 			for (i = 0; i < n; i++, buf++, j++, j %= m) {\
     26 				if (!j) {\
     27 					if (!first)\
     28 						ewriteall(STDOUT_FILENO, img, sizeof(img), "<stdout>");\
     29 					first = 0;\
     30 					img[0] = *buf++;\
     31 					img[1] = *buf++;\
     32 					img[2] = *buf++;\
     33 					img[3] = *buf;\
     34 					i += 3;\
     35 					j = 3;\
     36 				} else {\
     37 					img[j & 3] = ALGO;\
     38 				}\
     39 			}\
     40 			n *= sizeof(TYPE);\
     41 			memmove(stream->buf, stream->buf + n, stream->ptr -= n);\
     42 		} while (eread_stream(stream, SIZE_MAX));\
     43 		if (!first)\
     44 			ewriteall(STDOUT_FILENO, img, sizeof(img), "<stdout>");\
     45 	}
     46 LIST_OPERATORS(lf, double)
     47 LIST_OPERATORS(f, float)
     48 #undef X
     49 
     50 static process_func
     51 get_process_lf(const char *operation)
     52 {
     53 #define X(NAME, _ALGO, PIXFMT, TYPE)\
     54 	if (!strcmp(operation, #NAME)) return process_##PIXFMT##_##NAME;
     55 	LIST_OPERATORS(lf, double)
     56 #undef X
     57 	eprintf("algorithm not recognised: %s\n", operation);
     58 	return NULL;
     59 }
     60 
     61 static process_func
     62 get_process_f(const char *operation)
     63 {
     64 #define X(NAME, _ALGO, PIXFMT, TYPE)\
     65 	if (!strcmp(operation, #NAME)) return process_##PIXFMT##_##NAME;
     66 	LIST_OPERATORS(f, float)
     67 #undef X
     68 	eprintf("algorithm not recognised: %s\n", operation);
     69 	return NULL;
     70 }
     71 
     72 int
     73 main(int argc, char *argv[])
     74 {
     75 	struct stream stream;
     76 	process_func process;
     77 
     78 	UNOFLAGS(argc != 1);
     79 
     80 	eopen_stream(&stream, NULL);
     81 	echeck_dimensions(&stream, WIDTH | HEIGHT, NULL);
     82 
     83 	CHECK_N_CHAN(&stream, 4, 4);
     84 	if (stream.encoding == DOUBLE)
     85 		process = get_process_lf(argv[0]);
     86 	else if (stream.encoding == FLOAT)
     87 		process = get_process_f(argv[0]);
     88 	else
     89 		eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt);
     90 
     91 	if (DPRINTF_HEAD(STDOUT_FILENO, stream.frames, 1, 1, stream.pixfmt) < 0)
     92 		eprintf("dprintf:");
     93 	process(&stream);
     94 	if (stream.ptr)
     95 		eprintf("%s: incomplete frame\n", stream.file);
     96 	return 0;
     97 }