blind

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

commit 076d0dc569608c276b25742605d35b0ac44dbf46
parent 7bd1282fba79997816521e25485ab890a0a0126d
Author: Mattias Andrée <maandree@kth.se>
Date:   Sun, 15 Jan 2017 20:52:36 +0100

Fix errors

Signed-off-by: Mattias Andrée <maandree@kth.se>

Diffstat:
MTODO | 7-------
Msrc/blind-arithm.c | 51+++++++++++++++++++++++++++++++++++++++++----------
Msrc/blind-dissolve.c | 4++--
Msrc/blind-invert-luma.c | 78+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------
Msrc/blind-set-alpha.c | 2++
Msrc/blind-set-luma.c | 39+++++++++++++++++++++++++++++++++++++--
Msrc/blind-set-saturation.c | 22++++++++++++++++------
7 files changed, 165 insertions(+), 38 deletions(-)

diff --git a/TODO b/TODO @@ -10,17 +10,10 @@ blind-apply-kernel apply a convolution matrix blind-find-frame a graphical tool for locating frames, should highlight key frames UNTESTED: - blind-colour-srgb blind-crop blind-cut - blind-dissolve blind-extend blind-from-text blind-gauss-blur - blind-invert-luma blind-rewrite-head - blind-set-alpha - blind-set-luma - blind-set-saturation - blind-split blind-to-text diff --git a/src/blind-arithm.c b/src/blind-arithm.c @@ -8,7 +8,12 @@ #include <string.h> #include <unistd.h> -USAGE("operation right-hand-stream") +USAGE("[-ayxz] operation right-hand-stream") + +static int skip_a = 0; +static int skip_x = 0; +static int skip_y = 0; +static int skip_z = 0; /* Because the syntax for a function returning a function pointer is disgusting. */ typedef void (*process_func)(struct stream *left, struct stream *right, size_t n); @@ -30,14 +35,22 @@ typedef void (*process_func)(struct stream *left, struct stream *right, size_t n size_t i;\ double *lh, rh;\ for (i = 0; i < n; i += 4 * sizeof(double)) {\ - lh = ((double *)(left->buf + i)) + 0, rh = ((double *)(right->buf + i))[0];\ - ALGO;\ - lh = ((double *)(left->buf + i)) + 1, rh = ((double *)(right->buf + i))[1];\ - ALGO;\ - lh = ((double *)(left->buf + i)) + 2, rh = ((double *)(right->buf + i))[2];\ - ALGO;\ - lh = ((double *)(left->buf + i)) + 3, rh = ((double *)(right->buf + i))[3];\ - ALGO;\ + if (!skip_x) {\ + lh = ((double *)(left->buf + i)) + 0, rh = ((double *)(right->buf + i))[0];\ + ALGO;\ + }\ + if (!skip_y) {\ + lh = ((double *)(left->buf + i)) + 1, rh = ((double *)(right->buf + i))[1];\ + ALGO;\ + }\ + if (!skip_z) {\ + lh = ((double *)(left->buf + i)) + 2, rh = ((double *)(right->buf + i))[2];\ + ALGO;\ + }\ + if (!skip_a) {\ + lh = ((double *)(left->buf + i)) + 3, rh = ((double *)(right->buf + i))[3];\ + ALGO;\ + }\ }\ } LIST_OPERATORS @@ -60,7 +73,25 @@ main(int argc, char *argv[]) struct stream left, right; process_func process = NULL; - ENOFLAGS(argc != 2); + ARGBEGIN { + case 'a': + skip_a = 1; + break; + case 'x': + skip_x = 1; + break; + case 'y': + skip_y = 1; + break; + case 'z': + skip_z = 1; + break; + default: + usage(); + } ARGEND; + + if (argc != 2) + usage(); left.file = "<stdin>"; left.fd = STDIN_FILENO; diff --git a/src/blind-dissolve.c b/src/blind-dissolve.c @@ -55,14 +55,14 @@ main(int argc, char *argv[]) stream.fd = STDIN_FILENO; stream.file = "<stdin>"; einit_stream(&stream); - fprint_stream_head(stdout, &stream); - efflush(stdout, "<stdout>"); if (!strcmp(stream.pixfmt, "xyza")) process = reverse ? process_xyza_r : process_xyza; else eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt); + fprint_stream_head(stdout, &stream); + efflush(stdout, "<stdout>"); fmd = fm = stream.frames - 1; process_each_frame_segmented(&stream, STDOUT_FILENO, "<stdout>", process); diff --git a/src/blind-invert-luma.c b/src/blind-invert-luma.c @@ -7,19 +7,29 @@ #include <string.h> #include <unistd.h> -USAGE("[-i] mask-stream") +USAGE("[-iw] mask-stream") static void process_xyza(struct stream *colour, struct stream *mask, size_t n) { size_t i; - double w, y; + double w, y, yo, X, Z; + X = D65_XYY_X / D65_XYY_Y; + Z = 1 / D65_XYY_Y - 1 - X; for (i = 0; i < n; i += colour->pixel_size) { w = ((double *)(mask->buf + i))[1]; w *= ((double *)(mask->buf + i))[3]; - y = ((double *)(colour->buf + i))[3]; - y = (1 - y) * w + y * (1 - w); - ((double *)(colour->buf + i))[3] = y; + yo = ((double *)(colour->buf + i))[1]; + y = (1 - yo) * w + yo * (1 - w); + ((double *)(colour->buf + i))[0] += (y - yo) * X; + ((double *)(colour->buf + i))[1] = y; + ((double *)(colour->buf + i))[2] += (y - yo) * Z; + /* + * Explaination: + * Y is the luma and ((X / Xn - Y / Yn), (Z / Zn - Y / Yn)) + * is the chroma (according to CIELAB), where (Xn, Yn, Zn) + * is the white point. + */ } } @@ -27,20 +37,60 @@ static void process_xyza_i(struct stream *colour, struct stream *mask, size_t n) { size_t i; - double w, y; + double w, y, yo, X, Z; + X = D65_XYY_X / D65_XYY_Y; + Z = 1 / D65_XYY_Y - 1 - X; for (i = 0; i < n; i += colour->pixel_size) { w = 1 - ((double *)(mask->buf + i))[1]; w *= ((double *)(mask->buf + i))[3]; - y = ((double *)(colour->buf + i))[3]; - y = (1 - y) * w + y * (1 - w); - ((double *)(colour->buf + i))[3] = y; + yo = ((double *)(colour->buf + i))[1]; + y = (1 - yo) * w + yo * (1 - w); + ((double *)(colour->buf + i))[0] += (y - yo) * X; + ((double *)(colour->buf + i))[1] = y; + ((double *)(colour->buf + i))[2] += (y - yo) * Z; + } +} + +static void +process_xyza_w(struct stream *colour, struct stream *mask, size_t n) +{ + size_t i; + double w, y, yo, X, Z; + for (i = 0; i < n; i += colour->pixel_size) { + X = ((double *)(mask->buf + i))[0]; + Z = ((double *)(mask->buf + i))[2]; + w = ((double *)(mask->buf + i))[1]; + w *= ((double *)(mask->buf + i))[3]; + yo = ((double *)(colour->buf + i))[1]; + y = (1 - yo) * w + yo * (1 - w); + ((double *)(colour->buf + i))[0] += (y - yo) * X; + ((double *)(colour->buf + i))[1] = y; + ((double *)(colour->buf + i))[2] += (y - yo) * Z; + } +} + +static void +process_xyza_iw(struct stream *colour, struct stream *mask, size_t n) +{ + size_t i; + double w, y, yo, X, Z; + for (i = 0; i < n; i += colour->pixel_size) { + X = ((double *)(mask->buf + i))[0]; + Z = ((double *)(mask->buf + i))[2]; + w = 1 - ((double *)(mask->buf + i))[1]; + w *= ((double *)(mask->buf + i))[3]; + yo = ((double *)(colour->buf + i))[1]; + y = (1 - yo) * w + yo * (1 - w); + ((double *)(colour->buf + i))[0] += (y - yo) * X; + ((double *)(colour->buf + i))[1] = y; + ((double *)(colour->buf + i))[2] += (y - yo) * Z; } } int main(int argc, char *argv[]) { - int invert = 0; + int invert = 0, whitepoint = 0; struct stream colour, mask; void (*process)(struct stream *colour, struct stream *mask, size_t n) = NULL; @@ -48,6 +98,9 @@ main(int argc, char *argv[]) case 'i': invert = 1; break; + case 'w': + whitepoint = 1; + break; default: usage(); } ARGEND; @@ -64,10 +117,13 @@ main(int argc, char *argv[]) einit_stream(&mask); if (!strcmp(colour.pixfmt, "xyza")) - process = invert ? process_xyza_i : process_xyza; + process = invert ? whitepoint ? process_xyza_iw : process_xyza_i + : whitepoint ? process_xyza_w : process_xyza; else eprintf("pixel format %s is not supported, try xyza\n", colour.pixfmt); + fprint_stream_head(stdout, &colour); + efflush(stdout, "<stdout>"); process_two_streams(&colour, &mask, STDOUT_FILENO, "<stdout>", process); return 0; } diff --git a/src/blind-set-alpha.c b/src/blind-set-alpha.c @@ -64,6 +64,8 @@ main(int argc, char *argv[]) else eprintf("pixel format %s is not supported, try xyza\n", colour.pixfmt); + fprint_stream_head(stdout, &colour); + efflush(stdout, "<stdout>"); process_two_streams(&colour, &alpha, STDOUT_FILENO, "<stdout>", process); return 0; } diff --git a/src/blind-set-luma.c b/src/blind-set-luma.c @@ -13,11 +13,44 @@ static void process_xyza(struct stream *colour, struct stream *luma, size_t n) { size_t i; - double a; + double a, y; for (i = 0; i < n; i += colour->pixel_size) { a = ((double *)(luma->buf + i))[1]; a *= ((double *)(luma->buf + i))[3]; - ((double *)(colour->buf + i))[1] *= a; + y = ((double *)(colour->buf + i))[1]; + ((double *)(colour->buf + i))[0] += y * a - y; + ((double *)(colour->buf + i))[1] = y * a; + ((double *)(colour->buf + i))[2] += y * a - y; + /* + * Note, this changes the luma only, not the saturation, + * so the result may look a bit weird. To change both + * you can use `blind-arithm mul`. + * + * Explaination: + * Y is the luma, but (X, Z) is not the chroma, + * but in CIELAB, L* is the luma and (a*, *b) is + * the chroma. Multiplying + * + * ⎛0 1 0⎞ + * ⎜1 −1 0⎟ + * ⎝0 1 −1⎠ + * + * (X Y Z)' gives a colour model similar to + * CIE L*a*b*: a model where each parameter is + * a linear transformation of the corresponding + * parameter in CIE L*a*b*. The inverse of that + * matrix is + * + * ⎛1 1 0⎞ + * ⎜1 0 0⎟ + * ⎝0 0 −1⎠ + * + * and + * + * ⎛1 1 0⎞⎛a 0 0⎞⎛0 1 0⎞ ⎛1 a−1 0⎞ + * ⎜1 0 0⎟⎜0 1 0⎟⎜1 −1 0⎟ = ⎜0 a 0⎟. + * ⎝0 0 −1⎠⎝0 0 1⎠⎝0 1 −1⎠ ⎝0 a−1 1⎠ + */ } } @@ -42,6 +75,8 @@ main(int argc, char *argv[]) else eprintf("pixel format %s is not supported, try xyza\n", colour.pixfmt); + fprint_stream_head(stdout, &colour); + efflush(stdout, "<stdout>"); process_two_streams(&colour, &luma, STDOUT_FILENO, "<stdout>", process); return 0; } diff --git a/src/blind-set-saturation.c b/src/blind-set-saturation.c @@ -13,16 +13,23 @@ static void process_xyza(struct stream *colour, struct stream *satur, size_t n) { size_t i; - double s, *x, *z, X, Z; + double s, *x, y, *z, X, Z; X = D65_XYY_X / D65_XYY_Y; Z = 1 / D65_XYY_Y - 1 - X; for (i = 0; i < n; i += colour->pixel_size) { s = ((double *)(satur->buf + i))[1]; s *= ((double *)(satur->buf + i))[3]; x = ((double *)(colour->buf + i)) + 0; + y = ((double *)(colour->buf + i))[1]; z = ((double *)(colour->buf + i)) + 2; - *x = (*x - X) * s + X; - *z = (*z - Z) * s + Z; + *x = ((*x / X - y) * s + y) * X; + *z = ((*z / Z - y) * s + y) * Z; + /* + * Explaination: + * Y is the luma and ((X / Xn - Y / Yn), (Z / Zn - Y / Yn)) + * is the chroma (according to CIELAB), where (Xn, Yn, Zn) + * is the white point. + */ } } @@ -30,16 +37,17 @@ static void process_xyza_w(struct stream *colour, struct stream *satur, size_t n) { size_t i; - double s, *x, *z, X, Z; + double s, *x, y, *z, X, Z; for (i = 0; i < n; i += colour->pixel_size) { X = ((double *)(satur->buf + i))[0]; Z = ((double *)(satur->buf + i))[2]; s = ((double *)(satur->buf + i))[1]; s *= ((double *)(satur->buf + i))[3]; x = ((double *)(colour->buf + i)) + 0; + y = ((double *)(colour->buf + i))[1]; z = ((double *)(colour->buf + i)) + 2; - *x = (*x - X) * s + X; - *z = (*z - Z) * s + Z; + *x = ((*x / X - y) * s + y) * X; + *z = ((*z / Z - y) * s + y) * Z; } } @@ -74,6 +82,8 @@ main(int argc, char *argv[]) else eprintf("pixel format %s is not supported, try xyza\n", colour.pixfmt); + fprint_stream_head(stdout, &colour); + efflush(stdout, "<stdout>"); process_two_streams(&colour, &satur, STDOUT_FILENO, "<stdout>", process); return 0; }