commit 975a02fba76fce7526278ea09a27cc0aae608d30
Author:     Mattias Andrée <[email protected]>
AuthorDate: Wed Jul 12 02:09:03 2017 +0200
Commit:     Mattias Andrée <[email protected]>
CommitDate: Wed Jul 12 02:09:03 2017 +0200

    Add blind-get-colours
    
    Signed-off-by: Mattias Andrée <[email protected]>

diff --git a/Makefile b/Makefile
index 87ecbe7..f9ab6a3 100644
--- a/Makefile
+++ b/Makefile
@@ -33,6 +33,7 @@ BIN =\
        blind-from-text\
        blind-from-video\
        blind-gauss-blur\
+       blind-get-colours\
        blind-interleave\
        blind-invert-luma\
        blind-linear-gradient\
diff --git a/README b/README
index eb2cd2e..0adf031 100644
--- a/README
+++ b/README
@@ -99,6 +99,9 @@ UTILITIES
        blind-gauss-blur(1)
               Apply Gaussian blur to a video
 
+       blind-get-colours(1)
+              Get a frame with all colours from a video
+
        blind-interleave(1)
               Framewise interleave videos
 
diff --git a/man/blind-get-colours.1 b/man/blind-get-colours.1
new file mode 100644
index 0000000..6b9f82f
--- /dev/null
+++ b/man/blind-get-colours.1
@@ -0,0 +1,15 @@
+.TH BLIND-GET-COLOURS 1 blind
+.SH NAME
+blind-get-colours - Get a frame with all colours from a video
+.SH SYNOPSIS
+.B blind-get-colours
+.SH DESCRIPTION
+.B blind-get-colours
+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-repeat-tessellation (1)
+.SH AUTHORS
+Mattias Andrée
+.RI < [email protected] >
diff --git a/man/blind-repeat-tessellation.1 b/man/blind-repeat-tessellation.1
index 9e34737..37365c0 100644
--- a/man/blind-repeat-tessellation.1
+++ b/man/blind-repeat-tessellation.1
@@ -28,7 +28,8 @@ requires enough free memory to load one full frame of
 the video from stdin into memory. A frame requires 32
 bytes per pixel it contains.
 .SH SEE ALSO
-.BR blind (7)
+.BR blind (7),
+.BR blind-get-colours (1)
 .SH AUTHORS
 Mattias Andrée
 .RI < [email protected] >
diff --git a/man/blind.7 b/man/blind.7
index 8d65ddd..e3965c8 100644
--- a/man/blind.7
+++ b/man/blind.7
@@ -115,6 +115,9 @@ Converts a regular, cooked video to a blind video
 .BR blind-gauss-blur (1)
 Apply Gaussian blur to a video
 .TP
+.BR blind-get-colours (1)
+Get a frame with all colours from a video
+.TP
 .BR blind-interleave (1)
 Framewise interleave videos
 .TP
diff --git a/src/blind-get-colours.c b/src/blind-get-colours.c
new file mode 100644
index 0000000..87d94b9
--- /dev/null
+++ b/src/blind-get-colours.c
@@ -0,0 +1,88 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+USAGE("")
+
+
+static size_t width;
+
+
+static int
+pixcmp(const void *a, const void *b)
+{
+       return memcmp(a, b, width);
+}
+
+
+static size_t
+unique(char *base, size_t n)
+{
+       size_t i, r = 1;
+       for (i = 1; i < n; i++)
+               if (pixcmp(base + (r - 1) * width, base + i * width) && r++ != 
i)
+                       memcpy(base + (r - 1) * width, base + i * width, width);
+       return r;
+}
+
+
+static size_t
+merge(char **sink, size_t n, char *new, size_t m, size_t *siz)
+{
+       size_t i, j;
+       int c;
+       for (i = j = 0; i < n && j < m; i++) {
+               c = pixcmp(*sink + i * width, new + j * width);
+               if (c > 0) {
+                       if (n == *siz) {
+                               *siz = n ? n * 2 : 8;
+                               *sink = erealloc2(*sink, *siz, width);
+                       }
+                       n += 1;
+                       memmove(*sink + (i + 1) * width, *sink + i * width, (n 
- i - 1) * width);
+                       memcpy(*sink + i * width, new + j * width, width);
+               }
+               j += c >= 0;
+       }
+       m -= j;
+       if (n + m > *siz) {
+               *siz = n + m;
+               *sink = erealloc2(*sink, *siz, width);
+       }
+       memcpy(*sink + n * width, new + j * width, m * width);
+       return n + m;
+}
+
+
+int
+main(int argc, char *argv[])
+{
+       struct stream stream;
+       char *colours = NULL;
+       size_t ptr = 0, siz = 0;
+       size_t n, m;
+
+       UNOFLAGS(argc);
+
+       eopen_stream(&stream, NULL);
+       width = stream.pixel_size;
+
+       do {
+               n = stream.ptr / width;
+
+               qsort(stream.buf, n, width, pixcmp);
+               m = unique(stream.buf, n);
+               ptr = merge(&colours, ptr, stream.buf, m, &siz);
+
+               n *= width;
+               memmove(stream.buf, stream.buf + n, stream.ptr -= n);
+       } while (eread_stream(&stream, SIZE_MAX));
+
+       stream.frames = 1;
+       stream.width = ptr;
+       stream.height = 1;
+       fprint_stream_head(stdout, &stream);
+       efflush(stdout, "<stdout>");
+       ewriteall(STDOUT_FILENO, colours, ptr * width, "<stdout>");
+
+       return 0;
+}

Reply via email to