commit 1fdf6986e7bc23e2bdf4b2b7973652a2cb2dd3b7
Author:     Mattias Andrée <[email protected]>
AuthorDate: Wed Jul 12 03:40:51 2017 +0200
Commit:     Mattias Andrée <[email protected]>
CommitDate: Wed Jul 12 03:40:51 2017 +0200

    Add blind-apply-palette and blind-colour-ciexyz always outputs all three 
parameters
    
    Signed-off-by: Mattias Andrée <[email protected]>

diff --git a/Makefile b/Makefile
index f9ab6a3..749f41c 100644
--- 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
new file mode 100644
index 0000000..fa66096
--- /dev/null
+++ 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 < [email protected] >
diff --git a/man/blind-get-colours.1 b/man/blind-get-colours.1
index 6b9f82f..4153180 100644
--- 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
index 37365c0..bd4255f 100644
--- 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 < [email protected] >
diff --git a/src/blind-apply-palette.c b/src/blind-apply-palette.c
new file mode 100644
index 0000000..e75b31c
--- /dev/null
+++ 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
index e7b1448..602457e 100644
--- 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
index 763cae8..64f48c5 100644
--- 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;

Reply via email to