Update blind-convert to support unconverted output from ffmpeg and partially converted output - 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 b640dfad6fd5c0ae3a9bfdd9b4bd54e387b0cc51
 (DIR) parent 61dbc5af8844e0fbebbe4cdf6f796e8b6837c76b
 (HTM) Author: Mattias Andrée <maandree@kth.se>
       Date:   Sun,  6 Aug 2017 02:52:29 +0200
       
       Update blind-convert to support unconverted output from ffmpeg and partially converted output
       
       Signed-off-by: Mattias Andrée <maandree@kth.se>
       
       Diffstat:
         M man/blind-convert.1                 |      44 ++++++++-----------------------
         M man/blind-from-video.1              |      11 -----------
         M src/blind-affine-colour.c           |       2 +-
         M src/blind-convert.c                 |     398 +++++++++++++++++++++++++++----
         M src/blind-dissolve.c                |       2 +-
         M src/blind-from-named.c              |       4 ++--
         M src/blind-from-portable.c           |      12 ++++++------
         M src/blind-mosaic-corners.c          |       8 ++++----
         M src/blind-single-colour.c           |       5 ++---
         M src/blind-to-portable.c             |      12 ++++++------
         M src/blind-transition.c              |       2 +-
         M src/common.h                        |       4 ++--
         M src/stream.c                        |     188 ++++++++++++-------------------
         M src/stream.h                        |       7 +++----
         M src/util/colour.h                   |     104 ++++++++++++++++----------------
         M src/video-math.h                    |      12 ++++++------
       
       16 files changed, 516 insertions(+), 299 deletions(-)
       ---
 (DIR) diff --git a/man/blind-convert.1 b/man/blind-convert.1
       @@ -78,67 +78,45 @@ but single-precision float-point if input is
        single-precision float-point.
        .TP
        .B raw4 f
       -Host-endian, single-precision float-point XY'Z.
       -.TP
       -.B raw4 !f
       -Host-endian, double-precision float-point XY'Z.
       -.TP
       -.B raw4
       -Host-endian, double-precision float-point XY'Z,
       -but single-precision float-point if input is
       -single-precision float-point.
       -.TP
       -.B raw4a f
       -Host-endian, single-precision float-point XY'ZA.
       -.TP
       -.B raw4a !f
       -Host-endian, double-precision float-point XY'ZA.
       -.TP
       -.B raw4a 
       -Host-endian, double-precision float-point XY'ZA,
       -but single-precision float-point if input is
       -single-precision float-point.
       -.TP
       -.B raw5 f
        Host-endian, single-precision float-point sR'G'B'.
        .TP
       -.B raw5 !f
       +.B raw4 !f
        Host-endian, double-precision float-point sR'G'B'.
        .TP
       -.B raw5
       +.B raw4
        Host-endian, double-precision float-point sR'G'B',
        but single-precision float-point if input is
        single-precision float-point.
        .TP
       -.B raw5a f
       +.B raw4a f
        Host-endian, single-precision float-point sR'G'B'A.
        .TP
       -.B raw5a !f
       +.B raw4a !f
        Host-endian, double-precision float-point sR'G'B'A.
        .TP
       -.B raw5a
       +.B raw4a
        Host-endian, double-precision float-point sR'G'B'A,
        but single-precision float-point if input is
        single-precision float-point.
        .TP
       -.B raw6 f
       +.B raw5 f
        Host-endian, single-precision float-point sRGB.
        .TP
       -.B raw6 !f
       +.B raw5 !f
        Host-endian, double-precision float-point sRGB.
        .TP
       -.B raw6
       +.B raw5
        Host-endian, double-precision float-point sRGB,
        but single-precision float-point if input is
        single-precision float-point.
        .TP
       -.B raw6a f
       +.B raw5a f
        Host-endian, single-precision float-point sRGBA.
        .TP
       -.B raw6a !f
       +.B raw5a !f
        Host-endian, double-precision float-point sRGBA.
        .TP
       -.B raw6a
       +.B raw5a
        Host-endian, double-precision float-point sRGBA,
        but single-precision float-point if input is
        single-precision float-point.
 (DIR) diff --git a/man/blind-from-video.1 b/man/blind-from-video.1
       @@ -50,17 +50,6 @@ drafting or if you will not modify the colours. If you use this
        flag, you should also use it in
        .BR blind-to-video (1),
        otherwise the colours will be modified.
       -
       -This is similar to
       -.B -F raw
       -and piping the output to
       -.BR blind-convert (1)
       -with
       -.BR "-F raw4" ,
       -however, the
       -.B xyza
       -is recorded instead of
       -.BR raw4 .
        .TP
        .BR -F " "\fIpixel-format\fP
        Select pixel format, see
 (DIR) diff --git a/src/blind-affine-colour.c b/src/blind-affine-colour.c
       @@ -41,7 +41,7 @@ main(int argc, char *argv[])
        
                SELECT_PROCESS_FUNCTION(&colour);
                if (skip_alpha && colour.alpha_chan != -1)
       -                CHECK_CHANS(&colour, == colour.n_chan - 1, == colour.luma_chan);
       +                CHECK_CHANS(&colour, == (short int)(colour.n_chan - 1), == colour.luma_chan);
                else
                        skip_alpha = 0;
        
 (DIR) diff --git a/src/blind-convert.c b/src/blind-convert.c
       @@ -3,80 +3,380 @@
        
        USAGE("pixel-format ...")
        
       -static void (*outconv)(double *xyzas, size_t n);
       +static int in_level = INT_MAX;
       +static int out_level = INT_MAX;
        
       -#define INCONV(TYPE)\
       +static void
       +lf_to_f(double *in, float *out, size_t n)
       +{
       +        size_t i;
       +        for (i = 0; i < n; i++)
       +                out[i] = (float)(in[i]);
       +}
       +
       +static void
       +f_to_lf(double *in, float *out, size_t n)
       +{
       +        size_t i;
       +        for (i = 0; i < n; i++)
       +                out[i] = (double)(in[i]);
       +}
       +
       +#if !defined(HOST_ENDIAN_IS_LITTLE_ENDIAN_16)
       +static void
       +le_to_h_16(uint16_t *buf, size_t n)
       +{
       +        size_t i;
       +        for (i = 0; i < n; i++)
       +                buf[i] = letoh(buf[i]);
       +}
       +
       +static void
       +h_to_le_16(uint16_t *buf, size_t n)
       +{
       +        size_t i;
       +        for (i = 0; i < n; i++)
       +                buf[i] = htole(buf[i]);
       +}
       +#else
       +# define le_to_h_16(buf, n) ((void) buf, (void) n)
       +# define h_to_le_16(buf, n) ((void) buf, (void) n)
       +#endif
       +
       +static size_t
       +remove_alpha_u16(uint16_t *buf, size_t n)
       +{
       +        size_t i, j;
       +        long int a, max = (long int)UINT16_MAX;
       +        for (i = j = 0; i < n; i += 4, j += 3) {
       +                a = (long int)(buf[i + 3]);
       +                buf[j + 0] = (uint16_t)(((long int)(buf[i + 0]) -  16L * 256L) * a / max +  16L * 256L);
       +                buf[j + 1] = (uint16_t)(((long int)(buf[i + 1]) - 128L * 256L) * a / max + 128L * 256L);
       +                buf[j + 2] = (uint16_t)(((long int)(buf[i + 2]) - 128L * 256L) * a / max + 128L * 256L);
       +        }
       +        return j;
       +}
       +
       +#define REMOVE_ALPHA()\
       +        do {\
       +                size_t i, j;\
       +                for (i = j = 0; i < n; i += 4, j += 3) {\
       +                        buf[j + 0] = buf[i + 0] * buf[i + 3];\
       +                        buf[j + 1] = buf[i + 1] * buf[i + 3];\
       +                        buf[j + 2] = buf[i + 2] * buf[i + 3];\
       +                }\
       +                return j;\
       +        } while (0)
       +
       +static size_t remove_alpha_lf(double *buf, size_t n) { REMOVE_ALPHA(); }
       +static size_t remove_alpha_f (float  *buf, size_t n) { REMOVE_ALPHA(); }
       +
       +#define ADD_ALPHA(TYPE, MAX)\
       +        do {\
       +                size_t i = n, j = n + n / 3;\
       +                for (; i; i -= 3, j -= 4) {\
       +                        out[j - 1] = (TYPE)(MAX);\
       +                        out[j - 2] = in[i - 1];\
       +                        out[j - 3] = in[i - 2];\
       +                        out[j - 4] = in[i - 3];\
       +                }\
       +                return n + n / 3;\
       +        } while (0)
       +
       +static size_t add_alpha_u16(uint16_t *in, uint16_t *out, size_t n) { ADD_ALPHA(uint16_t, UINT16_MAX); }
       +static size_t add_alpha_lf (double   *in, double   *out, size_t n) { ADD_ALPHA(double,   1); }
       +static size_t add_alpha_f  (float    *in, float    *out, size_t n) { ADD_ALPHA(float,    1); }
       +
       +static void
       +raw0_to_raw1(uint16_t *buf, size_t n)
       +{
       +        size_t i;
       +        uint16_t t;
       +        for (i = 0; i < n; i += 4, buf += 4)
       +                t = buf[0], buf[0] = buf[1], buf[1] = buf[2], buf[2] = buf[3], buf[3] = t;
       +}
       +
       +static void
       +raw1_to_raw0(uint16_t *buf, size_t n)
       +{
       +        size_t i;
       +        uint16_t t;
       +        for (i = 0; i < n; i += 4, buf += 4)
       +                t = buf[3], buf[3] = buf[2], buf[2] = buf[1], buf[1] = buf[0], buf[0] = t;
       +}
       +
       +#define RAW2_TO_RAW3(TYPE, WITH_ALPHA)\
       +        do {\
       +                size_t i;\
       +                TYPE max = (TYPE)UINT16_MAX;\
       +                if (sizeof(*in) > sizeof(*out)) {\
       +                        for (i = 0; i < n; i += 3 + WITH_ALPHA) {\
       +                                out[i + 0] = (TYPE)((long int)(in[i + 0]) -  16L * 256L) / max;\
       +                                out[i + 1] = (TYPE)((long int)(in[i + 1]) - 128L * 256L) / max;\
       +                                out[i + 2] = (TYPE)((long int)(in[i + 2]) - 128L * 256L) / max;\
       +                                if (WITH_ALPHA)\
       +                                        out[i + 3] = (TYPE)(in[i + 3]) / max;\
       +                        }\
       +                } else {\
       +                        for (i = n; i; i -= 3 + WITH_ALPHA) {\
       +                                if (WITH_ALPHA)\
       +                                        out[i - 1] = (TYPE)(in[i - 1]) / max;\
       +                                out[i - 1 - WITH_ALPHA] = (TYPE)((long int)(in[i - 1 - WITH_ALPHA]) - 128L * 256L) / max;\
       +                                out[i - 2 - WITH_ALPHA] = (TYPE)((long int)(in[i - 2 - WITH_ALPHA]) - 128L * 256L) / max;\
       +                                out[i - 3 - WITH_ALPHA] = (TYPE)((long int)(in[i - 3 - WITH_ALPHA]) -  16L * 256L) / max;\
       +                        }\
       +                }\
       +        } while (0)
       +
       +static void raw2_to_raw3_lf  (uint16_t *in, double *out, size_t n) { RAW2_TO_RAW3(double, 0); }
       +static void raw2_to_raw3_f   (uint16_t *in, float  *out, size_t n) { RAW2_TO_RAW3(float,  0); }
       +static void raw2a_to_raw3a_lf(uint16_t *in, double *out, size_t n) { RAW2_TO_RAW3(double, 1); }
       +static void raw2a_to_raw3a_f (uint16_t *in, float  *out, size_t n) { RAW2_TO_RAW3(float,  1); }
       +
       +#define RAW3_TO_RAW2(TYPE, WITH_ALPHA)\
                do {\
       -                double buf[sizeof(stream->buf) / (4 * sizeof(TYPE)) * 4];\
       -                double *interm;\
       -                TYPE *in;\
       -                size_t n, m;\
       -                do {\
       -                        in = (TYPE *)stream->buf;\
       -                        interm = buf;\
       -                        n = stream->ptr / stream->pixel_size;\
       -                        for (m = n; m--; in += 4, interm += 4) { \
       -                                interm[0] = (double)(in[0]);\
       -                                interm[1] = (double)(in[1]);\
       -                                interm[2] = (double)(in[2]);\
       -                                interm[3] = (double)(in[3]);\
       +                size_t i;\
       +                TYPE max = (TYPE)UINT16_MAX;\
       +                long int y, u, v;\
       +                if (sizeof(*in) > sizeof(*out)) {\
       +                        for (i = 0; i < n; i += 3 + WITH_ALPHA) {\
       +                                y = (long int)(in[i + 0] * max) +  16L * 256L;\
       +                                u = (long int)(in[i + 1] * max) + 128L * 256L;\
       +                                v = (long int)(in[i + 2] * max) + 128L * 256L;\
       +                                out[i + 0] = (uint16_t)CLIP(0, y, 0xFFFFL);\
       +                                out[i + 1] = (uint16_t)CLIP(0, u, 0xFFFFL);\
       +                                out[i + 2] = (uint16_t)CLIP(0, v, 0xFFFFL);\
       +                                if (WITH_ALPHA) {\
       +                                        v = (long int)(in[i + 3] * max);\
       +                                        out[i + 3] = (uint16_t)CLIP(0, v, 0xFFFFL);\
       +                                }\
       +                        }\
       +                } else {\
       +                        for (i = n; i; i -= 3 + WITH_ALPHA) {\
       +                                if (WITH_ALPHA) {\
       +                                        v = (long int)(in[i - 1] * max);\
       +                                        out[i - 1] = (uint16_t)CLIP(0, v, 0xFFFFL); \
       +                                }\
       +                                v = (long int)(in[i - 1 - WITH_ALPHA] * max) + 128L * 256L;\
       +                                u = (long int)(in[i - 2 - WITH_ALPHA] * max) + 128L * 256L;\
       +                                y = (long int)(in[i - 3 - WITH_ALPHA] * max) +  16L * 256L;\
       +                                out[i - 1 - WITH_ALPHA] = (uint16_t)CLIP(0, v, 0xFFFFL);\
       +                                out[i - 2 - WITH_ALPHA] = (uint16_t)CLIP(0, u, 0xFFFFL);\
       +                                out[i - 3 - WITH_ALPHA] = (uint16_t)CLIP(0, y, 0xFFFFL);\
                                }\
       -                        outconv(buf, n);\
       -                        n *= stream->pixel_size;\
       -                        memmove(stream->buf, stream->buf + n, stream->ptr -= n);\
       -                } while (eread_stream(stream, SIZE_MAX));\
       -                if (stream->ptr)\
       -                        eprintf("%s: incomplete frame\n", stream->file);\
       +                }\
                } while (0)
        
       -#define OUTCONV(TYPE)\
       +static void raw3_to_raw2_lf  (double *in, uint16_t *out, size_t n) { RAW3_TO_RAW2(double, 0); }
       +static void raw3_to_raw2_f   (float  *in, uint16_t *out, size_t n) { RAW3_TO_RAW2(float,  0); }
       +static void raw3a_to_raw2a_lf(double *in, uint16_t *out, size_t n) { RAW3_TO_RAW2(double, 1); }
       +static void raw3a_to_raw2a_f (float  *in, uint16_t *out, size_t n) { RAW3_TO_RAW2(float,  1); }
       +
       +#define CONVERT_COLOUR_SPACE(TYPE, CONV)\
                do {\
       -                TYPE *out = alloca(n * 4 * sizeof(TYPE));\
       -                size_t i, m = n * 4;\
       -                for (i = 0; i < m; i++)\
       -                        out[i] = (TYPE)(xyzas[i]);\
       -                ewriteall(STDOUT_FILENO, out, n * 4 * sizeof(TYPE), "<stdout>");\
       +                size_t i, s = 3 + (size_t)a;\
       +                for (i = 0; i < n; i += s)\
       +                        CONV(buf[i + 0], buf[i + 1], buf[i + 2], buf + i + 0, buf + i + 1, buf + i + 2);\
                } while (0)
        
       -static void inconv_xyza (struct stream *stream) {INCONV(double);}
       -static void inconv_xyzaf(struct stream *stream) {INCONV(float);}
       +static void conv_yuv_to_srgb_lf(double *buf, size_t n, int a) { CONVERT_COLOUR_SPACE(double, yuv_to_srgb); }
       +static void conv_yuv_to_srgb_f (float  *buf, size_t n, int a) { CONVERT_COLOUR_SPACE(float,  yuv_to_srgb); }
       +static void conv_srgb_to_yuv_lf(double *buf, size_t n, int a) { CONVERT_COLOUR_SPACE(double, srgb_to_yuv); }
       +static void conv_srgb_to_yuv_f (float  *buf, size_t n, int a) { CONVERT_COLOUR_SPACE(float,  srgb_to_yuv); }
       +static void conv_xyz_to_srgb_lf(double *buf, size_t n, int a) { CONVERT_COLOUR_SPACE(double, ciexyz_to_srgb); }
       +static void conv_xyz_to_srgb_f (float  *buf, size_t n, int a) { CONVERT_COLOUR_SPACE(float,  ciexyz_to_srgb); }
       +static void conv_srgb_to_xyz_lf(double *buf, size_t n, int a) { CONVERT_COLOUR_SPACE(double, srgb_to_ciexyz); }
       +static void conv_srgb_to_xyz_f (float  *buf, size_t n, int a) { CONVERT_COLOUR_SPACE(float,  srgb_to_ciexyz); }
       +
       +#define CHANGE_TRANSFER(TYPE, CONV)\
       +        do {\
       +                size_t i, s = 3 + (size_t)a;\
       +                for (i = 0; i < n; i += s) {\
       +                        buf[i + 0] = CONV(buf[i + 0]);\
       +                        buf[i + 1] = CONV(buf[i + 1]);\
       +                        buf[i + 2] = CONV(buf[i + 2]);\
       +                }\
       +        } while (0)
       +
       +static void conv_srgbt_to_srgb_lf(double *buf, size_t n, int a) { CHANGE_TRANSFER(double, srgb_decode); }
       +static void conv_srgbt_to_srgb_f (float  *buf, size_t n, int a) { CHANGE_TRANSFER(float,  srgb_decode); }
       +static void conv_srgb_to_srgbt_lf(double *buf, size_t n, int a) { CHANGE_TRANSFER(double, srgb_encode); }
       +static void conv_srgb_to_srgbt_f (float  *buf, size_t n, int a) { CHANGE_TRANSFER(float,  srgb_encode); }
       +
       +#define CONVERT_COLOUR_SPACE_AUTO(CONV)\
       +        static void\
       +        conv_##CONV(enum encoding encoding, int with_alpha, void *buf, size_t n)\
       +        {\
       +                if (encoding == DOUBLE)\
       +                        conv_##CONV##_lf(buf, n, !!with_alpha);\
       +                else\
       +                        conv_##CONV##_f(buf, n, !!with_alpha);\
       +        }
       +CONVERT_COLOUR_SPACE_AUTO(yuv_to_srgb)
       +CONVERT_COLOUR_SPACE_AUTO(srgb_to_yuv)
       +CONVERT_COLOUR_SPACE_AUTO(xyz_to_srgb)
       +CONVERT_COLOUR_SPACE_AUTO(srgb_to_xyz)
       +CONVERT_COLOUR_SPACE_AUTO(srgbt_to_srgb)
       +CONVERT_COLOUR_SPACE_AUTO(srgb_to_srgbt)
       +
       +static void
       +convert(struct stream *stream, struct stream *out, void *buf, size_t n)
       +{
       +        enum encoding encoding = stream->encoding;
       +
       +        if (in_level <= 0 && out_level > 0)
       +                raw0_to_raw1(buf, n);
        
       -static void outconv_xyza (double *xyzas, size_t n) {OUTCONV(double);}
       -static void outconv_xyzaf(double *xyzas, size_t n) {OUTCONV(float);}
       +        if (in_level <= 1 && out_level > 1)
       +                le_to_h_16(buf, n);
       +
       +        if (in_level <= 2 && out_level > 2) {
       +                if (out->encoding == DOUBLE && stream->alpha)
       +                        raw2a_to_raw3a_lf(buf, buf, n);
       +                else if (out->encoding == FLOAT && stream->alpha)
       +                        raw2a_to_raw3a_f(buf, buf, n);
       +                else if (out->encoding == DOUBLE)
       +                        raw2_to_raw3_lf(buf, buf, n);
       +                else if (out->encoding == FLOAT)
       +                        raw2_to_raw3_f(buf, buf, n);
       +                encoding = out->encoding;
       +        } else if (stream->encoding == FLOAT && out->encoding == DOUBLE) {
       +                f_to_lf(buf, buf, n);
       +                encoding = out->encoding;
       +        } else if (stream->encoding == DOUBLE && out->encoding == FLOAT) {
       +                lf_to_f(buf, buf, n);
       +                encoding = out->encoding;
       +        }
       +
       +        if (stream->alpha && !out->alpha) {
       +                if (encoding == DOUBLE)
       +                        n = remove_alpha_lf(buf, n);
       +                else if (encoding == FLOAT)
       +                        n = remove_alpha_f(buf, n);
       +                else
       +                        n = remove_alpha_u16(buf, n);
       +        } else if (!stream->alpha && out->alpha) {
       +                if (encoding == DOUBLE)
       +                        n = add_alpha_lf(buf, buf, n);
       +                else if (encoding == FLOAT)
       +                        n = add_alpha_f(buf, buf, n);
       +                else
       +                        n = add_alpha_u16(buf, buf, n);
       +        }
       +
       +        if (stream->space == CIEXYZ && out->space == YUV_NONLINEAR) {
       +                conv_xyz_to_srgb(encoding, out->alpha, buf, n);
       +                conv_srgb_to_srgbt(encoding, out->alpha, buf, n);
       +                conv_srgb_to_yuv(encoding, out->alpha, buf, n);
       +        } else if (stream->space == CIEXYZ && out->space == SRGB_NONLINEAR) {
       +                conv_xyz_to_srgb(encoding, out->alpha, buf, n);
       +                conv_srgb_to_srgbt(encoding, out->alpha, buf, n);
       +        } else if (stream->space == CIEXYZ && out->space == SRGB) {
       +                conv_xyz_to_srgb(encoding, out->alpha, buf, n);
       +        } else if (stream->space == YUV_NONLINEAR && out->space == CIEXYZ) {
       +                conv_yuv_to_srgb(encoding, out->alpha, buf, n);
       +                conv_srgbt_to_srgb(encoding, out->alpha, buf, n);
       +                conv_srgb_to_xyz(encoding, out->alpha, buf, n);
       +        } else if (stream->space == YUV_NONLINEAR && out->space == SRGB_NONLINEAR) {
       +                conv_yuv_to_srgb(encoding, out->alpha, buf, n);
       +        } else if (stream->space == YUV_NONLINEAR && out->space == SRGB) {
       +                conv_yuv_to_srgb(encoding, out->alpha, buf, n);
       +                conv_srgbt_to_srgb(encoding, out->alpha, buf, n);
       +        } else if (stream->space == SRGB_NONLINEAR && out->space == CIEXYZ) {
       +                conv_srgbt_to_srgb(encoding, out->alpha, buf, n);
       +                conv_srgb_to_xyz(encoding, out->alpha, buf, n);
       +        } else if (stream->space == SRGB_NONLINEAR && out->space == YUV_NONLINEAR) {
       +                conv_srgb_to_yuv(encoding, out->alpha, buf, n);
       +        } else if (stream->space == SRGB_NONLINEAR && out->space == SRGB) {
       +                conv_srgbt_to_srgb(encoding, out->alpha, buf, n);
       +        } else if (stream->space == SRGB && out->space == CIEXYZ) {
       +                conv_srgb_to_xyz(encoding, out->alpha, buf, n);
       +        } else if (stream->space == SRGB && out->space == YUV_NONLINEAR) {
       +                conv_srgb_to_srgbt(encoding, out->alpha, buf, n);
       +                conv_srgb_to_yuv(encoding, out->alpha, buf, n);
       +        } else if (stream->space == SRGB && out->space == SRGB_NONLINEAR) {
       +                conv_srgb_to_srgbt(encoding, out->alpha, buf, n);
       +        }
       +
       +        if (out_level <= 2 && in_level > 2) {
       +                if (encoding == DOUBLE && out->alpha)
       +                        raw3a_to_raw2a_lf(buf, buf, n);
       +                else if (encoding == FLOAT && out->alpha)
       +                        raw3a_to_raw2a_f(buf, buf, n);
       +                else if (encoding == DOUBLE)
       +                        raw3_to_raw2_lf(buf, buf, n);
       +                else if (encoding == FLOAT)
       +                        raw3_to_raw2_f(buf, buf, n);
       +        }
       +
       +        if (out_level <= 1 && in_level > 1)
       +                h_to_le_16(buf, n);
       +
       +        if (out_level <= 0 && in_level > 0)
       +                raw1_to_raw0(buf, n);
       +
       +        ewriteall(STDOUT_FILENO, buf, n * out->chan_size, "<stdout>");
       +}
        
        int
        main(int argc, char *argv[])
        {
       -        struct stream stream;
       +        struct stream stream, out;
                const char *pixfmt;
       -        void (*inconv)(struct stream *stream);
       +        void *buf = NULL;
       +        size_t n;
        
                UNOFLAGS(!argc);
        
                eopen_stream(&stream, NULL);
        
       -        if (!strcmp(stream.pixfmt, "xyza"))
       -                inconv = inconv_xyza;
       -        else if (!strcmp(stream.pixfmt, "xyza f"))
       -                inconv = inconv_xyzaf;
       -        else
       -                eprintf("input pixel format %s is not supported\n", stream.pixfmt);
       -
       +        memcpy(&out, &stream, sizeof(out));
                pixfmt = stream.pixfmt;
                while (*argv)
                        pixfmt = get_pixel_format(*argv++, pixfmt);
       -
       -        if (!strcmp(pixfmt, "xyza"))
       -                outconv = outconv_xyza;
       -        else if (!strcmp(pixfmt, "xyza f"))
       -                outconv = outconv_xyzaf;
       -        else
       +        strcpy(out.pixfmt, pixfmt);
       +        if (set_pixel_format(&out, NULL))
                        eprintf("output pixel format %s is not supported\n", pixfmt);
        
       -        strcpy(stream.pixfmt, pixfmt);
       -        fprint_stream_head(stdout, &stream);
       +        fprint_stream_head(stdout, &out);
                efflush(stdout, "<stdout>");
        
       -        inconv(&stream);
       +        if (!strcmp(stream.pixfmt, out.pixfmt)) {
       +                esend_stream(&stream, STDOUT_FILENO, "<stdout>");
       +                return 0;
       +        }
       +
       +        if (stream.alpha_chan == 0)
       +                in_level = 0;
       +        else if (stream.endian == LITTLE)
       +                in_level = 1;
       +        else if (stream.encoding == UINT16)
       +                in_level = 2;
       +        if (out.alpha_chan == 0)
       +                out_level = 0;
       +        else if (out.endian == LITTLE)
       +                out_level = 1;
       +        else if (out.encoding == UINT16)
       +                out_level = 2;
       +
       +        if (out.encoding == UINT16)
       +                out.encoding = stream.encoding;
       +
       +        n = MAX(stream.chan_size, out.chan_size) * MAX(stream.n_chan, out.n_chan);
       +        if (n > stream.pixel_size)
       +                buf = emalloc(sizeof(stream.buf) / stream.chan_size * n);
       +
       +        do {
       +                n = stream.ptr / stream.pixel_size * stream.n_chan;
       +                if (buf)
       +                        memcpy(buf, stream.buf, n * stream.chan_size);
       +                convert(&stream, &out, buf ? buf : stream.buf, n);
       +                n *= stream.chan_size;
       +                memmove(stream.buf, stream.buf + n, stream.ptr -= n);
       +        } while (eread_stream(&stream, SIZE_MAX));
       +        if (stream.ptr)
       +                eprintf("%s: incomplete frame\n", stream.file);
       +
       +        free(buf);
                return 0;
        }
 (DIR) diff --git a/src/blind-dissolve.c b/src/blind-dissolve.c
       @@ -10,7 +10,7 @@ static int reverse = 0;
        
        #define PROCESS(TYPE)\
                do {\
       -                size_t i = stream->alpha_chan * stream->chan_size;\
       +                size_t i = (size_t)(stream->alpha_chan) * stream->chan_size;\
                        TYPE a = fm ? (TYPE)(reverse ? f : fm - f) / fm_##TYPE : (TYPE)0.5;\
                        for (; i < n; i += stream->pixel_size)\
                                *(TYPE *)(stream->buf + i) *= a;\
 (DIR) diff --git a/src/blind-from-named.c b/src/blind-from-named.c
       @@ -48,7 +48,7 @@ main(int argc, char *argv[])
                int filedes = -1;
                int tries = 11;
                int sockfd, fd;
       -        ssize_t n;
       +        size_t n;
        
                ARGBEGIN {
                case 'a':
       @@ -108,6 +108,6 @@ retry:
                }
        
                while ((n = eread(fd, buf, sizeof(buf), "<received file>")))
       -                ewriteall(STDOUT_FILENO, buf, (size_t)n, "<stdout>");
       +                ewriteall(STDOUT_FILENO, buf, n, "<stdout>");
                return 0;
        }
 (DIR) diff --git a/src/blind-from-portable.c b/src/blind-from-portable.c
       @@ -57,7 +57,7 @@ static int strict = 1;
                        strict *= !USING_BINARY##BITS;\
                        if (!strict && sizeof(ITYPE) != sizeof(OTYPE))\
                                eprintf("-s is supported not on this machine\n");\
       -                if (stream->endian == HOST_ENDIAN && !strict) {\
       +                if (stream->endian == HOST && !strict) {\
                                esend_stream(stream, STDOUT_FILENO, "<stdout>");\
                                break;\
                        }\
       @@ -82,7 +82,7 @@ static int strict = 1;
                do {\
                        size_t i, n;\
                        TYPE *buf = (TYPE *)(stream->buf);\
       -                if (stream->endian == HOST_ENDIAN) {\
       +                if (stream->endian == HOST) {\
                                esend_stream(stream, STDOUT_FILENO, "<stdout>");\
                                break;\
                        }\
       @@ -124,11 +124,11 @@ main(int argc, char *argv[])
        
                eopen_stream(&stream, NULL);
        #if defined(HOST_ENDIAN_IS_LITTLE_ENDIAN)
       -        if (stream.endian == LITTLE_ENDIAN)
       -                stream.endian = HOST_ENDIAN;
       +        if (stream.endian == LITTLE)
       +                stream.endian = HOST;
        #elif defined(HOST_ENDIAN_IS_BIG_ENDIAN)
       -        if (stream.endian == BIG_ENDIAN)
       -                stream.endian = HOST_ENDIAN;
       +        if (stream.endian == BIG)
       +                stream.endian = HOST;
        #endif
        
                SELECT_PROCESS_FUNCTION(&stream);
 (DIR) diff --git a/src/blind-mosaic-corners.c b/src/blind-mosaic-corners.c
       @@ -86,10 +86,10 @@ main(int argc, char *argv[])
                                j = 1;
                                memcpy(found, here, pixsize);
        
       -                        dr = x != stream.width - 1 ? pixsize : tiled_x ? pixsize - stream.row_size : 0;
       -                        dl = x ? -pixsize : tiled_x ? stream.row_size - pixsize : 0;
       -                        dd = y != stream.height - 1 ? stream.row_size : tiled_y ? stream.row_size - stream.frame_size : 0;
       -                        du = y ? -stream.row_size : tiled_y ? stream.frame_size - stream.row_size : 0;
       +                        dr = (ssize_t)(x != stream.width - 1 ? pixsize : tiled_x ? pixsize - stream.row_size : 0);
       +                        dl = (ssize_t)(x ? -pixsize : tiled_x ? stream.row_size - pixsize : 0);
       +                        dd = (ssize_t)(y != stream.height - 1 ? stream.row_size : tiled_y ? stream.row_size - stream.frame_size : 0);
       +                        du = (ssize_t)(y ? -stream.row_size : tiled_y ? stream.frame_size - stream.row_size : 0);
        
                                memcpy(found + j++ * pixsize, here + dr, pixsize);
                                memcpy(found + j++ * pixsize, here + dl, pixsize);
 (DIR) diff --git a/src/blind-single-colour.c b/src/blind-single-colour.c
       @@ -77,8 +77,7 @@ PROCESS(void)
        {
                typedef TYPE pixel_t[4];
                pixel_t buf[BUFSIZ / 4];
       -        size_t x, y, n;
       -        ssize_t r;
       +        size_t x, y, n, r;
                for (x = 0; x < ELEMENTSOF(buf); x++) {
                        buf[x][0] = (TYPE)X;
                        buf[x][1] = (TYPE)Y;
       @@ -88,7 +87,7 @@ PROCESS(void)
                while (inf || stream.frames--)
                        for (y = stream.height; y--;)
                                for (x = stream.width * sizeof(*buf); x;)
       -                                for (x -= n = MIN(sizeof(buf), x); n; n -= (size_t)r)
       +                                for (x -= n = MIN(sizeof(buf), x); n; n -= r)
                                                r = ewrite(STDOUT_FILENO, buf, n, "<stdout>");
        }
        
 (DIR) diff --git a/src/blind-to-portable.c b/src/blind-to-portable.c
       @@ -74,7 +74,7 @@ static int strict = 1;
                        strict *= !USING_BINARY##BITS;\
                        if (!strict && sizeof(ITYPE) != sizeof(OTYPE))\
                                eprintf("-s is supported not on this machine\n");\
       -                if (stream->endian == LITTLE_ENDIAN && !strict) {\
       +                if (stream->endian == LITTLE && !strict) {\
                                esend_stream(stream, STDOUT_FILENO, "<stdout>");\
                                break;\
                        }\
       @@ -99,7 +99,7 @@ static int strict = 1;
                do {\
                        size_t i, n;\
                        TYPE *buf = (TYPE *)(stream->buf);\
       -                if (stream->endian == LITTLE_ENDIAN) {\
       +                if (stream->endian == LITTLE) {\
                                esend_stream(stream, STDOUT_FILENO, "<stdout>");\
                                break;\
                        }\
       @@ -141,11 +141,11 @@ main(int argc, char *argv[])
        
                eopen_stream(&stream, NULL);
        #if defined(HOST_ENDIAN_IS_LITTLE_ENDIAN)
       -        if (stream.endian == HOST_ENDIAN)
       -                stream.endian = LITTLE_ENDIAN;
       +        if (stream.endian == HOST)
       +                stream.endian = LITTLE;
        #elif defined(HOST_ENDIAN_IS_BIG_ENDIAN)
       -        if (stream.endian == HOST_ENDIAN)
       -                stream.endian = BIG_ENDIAN;
       +        if (stream.endian == HOST)
       +                stream.endian = BIG;
        #endif
        
                SELECT_PROCESS_FUNCTION(&stream);
 (DIR) diff --git a/src/blind-transition.c b/src/blind-transition.c
       @@ -14,7 +14,7 @@ static struct stream softness;
        #define PROCESS(TYPE)\
                do {\
                        size_t i, j = 0;\
       -                TYPE a, s, t = fm ? (TYPE)(reverse ? fm - f : f) / fm_##TYPE : 0.5;\
       +                TYPE a, s, t = fm ? (TYPE)(reverse ? fm - f : f) / fm_##TYPE : (TYPE)0.5;\
                        if (!softness_file) {\
                                for (i = 0; i < n; i += stream->pixel_size) {\
                                        a = ((TYPE *)(stream->buf + i))[1];\
 (DIR) diff --git a/src/common.h b/src/common.h
       @@ -66,7 +66,7 @@
        #endif
        
        #if !defined(PIPE_BUF)
       -# define PIPE_BUF BUFSIZ
       +# define PIPE_BUF 512
        #endif
        
        #ifndef DONT_INCLUDE_FLOAT
       @@ -113,7 +113,7 @@
        
        #define SELECT_PROCESS_FUNCTION(stream)\
                do {\
       -                if ((stream)->endian != HOST_ENDIAN)\
       +                if ((stream)->endian != HOST)\
                                eprintf("pixel format %s is not supported, try xyza\n", (stream)->pixfmt);\
                        SELECT_PROCESS_FUNCTION_FLOAT(stream);\
                        SELECT_PROCESS_FUNCTION_DOUBLE(stream);\
 (DIR) diff --git a/src/stream.c b/src/stream.c
       @@ -98,7 +98,7 @@ set_pixel_format(struct stream *stream, const char *pixfmt)
        #define TEST_ENCODING_AGNOSTIC(FMT) (!strcmp(stream->pixfmt, FMT) || !strcmp(stream->pixfmt, FMT" f"))
        
                if (pixfmt) {
       -                pixfmt = get_pixel_format(pixfmt, "xyza");
       +                pixfmt = get_pixel_format(pixfmt, stream->pixfmt[0] ? stream->pixfmt : "xyza");
                        if (strlen(pixfmt) >= sizeof(stream->pixfmt))
                                return -1;
                        strcpy(stream->pixfmt, pixfmt);
       @@ -107,7 +107,7 @@ set_pixel_format(struct stream *stream, const char *pixfmt)
                stream->n_chan = 4;
                stream->alpha = UNPREMULTIPLIED;
                stream->encoding = DOUBLE;
       -        stream->endian = HOST_ENDIAN;
       +        stream->endian = HOST;
                stream->alpha_chan = 3;
                stream->luma_chan = -1;
        
       @@ -119,13 +119,13 @@ set_pixel_format(struct stream *stream, const char *pixfmt)
                } else if (!strcmp(stream->pixfmt, "raw0")) {
                        stream->space = YUV_NONLINEAR;
                        stream->encoding = UINT16;
       -                stream->endian = LITTLE_ENDIAN;
       +                stream->endian = LITTLE;
                        stream->alpha_chan = 0;
                        stream->luma_chan = 1;
                } else if (!strcmp(stream->pixfmt, "raw1")) {
                        stream->space = YUV_NONLINEAR;
                        stream->encoding = UINT16;
       -                stream->endian = LITTLE_ENDIAN;
       +                stream->endian = LITTLE;
                } else if (!strcmp(stream->pixfmt, "raw2a") || !strcmp(stream->pixfmt, "raw2")) {
                        stream->space = YUV_NONLINEAR;
                        stream->alpha = stream->pixfmt[4] == 'a' ? UNPREMULTIPLIED : NO_ALPHA;
       @@ -133,19 +133,15 @@ set_pixel_format(struct stream *stream, const char *pixfmt)
                } else if (TEST_ENCODING_AGNOSTIC("raw3") || TEST_ENCODING_AGNOSTIC("raw3a")) {
                        stream->space = YUV_NONLINEAR;
                        stream->alpha = stream->pixfmt[4] == 'a' ? UNPREMULTIPLIED : NO_ALPHA;
       -                stream->encoding = strlen(stream->pixfmt) > 6 ? FLOAT : DOUBLE;
       +                stream->encoding = strlen(stream->pixfmt) > 5 ? FLOAT : DOUBLE;
                } else if (TEST_ENCODING_AGNOSTIC("raw4") || TEST_ENCODING_AGNOSTIC("raw4a")) {
       -                stream->space = CIEXYZ_NONLINEAR;
       -                stream->alpha = stream->pixfmt[4] == 'a' ? UNPREMULTIPLIED : NO_ALPHA;
       -                stream->encoding = strlen(stream->pixfmt) > 6 ? FLOAT : DOUBLE;
       -        } else if (TEST_ENCODING_AGNOSTIC("raw5") || TEST_ENCODING_AGNOSTIC("raw5a")) {
                        stream->space = SRGB_NONLINEAR;
                        stream->alpha = stream->pixfmt[4] == 'a' ? UNPREMULTIPLIED : NO_ALPHA;
       -                stream->encoding = strlen(stream->pixfmt) > 6 ? FLOAT : DOUBLE;
       -        } else if (TEST_ENCODING_AGNOSTIC("raw6") || TEST_ENCODING_AGNOSTIC("raw6a")) {
       +                stream->encoding = strlen(stream->pixfmt) > 5 ? FLOAT : DOUBLE;
       +        } else if (TEST_ENCODING_AGNOSTIC("raw5") || TEST_ENCODING_AGNOSTIC("raw5a")) {
                        stream->space = SRGB;
                        stream->alpha = stream->pixfmt[4] == 'a' ? UNPREMULTIPLIED : NO_ALPHA;
       -                stream->encoding = strlen(stream->pixfmt) > 6 ? FLOAT : DOUBLE;
       +                stream->encoding = strlen(stream->pixfmt) > 5 ? FLOAT : DOUBLE;
                } else {
                        return -1;
                }
       @@ -156,25 +152,21 @@ set_pixel_format(struct stream *stream, const char *pixfmt)
                }
        
                if (stream->luma_chan == -1) {
       -                switch (stream->space) {
       -                case CIEXYZ:
       -                case CIEXYZ_NONLINEAR:
       +                if (stream->space == CIEXYZ)
                                stream->luma_chan = 1;
       -                        break;
       -                case YUV_NONLINEAR:
       +                else if (stream->space == YUV_NONLINEAR)
                                stream->luma_chan = 0;
       -                        break;
       -                default:
       -                        break;
       -                }
                }
        
                switch (stream->encoding) {
       +        case FLOAT:
       +                stream->chan_size = sizeof(float);
       +                break;
                case DOUBLE:
                        stream->chan_size = sizeof(double);
                        break;
       -        case FLOAT:
       -                stream->chan_size = sizeof(float);
       +        case LONG_DOUBLE:
       +                stream->chan_size = sizeof(long double);
                        break;
                case UINT8:
                        stream->chan_size = sizeof(uint8_t);
       @@ -310,108 +302,68 @@ encheck_compat(int status, const struct stream *a, const struct stream *b)
        const char *
        get_pixel_format(const char *specified, const char *current)
        {
       -        enum colour_space space;
       +        enum colour_space space = CIEXYZ;
                enum alpha alpha = UNPREMULTIPLIED;
       -        enum encoding encoding = DOUBLE;
       -        enum endian endian = HOST_ENDIAN;
       -        int alpha_first = 0;
       -
       -        if (!strcmp(current, "xyza"))
       -                space = CIEXYZ;
       -        else if (!strcmp(current, "xyza f"))
       -                space = CIEXYZ;
       -        else if (!strcmp(current, "raw0"))
       -                space = YUV_NONLINEAR, encoding = UINT16, endian = LITTLE_ENDIAN, alpha_first = 1;
       -        else if (!strcmp(current, "raw1"))
       -                space = YUV_NONLINEAR, encoding = UINT16, endian = LITTLE_ENDIAN;
       -        else if (!strcmp(current, "raw2"))
       -                space = YUV_NONLINEAR, encoding = UINT16, alpha = NO_ALPHA;
       -        else if (!strcmp(current, "raw2a"))
       -                space = YUV_NONLINEAR, encoding = UINT16;
       -        else if (!strcmp(current, "raw3"))
       -                space = YUV_NONLINEAR, alpha = NO_ALPHA;
       -        else if (!strcmp(current, "raw3a"))
       -                space = YUV_NONLINEAR;
       -        else if (!strcmp(current, "raw4"))
       -                space = CIEXYZ_NONLINEAR, alpha = NO_ALPHA;
       -        else if (!strcmp(current, "raw4a"))
       -                space = CIEXYZ_NONLINEAR;
       -        else if (!strcmp(current, "raw5"))
       -                space = SRGB_NONLINEAR, alpha = NO_ALPHA;
       -        else if (!strcmp(current, "raw5a"))
       -                space = SRGB_NONLINEAR;
       -        else if (!strcmp(current, "raw6"))
       -                space = SRGB, alpha = NO_ALPHA;
       -        else if (!strcmp(current, "raw6a"))
       -                space = SRGB;
       +        enum encoding encoding = UINT16;
       +        int level = -1;
       +        size_t n = strlen(specified);
       +
       +        if ((n >= 2 && !strcmp(specified - 2, " f")) ||
       +            !strcmp(specified, "raw0") || !strcmp(specified, "raw1") ||
       +            !strcmp(specified, "raw2") || !strcmp(specified, "raw2a"))
       +                return specified;
       +
       +        if      (!strcmp(current, "xyza"))    space = CIEXYZ, encoding = DOUBLE;
       +        else if (!strcmp(current, "xyza f"))  space = CIEXYZ, encoding = FLOAT;
       +        else if (!strcmp(current, "raw0"))    level = 0;
       +        else if (!strcmp(current, "raw1"))    level = 1;
       +        else if (!strcmp(current, "raw2"))    level = 2, alpha = NO_ALPHA;
       +        else if (!strcmp(current, "raw2a"))   level = 2;
       +        else if (!strcmp(current, "raw3"))    level = 3, encoding = DOUBLE, alpha = NO_ALPHA;
       +        else if (!strcmp(current, "raw3a"))   level = 3, encoding = DOUBLE;
       +        else if (!strcmp(current, "raw3 f"))  level = 3, encoding = FLOAT, alpha = NO_ALPHA;
       +        else if (!strcmp(current, "raw3a f")) level = 3, encoding = FLOAT;
       +        else if (!strcmp(current, "raw4"))    level = 4, encoding = DOUBLE, alpha = NO_ALPHA;
       +        else if (!strcmp(current, "raw4a"))   level = 4, encoding = DOUBLE;
       +        else if (!strcmp(current, "raw4 f"))  level = 4, encoding = FLOAT, alpha = NO_ALPHA;
       +        else if (!strcmp(current, "raw4a f")) level = 4, encoding = FLOAT;
       +        else if (!strcmp(current, "raw5"))    level = 5, encoding = DOUBLE, alpha = NO_ALPHA;
       +        else if (!strcmp(current, "raw5a"))   level = 5, encoding = DOUBLE;
       +        else if (!strcmp(current, "raw5 f"))  level = 5, encoding = FLOAT, alpha = NO_ALPHA;
       +        else if (!strcmp(current, "raw5a f")) level = 5, encoding = FLOAT;
                else
                        return specified;
        
       -        if (!strcmp(specified, "xyza"))
       -                space = CIEXYZ, alpha = UNPREMULTIPLIED;
       -        else if (!strcmp(specified, "xyza !f"))
       -                return "xyza";
       -        else if (!strcmp(specified, "f"))
       -                encoding = FLOAT;
       -        else if (!strcmp(specified, "!f"))
       -                encoding = DOUBLE;
       -        else if (!strcmp(specified, "raw3 !f"))
       -                return "raw3";
       -        else if (!strcmp(specified, "raw3a !f"))
       -                return "raw3a";
       -        else if (!strcmp(specified, "raw4 !f"))
       -                return "raw4";
       -        else if (!strcmp(specified, "raw4a !f"))
       -                return "raw4a";
       -        else if (!strcmp(specified, "raw5 !f"))
       -                return "raw5";
       -        else if (!strcmp(specified, "raw5a !f"))
       -                return "raw5a";
       -        else if (!strcmp(specified, "raw6 !f"))
       -                return "raw6";
       -        else if (!strcmp(specified, "raw6a !f"))
       -                return "raw6a";
       -        else if (!strcmp(specified, "raw3"))
       -                space = YUV_NONLINEAR, alpha = NO_ALPHA;
       -        else if (!strcmp(specified, "raw4"))
       -                space = CIEXYZ_NONLINEAR, alpha = NO_ALPHA;
       -        else if (!strcmp(specified, "raw5"))
       -                space = SRGB_NONLINEAR, alpha = NO_ALPHA;
       -        else if (!strcmp(specified, "raw6"))
       -                space = SRGB, alpha = NO_ALPHA;
       -        else if (!strcmp(specified, "raw3a"))
       -                space = YUV_NONLINEAR, alpha = UNPREMULTIPLIED;
       -        else if (!strcmp(specified, "raw4a"))
       -                space = CIEXYZ_NONLINEAR, alpha = UNPREMULTIPLIED;
       -        else if (!strcmp(specified, "raw5a"))
       -                space = SRGB_NONLINEAR, alpha = UNPREMULTIPLIED;
       -        else if (!strcmp(specified, "raw6a"))
       -                space = SRGB, alpha = UNPREMULTIPLIED;
       +        if      (!strcmp(specified, "f"))        encoding = FLOAT;
       +        else if (!strcmp(specified, "!f"))       encoding = DOUBLE;
       +        else if (!strcmp(specified, "xyza"))     level = -1, alpha = UNPREMULTIPLIED, space = CIEXYZ;
       +        else if (!strcmp(specified, "raw3"))     level = 3, alpha = NO_ALPHA;
       +        else if (!strcmp(specified, "raw3a"))    level = 3, alpha = UNPREMULTIPLIED;
       +        else if (!strcmp(specified, "raw4"))     level = 4, alpha = NO_ALPHA;
       +        else if (!strcmp(specified, "raw4a"))    level = 4, alpha = UNPREMULTIPLIED;
       +        else if (!strcmp(specified, "raw5"))     level = 5, alpha = NO_ALPHA;
       +        else if (!strcmp(specified, "raw5a"))    level = 5, alpha = UNPREMULTIPLIED;
       +        else if (!strcmp(specified, "xyza !f"))  return "xyza";
       +        else if (!strcmp(specified, "raw3 !f"))  return "raw3";
       +        else if (!strcmp(specified, "raw3a !f")) return "raw3a";
       +        else if (!strcmp(specified, "raw4 !f"))  return "raw4";
       +        else if (!strcmp(specified, "raw4a !f")) return "raw4a";
       +        else if (!strcmp(specified, "raw5 !f"))  return "raw5";
       +        else if (!strcmp(specified, "raw5a !f")) return "raw5a";
                else
                        return specified;
        
       -        if (space == CIEXYZ && alpha == UNPREMULTIPLIED)
       -                return encoding == FLOAT ? "xyza f" : "xyza";
       -        else if (space == YUV_NONLINEAR && alpha == UNPREMULTIPLIED && encoding == UINT16 && endian == LITTLE_ENDIAN)
       -                return alpha_first ? "raw0" : "raw1";
       -        else if (space == YUV_NONLINEAR && encoding == UINT16)
       -                return alpha ? "raw2" : "raw2a";
       -        else if (space == YUV_NONLINEAR && encoding == DOUBLE)
       -                return alpha ? "raw3" : "raw3a";
       -        else if (space == YUV_NONLINEAR && encoding == FLOAT)
       -                return alpha ? "raw3 f" : "raw3a f";
       -        else if (space == CIEXYZ_NONLINEAR && encoding == DOUBLE)
       -                return alpha ? "raw4" : "raw4a";
       -        else if (space == CIEXYZ_NONLINEAR && encoding == FLOAT)
       -                return alpha ? "raw4 f" : "raw4a f";
       -        else if (space == SRGB_NONLINEAR && encoding == DOUBLE)
       -                return alpha ? "raw5" : "raw5a";
       -        else if (space == SRGB_NONLINEAR && encoding == FLOAT)
       -                return alpha ? "raw5 f" : "raw5a f";
       -        else if (space == SRGB && encoding == DOUBLE)
       -                return alpha ? "raw6" : "raw6a";
       -        else if (space == SRGB && encoding == FLOAT)
       -                return alpha ? "raw6 f" : "raw6a f";
       +        if      (level == 0 && encoding == UINT16) return "raw0";
       +        else if (level == 1 && encoding == UINT16) return "raw1";
       +        else if (level == 2 && encoding == UINT16) return alpha ? "raw2a"   : "raw2";
       +        else if (level == 3 && encoding == DOUBLE) return alpha ? "raw3a"   : "raw3";
       +        else if (level == 3 && encoding == FLOAT)  return alpha ? "raw3a f" : "raw3 f";
       +        else if (level == 4 && encoding == DOUBLE) return alpha ? "raw4a"   : "raw4";
       +        else if (level == 4 && encoding == FLOAT)  return alpha ? "raw4a f" : "raw4 f";
       +        else if (level == 5 && encoding == DOUBLE) return alpha ? "raw5a"   : "raw5";
       +        else if (level == 5 && encoding == FLOAT)  return alpha ? "raw5a f" : "raw5 f";
       +        else if (level < 0 && space == CIEXYZ && alpha == UNPREMULTIPLIED)
       +                return encoding == FLOAT ? "xyza f" : encoding == DOUBLE ? "xyza" : specified;
                else
                        return specified;
        }
 (DIR) diff --git a/src/stream.h b/src/stream.h
       @@ -65,7 +65,6 @@ enum dimension {
        
        enum colour_space {
                CIEXYZ,
       -        CIEXYZ_NONLINEAR,
                YUV_NONLINEAR,
                SRGB_NONLINEAR,
                SRGB
       @@ -88,9 +87,9 @@ enum encoding {
        };
        
        enum endian {
       -        HOST_ENDIAN,
       -        LITTLE_ENDIAN,
       -        BIG_ENDIAN /* not used */
       +        HOST,
       +        LITTLE,
       +        BIG /* not used */
        };
        
        struct stream {
 (DIR) diff --git a/src/util/colour.h b/src/util/colour.h
       @@ -57,68 +57,68 @@ SRGB_DECODE(float, _f, f)
                MATRIX_MULTIPLY_FUNCTION(FUNCTION_BASE##_f, float,  __VA_ARGS__)
        
        MATRIX_MULTIPLY_FUNCTIONS(yuv_to_srgb,
       -                          1,
       -                          0.00028328010485821202317155420580263580632163211703,
       -                          1.14070449590558520291949662350816652178764343261719,
       -                          1,
       -                          -0.39630886669497211727275498560629785060882568359375,
       -                          -0.58107364288228224857846271333983168005943298339844,
       -                          1,
       -                          2.03990003507541306504435851820744574069976806640625,
       -                          0.00017179031692307700847528739718228507626918144524)
       +                          1,
       +                          0.00028328010485821202317155420580263580632163211703,
       +                          1.14070449590558520291949662350816652178764343261719,
       +                          1,
       +                          -0.39630886669497211727275498560629785060882568359375,
       +                          -0.58107364288228224857846271333983168005943298339844,
       +                          1,
       +                          2.03990003507541306504435851820744574069976806640625,
       +                          0.00017179031692307700847528739718228507626918144524)
        
        MATRIX_MULTIPLY_FUNCTIONS(srgb_to_yuv,
       -                          0.299, 0.587, 0.114,
       -                          -0.14662756598240470062854967636667424812912940979004,
       -                          -0.28771586836102963635752871596196200698614120483398,
       -                           0.43434343434343436474165400795754976570606231689453,
       -                           0.61456892577224520035628074765554629266262054443359,
       -                          -0.51452282157676354490405401520547457039356231689453,
       -                          -0.10004610419548178035231700278018251992762088775635)
       +                          0.299, 0.587, 0.114,
       +                          -0.14662756598240470062854967636667424812912940979004,
       +                          -0.28771586836102963635752871596196200698614120483398,
       +                           0.43434343434343436474165400795754976570606231689453,
       +                           0.61456892577224520035628074765554629266262054443359,
       +                          -0.51452282157676354490405401520547457039356231689453,
       +                          -0.10004610419548178035231700278018251992762088775635)
        
        MATRIX_MULTIPLY_FUNCTIONS(ciexyz_to_srgb,
       -                           3.240446254647737500675930277794,
       -                          -1.537134761820080575134284117667,
       -                          -0.498530193022728718155178739835,
       -                          -0.969266606244679751469561779231,
       -                           1.876011959788370209167851498933,
       -                           0.041556042214430065351304932619,
       -                           0.055643503564352832235773149705,
       -                          -0.204026179735960239147729566866,
       -                           1.057226567722703292062647051353)
       +                           3.240446254647737500675930277794,
       +                          -1.537134761820080575134284117667,
       +                          -0.498530193022728718155178739835,
       +                          -0.969266606244679751469561779231,
       +                           1.876011959788370209167851498933,
       +                           0.041556042214430065351304932619,
       +                           0.055643503564352832235773149705,
       +                          -0.204026179735960239147729566866,
       +                           1.057226567722703292062647051353)
        
        MATRIX_MULTIPLY_FUNCTIONS(srgb_to_ciexyz,
       -                          0.412457445582367576708548995157,
       -                          0.357575865245515878143578447634,
       -                          0.180437247826399665973085006954,
       -                          0.212673370378408277403536885686,
       -                          0.715151730491031756287156895269,
       -                          0.072174899130559869164791564344,
       -                          0.019333942761673460208893260415,
       -                          0.119191955081838593666354597644,
       -                          0.950302838552371742508739771438)
       +                          0.412457445582367576708548995157,
       +                          0.357575865245515878143578447634,
       +                          0.180437247826399665973085006954,
       +                          0.212673370378408277403536885686,
       +                          0.715151730491031756287156895269,
       +                          0.072174899130559869164791564344,
       +                          0.019333942761673460208893260415,
       +                          0.119191955081838593666354597644,
       +                          0.950302838552371742508739771438)
        
        MATRIX_MULTIPLY_FUNCTIONS(scaled_yuv_to_ciexyz,
       -                           0.00001450325106667098632156481796684488472237717360,
       -                           0.00000345586790639342739093228633329157872822179343,
       -                           0.00000400923398630552893485111398685916128670214675,
       -                           0.00001525902189669641837040624243737596543724066578,
       -                          -0.00000207722814409390653614547427030512238843584782,
       -                          -0.00000263898607692305410302407824019166326934282552,
       -                           0.00001661446153041708825425643025752719950105529279,
       -                           0.00002885925752619118069149627137104374696718878113,
       -                          -0.00000071781086875769179526501342566979779746816348)
       +                           0.00001450325106667098632156481796684488472237717360,
       +                           0.00000345586790639342739093228633329157872822179343,
       +                           0.00000400923398630552893485111398685916128670214675,
       +                           0.00001525902189669641837040624243737596543724066578,
       +                          -0.00000207722814409390653614547427030512238843584782,
       +                          -0.00000263898607692305410302407824019166326934282552,
       +                           0.00001661446153041708825425643025752719950105529279,
       +                           0.00002885925752619118069149627137104374696718878113,
       +                          -0.00000071781086875769179526501342566979779746816348)
        
        MATRIX_MULTIPLY_FUNCTIONS(ciexyz_to_scaled_yuv,
       -                            26625.38231027395886485464870929718017578125,
       -                            40524.0090949436053051613271236419677734375,
       -                             -271.5313105642117079696618020534515380859375,
       -                           -11278.3751445417292416095733642578125,
       -                           -26409.91773157499847002327442169189453125,
       -                            34100.5706543184860493056476116180419921875,
       -                           162829.60100012840121053159236907958984375,
       -                          -123829.313212639070115983486175537109375,
       -                           -28411.65702312920984695665538311004638671875)
       +                            26625.38231027395886485464870929718017578125,
       +                            40524.0090949436053051613271236419677734375,
       +                             -271.5313105642117079696618020534515380859375,
       +                           -11278.3751445417292416095733642578125,
       +                           -26409.91773157499847002327442169189453125,
       +                            34100.5706543184860493056476116180419921875,
       +                           162829.60100012840121053159236907958984375,
       +                          -123829.313212639070115983486175537109375,
       +                           -28411.65702312920984695665538311004638671875)
        
        #undef MATRIX_MULTIPLY_FUNCTIONS
        #undef MATRIX_MULTIPLY_FUNCTION
 (DIR) diff --git a/src/video-math.h b/src/video-math.h
       @@ -139,19 +139,19 @@ degcos_f(float u)
        #define htole(A) (_Generic((A),\
                                   uint8_t: (A),\
                                    int8_t: (uint8_t)(A),\
       -                           uint16_t: htole16(A),\
       +                           uint16_t: htole16((uint16_t)(A)),\
                                    int16_t: (uint16_t)htole16((uint16_t)(A)),\
       -                           uint32_t: htole32(A),\
       +                           uint32_t: htole32((uint32_t)(A)),\
                                    int32_t: (uint32_t)htole32((uint32_t)(A)),\
       -                           uint64_t: htole64(A),\
       +                           uint64_t: htole64((uint64_t)(A)),\
                                    int64_t: (uint64_t)htole64((uint64_t)(A))))
        
        #define letoh(A) (_Generic((A),\
                                   uint8_t: (A),\
                                    int8_t: (uint8_t)(A),\
       -                           uint16_t: le16toh(A),\
       +                           uint16_t: le16toh((uint16_t)(A)),\
                                    int16_t: (uint16_t)le16toh((uint16_t)(A)),\
       -                           uint32_t: le32toh(A),\
       +                           uint32_t: le32toh((uint32_t)(A)),\
                                    int32_t: (uint32_t)le32toh((uint32_t)(A)),\
       -                           uint64_t: le64toh(A),\
       +                           uint64_t: le64toh((uint64_t)(A)),\
                                    int64_t: (uint64_t)le64toh((uint64_t)(A))))