blind

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

commit 1fdf6986e7bc23e2bdf4b2b7973652a2cb2dd3b7
parent 975a02fba76fce7526278ea09a27cc0aae608d30
Author: Mattias Andrée <maandree@kth.se>
Date:   Wed, 12 Jul 2017 03:40:51 +0200

Add blind-apply-palette and blind-colour-ciexyz always outputs all three parameters

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

Diffstat:
Makefile | 1+
man/blind-apply-palette.1 | 23+++++++++++++++++++++++
man/blind-get-colours.1 | 1+
man/blind-repeat-tessellation.1 | 3++-
src/blind-apply-palette.c | 107+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/blind-chroma-key.c | 1+
src/blind-colour-ciexyz.c | 14++++++++++----
7 files changed, 145 insertions(+), 5 deletions(-)

diff --git a/Makefile b/Makefile @@ -2,6 +2,7 @@ CONFIGFILE = config.mk include $(CONFIGFILE) BIN =\ + blind-apply-palette\ blind-arithm\ blind-cat-cols\ blind-cat-rows\ diff --git a/man/blind-apply-palette.1 b/man/blind-apply-palette.1 @@ -0,0 +1,23 @@ +.TH BLIND-APPLY-PALETTE 1 blind +.SH NAME +blind-apply-palette - Apply a colour palette to a video +.SH SYNOPSIS +.B blind-apply-palette +.I palette-stream +.SH DESCRIPTION +.B blind-apply-palette +reads a video from stdin and video from +.IR palette-stream . +For each frame, the colours in the video from +stdin are replaces with the closest match colour +from the same from in the video in +.IR palette-stream . +The resulting video is printed to stdout. +.SH SEE ALSO +.BR blind (7), +.BR blind-repeat (1), +.BR blind-get-colours (1), +.BR blind-repeat-tessellation (1) +.SH AUTHORS +Mattias Andrée +.RI < maandree@kth.se > diff --git a/man/blind-get-colours.1 b/man/blind-get-colours.1 @@ -9,6 +9,7 @@ reads a video from stdin and prints a single-frame video to stdout contain all colours from the video. .SH SEE ALSO .BR blind (7), +.BR blind-apply-palette (1), .BR blind-repeat-tessellation (1) .SH AUTHORS Mattias Andrée diff --git a/man/blind-repeat-tessellation.1 b/man/blind-repeat-tessellation.1 @@ -29,7 +29,8 @@ the video from stdin into memory. A frame requires 32 bytes per pixel it contains. .SH SEE ALSO .BR blind (7), -.BR blind-get-colours (1) +.BR blind-get-colours (1), +.BR blind-apply-palette (1) .SH AUTHORS Mattias Andrée .RI < maandree@kth.se > diff --git a/src/blind-apply-palette.c b/src/blind-apply-palette.c @@ -0,0 +1,107 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + +USAGE("palette-stream") + + +static double (*compare)(double x1, double y1, double z1, double a1, double x2, double y2, double z2, double a2); +/* TODO add more formulae: https://en.wikipedia.org/wiki/Color_difference */ + + +static double +distance_xyz(double x1, double y1, double z1, double a1, double x2, double y2, double z2, double a2) +{ + x2 -= x1, x2 *= x2; + y2 -= y1, y2 *= y2; + z2 -= z1, z2 *= z2; + a2 -= a1, a2 *= a2; + return sqrt(x2 + y2 + z2 + a2); +} + + +#define PROCESS(TYPE, SUFFIX)\ + static void\ + process_##SUFFIX(struct stream *stream, struct stream *palette, char *pal)\ + {\ + size_t i, j, n, m;\ + size_t palsiz = palette->width * palette->height;\ + size_t best = 0;\ + TYPE x, y, z, a, lx = 0, ly = 0, lz = 0, la = 0;\ + TYPE cx, cy, cz, ca;\ + double distance, best_distance = 0;\ + while (eread_frame(palette, pal)) {\ + m = stream->frame_size;\ + do {\ + n = MIN(stream->ptr, m) / stream->pixel_size;\ + for (i = 0; i < n; i++) {\ + x = ((TYPE *)(stream->buf + i * stream->pixel_size))[0];\ + y = ((TYPE *)(stream->buf + i * stream->pixel_size))[1];\ + z = ((TYPE *)(stream->buf + i * stream->pixel_size))[2];\ + a = ((TYPE *)(stream->buf + i * stream->pixel_size))[3];\ + if ((!i && m == stream->frame_size) || x != lx || y != ly || z != lz || a != la) {\ + for (j = 0; j < palsiz; j++) {\ + cx = ((TYPE *)(pal + j * stream->pixel_size))[0];\ + cy = ((TYPE *)(pal + j * stream->pixel_size))[1];\ + cz = ((TYPE *)(pal + j * stream->pixel_size))[2];\ + ca = ((TYPE *)(pal + j * stream->pixel_size))[3];\ + distance = compare((double)x, (double)y, (double)z, (double)a,\ + (double)cx, (double)cy, (double)cz, (double)ca);\ + if (!j || distance < best_distance) {\ + best_distance = distance;\ + best = j;\ + }\ + }\ + lx = x, ly = y, lz = z, la = a;\ + }\ + memcpy(stream->buf + i * stream->pixel_size,\ + pal + best * stream->pixel_size,\ + stream->pixel_size);\ + }\ + m -= n *= stream->pixel_size;\ + ewriteall(STDOUT_FILENO, stream->buf, n, "<stdout>");\ + memmove(stream->buf, stream->buf + n, stream->ptr -= n);\ + } while (m && eread_stream(stream, SIZE_MAX));\ + if (m)\ + eprintf("%s: incomplete frame\n", stream->file);\ + }\ + } + +PROCESS(double, lf) +PROCESS(float, f) + + +int +main(int argc, char *argv[]) +{ + struct stream stream, palette; + void (*process)(struct stream *stream, struct stream *palette, char *pal); + char *pal; + + compare = distance_xyz; + + UNOFLAGS(argc != 1); + + eopen_stream(&stream, NULL); + eopen_stream(&palette, argv[0]); + + if (!strcmp(stream.pixfmt, "xyza")) + process = process_lf; + else if (!strcmp(stream.pixfmt, "xyza f")) + process = process_f; + else + eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt); + + if (strcmp(stream.pixfmt, palette.pixfmt)) + eprintf("videos use incompatible pixel formats\n"); + + echeck_dimensions(&stream, WIDTH | HEIGHT, NULL); + echeck_dimensions(&palette, WIDTH | HEIGHT, NULL); + pal = emalloc(palette.frame_size); + fprint_stream_head(stdout, &stream); + efflush(stdout, "<stdout>"); + + process(&stream, &palette, pal); + + free(pal); + return 0; +} diff --git a/src/blind-chroma-key.c b/src/blind-chroma-key.c @@ -27,6 +27,7 @@ USAGE("key-stream") z = z1 - keyxyza[6];\ a2 = keyxyza[7];\ variance2 = x * x + y * y + z * z;\ + /* TODO add more formulae: https://en.wikipedia.org/wiki/Color_difference */\ if (a2 > a1) {\ a1 = 1 - a1;\ a2 = 1 - a2;\ diff --git a/src/blind-colour-ciexyz.c b/src/blind-colour-ciexyz.c @@ -6,14 +6,20 @@ USAGE("(X Y Z | Y)") int main(int argc, char *argv[]) { + double X, Y, Z; + UNOFLAGS(0); - if (argc == 1) - printf("%s\n", argv[0]); - else if (argc == 3) + if (argc == 1) { + Y = etolf_arg("the Y value", argv[0]); + X = Y * D65_XYZ_X; + Z = Y * D65_XYZ_Z; + printf("%lf %lf %lf\n", X, Y, Z); + } else if (argc == 3) { printf("%s %s %s\n", argv[0], argv[1], argv[2]); - else + } else { usage(); + } efshut(stdout, "<stdout>"); return 0;