blind

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

blind-affine-colour.c (3345B)


      1 /* See LICENSE file for copyright and license details. */
      2 #ifndef TYPE
      3 #include "common.h"
      4 
      5 USAGE("[-alp] matrix-stream")
      6 
      7 static int skip_alpha = 0;
      8 static int linear = 0;
      9 static int per_pixel = 0;
     10 static size_t dim;
     11 
     12 #define FILE "blind-affine-colour.c"
     13 #include "define-functions.h"
     14 
     15 int
     16 main(int argc, char *argv[])
     17 {
     18 	struct stream colour, matrix;
     19 	void (*process)(struct stream *colour, struct stream *matrix);
     20 	size_t h;
     21 
     22 	ARGBEGIN {
     23 	case 'a':
     24 		skip_alpha = 1;
     25 		break;
     26 	case 'l':
     27 		linear = 1;
     28 		break;
     29 	case 'p':
     30 		per_pixel = 1;
     31 		break;
     32 	default:
     33 		usage();
     34 	} ARGEND;
     35 
     36 	if (argc != 1)
     37 		usage();
     38 
     39 	eopen_stream(&colour, NULL);
     40 	eopen_stream(&matrix, argv[0]);
     41 
     42 	SELECT_PROCESS_FUNCTION(&colour);
     43 	if (skip_alpha && colour.alpha_chan != -1)
     44 		CHECK_CHANS(&colour, == (short int)(colour.n_chan - 1), == colour.luma_chan);
     45 	else
     46 		skip_alpha = 0;
     47 
     48 	if (strcmp(colour.pixfmt, matrix.pixfmt))
     49 		eprintf("videos use incompatible pixel formats\n");
     50 
     51 	dim = colour.n_chan - (size_t)skip_alpha + (size_t)!linear;
     52 	h = matrix.height, matrix.height = dim;
     53 	echeck_dimensions(&matrix, WIDTH | HEIGHT, "matrix");
     54 	matrix.height = h;
     55 
     56 	if (per_pixel) {
     57 		if (matrix.height != dim * colour.height || matrix.width != dim * colour.width)
     58 			eprintf("the matrice should have the size %zux%zu, but are %zux%zu",
     59 				dim * colour.height, dim * colour.width, matrix.height, matrix.width);
     60 	} else {
     61 		if (matrix.height != dim || matrix.width != dim)
     62 			eprintf("the matrice should have the size %zux%zu, but are %zux%zu",
     63 				dim, dim, matrix.height, matrix.width);
     64 	}
     65 
     66 	fprint_stream_head(stdout, &colour);
     67 	efflush(stdout, "<stdout>");
     68 	process(&colour, &matrix);
     69 	return 0;
     70 }
     71 
     72 #else
     73 
     74 static void
     75 PROCESS(struct stream *colour, struct stream *matrix)
     76 {
     77 	char *mbuf;
     78 	TYPE *mat, *pixel, V[5], M[ELEMENTSOF(V)][ELEMENTSOF(V)];
     79 	size_t ptr, i, j, w, x = 0, y = 0, cn;
     80 
     81 	mbuf = emalloc2(dim, matrix->row_size);
     82 	mat = (TYPE *)mbuf;
     83 	w = matrix->width * matrix->n_chan;
     84 	cn = colour->n_chan - (size_t)skip_alpha;
     85 
     86 	memset(M, 0, sizeof(M));
     87 	for (i = 0; i < ELEMENTSOF(V); i++)
     88 		M[i][i] = V[i] = 1;
     89 
     90 	do {
     91 		for (ptr = 0; ptr + colour->pixel_size <= colour->ptr; x = (x + 1) % colour->width, ptr += colour->pixel_size) {
     92 			if (!x) {
     93 				if (!y && !eread_segment(matrix, mbuf, dim * matrix->row_size))
     94 					break;
     95 				if (!per_pixel) {
     96 					if (!y) {
     97 						mat = (TYPE *)mbuf;
     98 						for (i = 0; i < dim; i++, mat += w)
     99 							for (j = 0; j < dim; j++)
    100 								M[i][j] = mat[j * matrix->n_chan + 1]
    101 									* mat[(j + 1) * matrix->n_chan - 1];
    102 					}
    103 					y = (y + 1) % colour->height;
    104 				}
    105 			}
    106 			if (per_pixel) {
    107 				mat = (TYPE *)(mbuf + x * dim * matrix->pixel_size);
    108 				for (i = 0; i < dim; i++, mat += w)
    109 					for (j = 0; j < dim; j++)
    110 						M[i][j] = mat[j * matrix->n_chan + 1]
    111 							* mat[(j + 1) * matrix->n_chan - 1];
    112 			}
    113 			pixel = (TYPE *)(colour->buf + ptr);
    114 			for (i = 0; i < dim; i++) {
    115 				V[i] = 0;
    116 				for (j = 0; j < cn; j++)
    117 					V[i] += M[i][j] * pixel[j];
    118 				for (; j < dim; j++)
    119 					V[i] += M[i][j];
    120 			}
    121 			for (i = 0; i < cn; i++)
    122 				pixel[i] = V[i] / V[cn];
    123 		}
    124 		ewriteall(STDOUT_FILENO, colour->buf, ptr, "<stdout>");
    125 		memmove(colour->buf, colour->buf + ptr, colour->ptr -= ptr);
    126 	} while (eread_stream(colour, SIZE_MAX));
    127 	if (colour->ptr)
    128 		eprintf("%s: incomplete frame\n", colour->file);
    129 
    130 	free(mbuf);
    131 }
    132 
    133 #endif