URI: 
       Add blind-apply-palette and blind-colour-ciexyz always outputs all three parameters - blind - suckless command-line video editing utility
  HTML git clone git://git.suckless.org/blind
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
   DIR commit 1fdf6986e7bc23e2bdf4b2b7973652a2cb2dd3b7
   DIR parent 975a02fba76fce7526278ea09a27cc0aae608d30
  HTML 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:
         M Makefile                            |       1 +
         A man/blind-apply-palette.1           |      23 +++++++++++++++++++++++
         M man/blind-get-colours.1             |       1 +
         M man/blind-repeat-tessellation.1     |       3 ++-
         A src/blind-apply-palette.c           |     107 +++++++++++++++++++++++++++++++
         M src/blind-chroma-key.c              |       1 +
         M src/blind-colour-ciexyz.c           |      14 ++++++++++----
       
       7 files changed, 145 insertions(+), 5 deletions(-)
       ---
   DIR 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\
   DIR 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 >
   DIR 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
   DIR 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 >
   DIR 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;
       +}
   DIR 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;\
   DIR 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;