blind

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

blind-invert-luma.c (3065B)


      1 /* See LICENSE file for copyright and license details. */
      2 #include "common.h"
      3 
      4 USAGE("[-iw] mask-stream")
      5 
      6 #define PROCESS(TYPE, INV)\
      7 	do {\
      8 		size_t i;\
      9 		TYPE w, y, yo;\
     10 		for (i = 0; i < n; i += colour->pixel_size) {\
     11 			w = INV ((TYPE *)(mask->buf + i))[1];\
     12 			w *= ((TYPE *)(mask->buf + i))[3];\
     13 			yo = ((TYPE *)(colour->buf + i))[1];\
     14 			y = (1 - yo) * w + yo * (1 - w);\
     15 			((TYPE *)(colour->buf + i))[0] += (y - yo) * (TYPE)D65_XYZ_X;\
     16 			((TYPE *)(colour->buf + i))[1] = y;\
     17 			((TYPE *)(colour->buf + i))[2] += (y - yo) * (TYPE)D65_XYZ_Z;\
     18 			/*
     19 			 * Explaination:
     20 			 *   Y is the luma and ((X / Xn - Y / Yn), (Z / Zn - Y / Yn))
     21 			 *   is the chroma (according to CIELAB), where (Xn, Yn, Zn)
     22 			 *   is the white point.
     23 			 */\
     24 		}\
     25 	} while (0)
     26 
     27 #define PROCESS_W(TYPE, INV)\
     28 	do {\
     29 		size_t i;\
     30 		TYPE w, y, yo, X, Z;\
     31 		for (i = 0; i < n; i += colour->pixel_size) {\
     32 			X = ((TYPE *)(mask->buf + i))[0];\
     33 			Z = ((TYPE *)(mask->buf + i))[2];\
     34 			w = INV ((TYPE *)(mask->buf + i))[1];\
     35 			w *= ((TYPE *)(mask->buf + i))[3];\
     36 			yo = ((TYPE *)(colour->buf + i))[1];\
     37 			y = (1 - yo) * w + yo * (1 - w);\
     38 			((TYPE *)(colour->buf + i))[0] += (y - yo) * X;\
     39 			((TYPE *)(colour->buf + i))[1] = y;\
     40 			((TYPE *)(colour->buf + i))[2] += (y - yo) * Z;\
     41 		}\
     42 	} while (0)
     43 
     44 static void process_lf   (struct stream *colour, struct stream *mask, size_t n) {PROCESS(double,);}
     45 static void process_lf_i (struct stream *colour, struct stream *mask, size_t n) {PROCESS(double, 1 -);}
     46 static void process_lf_w (struct stream *colour, struct stream *mask, size_t n) {PROCESS_W(double,);}
     47 static void process_lf_iw(struct stream *colour, struct stream *mask, size_t n) {PROCESS_W(double, 1 -);}
     48 static void process_f    (struct stream *colour, struct stream *mask, size_t n) {PROCESS(float,);}
     49 static void process_f_i  (struct stream *colour, struct stream *mask, size_t n) {PROCESS(float, 1 -);}
     50 static void process_f_w  (struct stream *colour, struct stream *mask, size_t n) {PROCESS_W(float,);}
     51 static void process_f_iw (struct stream *colour, struct stream *mask, size_t n) {PROCESS_W(float, 1 -);}
     52 
     53 int
     54 main(int argc, char *argv[])
     55 {
     56 	int invert = 0, whitepoint = 0;
     57 	struct stream colour, mask;
     58 	void (*process)(struct stream *colour, struct stream *mask, size_t n);
     59 
     60 	ARGBEGIN {
     61 	case 'i':
     62 		invert = 1;
     63 		break;
     64 	case 'w':
     65 		whitepoint = 1;
     66 		break;
     67 	default:
     68 		usage();
     69 	} ARGEND;
     70 
     71 	if (argc != 1)
     72 		usage();
     73 
     74 	eopen_stream(&colour, NULL);
     75 	eopen_stream(&mask, argv[0]);
     76 
     77 	CHECK_ALPHA(&colour);
     78 	CHECK_COLOUR_SPACE(&colour, CIEXYZ);
     79 	if (colour.encoding == DOUBLE)
     80 		process = invert ? whitepoint ? process_lf_iw : process_lf_i
     81 				 : whitepoint ? process_lf_w  : process_lf;
     82 	else if (colour.encoding == FLOAT)
     83 		process = invert ? whitepoint ? process_f_iw : process_f_i
     84 				 : whitepoint ? process_f_w  : process_f;
     85 	else
     86 		eprintf("pixel format %s is not supported, try xyza\n", colour.pixfmt);
     87 
     88 	fprint_stream_head(stdout, &colour);
     89 	efflush(stdout, "<stdout>");
     90 	process_two_streams(&colour, &mask, STDOUT_FILENO, "<stdout>", process);
     91 	return 0;
     92 }