blind

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

blind-mosaic-corners.c (3095B)


      1 /* See LICENSE file for copyright and license details. */
      2 #include "common.h"
      3 
      4 USAGE("[-xy]")
      5 
      6 static size_t pixsize;
      7 
      8 static int
      9 pixcmp(const void *a, const void *b)
     10 {
     11 	return memcmp(a, b, pixsize);
     12 }
     13 
     14 static size_t
     15 count_unique(char *base, size_t n)
     16 {
     17 	size_t ret = 1, i;
     18 	qsort(base, n, pixsize, pixcmp);
     19 	for (i = 1; i < n; i++)
     20 		ret += !!memcmp(base + (i - 1) * pixsize, base + i * pixsize, pixsize);
     21 	return ret;
     22 }
     23 
     24 int
     25 main(int argc, char *argv[])
     26 {
     27 	int tiled_x = 0;
     28 	int tiled_y = 0;
     29 	struct stream stream;
     30 	void *colours[2];
     31 	char *buf, *corners, *here, *found;
     32 	ssize_t dl, dr, du, dd;
     33 	size_t i, j, n, x, y;
     34 	int v;
     35 
     36 	ARGBEGIN {
     37 	case 'x':
     38 		tiled_x = 1;
     39 		break;
     40 	case 'y':
     41 		tiled_y = 1;
     42 		break;
     43 	default:
     44 		usage();
     45 	} ARGEND;
     46 
     47 	if (argc)
     48 		usage();
     49 
     50 	eopen_stream(&stream, NULL);
     51 	echeck_dimensions(&stream, WIDTH | HEIGHT, NULL);
     52 
     53 	n = stream.width * stream.height;
     54 	buf = emalloc(stream.frame_size);
     55 	corners = emalloc((n + 7) / 8);
     56 
     57 	found = alloca(9 * stream.pixel_size);
     58 	colours[0] = alloca(stream.pixel_size);
     59 	colours[1] = alloca(stream.pixel_size);
     60 	memset(colours[0], 0, stream.pixel_size);
     61 
     62 	if (stream.encoding == DOUBLE) {
     63 		((double *)(colours[1]))[0] = (double)1;
     64 		((double *)(colours[1]))[1] = (double)1;
     65 		((double *)(colours[1]))[2] = (double)1;
     66 		((double *)(colours[1]))[3] = (double)1;
     67 	} else if (stream.encoding == FLOAT) {
     68 		((float *)(colours[1]))[0] = (float)1;
     69 		((float *)(colours[1]))[1] = (float)1;
     70 		((float *)(colours[1]))[2] = (float)1;
     71 		((float *)(colours[1]))[3] = (float)1;
     72 	} else {
     73 		eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt);
     74 	}
     75 
     76 	fprint_stream_head(stdout, &stream);
     77 	efflush(stdout, "<stdout>");
     78 
     79 	pixsize = stream.pixel_size;
     80 	while (eread_frame(&stream, buf)) {
     81 		memset(corners, 0, (n + 7) / 8);
     82 		for (i = 0; i < n; i++) {
     83 			here = buf + i * pixsize;
     84 			x = i % stream.width;
     85 			y = i / stream.width;
     86 			j = 1;
     87 			memcpy(found, here, pixsize);
     88 
     89 			dr = (ssize_t)(x != stream.width - 1 ? pixsize : tiled_x ? pixsize - stream.row_size : 0);
     90 			dl = (ssize_t)(x ? -pixsize : tiled_x ? stream.row_size - pixsize : 0);
     91 			dd = (ssize_t)(y != stream.height - 1 ? stream.row_size : tiled_y ? stream.row_size - stream.frame_size : 0);
     92 			du = (ssize_t)(y ? -stream.row_size : tiled_y ? stream.frame_size - stream.row_size : 0);
     93 
     94 			memcpy(found + j++ * pixsize, here + dr, pixsize);
     95 			memcpy(found + j++ * pixsize, here + dl, pixsize);
     96 			memcpy(found + j++ * pixsize, here + dd, pixsize);
     97 			memcpy(found + j++ * pixsize, here + du, pixsize);
     98 			memcpy(found + j++ * pixsize, here + dr + du, pixsize);
     99 			memcpy(found + j++ * pixsize, here + dl + du, pixsize);
    100 			memcpy(found + j++ * pixsize, here + dr + dd, pixsize);
    101 			memcpy(found + j++ * pixsize, here + dl + dd, pixsize);
    102 
    103 			if (j > 2 && count_unique(found, j) > 2)
    104 				corners[i >> 3] |= (char)(1 << (i & 7));
    105 		}
    106 		for (i = 0; i < n; i++) {
    107 			v = (corners[i >> 3] >> (i & 7)) & 1;
    108 			memcpy(buf + i * pixsize, colours[v], pixsize);
    109 		}
    110 		ewriteall(STDOUT_FILENO, buf, stream.frame_size, "<stdout>");
    111 	}
    112 
    113 	free(buf);
    114 	free(corners);
    115 	return 0;
    116 }