Misc code improvements - blind - suckless command-line video editing utility
 (HTM) git clone git://git.suckless.org/blind
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit d05d162cb81664f292834fa5d48d623d2b6147a7
 (DIR) parent c216ac3049102422a41ba2c9476b0dbf4f3e4034
 (HTM) Author: Mattias Andrée <maandree@kth.se>
       Date:   Sun, 16 Jul 2017 15:29:43 +0200
       
       Misc code improvements
       
       Signed-off-by: Mattias Andrée <maandree@kth.se>
       
       Diffstat:
         M src/blind-apply-palette.c           |       7 +------
         M src/blind-chroma-key.c              |       8 +-------
         M src/blind-cone-gradient.c           |      12 ++++--------
         M src/blind-coordinate-field.c        |      12 ++----------
         M src/blind-cross-product.c           |       8 +-------
         M src/blind-dot-product.c             |       8 +-------
         M src/blind-double-sine-wave.c        |       8 +-------
         M src/blind-dual-key.c                |       8 +-------
         M src/blind-extract-alpha.c           |       9 +--------
         M src/blind-find-rectangle.c          |       6 ++----
         M src/blind-flip.c                    |       2 +-
         M src/blind-from-named.c              |       3 ---
         M src/blind-from-portable.c           |      19 ++++++++-----------
         M src/blind-from-text.c               |      52 ++++++++++++++++----------------
         M src/blind-gauss-blur.c              |      18 ++++++------------
         M src/blind-get-colours.c             |       2 --
         M src/blind-hexagon-tessellation.c    |      15 +++++----------
         M src/blind-linear-gradient.c         |      12 ++++--------
         M src/blind-matrix-orthoproject.c     |       9 ++-------
         M src/blind-matrix-reflect.c          |       9 ++-------
         M src/blind-matrix-rotate.c           |       9 ++-------
         M src/blind-matrix-scale.c            |       9 ++-------
         M src/blind-matrix-shear.c            |       9 ++-------
         M src/blind-matrix-translate.c        |       9 ++-------
         M src/blind-matrix-transpose.c        |       9 ++-------
         M src/blind-mosaic-edges.c            |      66 +++++++++++++++----------------
         M src/blind-mosaic.c                  |       9 +--------
         M src/blind-multiply-matrices.c       |       7 +------
         M src/blind-next-frame.c              |      10 ++--------
         M src/blind-norm.c                    |       8 +-------
         M src/blind-premultiply.c             |       8 +-------
         M src/blind-quaternion-product.c      |       8 +-------
         M src/blind-radial-gradient.c         |      15 ++++++---------
         M src/blind-rectangle-tessellation.c  |      16 ++++++----------
         M src/blind-reverse.c                 |       4 +---
         M src/blind-rewrite-head.c            |       7 +------
         M src/blind-round-wave.c              |       8 +-------
         M src/blind-sawtooth-wave.c           |       8 +-------
         M src/blind-set-luma.c                |       8 +-------
         M src/blind-sinc-wave.c               |       7 +------
         M src/blind-sine-wave.c               |       8 +-------
         M src/blind-single-colour.c           |      10 ++--------
         M src/blind-spectrum.c                |       9 ++-------
         M src/blind-spiral-gradient.c         |      12 ++++--------
         M src/blind-square-gradient.c         |       7 +------
         M src/blind-time-blur.c               |      10 ++--------
         M src/blind-to-portable.c             |       9 ++-------
         M src/blind-to-text.c                 |      35 +++++++++++++++----------------
         M src/blind-triangle-tessellation.c   |      15 +++++----------
         M src/blind-triangular-wave.c         |       8 +-------
         M src/blind-unpremultiply.c           |       8 +-------
         M src/blind-vector-projection.c       |       8 +-------
         M src/common.h                        |       8 ++++++++
         M src/define-functions.h              |      12 ++++++++++++
         M src/stream.c                        |      24 ++++++++++++++++++------
         M src/stream.h                        |       6 +++---
       
       56 files changed, 216 insertions(+), 434 deletions(-)
       ---
 (DIR) diff --git a/src/blind-apply-palette.c b/src/blind-apply-palette.c
       @@ -34,12 +34,7 @@ main(int argc, char *argv[])
                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);
       +        SELECT_PROCESS_FUNCTION(&stream);
        
                if (strcmp(stream.pixfmt, palette.pixfmt))
                        eprintf("videos use incompatible pixel formats\n");
 (DIR) diff --git a/src/blind-chroma-key.c b/src/blind-chroma-key.c
       @@ -18,13 +18,7 @@ main(int argc, char *argv[])
                eopen_stream(&stream, NULL);
                eopen_stream(&key, 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);
       -
       +        SELECT_PROCESS_FUNCTION(&stream);
                if (strcmp(stream.pixfmt, key.pixfmt))
                        eprintf("videos use incompatible pixel formats\n");
        
 (DIR) diff --git a/src/blind-cone-gradient.c b/src/blind-cone-gradient.c
       @@ -41,12 +41,7 @@ main(int argc, char *argv[])
        
                eopen_stream(&stream, NULL);
        
       -        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);
       +        SELECT_PROCESS_FUNCTION(&stream);
        
                if (stream.width > 3 || stream.height > 3 ||
                    stream.width * stream.height < 2 ||
       @@ -72,7 +67,7 @@ PROCESS(struct stream *stream)
                pixel_t buf[BUFSIZ / sizeof(pixel_t)];
                TYPE *params, x1, y1, x2, y2;
                TYPE x, y, u, v, m = 1;
       -        size_t ix, iy, ptr = 0;
       +        size_t i, ix, iy, ptr = 0;
        
                for (;;) {
                        while (stream->ptr < stream->frame_size) {
       @@ -116,7 +111,8 @@ PROCESS(struct stream *stream)
                                                                v = 2 - v;
                                                }
                                        }
       -                                buf[ptr][0] = buf[ptr][1] = buf[ptr][2] = buf[ptr][3] = v;
       +                                for (i = 0; i < stream->n_chan; i++)
       +                                        buf[ptr][i] = x;
                                        if (++ptr == ELEMENTSOF(buf)) {
                                                ewriteall(STDOUT_FILENO, buf, sizeof(buf), "<stdout>");
                                                ptr = 0;
 (DIR) diff --git a/src/blind-coordinate-field.c b/src/blind-coordinate-field.c
       @@ -44,18 +44,10 @@ main(int argc, char *argv[])
                if (inf)
                        einf_check_fd(STDOUT_FILENO, "<stdout>");
        
       -        pixfmt = get_pixel_format(pixfmt, "xyza");
       -        if (!strcmp(pixfmt, "xyza"))
       -                process = process_lf;
       -        else if (!strcmp(pixfmt, "xyza f"))
       -                process = process_f;
       -        else
       -                eprintf("pixel format %s is not supported, try xyza\n", pixfmt);
       -
       -        strcpy(stream.pixfmt, pixfmt);
       +        eset_pixel_format(&stream, pixfmt);
       +        SELECT_PROCESS_FUNCTION(&stream);
                fprint_stream_head(stdout, &stream);
                efflush(stdout, "<stdout>");
       -
                process();
                return 0;
        }
 (DIR) diff --git a/src/blind-cross-product.c b/src/blind-cross-product.c
       @@ -18,13 +18,7 @@ main(int argc, char *argv[])
                eopen_stream(&left, NULL);
                eopen_stream(&right, argv[0]);
        
       -        if (left.encoding == DOUBLE)
       -                process = process_lf;
       -        else if (left.encoding == FLOAT)
       -                process = process_f;
       -        else
       -                eprintf("pixel format %s is not supported, try xyza\n", left.pixfmt);
       -
       +        SELECT_PROCESS_FUNCTION(&left);
                fprint_stream_head(stdout, &left);
                efflush(stdout, "<stdout>");
                process_two_streams(&left, &right, STDOUT_FILENO, "<stdout>", process);
 (DIR) diff --git a/src/blind-dot-product.c b/src/blind-dot-product.c
       @@ -18,13 +18,7 @@ main(int argc, char *argv[])
                eopen_stream(&left, NULL);
                eopen_stream(&right, argv[0]);
        
       -        if (left.encoding == DOUBLE)
       -                process = process_lf;
       -        else if (left.encoding == FLOAT)
       -                process = process_f;
       -        else
       -                eprintf("pixel format %s is not supported, try xyza\n", left.pixfmt);
       -
       +        SELECT_PROCESS_FUNCTION(&left);
                fprint_stream_head(stdout, &left);
                efflush(stdout, "<stdout>");
                process_two_streams(&left, &right, STDOUT_FILENO, "<stdout>", process);
 (DIR) diff --git a/src/blind-double-sine-wave.c b/src/blind-double-sine-wave.c
       @@ -28,13 +28,7 @@ main(int argc, char *argv[])
        
                eopen_stream(&stream, NULL);
        
       -        if (stream.encoding == DOUBLE)
       -                process = process_lf;
       -        else if (stream.encoding == FLOAT)
       -                process = process_f;
       -        else
       -                eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt);
       -
       +        SELECT_PROCESS_FUNCTION(&stream);
                fprint_stream_head(stdout, &stream);
                efflush(stdout, "<stdout>");
                process(&stream);
 (DIR) diff --git a/src/blind-dual-key.c b/src/blind-dual-key.c
       @@ -28,13 +28,7 @@ main(int argc, char *argv[])
                eopen_stream(&stream, NULL);
                eopen_stream(&dual, argv[6]);
        
       -        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);
       -
       +        SELECT_PROCESS_FUNCTION(&stream);
                fprint_stream_head(stdout, &stream);
                efflush(stdout, "<stdout>");
                process_two_streams(&stream, &dual, STDOUT_FILENO, "<stdout>", process);
 (DIR) diff --git a/src/blind-extract-alpha.c b/src/blind-extract-alpha.c
       @@ -19,18 +19,11 @@ main(int argc, char *argv[])
                eopen_stream(&stream, NULL);
                fd = eopen(argv[0], O_WRONLY | O_CREAT | O_TRUNC, 0666);
        
       -        if (stream.encoding == DOUBLE)
       -                process = process_lf;
       -        else if (stream.encoding == FLOAT)
       -                process = process_f;
       -        else
       -                eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt);
       -
       +        SELECT_PROCESS_FUNCTION(&stream);
                fprint_stream_head(stdout, &stream);
                efflush(stdout, "<stdout>");
                if (dprint_stream_head(fd, &stream) < 0)
                        eprintf("dprintf %s:", argv[0]);
       -
                process(&stream, fd, argv[0]);
                return 0;
        }
 (DIR) diff --git a/src/blind-find-rectangle.c b/src/blind-find-rectangle.c
       @@ -9,7 +9,6 @@ struct pair {
        };
        
        static struct stream stream;
       -static double X, Y, Z, alpha = 1;
        static size_t min_width = 1;
        static size_t min_height = 1;
        static size_t min_area = 1;
       @@ -76,6 +75,7 @@ main(int argc, char *argv[])
        {
                double colour_lf[4];
                float colour_f[4];
       +        double X, Y, Z, alpha = 1;
        
                ARGBEGIN {
                case 'a':
       @@ -117,14 +117,12 @@ main(int argc, char *argv[])
                        colour_lf[2] = Z;
                        colour_lf[3] = alpha;
                        process(colour_lf);
       -        } else if (stream.encoding == FLOAT) {
       +        } else {
                        colour_f[0] = (float)X;
                        colour_f[1] = (float)Y;
                        colour_f[2] = (float)Z;
                        colour_f[3] = (float)alpha;
                        process(colour_f);
       -        } else {
       -                eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt);
                }
        
                fshut(stdout, "<stdout>");
 (DIR) diff --git a/src/blind-flip.c b/src/blind-flip.c
       @@ -21,7 +21,7 @@ main(int argc, char *argv[])
                while (eread_frame(&stream, buf))
                        for (ptr = stream.frame_size; ptr;)
                                ewriteall(STDOUT_FILENO, buf + (ptr -= stream.row_size),
       -                                  stream.row_size, "<stdout>");
       +                                  stream.row_size, "<stdout>");
                /* ewriteall is faster than writev(3) and vmsplice(3) */
        
                free(buf);
 (DIR) diff --git a/src/blind-from-named.c b/src/blind-from-named.c
       @@ -40,9 +40,6 @@ erecv_fd(int sock)
        }
        
        #if !defined(HAVE_SENDFILE)
       -# if !defined(PIPE_BUF)
       -#  define PIPE_BUF BUFSIZ
       -# endif
        static ssize_t
        sendfile(int outfd, int infd, off_t *offset, size_t count)
        {
 (DIR) diff --git a/src/blind-from-portable.c b/src/blind-from-portable.c
       @@ -3,6 +3,8 @@
        
        USAGE("[-s]")
        
       +static int strict = 1;
       +
        #define CONV(ITYPE, SITYPE, OTYPE, EXPONENT, HA2EXPONENT, FRACTION)\
                do {\
                        static int cache_i = 0;\
       @@ -74,15 +76,14 @@ USAGE("[-s]")
        static double conv_double(uint64_t portable) {CONV(uint64_t, int64_t, double, 11, 1023, 52);}
        static float  conv_float (uint32_t portable) {CONV(uint32_t, int32_t, float,   8,  127, 23);}
        
       -static void process_lf(struct stream *stream, int strict) {PROCESS(uint64_t, double, 64);}
       -static void process_f (struct stream *stream, int strict) {PROCESS(uint32_t, float,  32);}
       +static void process_lf(struct stream *stream) {PROCESS(uint64_t, double, 64);}
       +static void process_f (struct stream *stream) {PROCESS(uint32_t, float,  32);}
        
        int
        main(int argc, char *argv[])
        {
                struct stream stream;
       -        int strict = 1;
       -        void (*process)(struct stream *stream, int strict);
       +        void (*process)(struct stream *stream);
        
                ARGBEGIN {
                case 's':
       @@ -91,20 +92,16 @@ main(int argc, char *argv[])
                default:
                        usage();
                } ARGEND;
       +
                if (argc)
                        usage();
        
                eopen_stream(&stream, NULL);
        
       -        if (stream.encoding == DOUBLE)
       -                process = process_lf;
       -        else if (stream.encoding == FLOAT)
       -                process = process_f;
       -        else
       -                eprintf("pixel format %s is not supported\n", stream.pixfmt);
       +        SELECT_PROCESS_FUNCTION(&stream);
        
                fprint_stream_head(stdout, &stream);
                efflush(stdout, "<stdout>");
       -        process(&stream, strict);
       +        process(&stream);
                return 0;
        }
 (DIR) diff --git a/src/blind-from-text.c b/src/blind-from-text.c
       @@ -1,27 +1,11 @@
        /* See LICENSE file for copyright and license details. */
       +#ifndef TYPE
        #include "common.h"
        
        USAGE("")
        
       -#define PROCESS(TYPE, FMT)\
       -        do {\
       -                TYPE buf[BUFSIZ / sizeof(TYPE)];\
       -                size_t i;\
       -                int r, done = 0;\
       -                while (!done) {\
       -                        for (i = 0; i < ELEMENTSOF(buf); i += (size_t)r) {\
       -                                r = scanf("%"FMT, buf + i);\
       -                                if (r == EOF) {\
       -                                        done = 1;\
       -                                        break;\
       -                                }\
       -                        }\
       -                        ewriteall(STDOUT_FILENO, buf, i * sizeof(*buf), "<stdout>");\
       -                }\
       -        } while (0)
       -
       -static void process_lf(void) { PROCESS(double, "lf"); }
       -static void process_f(void)  { PROCESS(float,  "f");  }
       +#define FILE "blind-from-text.c"
       +#include "define-functions.h"
        
        int
        main(int argc, char *argv[])
       @@ -54,15 +38,31 @@ main(int argc, char *argv[])
                ewriteall(STDOUT_FILENO, stream.buf, stream.ptr, "<stdout>");
                einit_stream(&stream);
        
       -        if (stream.encoding == DOUBLE)
       -                process = process_lf;
       -        else if (stream.encoding == FLOAT)
       -                process = process_f;
       -        else
       -                eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt);
       -
       +        SELECT_PROCESS_FUNCTION(&stream);
                process();
        
                efshut(stdin, "<stdin>");
                return 0;
        }
       +
       +#else
       +
       +static void
       +PROCESS(void)
       +{
       +        TYPE buf[BUFSIZ / sizeof(TYPE)];
       +        size_t i;
       +        int r, done = 0;
       +        while (!done) {
       +                for (i = 0; i < ELEMENTSOF(buf); i += (size_t)r) {
       +                        r = scanf("%"SCAN_TYPE, buf + i);
       +                        if (r == EOF) {
       +                                done = 1;
       +                                break;
       +                        }
       +                }
       +                ewriteall(STDOUT_FILENO, buf, i * sizeof(*buf), "<stdout>");
       +        }
       +}
       +
       +#endif
 (DIR) diff --git a/src/blind-gauss-blur.c b/src/blind-gauss-blur.c
       @@ -273,15 +273,15 @@ static size_t spread = 0;
                } while (0)
        
        static void
       -process_xyza(char *restrict output, char *restrict cbuf, char *restrict sbuf,
       -             struct stream *colour, struct stream *sigma)
       +process_lf(char *restrict output, char *restrict cbuf, char *restrict sbuf,
       +           struct stream *colour, struct stream *sigma)
        {
                PROCESS(double);
        }
        
        static void
       -process_xyzaf(char *restrict output, char *restrict cbuf, char *restrict sbuf,
       -             struct stream *colour, struct stream *sigma)
       +process_f(char *restrict output, char *restrict cbuf, char *restrict sbuf,
       +          struct stream *colour, struct stream *sigma)
        {
                PROCESS(float);
        }
       @@ -292,7 +292,7 @@ main(int argc, char *argv[])
                struct stream colour, sigma;
                char *arg;
                void (*process)(char *restrict output, char *restrict cbuf, char *restrict sbuf,
       -                        struct stream *colour, struct stream *sigma);
       +                        struct stream *colour, struct stream *sigma);
        
                ARGBEGIN {
                case 'a':
       @@ -333,12 +333,7 @@ main(int argc, char *argv[])
                eopen_stream(&colour, NULL);
                eopen_stream(&sigma, argv[0]);
        
       -        if (!strcmp(colour.pixfmt, "xyza"))
       -                process = process_xyza;
       -        else if (!strcmp(colour.pixfmt, "xyza f"))
       -                process = process_xyzaf;
       -        else
       -                eprintf("pixel format %s is not supported, try xyza\n", colour.pixfmt);
       +        SELECT_PROCESS_FUNCTION(&colour);
        
                echeck_compat(&colour, &sigma);
        
       @@ -348,6 +343,5 @@ main(int argc, char *argv[])
                fprint_stream_head(stdout, &colour);
                efflush(stdout, "<stdout>");
                process_each_frame_two_streams(&colour, &sigma, STDOUT_FILENO, "<stdout>", process);
       -
                return 0;
        }
 (DIR) diff --git a/src/blind-get-colours.c b/src/blind-get-colours.c
       @@ -63,11 +63,9 @@ main(int argc, char *argv[])
        
                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));
 (DIR) diff --git a/src/blind-hexagon-tessellation.c b/src/blind-hexagon-tessellation.c
       @@ -4,8 +4,7 @@
        USAGE("[-F pixel-format] block-diameter")
        
        #define SET_XYZA(TYPE)\
       -        (pixwidth *= sizeof(double),\
       -         colours = alloca(4 * pixwidth),\
       +        (colours = alloca(4 * stream.pixel_size),\
                 ((TYPE *)colours)[ 0] = (TYPE)0.412457445582367600,\
                 ((TYPE *)colours)[ 1] = (TYPE)0.212673370378408280,\
                 ((TYPE *)colours)[ 2] = (TYPE)0.019333942761673460,\
       @@ -30,7 +29,6 @@ main(int argc, char *argv[])
        {
                size_t diameter;
                const char *pixfmt = "xyza";
       -        size_t pixwidth = 4;
                char *colours;
                size_t x, y, y2;
                int k;
       @@ -48,15 +46,12 @@ main(int argc, char *argv[])
        
                diameter = etozu_arg("block-diameter", argv[0], 1, SIZE_MAX);
        
       -        pixfmt = get_pixel_format(pixfmt, "xyza");
       -        if (!strcmp(pixfmt, "xyza"))
       +        eset_pixel_format(&stream, pixfmt);
       +        if (stream.encoding == DOUBLE)
                        SET_XYZA(double);
       -        else if (!strcmp(pixfmt, "xyza f"))
       -                SET_XYZA(float);
                else
       -                eprintf("pixel format %s is not supported, try xyza\n", pixfmt);
       +                SET_XYZA(float);
        
       -        strcpy(stream.pixfmt, pixfmt);
                stream.width  = (size_t)((double)diameter * sqrt(3.));
                stream.height = diameter * 3 / 2;
                fprint_stream_head(stdout, &stream);
       @@ -100,7 +95,7 @@ main(int argc, char *argv[])
                                } else {
                                        k = (stream.width <= x * 4 && x * 4 < stream.width * 3) + 2;
                                }
       -                        ewriteall(STDOUT_FILENO, colours + (size_t)k * pixwidth, pixwidth, "<stdout>");
       +                        ewriteall(STDOUT_FILENO, colours + (size_t)k * stream.pixel_size, stream.pixel_size, "<stdout>");
                        }
                }
        
 (DIR) diff --git a/src/blind-linear-gradient.c b/src/blind-linear-gradient.c
       @@ -36,12 +36,7 @@ main(int argc, char *argv[])
        
                eopen_stream(&stream, NULL);
        
       -        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);
       +        SELECT_PROCESS_FUNCTION(&stream);
        
                if (stream.width > 2 || stream.height > 2 || stream.width * stream.height != 2)
                        eprintf("<stdin>: each frame must contain exactly 2 pixels\n");
       @@ -63,7 +58,7 @@ PROCESS(struct stream *stream)
                pixel_t buf[BUFSIZ / sizeof(pixel_t)];
                TYPE *params, x1, y1, x2, y2, norm2;
                TYPE x, y;
       -        size_t ix, iy, ptr = 0;
       +        size_t i, ix, iy, ptr = 0;
        
                for (;;) {
                        while (stream->ptr < stream->frame_size) {
       @@ -91,7 +86,8 @@ PROCESS(struct stream *stream)
                                        x = (x * x2 + y * y2) / norm2;
                                        if (bilinear)
                                                x = abs(x);
       -                                buf[ptr][0] = buf[ptr][1] = buf[ptr][2] = buf[ptr][3] = x;
       +                                for (i = 0; i < stream->n_chan; i++)
       +                                        buf[ptr][i] = x;
                                        if (++ptr == ELEMENTSOF(buf)) {
                                                ewriteall(STDOUT_FILENO, buf, sizeof(buf), "<stdout>");
                                                ptr = 0;
 (DIR) diff --git a/src/blind-matrix-orthoproject.c b/src/blind-matrix-orthoproject.c
       @@ -28,6 +28,8 @@ main(int argc, char *argv[])
        
                eopen_stream(&stream, NULL);
        
       +        SELECT_PROCESS_FUNCTION(&stream);
       +
                if (stream.width > 2 || stream.height > 2 || stream.width * stream.height != 2)
                        eprintf("<stdin>: each frame must contain exactly 2 pixels\n");
        
       @@ -36,13 +38,6 @@ main(int argc, char *argv[])
                fprint_stream_head(stdout, &stream);
                efflush(stdout, "<stdout>");
        
       -        if (stream.encoding == DOUBLE)
       -                process = process_lf;
       -        else if (stream.encoding == FLOAT)
       -                process = process_f;
       -        else
       -                eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt);
       -
                process(&stream);
                return 0;
        }
 (DIR) diff --git a/src/blind-matrix-reflect.c b/src/blind-matrix-reflect.c
       @@ -28,6 +28,8 @@ main(int argc, char *argv[])
        
                eopen_stream(&stream, NULL);
        
       +        SELECT_PROCESS_FUNCTION(&stream);
       +
                if (stream.width > 2 || stream.height > 2 || stream.width * stream.height != 2)
                        eprintf("<stdin>: each frame must contain exactly 2 pixels\n");
        
       @@ -36,13 +38,6 @@ main(int argc, char *argv[])
                fprint_stream_head(stdout, &stream);
                efflush(stdout, "<stdout>");
        
       -        if (stream.encoding == DOUBLE)
       -                process = process_lf;
       -        else if (stream.encoding == FLOAT)
       -                process = process_f;
       -        else
       -                eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt);
       -
                process(&stream);
                return 0;
        }
 (DIR) diff --git a/src/blind-matrix-rotate.c b/src/blind-matrix-rotate.c
       @@ -32,6 +32,8 @@ main(int argc, char *argv[])
        
                eopen_stream(&stream, NULL);
        
       +        SELECT_PROCESS_FUNCTION(&stream);
       +
                if (stream.width != 1 || stream.height != 1)
                        eprintf("<stdin>: each frame must contain exactly 1 pixels\n");
        
       @@ -40,13 +42,6 @@ main(int argc, char *argv[])
                fprint_stream_head(stdout, &stream);
                efflush(stdout, "<stdout>");
        
       -        if (stream.encoding == DOUBLE)
       -                process = process_lf;
       -        else if (stream.encoding == FLOAT)
       -                process = process_f;
       -        else
       -                eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt);
       -
                process(&stream);
                return 0;
        }
 (DIR) diff --git a/src/blind-matrix-scale.c b/src/blind-matrix-scale.c
       @@ -28,6 +28,8 @@ main(int argc, char *argv[])
        
                eopen_stream(&stream, NULL);
        
       +        SELECT_PROCESS_FUNCTION(&stream);
       +
                if (stream.width > 2 || stream.height > 2 || stream.width * stream.height != 2)
                        eprintf("<stdin>: each frame must contain exactly 2 pixels\n");
        
       @@ -36,13 +38,6 @@ main(int argc, char *argv[])
                fprint_stream_head(stdout, &stream);
                efflush(stdout, "<stdout>");
        
       -        if (stream.encoding == DOUBLE)
       -                process = process_lf;
       -        else if (stream.encoding == FLOAT)
       -                process = process_f;
       -        else
       -                eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt);
       -
                process(&stream);
                return 0;
        }
 (DIR) diff --git a/src/blind-matrix-shear.c b/src/blind-matrix-shear.c
       @@ -36,6 +36,8 @@ main(int argc, char *argv[])
        
                eopen_stream(&stream, NULL);
        
       +        SELECT_PROCESS_FUNCTION(&stream);
       +
                if (stream.width > 2 || stream.height > 2 || stream.width * stream.height != 2)
                        eprintf("<stdin>: each frame must contain exactly 2 pixels\n");
        
       @@ -44,13 +46,6 @@ main(int argc, char *argv[])
                fprint_stream_head(stdout, &stream);
                efflush(stdout, "<stdout>");
        
       -        if (stream.encoding == DOUBLE)
       -                process = process_lf;
       -        else if (stream.encoding == FLOAT)
       -                process = process_f;
       -        else
       -                eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt);
       -
                process(&stream);
                return 0;
        }
 (DIR) diff --git a/src/blind-matrix-translate.c b/src/blind-matrix-translate.c
       @@ -28,6 +28,8 @@ main(int argc, char *argv[])
        
                eopen_stream(&stream, NULL);
        
       +        SELECT_PROCESS_FUNCTION(&stream);
       +
                if (stream.width > 2 || stream.height > 2 || stream.width * stream.height != 2)
                        eprintf("<stdin>: each frame must contain exactly 2 pixels\n");
        
       @@ -36,13 +38,6 @@ main(int argc, char *argv[])
                fprint_stream_head(stdout, &stream);
                efflush(stdout, "<stdout>");
        
       -        if (stream.encoding == DOUBLE)
       -                process = process_lf;
       -        else if (stream.encoding == FLOAT)
       -                process = process_f;
       -        else
       -                eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt);
       -
                process(&stream);
                return 0;
        }
 (DIR) diff --git a/src/blind-matrix-transpose.c b/src/blind-matrix-transpose.c
       @@ -28,6 +28,8 @@ main(int argc, char *argv[])
        
                eopen_stream(&stream, NULL);
        
       +        SELECT_PROCESS_FUNCTION(&stream);
       +
                if (stream.width != 1 || stream.height != 1)
                        eprintf("<stdin>: each frame must contain exactly 1 pixels\n");
        
       @@ -36,13 +38,6 @@ main(int argc, char *argv[])
                fprint_stream_head(stdout, &stream);
                efflush(stdout, "<stdout>");
        
       -        if (stream.encoding == DOUBLE)
       -                process = process_lf;
       -        else if (stream.encoding == FLOAT)
       -                process = process_f;
       -        else
       -                eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt);
       -
                process(&stream);
                return 0;
        }
 (DIR) diff --git a/src/blind-mosaic-edges.c b/src/blind-mosaic-edges.c
       @@ -10,9 +10,7 @@ main(int argc, char *argv[])
                int tiled_y = 0;
                struct stream stream;
                void *colours[2];
       -        char *buf;
       -        char *edges;
       -        char *here;
       +        char *buf, *edges, *here;
                size_t i, n, x, y;
                int v;
        
       @@ -65,37 +63,37 @@ main(int argc, char *argv[])
                                x = i % stream.width;
                                y = i / stream.width;
        
       -                        if (x != stream.width - 1 &&
       -                            memcmp(here + stream.pixel_size, here, stream.pixel_size))
       -                                goto at_edge;
       -
       -                        if (tiled_x && x == stream.width - 1 &&
       -                            memcmp(here + stream.pixel_size - stream.row_size, here, stream.pixel_size))
       -                                goto at_edge;
       -
       -                        if (x &&
       -                            memcmp(here - stream.pixel_size, here, stream.pixel_size))
       -                                goto at_edge;
       -
       -                        if (tiled_x && !x &&
       -                            memcmp(here + stream.row_size - stream.pixel_size, here, stream.pixel_size))
       -                                goto at_edge;
       -
       -                        if (y != stream.height - 1 &&
       -                            memcmp(here + stream.row_size, here, stream.pixel_size))
       -                                goto at_edge;
       -
       -                        if (tiled_y && y == stream.height - 1 &&
       -                            memcmp(here + stream.row_size - stream.frame_size, here, stream.pixel_size))
       -                                goto at_edge;
       -
       -                        if (y &&
       -                            memcmp(here - stream.row_size, here, stream.pixel_size))
       -                                goto at_edge;
       -
       -                        if (tiled_y && !y &&
       -                            memcmp(here + stream.frame_size - stream.row_size, here, stream.pixel_size))
       -                                goto at_edge;
       +                        if (x != stream.width - 1) {
       +                                if (memcmp(here + stream.pixel_size, here, stream.pixel_size))
       +                                        goto at_edge;
       +                        } else if (tiled_x) {
       +                                if (memcmp(here + stream.pixel_size - stream.row_size, here, stream.pixel_size))
       +                                        goto at_edge;
       +                        }
       +
       +                        if (x) {
       +                                if (memcmp(here - stream.pixel_size, here, stream.pixel_size))
       +                                        goto at_edge;
       +                        } else if (tiled_x) {
       +                                if (memcmp(here + stream.row_size - stream.pixel_size, here, stream.pixel_size))
       +                                        goto at_edge;
       +                        }
       +
       +                        if (y != stream.height - 1) {
       +                                if (memcmp(here + stream.row_size, here, stream.pixel_size))
       +                                        goto at_edge;
       +                        } else if (tiled_y) {
       +                                if (memcmp(here + stream.row_size - stream.frame_size, here, stream.pixel_size))
       +                                        goto at_edge;
       +                        }
       +
       +                        if (y) {
       +                                if (memcmp(here - stream.row_size, here, stream.pixel_size))
       +                                        goto at_edge;
       +                        } else if (tiled_y) {
       +                                if (memcmp(here + stream.frame_size - stream.row_size, here, stream.pixel_size))
       +                                        goto at_edge;
       +                        }
        
                                continue;
                        at_edge:
 (DIR) diff --git a/src/blind-mosaic.c b/src/blind-mosaic.c
       @@ -157,18 +157,11 @@ main(int argc, char *argv[])
                eopen_stream(&colour, NULL);
                eopen_stream(&mosaic, argv[0]);
        
       -        if (!strcmp(colour.pixfmt, "xyza"))
       -                process = process_lf;
       -        else if (!strcmp(colour.pixfmt, "xyza f"))
       -                process = process_f;
       -        else
       -                eprintf("pixel format %s is not supported, try xyza\n", colour.pixfmt);
       -
       +        SELECT_PROCESS_FUNCTION(&colour);
                echeck_compat(&colour, &mosaic);
        
                fprint_stream_head(stdout, &colour);
                efflush(stdout, "<stdout>");
                process_each_frame_two_streams(&colour, &mosaic, STDOUT_FILENO, "<stdout>", process);
       -
                return 0;
        }
 (DIR) diff --git a/src/blind-multiply-matrices.c b/src/blind-multiply-matrices.c
       @@ -66,12 +66,7 @@ main(int argc, char *argv[])
                        height = streams[i].height;
                }
        
       -        if (streams->encoding == DOUBLE)
       -                process = process_lf;
       -        else if (streams->encoding == FLOAT)
       -                process = process_f;
       -        else
       -                eprintf("pixel format %s is not supported, try xyza\n", streams->pixfmt);
       +        SELECT_PROCESS_FUNCTION(streams);
        
                w = streams->width,  streams->width  = max_width;
                h = streams->height, streams->height = max_height;
 (DIR) diff --git a/src/blind-next-frame.c b/src/blind-next-frame.c
       @@ -6,13 +6,11 @@ USAGE("[-f frames] width height pixel-format ...")
        int
        main(int argc, char *argv[])
        {
       -        struct stream stream;
       +        struct stream stream = { .frames = 1, .fd = STDIN_FILENO, .file = "<stdin>" };
                size_t n;
                int i;
                char *p;
        
       -        stream.frames = 1;
       -
                ARGBEGIN {
                case 'f':
                        stream.frames = entozu_flag(2, 'f', UARGF(), 1, SIZE_MAX);
       @@ -24,10 +22,7 @@ main(int argc, char *argv[])
                if (argc < 3)
                        usage();
        
       -        stream.fd = STDIN_FILENO;
       -        stream.file = "<stdin>";
                stream.pixfmt[0] = '\0';
       -
                stream.width  = entozu_arg(2, "the width",  argv[0], 1, SIZE_MAX);
                stream.height = entozu_arg(2, "the height", argv[1], 1, SIZE_MAX);
                argv += 2, argc -= 2;
       @@ -42,8 +37,7 @@ main(int argc, char *argv[])
                                p = stpcpy(p, argv[i]);
                        }
                }
       -
       -        enset_pixel_size(2, &stream);
       +        enset_pixel_format(2, &stream, NULL);
        
                fprint_stream_head(stdout, &stream);
                enfflush(2, stdout, "<stdout>");
 (DIR) diff --git a/src/blind-norm.c b/src/blind-norm.c
       @@ -40,13 +40,7 @@ main(int argc, char *argv[])
        
                eopen_stream(&stream, NULL);
        
       -        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);
       -
       +        SELECT_PROCESS_FUNCTION(&stream);
                fprint_stream_head(stdout, &stream);
                efflush(stdout, "<stdout>");
                process(&stream);
 (DIR) diff --git a/src/blind-premultiply.c b/src/blind-premultiply.c
       @@ -36,13 +36,7 @@ main(int argc, char *argv[])
        
                eopen_stream(&stream, NULL);
        
       -        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);
       -
       +        SELECT_PROCESS_FUNCTION(&stream);
                fprint_stream_head(stdout, &stream);
                efflush(stdout, "<stdout>");
                process(&stream);
 (DIR) diff --git a/src/blind-quaternion-product.c b/src/blind-quaternion-product.c
       @@ -18,13 +18,7 @@ main(int argc, char *argv[])
                eopen_stream(&left, NULL);
                eopen_stream(&right, argv[0]);
        
       -        if (left.encoding == DOUBLE)
       -                process = process_lf;
       -        else if (left.encoding == FLOAT)
       -                process = process_f;
       -        else
       -                eprintf("pixel format %s is not supported, try xyza\n", left.pixfmt);
       -
       +        SELECT_PROCESS_FUNCTION(&left);
                fprint_stream_head(stdout, &left);
                efflush(stdout, "<stdout>");
                process_two_streams(&left, &right, STDOUT_FILENO, "<stdout>", process);
 (DIR) diff --git a/src/blind-radial-gradient.c b/src/blind-radial-gradient.c
       @@ -33,12 +33,7 @@ main(int argc, char *argv[])
        
                eopen_stream(&stream, NULL);
        
       -        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);
       +        SELECT_PROCESS_FUNCTION(&stream);
        
                if (stream.width > 3 || stream.height > 3 ||
                    stream.width * stream.height < 2 ||
       @@ -64,7 +59,7 @@ PROCESS(struct stream *stream)
                pixel_t buf[BUFSIZ / sizeof(pixel_t)];
                TYPE *params, x1, y1, x2, y2, norm, rd = 1, pe = 2, re = 2, e = 0.5;
                TYPE x, y, p, r, rx, ry;
       -        size_t ix, iy, ptr = 0;
       +        size_t i, ix, iy, ptr = 0;
                for (;;) {
                        while (stream->ptr < stream->frame_size) {
                                if (!eread_stream(stream, stream->frame_size - stream->ptr)) {
       @@ -97,7 +92,8 @@ PROCESS(struct stream *stream)
                                        for (ix = 0; ix < width; ix++) {
                                                x = (TYPE)ix - x1;
                                                x = sqrt(x * x + y) / norm;
       -                                        buf[ptr][0] = buf[ptr][1] = buf[ptr][2] = buf[ptr][3] = x;
       +                                        for (i = 0; i < stream->n_chan; i++)
       +                                                buf[ptr][i] = x;
                                                if (++ptr == ELEMENTSOF(buf)) {
                                                        ewriteall(STDOUT_FILENO, buf, sizeof(buf), "<stdout>");
                                                        ptr = 0;
       @@ -116,7 +112,8 @@ PROCESS(struct stream *stream)
                                                p = pow(abs(p / norm), pe);
                                                r = pow(abs(r / norm), re);
                                                x = pow(p + r, e);
       -                                        buf[ptr][0] = buf[ptr][1] = buf[ptr][2] = buf[ptr][3] = x;
       +                                        for (i = 0; i < stream->n_chan; i++)
       +                                                buf[ptr][i] = x;
                                                if (++ptr == ELEMENTSOF(buf)) {
                                                        ewriteall(STDOUT_FILENO, buf, sizeof(buf), "<stdout>");
                                                        ptr = 0;
 (DIR) diff --git a/src/blind-rectangle-tessellation.c b/src/blind-rectangle-tessellation.c
       @@ -4,8 +4,7 @@
        USAGE("[-F pixel-format] block-width block-height")
        
        #define SET_XYZA(TYPE)\
       -        (pixwidth *= sizeof(double),\
       -         colours = alloca(4 * pixwidth),\
       +        (colours = alloca(4 * stream.pixel_size),\
                 ((TYPE *)colours)[ 0] = (TYPE)0.412457445582367600,\
                 ((TYPE *)colours)[ 1] = (TYPE)0.212673370378408280,\
                 ((TYPE *)colours)[ 2] = (TYPE)0.019333942761673460,\
       @@ -30,7 +29,6 @@ main(int argc, char *argv[])
        {
                size_t width, height;
                const char *pixfmt = "xyza";
       -        size_t pixwidth = 4;
                char *colours;
                size_t x1, y1, x2, y2;
        
       @@ -48,15 +46,12 @@ main(int argc, char *argv[])
                width  = etozu_arg("block-width", argv[0], 1, SIZE_MAX);
                height = etozu_arg("block-height", argv[1], 1, SIZE_MAX);
        
       -        pixfmt = get_pixel_format(pixfmt, "xyza");
       -        if (!strcmp(pixfmt, "xyza"))
       +        eset_pixel_format(&stream, pixfmt);
       +        if (stream.encoding == DOUBLE)
                        SET_XYZA(double);
       -        else if (!strcmp(pixfmt, "xyza f"))
       -                SET_XYZA(float);
                else
       -                eprintf("pixel format %s is not supported, try xyza\n", pixfmt);
       +                SET_XYZA(float);
        
       -        strcpy(stream.pixfmt, pixfmt);
                stream.width  = 2 * width;
                stream.height = 2 * height;
                fprint_stream_head(stdout, &stream);
       @@ -66,7 +61,8 @@ main(int argc, char *argv[])
                        for (y2 = 0; y2 < height; y2++)
                                for (x1 = 0; x1 < 2; x1++)
                                        for (x2 = 0; x2 < width; x2++)
       -                                        ewriteall(STDOUT_FILENO, colours + (y1 * 2 + x1) * pixwidth, pixwidth, "<stdout>");
       +                                        ewriteall(STDOUT_FILENO, colours + (y1 * 2 + x1) * stream.pixel_size,
       +                                                  stream.pixel_size, "<stdout>");
        
                return 0;
        }
 (DIR) diff --git a/src/blind-reverse.c b/src/blind-reverse.c
       @@ -98,9 +98,7 @@ main(int argc, char *argv[])
                if (stream.frames * stream.frame_size > (size_t)SSIZE_MAX - stream.headlen)
                        eprintf("%s: video is too large\n", stream.file);
        
       -#if defined(POSIX_FADV_RANDOM)
       -        posix_fadvise(stream.fd, 0, 0, POSIX_FADV_RANDOM);
       -#endif
       +        fadvise_random(stream.fd, 0, 0);
        
                (inplace ? in_place : to_stdout)(&stream);
                close(stream.fd);
 (DIR) diff --git a/src/blind-rewrite-head.c b/src/blind-rewrite-head.c
       @@ -65,7 +65,6 @@ main(int argc, char *argv[])
                        usage();
                } ARGEND;
        
       -
                if (headless) {
                        if (argc != 5)
                                eprintf("all positional arguments are mandatory unless -h is used\n");
       @@ -73,14 +72,12 @@ main(int argc, char *argv[])
                        usage();
                }
        
       -
                memset(&stream, 0, sizeof(stream));
                stream.file = argv[0];
                stream.fd = eopen(stream.file, O_RDWR);
                if (!headless)
                        einit_stream(&stream);
        
       -
                if (argc < 2 || !strcmp(argv[1], "auto"))
                        frames_auto = 1;
                else
       @@ -102,14 +99,12 @@ main(int argc, char *argv[])
                else if (strcmp(argv[4], "same")) {
                        if (strlen(argv[4]) >= sizeof(stream.pixfmt))
                                eprintf("choosen pixel format is unsupported\n");
       -                strcpy(stream.pixfmt, argv[5]);
       -                if (set_pixel_size(&stream))
       +                if (set_pixel_format(&stream, argv[5]))
                                eprintf("choosen pixel format is unsupported\n");
                } else if (headless) {
                        eprintf("cannot use both 'same' and -h\n");
                }
        
       -
                rewrite(&stream, frames_auto);
                close(stream.fd);
                return 0;
 (DIR) diff --git a/src/blind-round-wave.c b/src/blind-round-wave.c
       @@ -28,13 +28,7 @@ main(int argc, char *argv[])
        
                eopen_stream(&stream, NULL);
        
       -        if (stream.encoding == DOUBLE)
       -                process = process_lf;
       -        else if (stream.encoding == FLOAT)
       -                process = process_f;
       -        else
       -                eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt);
       -
       +        SELECT_PROCESS_FUNCTION(&stream);
                fprint_stream_head(stdout, &stream);
                efflush(stdout, "<stdout>");
                process(&stream);
 (DIR) diff --git a/src/blind-sawtooth-wave.c b/src/blind-sawtooth-wave.c
       @@ -28,13 +28,7 @@ main(int argc, char *argv[])
        
                eopen_stream(&stream, NULL);
        
       -        if (stream.encoding == DOUBLE)
       -                process = process_lf;
       -        else if (stream.encoding == FLOAT)
       -                process = process_f;
       -        else
       -                eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt);
       -
       +        SELECT_PROCESS_FUNCTION(&stream);
                fprint_stream_head(stdout, &stream);
                efflush(stdout, "<stdout>");
                process(&stream);
 (DIR) diff --git a/src/blind-set-luma.c b/src/blind-set-luma.c
       @@ -18,13 +18,7 @@ main(int argc, char *argv[])
                eopen_stream(&colour, NULL);
                eopen_stream(&luma, argv[0]);
        
       -        if (!strcmp(colour.pixfmt, "xyza"))
       -                process = process_lf;
       -        else if (!strcmp(colour.pixfmt, "xyza f"))
       -                process = process_f;
       -        else
       -                eprintf("pixel format %s is not supported, try xyza\n", colour.pixfmt);
       -
       +        SELECT_PROCESS_FUNCTION(&colour);
                fprint_stream_head(stdout, &colour);
                efflush(stdout, "<stdout>");
                process_two_streams(&colour, &luma, STDOUT_FILENO, "<stdout>", process);
 (DIR) diff --git a/src/blind-sinc-wave.c b/src/blind-sinc-wave.c
       @@ -34,12 +34,7 @@ main(int argc, char *argv[])
                                eprintf("theta0-stream must be of dimension 1x1\n");
                }
        
       -        if (stream.encoding == DOUBLE)
       -                process = process_lf;
       -        else if (stream.encoding == FLOAT)
       -                process = process_f;
       -        else
       -                eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt);
       +        SELECT_PROCESS_FUNCTION(&stream);
        
                if (have_theta0 && strcmp(stream.pixfmt, theta0.pixfmt))
                        eprintf("videos use incompatible pixel formats\n");
 (DIR) diff --git a/src/blind-sine-wave.c b/src/blind-sine-wave.c
       @@ -28,13 +28,7 @@ main(int argc, char *argv[])
        
                eopen_stream(&stream, NULL);
        
       -        if (stream.encoding == DOUBLE)
       -                process = process_lf;
       -        else if (stream.encoding == FLOAT)
       -                process = process_f;
       -        else
       -                eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt);
       -
       +        SELECT_PROCESS_FUNCTION(&stream);
                fprint_stream_head(stdout, &stream);
                efflush(stdout, "<stdout>");
                process(&stream);
 (DIR) diff --git a/src/blind-single-colour.c b/src/blind-single-colour.c
       @@ -57,15 +57,9 @@ main(int argc, char *argv[])
                if (inf)
                        einf_check_fd(STDOUT_FILENO, "<stdout>");
        
       -        pixfmt = get_pixel_format(pixfmt, "xyza");
       -        if (!strcmp(pixfmt, "xyza"))
       -                process = process_lf;
       -        else if (!strcmp(pixfmt, "xyza f"))
       -                process = process_f;
       -        else
       -                eprintf("pixel format %s is not supported, try xyza\n", pixfmt);
       +        eset_pixel_format(&stream, pixfmt);
       +        SELECT_PROCESS_FUNCTION(&stream);
        
       -        strcpy(stream.pixfmt, pixfmt);
                fprint_stream_head(stdout, &stream);
                efflush(stdout, "<stdout>");
        
 (DIR) diff --git a/src/blind-spectrum.c b/src/blind-spectrum.c
       @@ -33,14 +33,9 @@ main(int argc, char *argv[])
                eopen_stream(&stream, NULL);
                eopen_stream(&spectrum, 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);
       +        SELECT_PROCESS_FUNCTION(&stream);
        
       -        if (strcmp(stream.pixfmt, spectrum.pixfmt))
       +        if (stream.n_chan != spectrum.n_chan || stream.encoding != spectrum.encoding)
                        eprintf("videos use incompatible pixel formats\n");
        
                echeck_dimensions(&spectrum, WIDTH | HEIGHT, "spectrum");
 (DIR) diff --git a/src/blind-spiral-gradient.c b/src/blind-spiral-gradient.c
       @@ -52,12 +52,7 @@ main(int argc, char *argv[])
        
                eopen_stream(&stream, NULL);
        
       -        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);
       +        SELECT_PROCESS_FUNCTION(&stream);
        
                if (stream.width > 5 || stream.height > 5 ||
                    stream.width * stream.height < 2 ||
       @@ -85,7 +80,7 @@ PROCESS(struct stream *stream)
                TYPE *params, x1, y1, x2, y2, b, r, u, v;
                TYPE x, y, a = 0, e = 1, p = 1, k = 1, ep = 1;
                TYPE x3 = 1, y3 = 0, rd = 1, P, R, Rx, Ry, Pe = 2, Re = 2, PRe = 0.5;
       -        size_t ix, iy, ptr = 0;
       +        size_t i, ix, iy, ptr = 0;
                for (;;) {
                        while (stream->ptr < stream->frame_size) {
                                if (!eread_stream(stream, stream->frame_size - stream->ptr)) {
       @@ -166,7 +161,8 @@ PROCESS(struct stream *stream)
                                                r = (TYPE)(int)(r + 1) + v / (2 * (TYPE)M_PI); 
                                        else
                                                r = mod(r, 1 / (TYPE)spirals) * (TYPE)spirals + r - mod(r, (TYPE)1);
       -                                buf[ptr][0] = buf[ptr][1] = buf[ptr][2] = buf[ptr][3] = r;
       +                                for (i = 0; i < stream->n_chan; i++)
       +                                        buf[ptr][i] = x;
                                        if (++ptr == ELEMENTSOF(buf)) {
                                                ewriteall(STDOUT_FILENO, buf, sizeof(buf), "<stdout>");
                                                ptr = 0;
 (DIR) diff --git a/src/blind-square-gradient.c b/src/blind-square-gradient.c
       @@ -33,12 +33,7 @@ main(int argc, char *argv[])
        
                eopen_stream(&stream, NULL);
        
       -        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);
       +        SELECT_PROCESS_FUNCTION(&stream);
        
                if (stream.width > 3 || stream.height > 3 ||
                    stream.width * stream.height < 2 ||
 (DIR) diff --git a/src/blind-time-blur.c b/src/blind-time-blur.c
       @@ -14,7 +14,7 @@ main(int argc, char *argv[])
        {
                struct stream colour, alpha;
                void (*process)(char *restrict output, char *restrict cbuf, char *restrict abuf,
       -                        struct stream *colour, struct stream *alpha);
       +                        struct stream *colour, struct stream *alpha);
        
                ARGBEGIN {
                default:
       @@ -27,13 +27,7 @@ main(int argc, char *argv[])
                eopen_stream(&colour, NULL);
                eopen_stream(&alpha, argv[0]);
        
       -        if (colour.encoding == DOUBLE)
       -                process = process_lf;
       -        else if (colour.encoding == FLOAT)
       -                process = process_f;
       -        else
       -                eprintf("pixel format %s is not supported, try xyza\n", colour.pixfmt);
       -
       +        SELECT_PROCESS_FUNCTION(&colour);
                echeck_compat(&colour, &alpha);
                fprint_stream_head(stdout, &colour);
                efflush(stdout, "<stdout>");
 (DIR) diff --git a/src/blind-to-portable.c b/src/blind-to-portable.c
       @@ -108,18 +108,13 @@ main(int argc, char *argv[])
                default:
                        usage();
                } ARGEND;
       +
                if (argc)
                        usage();
        
                eopen_stream(&stream, NULL);
        
       -        if (stream.encoding == DOUBLE)
       -                process = process_lf;
       -        else if (stream.encoding == FLOAT)
       -                process = process_f;
       -        else
       -                eprintf("pixel format %s is not supported\n", stream.pixfmt);
       -
       +        SELECT_PROCESS_FUNCTION(&stream);
                fprint_stream_head(stdout, &stream);
                efflush(stdout, "<stdout>");
                process(&stream, strict);
 (DIR) diff --git a/src/blind-to-text.c b/src/blind-to-text.c
       @@ -1,18 +1,11 @@
        /* See LICENSE file for copyright and license details. */
       +#ifndef TYPE
        #include "common.h"
        
        USAGE("")
        
       -#define PROCESS(TYPE, CAST, FMT)\
       -        do {\
       -                size_t i;\
       -                TYPE *p = (TYPE *)(stream->buf);\
       -                for (i = 0, n /= stream->chan_size; i < n; i++)\
       -                        printf("%"FMT"%c", (CAST)(p[i]), (i + 1) % stream->n_chan ? ' ' : '\n');\
       -        } while (0)
       -
       -static void process_lf(struct stream *stream, size_t n) {PROCESS(double, double, ".25lf");}
       -static void process_f (struct stream *stream, size_t n) {PROCESS(float,  double, ".25lf");}
       +#define FILE "blind-to-text.c"
       +#include "define-functions.h"
        
        int
        main(int argc, char *argv[])
       @@ -24,16 +17,22 @@ main(int argc, char *argv[])
        
                eopen_stream(&stream, NULL);
        
       -        if (stream.encoding == DOUBLE)
       -                process = process_lf;
       -        else if (stream.encoding == FLOAT)
       -                process = process_f;
       -        else
       -                eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt);
       -
       +        SELECT_PROCESS_FUNCTION(&stream);
                printf("%zu %zu %zu %s\n", stream.frames, stream.width, stream.height, stream.pixfmt);
       -
                process_stream(&stream, process);
                efshut(stdout, "<stdout>");
                return 0;
        }
       +
       +#else
       +
       +static void
       +PROCESS(struct stream *stream, size_t n)
       +{
       +        size_t i;
       +        TYPE *p = (TYPE *)(stream->buf);
       +        for (i = 0, n /= stream->chan_size; i < n; i++)
       +                printf("%.25"PRINT_TYPE"%c", (PRINT_CAST)(p[i]), (i + 1) % stream->n_chan ? ' ' : '\n');
       +}
       +
       +#endif
 (DIR) diff --git a/src/blind-triangle-tessellation.c b/src/blind-triangle-tessellation.c
       @@ -4,8 +4,7 @@
        USAGE("[-F pixel-format] block-width block-height")
        
        #define SET_XYZA(TYPE)\
       -        (pixwidth *= sizeof(double),\
       -         colours = alloca(8 * pixwidth),\
       +        (colours = alloca(8 * stream.pixel_size),\
                 ((TYPE *)colours)[ 0] = (TYPE)0.412457445582367600,\
                 ((TYPE *)colours)[ 1] = (TYPE)0.212673370378408280,\
                 ((TYPE *)colours)[ 2] = (TYPE)0.019333942761673460,\
       @@ -46,7 +45,6 @@ main(int argc, char *argv[])
        {
                size_t width, height;
                const char *pixfmt = "xyza";
       -        size_t pixwidth = 4;
                char *colours;
                size_t x1, y1, x2, y2, k;
        
       @@ -64,15 +62,12 @@ main(int argc, char *argv[])
                width  = etozu_arg("block-width",  argv[0], 1, SIZE_MAX);
                height = etozu_arg("block-height", argv[1], 1, SIZE_MAX);
        
       -        pixfmt = get_pixel_format(pixfmt, "xyza");
       -        if (!strcmp(pixfmt, "xyza"))
       +        eset_pixel_format(&stream, pixfmt);
       +        if (stream.encoding == DOUBLE)
                        SET_XYZA(double);
       -        else if (!strcmp(pixfmt, "xyza f"))
       -                SET_XYZA(float);
                else
       -                eprintf("pixel format %s is not supported, try xyza\n", pixfmt);
       +                SET_XYZA(float);
        
       -        strcpy(stream.pixfmt, pixfmt);
                stream.width  = 2 * width;
                stream.height = 2 * height;
                fprint_stream_head(stdout, &stream);
       @@ -83,7 +78,7 @@ main(int argc, char *argv[])
                                for (x1 = 0; x1 < 2; x1++) {
                                        for (x2 = 0; x2 < width; x2++) {
                                                k = y1 * 4 + x1 * 2 + (x2 * height > y2 * width);
       -                                        ewriteall(STDOUT_FILENO, colours + k * pixwidth, pixwidth, "<stdout>");
       +                                        ewriteall(STDOUT_FILENO, colours + k * stream.pixel_size, stream.pixel_size, "<stdout>");
                                        }
                                }
                        }
 (DIR) diff --git a/src/blind-triangular-wave.c b/src/blind-triangular-wave.c
       @@ -32,13 +32,7 @@ main(int argc, char *argv[])
        
                eopen_stream(&stream, NULL);
        
       -        if (stream.encoding == DOUBLE)
       -                process = process_lf;
       -        else if (stream.encoding == FLOAT)
       -                process = process_f;
       -        else
       -                eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt);
       -
       +        SELECT_PROCESS_FUNCTION(&stream);
                fprint_stream_head(stdout, &stream);
                efflush(stdout, "<stdout>");
                process(&stream);
 (DIR) diff --git a/src/blind-unpremultiply.c b/src/blind-unpremultiply.c
       @@ -36,13 +36,7 @@ main(int argc, char *argv[])
        
                eopen_stream(&stream, NULL);
        
       -        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);
       -
       +        SELECT_PROCESS_FUNCTION(&stream);
                fprint_stream_head(stdout, &stream);
                efflush(stdout, "<stdout>");
                process(&stream);
 (DIR) diff --git a/src/blind-vector-projection.c b/src/blind-vector-projection.c
       @@ -36,13 +36,7 @@ main(int argc, char *argv[])
                eopen_stream(&left, NULL);
                eopen_stream(&right, argv[0]);
        
       -        if (!strcmp(left.pixfmt, "xyza"))
       -                process = process_lf;
       -        else if (!strcmp(left.pixfmt, "xyza f"))
       -                process = process_f;
       -        else
       -                eprintf("pixel format %s is not supported, try xyza\n", left.pixfmt);
       -
       +        SELECT_PROCESS_FUNCTION(&left);
                fprint_stream_head(stdout, &left);
                efflush(stdout, "<stdout>");
                process_two_streams(&left, &right, STDOUT_FILENO, "<stdout>", process);
 (DIR) diff --git a/src/common.h b/src/common.h
       @@ -68,3 +68,11 @@
        #if !defined(PIPE_BUF)
        # define PIPE_BUF BUFSIZ
        #endif
       +
       +#define SELECT_PROCESS_FUNCTION(stream)\
       +        do {\
       +                if ((stream)->encoding == DOUBLE)\
       +                        process = process_lf;\
       +                else\
       +                        process = process_f;\
       +        } while (0)
 (DIR) diff --git a/src/define-functions.h b/src/define-functions.h
       @@ -2,12 +2,24 @@
        
        #define PROCESS process_lf
        #define TYPE double
       +#define SCAN_TYPE "lf"
       +#define PRINT_TYPE "lf"
       +#define PRINT_CAST double
        #include FILE
        #undef PROCESS
        #undef TYPE
       +#undef SCAN_TYPE
       +#undef PRINT_TYPE
       +#undef PRINT_CAST
        
        #define PROCESS process_f
        #define TYPE float
       +#define SCAN_TYPE "f"
       +#define PRINT_TYPE "lf"
       +#define PRINT_CAST double
        #include FILE
        #undef PROCESS
        #undef TYPE
       +#undef SCAN_TYPE
       +#undef PRINT_TYPE
       +#undef PRINT_CAST
 (DIR) diff --git a/src/stream.c b/src/stream.c
       @@ -73,7 +73,7 @@ eninit_stream(int status, struct stream *stream)
                memmove(stream->buf, stream->buf + 5, stream->ptr -= 5);
                stream->headlen = n + 5;
        
       -        enset_pixel_size(status, stream);
       +        enset_pixel_format(status, stream, NULL);
        
                stream->xptr = 0;
        
       @@ -93,8 +93,15 @@ enopen_stream(int status, struct stream *stream, const char *file)
        
        
        int
       -set_pixel_size(struct stream *stream)
       +set_pixel_format(struct stream *stream, const char *pixfmt)
        {
       +        if (pixfmt) {
       +                pixfmt = get_pixel_format(pixfmt, "xyza");
       +                if (strlen(pixfmt) >= sizeof(stream->pixfmt))
       +                        return -1;
       +                strcpy(stream->pixfmt, pixfmt);
       +        }
       +
                if (!strcmp(stream->pixfmt, "xyza")) {
                        stream->n_chan = 4;
                        stream->chan_size = sizeof(double);
       @@ -110,6 +117,7 @@ set_pixel_size(struct stream *stream)
                } else {
                        return -1;
                }
       +
                stream->pixel_size = stream->n_chan * stream->chan_size;
                stream->row_size   = stream->pixel_size * stream->width;
                stream->col_size   = stream->pixel_size * stream->height;
       @@ -118,11 +126,15 @@ set_pixel_size(struct stream *stream)
        }
        
        void
       -enset_pixel_size(int status, struct stream *stream)
       +enset_pixel_format(int status, struct stream *stream, const char *pixfmt)
        {
       -        if (set_pixel_size(stream))
       -                enprintf(status, "file %s uses unsupported pixel format: %s\n",
       -                         stream->file, stream->pixfmt);
       +        if (!set_pixel_format(stream, pixfmt)) {
       +                if (pixfmt)
       +                        enprintf(status, "pixel format %s is not supported, try xyza\n", pixfmt);
       +                else
       +                        enprintf(status, "%s: unsupported pixel format: %s\n",
       +                                 stream->file, stream->pixfmt);
       +        }
        }
        
        
 (DIR) diff --git a/src/stream.h b/src/stream.h
       @@ -37,7 +37,7 @@
        
        #define einit_stream(...)             eninit_stream(1, __VA_ARGS__)
        #define eopen_stream(...)             enopen_stream(1, __VA_ARGS__)
       -#define eset_pixel_size(...)          enset_pixel_size(1, __VA_ARGS__)
       +#define eset_pixel_format(...)        enset_pixel_format(1, __VA_ARGS__)
        #define eread_stream(...)             enread_stream(1, __VA_ARGS__)
        #define einf_check_fd(...)            eninf_check_fd(1, __VA_ARGS__)
        #define echeck_dimensions(...)        encheck_dimensions(1, __VA_ARGS__)
       @@ -100,8 +100,8 @@ struct stream {
        
        void eninit_stream(int status, struct stream *stream);
        void enopen_stream(int status, struct stream *stream, const char *file);
       -int set_pixel_size(struct stream *stream);
       -void enset_pixel_size(int status, struct stream *stream);
       +int set_pixel_format(struct stream *stream, const char *pixfmt);
       +void enset_pixel_format(int status, struct stream *stream, const char *pixfmt);
        void fprint_stream_head(FILE *fp, struct stream *stream);
        int dprint_stream_head(int fd, struct stream *stream);
        size_t enread_stream(int status, struct stream *stream, size_t n);