blind

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

blind-make-kernel.c (3372B)


      1 /* See LICENSE file for copyright and license details. */
      2 #include "common.h"
      3 
      4 USAGE("[-d denominator] ... [-nxyza] [-- value ...] ...")
      5 
      6 static void
      7 new_row(double **kernel, size_t *col, size_t *rows, size_t *cols)
      8 {
      9 	if (!*col)
     10 		return;
     11 	if (*rows && *col != *cols)
     12 		eprintf("the rows in the matrix do not have the same number of columns\n");
     13 	*kernel = erealloc3(*kernel, 1 + ++*rows, *cols = *col, sizeof(**kernel));
     14 	*col = 0;
     15 }
     16 
     17 static void
     18 new_col(char *arg, double **kernel, size_t *col, size_t *rows, size_t *cols)
     19 {
     20 	if (*rows && *col >= *cols)
     21 		eprintf("the rows in the matrix do not have the same number of columns\n");
     22 	if (!*rows)
     23 		*kernel = erealloc2(*kernel, *col + 1, sizeof(**kernel));
     24 	if (tolf(arg, &(*kernel)[*rows * *cols + (*col)++]))
     25 		eprintf("matrix cell values must be floating-point values\n");
     26 }
     27 
     28 static void
     29 finalise(double **kernel, size_t col, size_t *rows, size_t *cols)
     30 {
     31 	if (col)
     32 		new_row(kernel, &col, rows, cols);
     33 	if (!*rows)
     34 		eprintf("the matrix cannot be null-sized\n");
     35 }
     36 
     37 static double *
     38 read_matrix_cmdline(char *args[], size_t *rows, size_t *cols)
     39 {
     40 	size_t col = 0;
     41 	double *kernel = NULL;
     42 	*rows = *cols = 0;
     43 	for (; *args; args++) {
     44 		if (!strcmp(*args, "--"))
     45 			new_row(&kernel, &col, rows, cols);
     46 		else
     47 			new_col(*args, &kernel, &col, rows, cols);
     48 	}
     49 	finalise(&kernel, col, rows, cols);
     50 	return kernel;
     51 }
     52 
     53 static double *
     54 read_matrix_stdin(size_t *rows, size_t *cols)
     55 {
     56 	char *line = NULL, *p, *q;
     57 	size_t size = 0, col = 0;
     58 	double *kernel = NULL;
     59 	ssize_t len;
     60 	*rows = *cols = 0;
     61 	while ((len = getline(&line, &size, stdin)) >= 0) {
     62 		col = 0;
     63 		for (p = line;; p = q) {
     64 			while (*p && isspace(*p)) p++;
     65 			if (!*(q = p))
     66 				break;
     67 			while (*q && !isspace(*q)) q++;
     68 			*q++ = '\0';
     69 			new_col(p, &kernel, &col, rows, cols);
     70 		}
     71 		new_row(&kernel, &col, rows, cols);
     72 	}
     73 	free(line);
     74 	if (ferror(stdout))
     75 		eprintf("getline:");
     76 	finalise(&kernel, col, rows, cols);
     77 	return kernel;
     78 }
     79 
     80 int
     81 main(int argc, char *argv[])
     82 {
     83 	int normalise = 0;
     84 	double denominator = 1;
     85 	int id_x = 1, id_y = 1, id_z = 1, id_a = 1;
     86 	size_t rows, cols, y, x, n;
     87 	double *kernel, *kern, sum = 0, value;
     88 	double *buffer, *buf, id_val;
     89 
     90 	ARGBEGIN {
     91 	case 'd':
     92 		denominator *= etolf_flag('d', UARGF());
     93 		break;
     94 	case 'n':
     95 		normalise = 1;
     96 		break;
     97 	case 'x':
     98 		id_x = 0;
     99 		break;
    100 	case 'y':
    101 		id_y = 0;
    102 		break;
    103 	case 'z':
    104 		id_z = 0;
    105 		break;
    106 	case 'a':
    107 		id_a = 0;
    108 		break;
    109 	default:
    110 		usage();
    111 	} ARGEND;
    112 
    113 	if (id_x && id_y && id_z && id_a)
    114 		id_x = id_y = id_z = id_a = 0;
    115 
    116 	if (argc)
    117 		kernel = read_matrix_cmdline(argv, &rows, &cols);
    118 	else
    119 		kernel = read_matrix_stdin(&rows, &cols);
    120 
    121 	FPRINTF_HEAD(stdout, (size_t)1, cols, rows, "xyza");
    122 	efflush(stdout, "<stdout>");
    123 
    124 	buffer = emalloc2(cols, 4 * sizeof(double));
    125 	n = cols * 4 * sizeof(double);
    126 
    127 	if (normalise) {
    128 		kern = kernel;
    129 		for (y = 0; y < rows; y++)
    130 			for (x = 0; x < cols; x++)
    131 				sum += *kern++;
    132 		denominator *= sum;
    133 	}
    134 
    135 	kern = kernel;
    136 	for (y = 0; y < rows; y++) {
    137 		buf = buffer;
    138 		for (x = 0; x < cols; x++) {
    139 			id_val = (x == cols / 2 && y == rows / 2) ? 1. : 0.;
    140 			value = *kern++ / denominator;
    141 			buf[0] = id_x ? id_val : value;
    142 			buf[1] = id_y ? id_val : value;
    143 			buf[2] = id_z ? id_val : value;
    144 			buf[3] = id_a ? id_val : value;
    145 			buf += 4;
    146 		}
    147 		ewriteall(STDOUT_FILENO, buffer, n, "<stdout>");
    148 	}
    149 
    150 	free(kernel);
    151 	free(buffer);
    152 	return 0;
    153 }