URI: 
       Some improvements and fixes - 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 3569a10c97d41913dbf7cf3114cb4d2d5f17dc7f
   DIR parent 48ca891887e8260be43ae641b35c4129fd4d2093
  HTML Author: Mattias Andrée <maandree@kth.se>
       Date:   Sat, 15 Jul 2017 17:08:02 +0200
       
       Some improvements and fixes
       
       Signed-off-by: Mattias Andrée <maandree@kth.se>
       
       Diffstat:
         M TODO                                |       2 ++
         M man/blind-invert-matrix.1           |       5 -----
         M src/blind-apply-palette.c           |       4 ----
         M src/blind-chroma-key.c              |       2 --
         M src/blind-colour-ciexyz.c           |       2 +-
         M src/blind-colour-srgb.c             |       2 +-
         M src/blind-cone-gradient.c           |       2 --
         M src/blind-cross-product.c           |       4 ++--
         M src/blind-dot-product.c             |      22 ++++++++++++----------
         M src/blind-double-sine-wave.c        |      54 +++++++++++---------------------
         M src/blind-extract-alpha.c           |      23 +++++++++++------------
         M src/blind-find-rectangle.c          |       4 ++--
         M src/blind-from-portable.c           |      14 +++++++-------
         M src/blind-from-text.c               |      12 ++++++------
         M src/blind-get-colours.c             |       5 -----
         M src/blind-invert-matrix.c           |      32 +++++++++++++++----------------
         M src/blind-linear-gradient.c         |       2 --
         M src/blind-matrix-orthoproject.c     |      20 +++++++++++---------
         M src/blind-matrix-reflect.c          |      20 +++++++++++---------
         M src/blind-matrix-rotate.c           |      22 ++++++++++++----------
         M src/blind-matrix-scale.c            |      18 +++++++++++-------
         M src/blind-matrix-shear.c            |      20 ++++++++++++--------
         M src/blind-matrix-translate.c        |      18 +++++++++++-------
         M src/blind-matrix-transpose.c        |      15 ++++++++-------
         M src/blind-multiply-matrices.c       |      11 ++++++-----
         M src/blind-norm.c                    |       2 --
         M src/blind-premultiply.c             |       2 --
         M src/blind-quaternion-product.c      |       4 ++--
         M src/blind-radial-gradient.c         |       2 --
         M src/blind-round-wave.c              |      47 +++++++++++--------------------
         M src/blind-sawtooth-wave.c           |      40 +++++++++++--------------------
         M src/blind-sinc-wave.c               |       6 ++----
         M src/blind-sine-wave.c               |      54 +++++++++++---------------------
         M src/blind-spectrum.c                |       2 --
         M src/blind-spiral-gradient.c         |       2 --
         M src/blind-square-gradient.c         |       2 --
         M src/blind-time-blur.c               |      16 ++++++++--------
         M src/blind-to-portable.c             |      14 +++++++-------
         M src/blind-to-text.c                 |      21 +++++++++------------
         M src/blind-triangular-wave.c         |      58 +++++++++++--------------------
         M src/blind-unpremultiply.c           |       2 --
         M src/stream.c                        |      38 +++++++++++++++++++------------
         M src/stream.h                        |      21 ++++++++++++++++++---
       
       43 files changed, 297 insertions(+), 371 deletions(-)
       ---
   DIR diff --git a/TODO b/TODO
       @@ -1,3 +1,5 @@
       +Fix blind-from-named without command
       +
        blind-transform                affine transformation by matrix multiplication, -t for tiling, -s for
                                        improve quality on downscaling (pixels' neighbours must not change).
        blind-primary-key        replace a primary with transparency, -g for greyscaled images.
   DIR diff --git a/man/blind-invert-matrix.1 b/man/blind-invert-matrix.1
       @@ -21,11 +21,6 @@ resuling augment is printed.
        .B -e
        Apply optimisation that assumes all channels
        are identical.
       -.SH NOTES
       -.B blind-invert-matrix
       -fails if it encounters a non-invertable
       -matrix, however, this is not always the
       -case.
        .SH SEE ALSO
        .BR blind (7),
        .BR blind-multiply-matrices (1),
   DIR diff --git a/src/blind-apply-palette.c b/src/blind-apply-palette.c
       @@ -3,11 +3,9 @@
        
        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)
        {
       @@ -18,7 +16,6 @@ distance_xyz(double x1, double y1, double z1, double a1, double x2, double y2, d
                return sqrt(x2 + y2 + z2 + a2);
        }
        
       -
        #define PROCESS(TYPE, SUFFIX)\
                static void\
                process_##SUFFIX(struct stream *stream, struct stream *palette, char *pal)\
       @@ -69,7 +66,6 @@ distance_xyz(double x1, double y1, double z1, double a1, double x2, double y2, d
        PROCESS(double, lf)
        PROCESS(float, f)
        
       -
        int
        main(int argc, char *argv[])
        {
   DIR diff --git a/src/blind-chroma-key.c b/src/blind-chroma-key.c
       @@ -3,7 +3,6 @@
        
        USAGE("key-stream")
        
       -
        #define PROCESS(TYPE, SUFFIX)\
                static void\
                process_##SUFFIX(struct stream *stream, struct stream *key)\
       @@ -61,7 +60,6 @@ USAGE("key-stream")
        PROCESS(double, lf)
        PROCESS(float, f)
        
       -
        int
        main(int argc, char *argv[])
        {
   DIR diff --git a/src/blind-colour-ciexyz.c b/src/blind-colour-ciexyz.c
       @@ -14,7 +14,7 @@ main(int argc, char *argv[])
                        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);
       +                printf("%.50lf %.50lf %.50lf\n", X, Y, Z);
                } else if (argc == 3) {
                        printf("%s %s %s\n", argv[0], argv[1], argv[2]);
                } else {
   DIR diff --git a/src/blind-colour-srgb.c b/src/blind-colour-srgb.c
       @@ -36,7 +36,7 @@ main(int argc, char *argv[])
                }
        
                srgb_to_ciexyz(red, green, blue, &X, &Y, &Z);
       -        printf("%lf %lf %lf\n", X, Y, Z);
       +        printf("%.50lf %.50lf %.50lf\n", X, Y, Z);
                efshut(stdout, "<stdout>");
                return 0;
        }
   DIR diff --git a/src/blind-cone-gradient.c b/src/blind-cone-gradient.c
       @@ -9,7 +9,6 @@ static size_t width = 0;
        static size_t height = 0;
        static int with_multiplier = 0;
        
       -
        #define PROCESS(TYPE, SUFFIX)\
                static void\
                process_##SUFFIX(struct stream *stream)\
       @@ -74,7 +73,6 @@ static int with_multiplier = 0;
        PROCESS(double, lf)
        PROCESS(float, f)
        
       -
        int
        main(int argc, char *argv[])
        {
   DIR diff --git a/src/blind-cross-product.c b/src/blind-cross-product.c
       @@ -39,9 +39,9 @@ main(int argc, char *argv[])
                eopen_stream(&left, NULL);
                eopen_stream(&right, argv[0]);
        
       -        if (!strcmp(left.pixfmt, "xyza"))
       +        if (left.encoding == DOUBLE)
                        process = process_lf;
       -        else if (!strcmp(left.pixfmt, "xyza f"))
       +        else if (left.encoding == FLOAT)
                        process = process_f;
                else
                        eprintf("pixel format %s is not supported, try xyza\n", left.pixfmt);
   DIR diff --git a/src/blind-dot-product.c b/src/blind-dot-product.c
       @@ -7,14 +7,16 @@ USAGE("right-hand-stream")
                static void\
                process_##SUFFIX(struct stream *left, struct stream *right, size_t n)\
                {\
       -                size_t i;\
       -                TYPE *lx, *ly, *lz, *la, *rx, *ry, *rz, *ra;\
       -                for (i = 0; i < n; i += 4 * sizeof(TYPE)) {\
       -                        lx = ((TYPE *)(left->buf + i)) + 0, rx = ((TYPE *)(right->buf + i)) + 0;\
       -                        ly = ((TYPE *)(left->buf + i)) + 1, ry = ((TYPE *)(right->buf + i)) + 1;\
       -                        lz = ((TYPE *)(left->buf + i)) + 2, rz = ((TYPE *)(right->buf + i)) + 2;\
       -                        la = ((TYPE *)(left->buf + i)) + 3, ra = ((TYPE *)(right->buf + i)) + 3;\
       -                        *lx = *ly = *lz = *la = *lx * *rx + *ly * *ry + *lz * *rz + *la * *ra;\
       +                size_t i, j, s = left->n_chan * sizeof(TYPE);\
       +                TYPE v, *l, *r;\
       +                for (i = 0; i < n; i += s) {\
       +                        l = (TYPE *)(left->buf + i);\
       +                        r = (TYPE *)(right->buf + i);\
       +                        v = 0;\
       +                        for (j = 0; j < left->n_chan; j++)\
       +                                v += l[j] * r[j];\
       +                        for (j = 0; j < left->n_chan; j++)\
       +                                l[j] = v;\
                        }\
                }
        
       @@ -32,9 +34,9 @@ main(int argc, char *argv[])
                eopen_stream(&left, NULL);
                eopen_stream(&right, argv[0]);
        
       -        if (!strcmp(left.pixfmt, "xyza"))
       +        if (left.encoding == DOUBLE)
                        process = process_lf;
       -        else if (!strcmp(left.pixfmt, "xyza f"))
       +        else if (left.encoding == FLOAT)
                        process = process_f;
                else
                        eprintf("pixel format %s is not supported, try xyza\n", left.pixfmt);
   DIR diff --git a/src/blind-double-sine-wave.c b/src/blind-double-sine-wave.c
       @@ -5,51 +5,34 @@ USAGE("[-e]")
        
        static int equal = 0;
        
       -
        #define PROCESS(TYPE, SUFFIX)\
                static void\
                process_##SUFFIX(struct stream *stream)\
                {\
       -                size_t i, n;\
       -                TYPE x, y, z, a;\
       +                size_t i, j, n;\
       +                TYPE v, *p;\
                        do {\
       -                        n = stream->ptr / stream->pixel_size;\
                                if (equal) {\
       +                                n = stream->ptr / stream->pixel_size;\
                                        for (i = 0; i < n; i++) {\
       -                                        a = ((TYPE *)(stream->buf))[4 * i + 3];\
       -                                        a = posmod(a, (TYPE)2);\
       -                                        a = a > 1 ? 2 - a : a;\
       -                                        a = 1 - (sin(a * (2 * (TYPE)M_PI)) + 1) / 2;\
       -                                        ((TYPE *)(stream->buf))[4 * i + 0] = a;\
       -                                        ((TYPE *)(stream->buf))[4 * i + 1] = a;\
       -                                        ((TYPE *)(stream->buf))[4 * i + 2] = a;\
       -                                        ((TYPE *)(stream->buf))[4 * i + 3] = a;\
       +                                        p = (TYPE *)(stream->buf) + i * stream->n_chan;\
       +                                        v = posmod(*p, (TYPE)2);\
       +                                        v = v > 1 ? 2 - v : v;\
       +                                        v = 1 - (sin(v * (2 * (TYPE)M_PI)) + 1) / 2;\
       +                                        for (j = 0; j < stream->n_chan; j++)\
       +                                                p[j] = v;\
                                        }\
       +                                n *= stream->pixel_size;\
                                } else {\
       +                                n = stream->ptr / stream->chan_size;\
                                        for (i = 0; i < n; i++) {\
       -                                        x = ((TYPE *)(stream->buf))[4 * i + 0];\
       -                                        y = ((TYPE *)(stream->buf))[4 * i + 1];\
       -                                        z = ((TYPE *)(stream->buf))[4 * i + 2];\
       -                                        a = ((TYPE *)(stream->buf))[4 * i + 3];\
       -                                        x = posmod(x, (TYPE)1);\
       -                                        y = posmod(y, (TYPE)1);\
       -                                        z = posmod(z, (TYPE)1);\
       -                                        a = posmod(a, (TYPE)1);\
       -                                        x = x > 1 ? 2 - x : x;\
       -                                        y = y > 1 ? 2 - y : y;\
       -                                        z = z > 1 ? 2 - z : z;\
       -                                        a = a > 1 ? 2 - a : a;\
       -                                        x = 1 - (sin(x * (2 * (TYPE)M_PI)) + 1) / 2;\
       -                                        y = 1 - (sin(y * (2 * (TYPE)M_PI)) + 1) / 2;\
       -                                        z = 1 - (sin(z * (2 * (TYPE)M_PI)) + 1) / 2;\
       -                                        a = 1 - (sin(a * (2 * (TYPE)M_PI)) + 1) / 2;\
       -                                        ((TYPE *)(stream->buf))[4 * i + 0] = x;\
       -                                        ((TYPE *)(stream->buf))[4 * i + 1] = y;\
       -                                        ((TYPE *)(stream->buf))[4 * i + 2] = z;\
       -                                        ((TYPE *)(stream->buf))[4 * i + 3] = a;\
       +                                        p = (TYPE *)(stream->buf) + i;\
       +                                        v = posmod(*p, (TYPE)2);\
       +                                        v = v > 1 ? 2 - v : v;\
       +                                        *p = 1 - (sin(v * (2 * (TYPE)M_PI)) + 1) / 2;\
                                        }\
       +                                n *= stream->chan_size;\
                                }\
       -                        n *= stream->pixel_size;\
                                ewriteall(STDOUT_FILENO, stream->buf, n, "<stdout>");\
                                memmove(stream->buf, stream->buf + n, stream->ptr -= n);\
                        } while (eread_stream(stream, SIZE_MAX));\
       @@ -60,7 +43,6 @@ static int equal = 0;
        PROCESS(double, lf)
        PROCESS(float, f)
        
       -
        int
        main(int argc, char *argv[])
        {
       @@ -80,9 +62,9 @@ main(int argc, char *argv[])
        
                eopen_stream(&stream, NULL);
        
       -        if (!strcmp(stream.pixfmt, "xyza"))
       +        if (stream.encoding == DOUBLE)
                        process = process_lf;
       -        else if (!strcmp(stream.pixfmt, "xyza f"))
       +        else if (stream.encoding == FLOAT)
                        process = process_f;
                else
                        eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt);
   DIR diff --git a/src/blind-extract-alpha.c b/src/blind-extract-alpha.c
       @@ -8,17 +8,17 @@ USAGE("colour-file")
                process_##SUFFIX(struct stream *stream, int fd, const char *fname)\
                {\
                        char buf[sizeof(stream->buf)];\
       -                size_t i, n;\
       -                TYPE a;\
       +                size_t i, j, n;\
       +                TYPE a, *p, *b;\
                        do {\
                                n = stream->ptr / stream->pixel_size;\
       -                        for (i = 0; i < n; i++) {\
       -                                a = ((TYPE *)(stream->buf))[4 * i + 3];\
       -                                ((TYPE *)(stream->buf))[4 * i + 3] = 1;\
       -                                ((TYPE *)buf)[4 * i + 0] = a;\
       -                                ((TYPE *)buf)[4 * i + 1] = a;\
       -                                ((TYPE *)buf)[4 * i + 2] = a;\
       -                                ((TYPE *)buf)[4 * i + 3] = 1;\
       +                        p = (TYPE *)(stream->buf) + stream->n_chan - 1;\
       +                        b = (TYPE *)buf;\
       +                        for (i = 0; i < n; i++, p += stream->n_chan) {\
       +                                a = *p, *p = 1;\
       +                                for (j = stream->n_chan - 1; j--;)\
       +                                        *b++ = a;\
       +                                *b++ = 1;\
                                }\
                                n *= stream->pixel_size;\
                                ewriteall(fd, stream->buf, n, fname);\
       @@ -32,7 +32,6 @@ USAGE("colour-file")
        PROCESS(double, lf)
        PROCESS(float, f)
        
       -
        int
        main(int argc, char *argv[])
        {
       @@ -45,9 +44,9 @@ main(int argc, char *argv[])
                eopen_stream(&stream, NULL);
                fd = eopen(argv[0], O_WRONLY | O_CREAT | O_TRUNC, 0666);
        
       -        if (!strcmp(stream.pixfmt, "xyza"))
       +        if (stream.encoding == DOUBLE)
                        process = process_lf;
       -        else if (!strcmp(stream.pixfmt, "xyza f"))
       +        else if (stream.encoding == FLOAT)
                        process = process_f;
                else
                        eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt);
   DIR diff --git a/src/blind-find-rectangle.c b/src/blind-find-rectangle.c
       @@ -111,13 +111,13 @@ main(int argc, char *argv[])
                cache = emalloc2(stream.width + 1, sizeof(*cache));
                buf   = emalloc(stream.row_size);
        
       -        if (!strcmp(stream.pixfmt, "xyza")) {
       +        if (stream.encoding == DOUBLE) {
                        colour_lf[0] = X;
                        colour_lf[1] = Y;
                        colour_lf[2] = Z;
                        colour_lf[3] = alpha;
                        process(colour_lf);
       -        } else if (!strcmp(stream.pixfmt, "xyza f")) {
       +        } else if (stream.encoding == FLOAT) {
                        colour_f[0] = (float)X;
                        colour_f[1] = (float)Y;
                        colour_f[2] = (float)Z;
   DIR diff --git a/src/blind-from-portable.c b/src/blind-from-portable.c
       @@ -72,10 +72,10 @@ USAGE("[-s]")
                } while (0)
        
        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 float  conv_float (uint32_t portable) {CONV(uint32_t, int32_t, float,   8,  127, 23);}
        
       -static void process_xyza (struct stream *stream, int strict) {PROCESS(uint64_t, double, 64);}
       -static void process_xyzaf(struct stream *stream, int strict) {PROCESS(uint32_t, float, 32);}
       +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);}
        
        int
        main(int argc, char *argv[])
       @@ -96,10 +96,10 @@ main(int argc, char *argv[])
        
                eopen_stream(&stream, NULL);
        
       -        if (!strcmp(stream.pixfmt, "xyza"))
       -                process = process_xyza;
       -        else if (!strcmp(stream.pixfmt, "xyza f"))
       -                process = process_xyzaf;
       +        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);
        
   DIR diff --git a/src/blind-from-text.c b/src/blind-from-text.c
       @@ -20,8 +20,8 @@ USAGE("")
                        }\
                } while (0)
        
       -static void process_xyza (void) {PROCESS(double, "lf");}
       -static void process_xyzaf(void) {PROCESS(float, "f");}
       +static void process_lf(void) { PROCESS(double, "lf"); }
       +static void process_f(void)  { PROCESS(float,  "f");  }
        
        int
        main(int argc, char *argv[])
       @@ -54,10 +54,10 @@ main(int argc, char *argv[])
                ewriteall(STDOUT_FILENO, stream.buf, stream.ptr, "<stdout>");
                einit_stream(&stream);
        
       -        if (!strcmp(stream.pixfmt, "xyza"))
       -                process = process_xyza;
       -        else if (!strcmp(stream.pixfmt, "xyza f"))
       -                process = process_xyzaf;
       +        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);
        
   DIR diff --git a/src/blind-get-colours.c b/src/blind-get-colours.c
       @@ -3,17 +3,14 @@
        
        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)
        {
       @@ -24,7 +21,6 @@ unique(char *base, size_t n)
                return r;
        }
        
       -
        static size_t
        merge(char **sink, size_t n, char *new, size_t m, size_t *siz)
        {
       @@ -52,7 +48,6 @@ merge(char **sink, size_t n, char *new, size_t m, size_t *siz)
                return n + m;
        }
        
       -
        int
        main(int argc, char *argv[])
        {
   DIR diff --git a/src/blind-invert-matrix.c b/src/blind-invert-matrix.c
       @@ -10,7 +10,7 @@ static int equal = 0;
                        p2 = matrix + r2 * cn;\
                        t = p2[r1][0];\
                        for (c = 0; c < cn; c++)\
       -                        p1[c][0] -= p2[c][0] * t;\
       +                        p2[c][0] -= p1[c][0] * t;\
                } while (0)
        
        #define PROCESS(TYPE)\
       @@ -34,9 +34,9 @@ static int equal = 0;
                                        for (c = 0; c < cn; c++)\
                                                t = p1[c][0], p1[c][0] = p2[c][0], p2[c][0] = t;\
                                }\
       -                        t = p1[r1][0];\
       +                        t = 1 / p1[r1][0];\
                                for (c = 0; c < cn; c++)\
       -                                p1[c][0] /= t;\
       +                                p1[c][0] *= t;\
                                for (r2 = r1 + 1; r2 < rn; r2++)\
                                        SUB_ROWS();\
                        }\
       @@ -55,7 +55,7 @@ int
        main(int argc, char *argv[])
        {
                struct stream stream;
       -        size_t width, x, y, row_size, chan_size;
       +        size_t width, x, y, row_size;
                char *buf, *one = alloca(4 * sizeof(double)), *p;
                void (*process)(struct stream *stream, void *buf);
        
       @@ -81,22 +81,20 @@ main(int argc, char *argv[])
                stream.width = width;
                efflush(stdout, "<stdout>");
        
       +        one = alloca(stream.pixel_size);
                if (!strcmp(stream.pixfmt, "xyza")) {
       -                one = alloca(4 * sizeof(double));
                        *(double *)one = 1;
                        process = process_lf;
                } else if (!strcmp(stream.pixfmt, "xyza f")) {
       -                one = alloca(4 * sizeof(float));
                        *(float *)one = 1;
                        process = process_f;
                } else {
                        eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt);
                }
        
       -        chan_size = stream.pixel_size / 4;
       -        memcpy(one + 1 * chan_size, one, chan_size);
       -        memcpy(one + 2 * chan_size, one, chan_size);
       -        memcpy(one + 3 * chan_size, one, chan_size);
       +        memcpy(one + 1 * stream.chan_size, one, stream.chan_size);
       +        memcpy(one + 2 * stream.chan_size, one, stream.chan_size);
       +        memcpy(one + 3 * stream.chan_size, one, stream.chan_size);
        
                width = stream.width > stream.height ? stream.width : 2 * stream.height;
                buf = emalloc2(width, stream.col_size);
       @@ -111,19 +109,19 @@ main(int argc, char *argv[])
                                }
                        }
                        if (equal) {
       -                        process(&stream, buf + 1 * chan_size);
       +                        process(&stream, buf + 1 * stream.chan_size);
                                for (y = 0; y < stream.height; y++) {
                                        for (x = 0; x < stream.width; x++) {
                                                p = buf + y * row_size + x * stream.pixel_size;
       -                                        memcpy(p, p + chan_size, chan_size);
       -                                        memcpy(p + 2 * chan_size, p, 2 * chan_size);
       +                                        memcpy(p, p + stream.chan_size, stream.chan_size);
       +                                        memcpy(p + 2 * stream.chan_size, p, 2 * stream.chan_size);
                                        }
                                }
                        } else {
       -                        process(&stream, buf + 0 * chan_size);
       -                        process(&stream, buf + 1 * chan_size);
       -                        process(&stream, buf + 2 * chan_size);
       -                        process(&stream, buf + 3 * chan_size);
       +                        process(&stream, buf + 0 * stream.chan_size);
       +                        process(&stream, buf + 1 * stream.chan_size);
       +                        process(&stream, buf + 2 * stream.chan_size);
       +                        process(&stream, buf + 3 * stream.chan_size);
                        }
                        for (y = 0; y < stream.height; y++)
                                ewriteall(STDOUT_FILENO, buf + y * row_size + stream.col_size, row_size - stream.col_size, "<stdout>");
   DIR diff --git a/src/blind-linear-gradient.c b/src/blind-linear-gradient.c
       @@ -7,7 +7,6 @@ static int bilinear = 0;
        static size_t width = 0;
        static size_t height = 0;
        
       -
        #define PROCESS(TYPE, SUFFIX)\
                static void\
                process_##SUFFIX(struct stream *stream)\
       @@ -56,7 +55,6 @@ static size_t height = 0;
        PROCESS(double, lf)
        PROCESS(float, f)
        
       -
        int
        main(int argc, char *argv[])
        {
   DIR diff --git a/src/blind-matrix-orthoproject.c b/src/blind-matrix-orthoproject.c
       @@ -11,9 +11,9 @@ static int per_channel = 0;
                        pixel_t matrix[9];\
                        pixel_t buf[2];\
                        TYPE x2, y2, norm2;\
       -                int i;\
       +                size_t i;\
                        \
       -                for (i = 0; i < 4; i++) {\
       +                for (i = 0; i < stream->n_chan; i++) {\
                                matrix[0][i] = 1, matrix[1][i] = 0, matrix[2][i] = 0;\
                                matrix[3][i] = 0, matrix[4][i] = 1, matrix[5][i] = 0;\
                                matrix[6][i] = 0, matrix[7][i] = 0, matrix[8][i] = 1;\
       @@ -21,7 +21,7 @@ static int per_channel = 0;
                        \
                        while (eread_frame(stream, buf)) {\
                                if (per_channel) {\
       -                                for (i = 0; i < 4; i++) {\
       +                                for (i = 0; i < stream->n_chan; i++) {\
                                                x2 = buf[0][i] * buf[0][i];\
                                                y2 = buf[1][i] * buf[1][i];\
                                                norm2 = x2 + y2;\
       @@ -38,10 +38,12 @@ static int per_channel = 0;
                                        matrix[0][0] = x2 / norm2;\
                                        matrix[4][0] = y2 / norm2;\
                                        matrix[3][0] = matrix[1][0] = buf[0][1] * buf[1][1] / norm2;\
       -                                matrix[0][3] = matrix[0][2] = matrix[0][1] = matrix[0][0];\
       -                                matrix[1][3] = matrix[1][2] = matrix[1][1] = matrix[1][0];\
       -                                matrix[3][3] = matrix[3][2] = matrix[3][1] = matrix[3][0];\
       -                                matrix[4][3] = matrix[4][2] = matrix[4][1] = matrix[4][0];\
       +                                for (i = 1; i < stream->n_chan; i++) {\
       +                                        matrix[0][i] = matrix[0][0];\
       +                                        matrix[1][i] = matrix[1][0];\
       +                                        matrix[3][i] = matrix[3][0];\
       +                                        matrix[4][i] = matrix[4][0];\
       +                                }\
                                }\
                                ewriteall(STDOUT_FILENO, matrix, sizeof(matrix), "<stdout>");\
                        }\
       @@ -77,9 +79,9 @@ main(int argc, char *argv[])
                fprint_stream_head(stdout, &stream);
                efflush(stdout, "<stdout>");
        
       -        if (!strcmp(stream.pixfmt, "xyza"))
       +        if (stream.encoding == DOUBLE)
                        process = process_lf;
       -        else if (!strcmp(stream.pixfmt, "xyza f"))
       +        else if (stream.encoding == FLOAT)
                        process = process_f;
                else
                        eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt);
   DIR diff --git a/src/blind-matrix-reflect.c b/src/blind-matrix-reflect.c
       @@ -11,9 +11,9 @@ static int per_channel = 0;
                        pixel_t matrix[9];\
                        pixel_t buf[2];\
                        TYPE x2, y2, norm2;\
       -                int i;\
       +                size_t i;\
                        \
       -                for (i = 0; i < 4; i++) {\
       +                for (i = 0; i < stream->n_chan; i++) {\
                                matrix[0][i] = 1, matrix[1][i] = 0, matrix[2][i] = 0;\
                                matrix[3][i] = 0, matrix[4][i] = 1, matrix[5][i] = 0;\
                                matrix[6][i] = 0, matrix[7][i] = 0, matrix[8][i] = 1;\
       @@ -21,7 +21,7 @@ static int per_channel = 0;
                        \
                        while (eread_frame(stream, buf)) {\
                                if (per_channel) {\
       -                                for (i = 0; i < 4; i++) {\
       +                                for (i = 0; i < stream->n_chan; i++) {\
                                                x2 = buf[0][i] * buf[0][i];\
                                                y2 = buf[1][i] * buf[1][i];\
                                                norm2 = x2 + y2;\
       @@ -36,10 +36,12 @@ static int per_channel = 0;
                                        norm2 = x2 + y2;\
                                        matrix[4][0] = -(matrix[0][0] = (x2 - y2) / norm2);\
                                        matrix[3][0] = matrix[1][0] = 2 * buf[0][1] * buf[1][1] / norm2;\
       -                                matrix[0][3] = matrix[0][2] = matrix[0][1] = matrix[0][0];\
       -                                matrix[1][3] = matrix[1][2] = matrix[1][1] = matrix[1][0];\
       -                                matrix[3][3] = matrix[3][2] = matrix[3][1] = matrix[3][0];\
       -                                matrix[4][3] = matrix[4][2] = matrix[4][1] = matrix[4][0];\
       +                                for (i = 1; i < stream->n_chan; i++) {\
       +                                        matrix[0][i] = matrix[0][0];\
       +                                        matrix[1][i] = matrix[1][0];\
       +                                        matrix[3][i] = matrix[3][0];\
       +                                        matrix[4][i] = matrix[4][0];\
       +                                }\
                                }\
                                ewriteall(STDOUT_FILENO, matrix, sizeof(matrix), "<stdout>");\
                        }\
       @@ -75,9 +77,9 @@ main(int argc, char *argv[])
                fprint_stream_head(stdout, &stream);
                efflush(stdout, "<stdout>");
        
       -        if (!strcmp(stream.pixfmt, "xyza"))
       +        if (stream.encoding == DOUBLE)
                        process = process_lf;
       -        else if (!strcmp(stream.pixfmt, "xyza f"))
       +        else if (stream.encoding == FLOAT)
                        process = process_f;
                else
                        eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt);
   DIR diff --git a/src/blind-matrix-rotate.c b/src/blind-matrix-rotate.c
       @@ -11,9 +11,9 @@ static int in_degrees = 0;
                        typedef TYPE pixel_t[4];\
                        pixel_t matrix[9];\
                        pixel_t buf;\
       -                int i;\
       +                size_t i;\
                        \
       -                for (i = 0; i < 4; i++) {\
       +                for (i = 0; i < stream->n_chan; i++) {\
                                matrix[0][i] = 1, matrix[1][i] = 0, matrix[2][i] = 0;\
                                matrix[3][i] = 0, matrix[4][i] = 1, matrix[5][i] = 0;\
                                matrix[6][i] = 0, matrix[7][i] = 0, matrix[8][i] = 1;\
       @@ -21,12 +21,12 @@ static int in_degrees = 0;
                        \
                        while (eread_frame(stream, buf)) {\
                                if (per_channel && in_degrees) {\
       -                                for (i = 0; i < 4; i++) {\
       +                                for (i = 0; i < stream->n_chan; i++) {\
                                                matrix[4][i] = matrix[0][i] = degcos(buf[i]);\
                                                matrix[3][i] = -(matrix[1][i] = degsin(buf[i]));\
                                        }\
                                } else if (per_channel) {\
       -                                for (i = 0; i < 4; i++) {\
       +                                for (i = 0; i < stream->n_chan; i++) {\
                                                matrix[4][i] = matrix[0][i] = cos(buf[i]);\
                                                matrix[3][i] = -(matrix[1][i] = sin(buf[i]));\
                                        }\
       @@ -39,10 +39,12 @@ static int in_degrees = 0;
                                                matrix[4][0] = matrix[0][0] = cos(buf[1]);\
                                                matrix[3][0] = -(matrix[1][0] = sin(buf[1]));\
                                        }\
       -                                matrix[0][3] = matrix[0][2] = matrix[0][1] = matrix[0][0];\
       -                                matrix[1][3] = matrix[1][2] = matrix[1][1] = matrix[1][0];\
       -                                matrix[3][3] = matrix[3][2] = matrix[3][1] = matrix[3][0];\
       -                                matrix[4][3] = matrix[4][2] = matrix[4][1] = matrix[4][0];\
       +                                for (i = 0; i < stream->n_chan; i++) {\
       +                                        matrix[0][i] = matrix[0][0];\
       +                                        matrix[1][i] = matrix[1][0];\
       +                                        matrix[3][i] = matrix[3][0];\
       +                                        matrix[4][i] = matrix[4][0];\
       +                                }\
                                }\
                                ewriteall(STDOUT_FILENO, matrix, sizeof(matrix), "<stdout>");\
                        }\
       @@ -81,9 +83,9 @@ main(int argc, char *argv[])
                fprint_stream_head(stdout, &stream);
                efflush(stdout, "<stdout>");
        
       -        if (!strcmp(stream.pixfmt, "xyza"))
       +        if (stream.encoding == DOUBLE)
                        process = process_lf;
       -        else if (!strcmp(stream.pixfmt, "xyza f"))
       +        else if (stream.encoding == FLOAT)
                        process = process_f;
                else
                        eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt);
   DIR diff --git a/src/blind-matrix-scale.c b/src/blind-matrix-scale.c
       @@ -10,9 +10,9 @@ static int per_channel = 0;
                        typedef TYPE pixel_t[4];\
                        pixel_t matrix[9];\
                        pixel_t buf[2];\
       -                int i;\
       +                size_t i;\
                        \
       -                for (i = 0; i < 4; i++) {\
       +                for (i = 0; i < stream->n_chan; i++) {\
                                matrix[0][i] = 1, matrix[1][i] = 0, matrix[2][i] = 0;\
                                matrix[3][i] = 0, matrix[4][i] = 1, matrix[5][i] = 0;\
                                matrix[6][i] = 0, matrix[7][i] = 0, matrix[8][i] = 1;\
       @@ -20,13 +20,17 @@ static int per_channel = 0;
                        \
                        while (eread_frame(stream, buf)) {\
                                if (per_channel) {\
       -                                for (i = 0; i < 4; i++) {\
       +                                for (i = 0; i < stream->n_chan; i++) {\
                                                matrix[0][i] = buf[0][i];\
                                                matrix[4][i] = buf[1][i];\
                                        }\
                                } else {\
       -                                matrix[0][3] = matrix[0][2] = matrix[0][1] = matrix[0][0] = buf[0][1] * buf[0][3];\
       -                                matrix[4][3] = matrix[4][2] = matrix[4][1] = matrix[4][0] = buf[1][1] * buf[1][3];\
       +                                buf[0][1] *= buf[0][3];\
       +                                buf[1][1] *= buf[1][3];\
       +                                for (i = 0; i < stream->n_chan; i++) {\
       +                                        matrix[0][i] = buf[0][1];\
       +                                        matrix[4][i] = buf[1][1];\
       +                                }\
                                }\
                                ewriteall(STDOUT_FILENO, matrix, sizeof(matrix), "<stdout>");\
                        }\
       @@ -62,9 +66,9 @@ main(int argc, char *argv[])
                fprint_stream_head(stdout, &stream);
                efflush(stdout, "<stdout>");
        
       -        if (!strcmp(stream.pixfmt, "xyza"))
       +        if (stream.encoding == DOUBLE)
                        process = process_lf;
       -        else if (!strcmp(stream.pixfmt, "xyza f"))
       +        else if (stream.encoding == FLOAT)
                        process = process_f;
                else
                        eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt);
   DIR diff --git a/src/blind-matrix-shear.c b/src/blind-matrix-shear.c
       @@ -13,9 +13,9 @@ static int in_degrees = 0;
                        pixel_t matrix[9];\
                        pixel_t buf[2];\
                        TYPE conv = in_degrees ? (TYPE)(M_PI / 180.) : 1;\
       -                int i;\
       +                size_t i;\
                        \
       -                for (i = 0; i < 4; i++) {\
       +                for (i = 0; i < stream->n_chan; i++) {\
                                matrix[0][i] = 1, matrix[1][i] = 0, matrix[2][i] = 0;\
                                matrix[3][i] = 0, matrix[4][i] = 1, matrix[5][i] = 0;\
                                matrix[6][i] = 0, matrix[7][i] = 0, matrix[8][i] = 1;\
       @@ -23,19 +23,23 @@ static int in_degrees = 0;
                        \
                        while (eread_frame(stream, buf)) {\
                                if (by_angle) {\
       -                                for (i = !per_channel; i < (per_channel ? 4 : 2); i++) {\
       +                                for (i = !per_channel; i < (per_channel ? stream->n_chan : 2); i++) {\
                                                buf[0][i] = tan(buf[0][i] * conv);\
                                                buf[1][i] = tan(buf[1][i] * conv);\
                                        }\
                                }\
                                if (per_channel) {\
       -                                for (i = 0; i < 4; i++) {\
       +                                for (i = 0; i < stream->n_chan; i++) {\
                                                matrix[1][i] = buf[0][i];\
                                                matrix[3][i] = buf[1][i];\
                                        }\
                                } else {\
       -                                matrix[1][3] = matrix[1][2] = matrix[1][1] = matrix[1][0] = buf[0][1] * buf[0][3];\
       -                                matrix[3][3] = matrix[3][2] = matrix[3][1] = matrix[3][0] = buf[1][1] * buf[1][3];\
       +                                buf[0][1] *= buf[0][3];\
       +                                buf[1][1] *= buf[1][3];\
       +                                for (i = 0; i < stream->n_chan; i++) {\
       +                                        matrix[1][i] = buf[0][1];\
       +                                        matrix[3][i] = buf[1][1];\
       +                                }\
                                }\
                                ewriteall(STDOUT_FILENO, matrix, sizeof(matrix), "<stdout>");\
                        }\
       @@ -77,9 +81,9 @@ main(int argc, char *argv[])
                fprint_stream_head(stdout, &stream);
                efflush(stdout, "<stdout>");
        
       -        if (!strcmp(stream.pixfmt, "xyza"))
       +        if (stream.encoding == DOUBLE)
                        process = process_lf;
       -        else if (!strcmp(stream.pixfmt, "xyza f"))
       +        else if (stream.encoding == FLOAT)
                        process = process_f;
                else
                        eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt);
   DIR diff --git a/src/blind-matrix-translate.c b/src/blind-matrix-translate.c
       @@ -10,9 +10,9 @@ static int per_channel = 0;
                        typedef TYPE pixel_t[4];\
                        pixel_t matrix[9];\
                        pixel_t buf[2];\
       -                int i;\
       +                size_t i;\
                        \
       -                for (i = 0; i < 4; i++) {\
       +                for (i = 0; i < stream->n_chan; i++) {\
                                matrix[0][i] = 1, matrix[1][i] = 0, matrix[2][i] = 0;\
                                matrix[3][i] = 0, matrix[4][i] = 1, matrix[5][i] = 0;\
                                matrix[6][i] = 0, matrix[7][i] = 0, matrix[8][i] = 1;\
       @@ -20,13 +20,17 @@ static int per_channel = 0;
                        \
                        while (eread_frame(stream, buf)) {\
                                if (per_channel) {\
       -                                for (i = 0; i < 4; i++) {\
       +                                for (i = 0; i < stream->n_chan; i++) {\
                                                matrix[2][i] = buf[0][i];\
                                                matrix[5][i] = buf[1][i];\
                                        }\
                                } else {\
       -                                matrix[2][3] = matrix[2][2] = matrix[2][1] = matrix[2][0] = buf[0][1] * buf[0][3];\
       -                                matrix[5][3] = matrix[5][2] = matrix[5][1] = matrix[5][0] = buf[1][1] * buf[1][3];\
       +                                buf[0][1] *= buf[0][3];\
       +                                buf[1][1] *= buf[1][3];\
       +                                for (i = 0; i < stream->n_chan; i++) {\
       +                                        matrix[2][i] = buf[0][1];\
       +                                        matrix[5][i] = buf[1][1];\
       +                                }\
                                }\
                                ewriteall(STDOUT_FILENO, matrix, sizeof(matrix), "<stdout>");\
                        }\
       @@ -62,9 +66,9 @@ main(int argc, char *argv[])
                fprint_stream_head(stdout, &stream);
                efflush(stdout, "<stdout>");
        
       -        if (!strcmp(stream.pixfmt, "xyza"))
       +        if (stream.encoding == DOUBLE)
                        process = process_lf;
       -        else if (!strcmp(stream.pixfmt, "xyza f"))
       +        else if (stream.encoding == FLOAT)
                        process = process_f;
                else
                        eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt);
   DIR diff --git a/src/blind-matrix-transpose.c b/src/blind-matrix-transpose.c
       @@ -10,9 +10,9 @@ static int per_channel = 0;
                        typedef TYPE pixel_t[4];\
                        pixel_t matrix[9];\
                        pixel_t buf;\
       -                int i;\
       +                size_t i;\
                        \
       -                for (i = 0; i < 4; i++) {\
       +                for (i = 0; i < stream->n_chan; i++) {\
                                matrix[0][i] = 1, matrix[1][i] = 0, matrix[2][i] = 0;\
                                matrix[3][i] = 0, matrix[4][i] = 1, matrix[5][i] = 0;\
                                matrix[6][i] = 0, matrix[7][i] = 0, matrix[8][i] = 1;\
       @@ -20,13 +20,14 @@ static int per_channel = 0;
                        \
                        while (eread_frame(stream, buf)) {\
                                if (per_channel) {\
       -                                for (i = 0; i < 4; i++) {\
       +                                for (i = 0; i < stream->n_chan; i++) {\
                                                matrix[3][i] = matrix[1][i] = buf[i];\
                                                matrix[4][i] = matrix[0][i] = 1 - buf[i];\
                                        }\
                                } else {\
       -                                for (i = 0; i < 4; i++) {\
       -                                        matrix[3][i] = matrix[1][i] = buf[1] * buf[3];\
       +                                buf[1] *= buf[3];\
       +                                for (i = 0; i < stream->n_chan; i++) {\
       +                                        matrix[3][i] = matrix[1][i] = buf[1];\
                                                matrix[4][i] = matrix[0][i] = 1 - matrix[3][i];\
                                        }\
                                }\
       @@ -64,9 +65,9 @@ main(int argc, char *argv[])
                fprint_stream_head(stdout, &stream);
                efflush(stdout, "<stdout>");
        
       -        if (!strcmp(stream.pixfmt, "xyza"))
       +        if (stream.encoding == DOUBLE)
                        process = process_lf;
       -        else if (!strcmp(stream.pixfmt, "xyza f"))
       +        else if (stream.encoding == FLOAT)
                        process = process_f;
                else
                        eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt);
   DIR diff --git a/src/blind-multiply-matrices.c b/src/blind-multiply-matrices.c
       @@ -30,15 +30,16 @@ static size_t max_frame_size;
                                                for (y = r = 0; y < h2; y++) {\
                                                        for (x = 0; x < w; x++, r++) {\
                                                                for (k = 0; k < h; k++) \
       -                                                                res[r][1] += left[y * h + k][1] * right[k * w + x][1];\
       -                                                        res[r][3] = res[r][2] = res[r][0] = res[r][1];\
       +                                                                res[r][0] += left[y * h + k][0] * right[k * w + x][0];\
       +                                                        for (j = 1; j < streams->n_chan; j++)\
       +                                                                res[r][j] = res[r][0];\
                                                        }\
                                                }\
                                        } else {\
                                                for (y = r = 0; y < h2; y++)\
                                                        for (x = 0; x < w; x++, r++) \
                                                                for (k = 0; k < h; k++)\
       -                                                                for (j = 0; j < 4; j++)\
       +                                                                for (j = 0; j < streams->n_chan; j++)\
                                                                                res[r][j] += left[y * h + k][j] * right[k * w + x][j];\
                                        }\
                                        \
       @@ -112,9 +113,9 @@ main(int argc, char *argv[])
                        height = streams[i].height;
                }
        
       -        if (!strcmp(streams->pixfmt, "xyza"))
       +        if (streams->encoding == DOUBLE)
                        process = process_lf;
       -        else if (!strcmp(streams->pixfmt, "xyza f"))
       +        else if (streams->encoding == FLOAT)
                        process = process_f;
                else
                        eprintf("pixel format %s is not supported, try xyza\n", streams->pixfmt);
   DIR diff --git a/src/blind-norm.c b/src/blind-norm.c
       @@ -8,7 +8,6 @@ static int skip_x = 0;
        static int skip_y = 0;
        static int skip_z = 0;
        
       -
        #define PROCESS(TYPE, SUFFIX)\
                static void\
                process_##SUFFIX(struct stream *stream)\
       @@ -43,7 +42,6 @@ static int skip_z = 0;
        PROCESS(double, lf)
        PROCESS(float, f)
        
       -
        int
        main(int argc, char *argv[])
        {
   DIR diff --git a/src/blind-premultiply.c b/src/blind-premultiply.c
       @@ -7,7 +7,6 @@ static int skip_x = 0;
        static int skip_y = 0;
        static int skip_z = 0;
        
       -
        #define PROCESS(TYPE, SUFFIX)\
                static void\
                process_##SUFFIX(struct stream *stream)\
       @@ -36,7 +35,6 @@ static int skip_z = 0;
        PROCESS(double, lf)
        PROCESS(float, f)
        
       -
        int
        main(int argc, char *argv[])
        {
   DIR diff --git a/src/blind-quaternion-product.c b/src/blind-quaternion-product.c
       @@ -39,9 +39,9 @@ main(int argc, char *argv[])
                eopen_stream(&left, NULL);
                eopen_stream(&right, argv[0]);
        
       -        if (!strcmp(left.pixfmt, "xyza"))
       +        if (left.encoding == DOUBLE)
                        process = process_lf;
       -        else if (!strcmp(left.pixfmt, "xyza f"))
       +        else if (left.encoding == FLOAT)
                        process = process_f;
                else
                        eprintf("pixel format %s is not supported, try xyza\n", left.pixfmt);
   DIR diff --git a/src/blind-radial-gradient.c b/src/blind-radial-gradient.c
       @@ -7,7 +7,6 @@ static size_t width = 0;
        static size_t height = 0;
        static int with_params;
        
       -
        #define PROCESS(TYPE, SUFFIX)\
                static void\
                process_##SUFFIX(struct stream *stream)\
       @@ -82,7 +81,6 @@ static int with_params;
        PROCESS(double, lf)
        PROCESS(float, f)
        
       -
        int
        main(int argc, char *argv[])
        {
   DIR diff --git a/src/blind-round-wave.c b/src/blind-round-wave.c
       @@ -5,46 +5,32 @@ USAGE("[-e]")
        
        static int equal = 0;
        
       -
        #define PROCESS(TYPE, SUFFIX)\
                static void\
                process_##SUFFIX(struct stream *stream)\
                {\
       -                size_t i, n;\
       -                TYPE x, y, z, a;\
       +                size_t i, j, n;\
       +                TYPE v, *p;\
                        do {\
       -                        n = stream->ptr / stream->pixel_size;\
                                if (equal) {\
       +                                n = stream->ptr / stream->pixel_size;\
                                        for (i = 0; i < n; i++) {\
       -                                        a = ((TYPE *)(stream->buf))[4 * i + 3];\
       -                                        a = mod(a + 1, (TYPE)4) - 1;\
       -                                        a = a < 1 ? 1 - a * a / 2 : (a - 2) * (a - 2) / 2;\
       -                                        ((TYPE *)(stream->buf))[4 * i + 0] = a;\
       -                                        ((TYPE *)(stream->buf))[4 * i + 1] = a;\
       -                                        ((TYPE *)(stream->buf))[4 * i + 2] = a;\
       -                                        ((TYPE *)(stream->buf))[4 * i + 3] = a;\
       +                                        p = (TYPE *)(stream->buf) + i * stream->n_chan;\
       +                                        v = posmod(*p + 1, (TYPE)4) - 1;\
       +                                        v = v < 1 ? 1 - v * v / 2 : (v - 2) * (v - 2) / 2;\
       +                                        for (j = 0; j < stream->n_chan; j++)\
       +                                                p[j] = v;\
                                        }\
       +                                n *= stream->pixel_size;\
                                } else {\
       +                                n = stream->ptr / stream->chan_size;\
                                        for (i = 0; i < n; i++) {\
       -                                        x = ((TYPE *)(stream->buf))[4 * i + 0];\
       -                                        y = ((TYPE *)(stream->buf))[4 * i + 1];\
       -                                        z = ((TYPE *)(stream->buf))[4 * i + 2];\
       -                                        a = ((TYPE *)(stream->buf))[4 * i + 3];\
       -                                        x = mod(x + 1, (TYPE)4) - 1;\
       -                                        y = mod(y + 1, (TYPE)4) - 1;\
       -                                        z = mod(z + 1, (TYPE)4) - 1;\
       -                                        a = mod(a + 1, (TYPE)4) - 1;\
       -                                        x = x < 1 ? 1 - x * x / 2 : (x - 2) * (x - 2) / 2;\
       -                                        y = y < 1 ? 1 - y * y / 2 : (y - 2) * (y - 2) / 2;\
       -                                        z = z < 1 ? 1 - z * z / 2 : (z - 2) * (z - 2) / 2;\
       -                                        a = a < 1 ? 1 - a * a / 2 : (a - 2) * (a - 2) / 2;\
       -                                        ((TYPE *)(stream->buf))[4 * i + 0] = x;\
       -                                        ((TYPE *)(stream->buf))[4 * i + 1] = y;\
       -                                        ((TYPE *)(stream->buf))[4 * i + 2] = z;\
       -                                        ((TYPE *)(stream->buf))[4 * i + 3] = a;\
       +                                        p = (TYPE *)(stream->buf) + i;\
       +                                        v = posmod(*p + 1, (TYPE)4) - 1;\
       +                                        *p = v < 1 ? 1 - v * v / 2 : (v - 2) * (v - 2) / 2;\
                                        }\
       +                                n *= stream->chan_size;\
                                }\
       -                        n *= stream->pixel_size;\
                                ewriteall(STDOUT_FILENO, stream->buf, n, "<stdout>");\
                                memmove(stream->buf, stream->buf + n, stream->ptr -= n);\
                        } while (eread_stream(stream, SIZE_MAX));\
       @@ -55,7 +41,6 @@ static int equal = 0;
        PROCESS(double, lf)
        PROCESS(float, f)
        
       -
        int
        main(int argc, char *argv[])
        {
       @@ -75,9 +60,9 @@ main(int argc, char *argv[])
        
                eopen_stream(&stream, NULL);
        
       -        if (!strcmp(stream.pixfmt, "xyza"))
       +        if (stream.encoding == DOUBLE)
                        process = process_lf;
       -        else if (!strcmp(stream.pixfmt, "xyza f"))
       +        else if (stream.encoding == FLOAT)
                        process = process_f;
                else
                        eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt);
   DIR diff --git a/src/blind-sawtooth-wave.c b/src/blind-sawtooth-wave.c
       @@ -5,41 +5,30 @@ USAGE("[-e]")
        
        static int equal = 0;
        
       -
        #define PROCESS(TYPE, SUFFIX)\
                static void\
                process_##SUFFIX(struct stream *stream)\
                {\
       -                size_t i, n;\
       -                TYPE x, y, z, a;\
       +                size_t i, j, n;\
       +                TYPE v, *p;\
                        do {\
       -                        n = stream->ptr / stream->pixel_size;\
                                if (equal) {\
       +                                n = stream->ptr / stream->pixel_size;\
                                        for (i = 0; i < n; i++) {\
       -                                        a = ((TYPE *)(stream->buf))[4 * i + 3];\
       -                                        a = posmod(a, (TYPE)1);\
       -                                        ((TYPE *)(stream->buf))[4 * i + 0] = a;\
       -                                        ((TYPE *)(stream->buf))[4 * i + 1] = a;\
       -                                        ((TYPE *)(stream->buf))[4 * i + 2] = a;\
       -                                        ((TYPE *)(stream->buf))[4 * i + 3] = a;\
       +                                        p = (TYPE *)(stream->buf) + i * stream->n_chan;\
       +                                        v = posmod(*p, (TYPE)1);\
       +                                        for (j = 0; j < stream->n_chan; j++)\
       +                                                p[j] = v;\
                                        }\
       +                                n *= stream->pixel_size;\
                                } else {\
       +                                n = stream->ptr / stream->chan_size;\
                                        for (i = 0; i < n; i++) {\
       -                                        x = ((TYPE *)(stream->buf))[4 * i + 0];\
       -                                        y = ((TYPE *)(stream->buf))[4 * i + 1];\
       -                                        z = ((TYPE *)(stream->buf))[4 * i + 2];\
       -                                        a = ((TYPE *)(stream->buf))[4 * i + 3];\
       -                                        x = posmod(x, (TYPE)1);\
       -                                        y = posmod(y, (TYPE)1);\
       -                                        z = posmod(z, (TYPE)1);\
       -                                        a = posmod(a, (TYPE)1);\
       -                                        ((TYPE *)(stream->buf))[4 * i + 0] = x;\
       -                                        ((TYPE *)(stream->buf))[4 * i + 1] = y;\
       -                                        ((TYPE *)(stream->buf))[4 * i + 2] = z;\
       -                                        ((TYPE *)(stream->buf))[4 * i + 3] = a;\
       +                                        p = (TYPE *)(stream->buf) + i;\
       +                                        *p = posmod(*p, (TYPE)1);\
                                        }\
       +                                n *= stream->chan_size;\
                                }\
       -                        n *= stream->pixel_size;\
                                ewriteall(STDOUT_FILENO, stream->buf, n, "<stdout>");\
                                memmove(stream->buf, stream->buf + n, stream->ptr -= n);\
                        } while (eread_stream(stream, SIZE_MAX));\
       @@ -50,7 +39,6 @@ static int equal = 0;
        PROCESS(double, lf)
        PROCESS(float, f)
        
       -
        int
        main(int argc, char *argv[])
        {
       @@ -70,9 +58,9 @@ main(int argc, char *argv[])
        
                eopen_stream(&stream, NULL);
        
       -        if (!strcmp(stream.pixfmt, "xyza"))
       +        if (stream.encoding == DOUBLE)
                        process = process_lf;
       -        else if (!strcmp(stream.pixfmt, "xyza f"))
       +        else if (stream.encoding == FLOAT)
                        process = process_f;
                else
                        eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt);
   DIR diff --git a/src/blind-sinc-wave.c b/src/blind-sinc-wave.c
       @@ -5,7 +5,6 @@ USAGE("[-e] [theta0-stream]")
        
        static int equal = 0;
        
       -
        #define PROCESS(TYPE, SUFFIX)\
                static void\
                process_##SUFFIX(struct stream *grad, struct stream *theta0)\
       @@ -70,7 +69,6 @@ static int equal = 0;
        PROCESS(double, lf)
        PROCESS(float, f)
        
       -
        int
        main(int argc, char *argv[])
        {
       @@ -96,9 +94,9 @@ main(int argc, char *argv[])
                                eprintf("theta0-stream must be of dimension 1x1\n");
                }
        
       -        if (!strcmp(stream.pixfmt, "xyza"))
       +        if (stream.encoding == DOUBLE)
                        process = process_lf;
       -        else if (!strcmp(stream.pixfmt, "xyza f"))
       +        else if (stream.encoding == FLOAT)
                        process = process_f;
                else
                        eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt);
   DIR diff --git a/src/blind-sine-wave.c b/src/blind-sine-wave.c
       @@ -5,51 +5,34 @@ USAGE("[-e]")
        
        static int equal = 0;
        
       -
        #define PROCESS(TYPE, SUFFIX)\
                static void\
                process_##SUFFIX(struct stream *stream)\
                {\
       -                size_t i, n;\
       -                TYPE x, y, z, a;\
       +                size_t i, j, n;\
       +                TYPE v, *p;\
                        do {\
       -                        n = stream->ptr / stream->pixel_size;\
                                if (equal) {\
       +                                n = stream->ptr / stream->pixel_size;\
                                        for (i = 0; i < n; i++) {\
       -                                        a = ((TYPE *)(stream->buf))[4 * i + 3];\
       -                                        a = posmod(a, (TYPE)2);\
       -                                        a = a > 1 ? 2 - a : a;\
       -                                        a = 1 - (cos(a * (TYPE)M_PI) + 1) / 2;\
       -                                        ((TYPE *)(stream->buf))[4 * i + 0] = a;\
       -                                        ((TYPE *)(stream->buf))[4 * i + 1] = a;\
       -                                        ((TYPE *)(stream->buf))[4 * i + 2] = a;\
       -                                        ((TYPE *)(stream->buf))[4 * i + 3] = a;\
       +                                        p = (TYPE *)(stream->buf) + i * stream->n_chan;\
       +                                        v = posmod(*p, (TYPE)2);\
       +                                        v = v > 1 ? 2 - v : v;\
       +                                        v = 1 - (cos(v * (TYPE)M_PI) + 1) / 2;\
       +                                        for (j = 0; j < stream->n_chan; j++)\
       +                                                p[j] = v;\
                                        }\
       +                                n *= stream->pixel_size;\
                                } else {\
       +                                n = stream->ptr / stream->chan_size;\
                                        for (i = 0; i < n; i++) {\
       -                                        x = ((TYPE *)(stream->buf))[4 * i + 0];\
       -                                        y = ((TYPE *)(stream->buf))[4 * i + 1];\
       -                                        z = ((TYPE *)(stream->buf))[4 * i + 2];\
       -                                        a = ((TYPE *)(stream->buf))[4 * i + 3];\
       -                                        x = posmod(x, (TYPE)1);\
       -                                        y = posmod(y, (TYPE)1);\
       -                                        z = posmod(z, (TYPE)1);\
       -                                        a = posmod(a, (TYPE)1);\
       -                                        x = x > 1 ? 2 - x : x;\
       -                                        y = y > 1 ? 2 - y : y;\
       -                                        z = z > 1 ? 2 - z : z;\
       -                                        a = a > 1 ? 2 - a : a;\
       -                                        x = 1 - (cos(x * (TYPE)M_PI) + 1) / 2;\
       -                                        y = 1 - (cos(y * (TYPE)M_PI) + 1) / 2;\
       -                                        z = 1 - (cos(z * (TYPE)M_PI) + 1) / 2;\
       -                                        a = 1 - (cos(a * (TYPE)M_PI) + 1) / 2;\
       -                                        ((TYPE *)(stream->buf))[4 * i + 0] = x;\
       -                                        ((TYPE *)(stream->buf))[4 * i + 1] = y;\
       -                                        ((TYPE *)(stream->buf))[4 * i + 2] = z;\
       -                                        ((TYPE *)(stream->buf))[4 * i + 3] = a;\
       +                                        p = (TYPE *)(stream->buf) + i;\
       +                                        v = posmod(*p, (TYPE)2);\
       +                                        v = v > 1 ? 2 - v : v;\
       +                                        *p = 1 - (cos(v * (TYPE)M_PI) + 1) / 2;\
                                        }\
       +                                n *= stream->chan_size;\
                                }\
       -                        n *= stream->pixel_size;\
                                ewriteall(STDOUT_FILENO, stream->buf, n, "<stdout>");\
                                memmove(stream->buf, stream->buf + n, stream->ptr -= n);\
                        } while (eread_stream(stream, SIZE_MAX));\
       @@ -60,7 +43,6 @@ static int equal = 0;
        PROCESS(double, lf)
        PROCESS(float, f)
        
       -
        int
        main(int argc, char *argv[])
        {
       @@ -80,9 +62,9 @@ main(int argc, char *argv[])
        
                eopen_stream(&stream, NULL);
        
       -        if (!strcmp(stream.pixfmt, "xyza"))
       +        if (stream.encoding == DOUBLE)
                        process = process_lf;
       -        else if (!strcmp(stream.pixfmt, "xyza f"))
       +        else if (stream.encoding == FLOAT)
                        process = process_f;
                else
                        eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt);
   DIR diff --git a/src/blind-spectrum.c b/src/blind-spectrum.c
       @@ -6,7 +6,6 @@ USAGE("[-y] [-z depth] spectrum-stream")
        static int luma = 0;
        static size_t nz = 1;
        
       -
        #define PROCESS(TYPE, SUFFIX)\
                static void\
                process_##SUFFIX(struct stream *stream, struct stream *spectrum)\
       @@ -123,7 +122,6 @@ static size_t nz = 1;
        PROCESS(double, lf)
        PROCESS(float, f)
        
       -
        int
        main(int argc, char *argv[])
        {
   DIR diff --git a/src/blind-spiral-gradient.c b/src/blind-spiral-gradient.c
       @@ -12,7 +12,6 @@ static size_t height = 0;
        static int with_params;
        static int with_vector;
        
       -
        #define PROCESS(TYPE, SUFFIX)\
                static void\
                process_##SUFFIX(struct stream *stream)\
       @@ -116,7 +115,6 @@ static int with_vector;
        PROCESS(double, lf)
        PROCESS(float, f)
        
       -
        int
        main(int argc, char *argv[])
        {
   DIR diff --git a/src/blind-square-gradient.c b/src/blind-square-gradient.c
       @@ -7,7 +7,6 @@ static size_t width = 0;
        static size_t height = 0;
        static int with_multiplier;
        
       -
        #define PROCESS(TYPE, SUFFIX)\
                static void\
                process_##SUFFIX(struct stream *stream)\
       @@ -63,7 +62,6 @@ static int with_multiplier;
        PROCESS(double, lf)
        PROCESS(float, f)
        
       -
        int
        main(int argc, char *argv[])
        {
   DIR diff --git a/src/blind-time-blur.c b/src/blind-time-blur.c
       @@ -35,15 +35,15 @@ static int first = 1;
                } while (0)
        
        static void
       -process_xyza(char *output, char *restrict cbuf, char *restrict abuf,
       -             struct stream *colour, struct stream *alpha)
       +process_lf(char *output, char *restrict cbuf, char *restrict abuf,
       +           struct stream *colour, struct stream *alpha)
        {
                PROCESS(double);
        }
        
        static void
       -process_xyzaf(char *output, char *restrict cbuf, char *restrict abuf,
       -              struct stream *colour, struct stream *alpha)
       +process_f(char *output, char *restrict cbuf, char *restrict abuf,
       +          struct stream *colour, struct stream *alpha)
        {
                PROCESS(float);
        }
       @@ -66,10 +66,10 @@ main(int argc, char *argv[])
                eopen_stream(&colour, NULL);
                eopen_stream(&alpha, argv[0]);
        
       -        if (!strcmp(colour.pixfmt, "xyza"))
       -                process = process_xyza;
       -        else if (!strcmp(colour.pixfmt, "xyza f"))
       -                process = process_xyzaf;
       +        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);
        
   DIR diff --git a/src/blind-to-portable.c b/src/blind-to-portable.c
       @@ -89,10 +89,10 @@ USAGE("[-s]")
                } while (0)
        
        static uint64_t conv_double(double host) {CONV(double, uint64_t, int64_t, 11, 1023, 52);}
       -static uint32_t conv_float (float  host) {CONV(float, uint32_t, int32_t, 8, 127, 23);}
       +static uint32_t conv_float (float  host) {CONV(float,  uint32_t, int32_t,  8,  127, 23);}
        
       -static void process_xyza (struct stream *stream, int strict) {PROCESS(double, uint64_t, 64);}
       -static void process_xyzaf(struct stream *stream, int strict) {PROCESS(float, uint32_t, 32);}
       +static void process_lf(struct stream *stream, int strict) {PROCESS(double, uint64_t, 64);}
       +static void process_f (struct stream *stream, int strict) {PROCESS(float,  uint32_t, 32);}
        
        int
        main(int argc, char *argv[])
       @@ -113,10 +113,10 @@ main(int argc, char *argv[])
        
                eopen_stream(&stream, NULL);
        
       -        if (!strcmp(stream.pixfmt, "xyza"))
       -                process = process_xyza;
       -        else if (!strcmp(stream.pixfmt, "xyza f"))
       -                process = process_xyzaf;
       +        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);
        
   DIR diff --git a/src/blind-to-text.c b/src/blind-to-text.c
       @@ -8,16 +8,13 @@ USAGE("")
        #define PROCESS(TYPE, CAST, FMT)\
                do {\
                        size_t i;\
       -                for (i = 0; i < n; i += stream->pixel_size)\
       -                        printf("%"FMT" %"FMT" %"FMT" %"FMT"\n",\
       -                               (CAST)(((TYPE *)(stream->buf + i))[0]),\
       -                               (CAST)(((TYPE *)(stream->buf + i))[1]),\
       -                               (CAST)(((TYPE *)(stream->buf + i))[2]),\
       -                               (CAST)(((TYPE *)(stream->buf + i))[3]));\
       +                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_xyza (struct stream *stream, size_t n) {PROCESS(double, double, ".25lf");}
       -static void process_xyzaf(struct stream *stream, size_t n) {PROCESS(float,  double, ".25lf");}
       +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");}
        
        int
        main(int argc, char *argv[])
       @@ -29,10 +26,10 @@ main(int argc, char *argv[])
        
                eopen_stream(&stream, NULL);
        
       -        if (!strcmp(stream.pixfmt, "xyza"))
       -                process = process_xyza;
       -        else if (!strcmp(stream.pixfmt, "xyza f"))
       -                process = process_xyzaf;
       +        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);
        
   DIR diff --git a/src/blind-triangular-wave.c b/src/blind-triangular-wave.c
       @@ -6,54 +6,37 @@ USAGE("[-es]")
        static int equal = 0;
        static int spiral = 0;
        
       -
        #define PROCESS(TYPE, SUFFIX)\
                static void\
                process_##SUFFIX(struct stream *stream)\
                {\
       -                size_t i, n;\
       -                TYPE x, y, z, a;\
       +                size_t i, j, n;\
       +                TYPE v, *p;\
                        do {\
       -                        n = stream->ptr / stream->pixel_size;\
                                if (equal) {\
       +                                n = stream->ptr / stream->pixel_size;\
                                        for (i = 0; i < n; i++) {\
       -                                        a = ((TYPE *)(stream->buf))[4 * i + 3];\
       -                                        a = posmod(a, (TYPE)2);\
       -                                        a = a > 1 ? 2 - a : a;\
       +                                        p = (TYPE *)(stream->buf) + i * stream->n_chan;\
       +                                        v = posmod(*p, (TYPE)2);\
       +                                        v = v > 1 ? 2 - v : v;\
                                                if (spiral)\
       -                                                a = (a > (TYPE)0.5 ? 1 - a : a) * 2; \
       -                                        ((TYPE *)(stream->buf))[4 * i + 0] = a;\
       -                                        ((TYPE *)(stream->buf))[4 * i + 1] = a;\
       -                                        ((TYPE *)(stream->buf))[4 * i + 2] = a;\
       -                                        ((TYPE *)(stream->buf))[4 * i + 3] = a;\
       +                                                v = (v > (TYPE)0.5 ? 1 - v : v) * 2;\
       +                                        for (j = 0; j < stream->n_chan; j++)\
       +                                                p[j] = v;\
                                        }\
       +                                n *= stream->pixel_size;\
                                } else {\
       +                                n = stream->ptr / stream->chan_size;\
                                        for (i = 0; i < n; i++) {\
       -                                        x = ((TYPE *)(stream->buf))[4 * i + 0];\
       -                                        y = ((TYPE *)(stream->buf))[4 * i + 1];\
       -                                        z = ((TYPE *)(stream->buf))[4 * i + 2];\
       -                                        a = ((TYPE *)(stream->buf))[4 * i + 3];\
       -                                        x = posmod(x, (TYPE)2);\
       -                                        y = posmod(y, (TYPE)2);\
       -                                        z = posmod(z, (TYPE)2);\
       -                                        a = posmod(a, (TYPE)2);\
       -                                        x = x > 1 ? 2 - x : x;\
       -                                        y = y > 1 ? 2 - y : y;\
       -                                        z = z > 1 ? 2 - z : z;\
       -                                        a = a > 1 ? 2 - a : a;\
       -                                        if (spiral) {\
       -                                                x = (x > (TYPE)0.5 ? 1 - x : x) * 2;\
       -                                                y = (y > (TYPE)0.5 ? 1 - y : y) * 2;\
       -                                                z = (z > (TYPE)0.5 ? 1 - z : z) * 2;\
       -                                                a = (a > (TYPE)0.5 ? 1 - a : a) * 2;\
       -                                        }\
       -                                        ((TYPE *)(stream->buf))[4 * i + 0] = x;\
       -                                        ((TYPE *)(stream->buf))[4 * i + 1] = y;\
       -                                        ((TYPE *)(stream->buf))[4 * i + 2] = z;\
       -                                        ((TYPE *)(stream->buf))[4 * i + 3] = a;\
       +                                        p = (TYPE *)(stream->buf) + i;\
       +                                        v = posmod(*p, (TYPE)2);\
       +                                        v = v > 1 ? 2 - v : v;\
       +                                        if (spiral)\
       +                                                v = (v > (TYPE)0.5 ? 1 - v : v) * 2;\
       +                                        *p = v;\
                                        }\
       +                                n *= stream->chan_size;\
                                }\
       -                        n *= stream->pixel_size;\
                                ewriteall(STDOUT_FILENO, stream->buf, n, "<stdout>");\
                                memmove(stream->buf, stream->buf + n, stream->ptr -= n);\
                        } while (eread_stream(stream, SIZE_MAX));\
       @@ -64,7 +47,6 @@ static int spiral = 0;
        PROCESS(double, lf)
        PROCESS(float, f)
        
       -
        int
        main(int argc, char *argv[])
        {
       @@ -87,9 +69,9 @@ main(int argc, char *argv[])
        
                eopen_stream(&stream, NULL);
        
       -        if (!strcmp(stream.pixfmt, "xyza"))
       +        if (stream.encoding == DOUBLE)
                        process = process_lf;
       -        else if (!strcmp(stream.pixfmt, "xyza f"))
       +        else if (stream.encoding == FLOAT)
                        process = process_f;
                else
                        eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt);
   DIR diff --git a/src/blind-unpremultiply.c b/src/blind-unpremultiply.c
       @@ -7,7 +7,6 @@ static int skip_x = 0;
        static int skip_y = 0;
        static int skip_z = 0;
        
       -
        #define PROCESS(TYPE, SUFFIX)\
                static void\
                process_##SUFFIX(struct stream *stream)\
       @@ -38,7 +37,6 @@ static int skip_z = 0;
        PROCESS(double, lf)
        PROCESS(float, f)
        
       -
        int
        main(int argc, char *argv[])
        {
   DIR diff --git a/src/stream.c b/src/stream.c
       @@ -95,12 +95,22 @@ enopen_stream(int status, struct stream *stream, const char *file)
        int
        set_pixel_size(struct stream *stream)
        {
       -        if (!strcmp(stream->pixfmt, "xyza"))
       -                stream->pixel_size = 4 * sizeof(double);
       -        else if (!strcmp(stream->pixfmt, "xyza f"))
       -                stream->pixel_size = 4 * sizeof(float);
       -        else
       +        if (!strcmp(stream->pixfmt, "xyza")) {
       +                stream->n_chan = 4;
       +                stream->chan_size = sizeof(double);
       +                stream->space = CIEXYZ;
       +                stream->alpha = UNPREMULTIPLIED;
       +                stream->encoding = DOUBLE;
       +        } else if (!strcmp(stream->pixfmt, "xyza f")) {
       +                stream->n_chan = 4;
       +                stream->chan_size = sizeof(float);
       +                stream->space = CIEXYZ;
       +                stream->alpha = UNPREMULTIPLIED;
       +                stream->encoding = FLOAT;
       +        } 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;
                stream->frame_size = stream->pixel_size * stream->height * stream->width;
       @@ -212,31 +222,31 @@ encheck_compat(int status, const struct stream *a, const struct stream *b)
        const char *
        get_pixel_format(const char *specified, const char *current)
        {
       -        const char *base = NULL;
       -        int as_float = 0;
       +        enum colour_space space;
       +        enum encoding encoding;
        
                if (!strcmp(current, "xyza"))
       -                base = "xyza";
       +                space = CIEXYZ, encoding = DOUBLE;
                else if (!strcmp(current, "xyza f"))
       -                base = "xyza", as_float = 1;
       +                space = CIEXYZ, encoding = FLOAT;
                else
                        return specified;
        
                if (!strcmp(specified, "xyza"))
       -                base = "xyza";
       +                space = CIEXYZ;
                else if (!strcmp(specified, "xyza f"))
                        return "xyza f";
                else if (!strcmp(specified, "xyza !f"))
                        return "xyza";
                else if (!strcmp(specified, "f"))
       -                as_float = 1;
       +                encoding = FLOAT;
                else if (!strcmp(specified, "!f"))
       -                as_float = 0;
       +                encoding = DOUBLE;
                else
                        return specified;
        
       -        if (!strcmp(base, "xyza"))
       -                return as_float ? "xyza f" : "xyza";
       +        if (space == CIEXYZ)
       +                return encoding == FLOAT ? "xyza f" : "xyza";
                else
                        return specified;
        }
   DIR diff --git a/src/stream.h b/src/stream.h
       @@ -63,16 +63,31 @@ enum dimension {
                LENGTH = 4
        };
        
       +enum colour_space {
       +        CIEXYZ
       +};
       +
       +enum alpha {
       +        UNPREMULTIPLIED
       +};
       +
       +enum encoding {
       +        FLOAT,
       +        DOUBLE
       +};
       +
        struct stream {
                size_t frames;
                size_t width;
                size_t height;
       +        size_t n_chan;
       +        size_t chan_size;
                size_t pixel_size;
                char pixfmt[32];
       +        enum colour_space space;
       +        enum alpha alpha;
       +        enum encoding encoding;
                int fd;
       -#if INT_MAX != LONG_MAX
       -        int padding__;
       -#endif
                size_t ptr;
                size_t xptr;
                char buf[BUFSIZ];