blind

suckless command-line video editing utility
git clone git://git.suckless.org/blind
Log | Files | Refs | README | LICENSE

commit ba67e5506bd93eef064d72883ff94dbadee14082
parent 7f85e13e7cdf86ecd84977cc22ebc905bf84608c
Author: Mattias Andrée <maandree@kth.se>
Date:   Sat,  5 Aug 2017 00:03:44 +0200

Add support for skipping conversion to CIEXYZ (not complete)

Some tools are colour space agnostic or even encoding
agnostic, by skipping conversion to CIEXYZ when these
tools are used, the rendering time can be significantly
reduced. The video can also be split horizontally and
vertically, and latted merged back, so it is not necessary
to convert the entire video if only parts of it actually
need it.

Because some tools are less agnostic than other tools,
partial conversion to CIEXYZ is also added.

blind-convert must be updated, and all tools most be test

Signed-off-by: Mattias Andrée <maandree@kth.se>

Diffstat:
TODO | 11++---------
man/blind-colour-matrix.1 | 4+++-
man/blind-convert.1 | 102+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
man/blind-coordinate-field.1 | 4+++-
man/blind-from-video.1 | 26++++++++++++++++++++++++--
man/blind-rectangle-tessellation.1 | 4+++-
man/blind-repeat.1 | 8+++++++-
man/blind-single-colour.1 | 4+++-
man/blind-triangle-tessellation.1 | 4+++-
src/blind-affine-colour.c | 4++++
src/blind-apply-kernel.c | 2++
src/blind-apply-palette.c | 1+
src/blind-arithm.c | 7++++++-
src/blind-chroma-key.c | 2++
src/blind-colour-matrix.c | 6+++++-
src/blind-cone-gradient.c | 1+
src/blind-coordinate-field.c | 2++
src/blind-cross-product.c | 3+++
src/blind-dissolve.c | 12+++++-------
src/blind-dual-key.c | 3+++
src/blind-extract-alpha.c | 4+++-
src/blind-find-rectangle.c | 7++++++-
src/blind-from-portable.c | 46+++++++++++++++++++++++++++++++++++++++-------
src/blind-from-text.c | 1+
src/blind-from-video.c | 33++++++++++++++++++++-------------
src/blind-gauss-blur.c | 2++
src/blind-hexagon-tessellation.c | 5++++-
src/blind-invert-luma.c | 30++++++++++++++++--------------
src/blind-invert-matrix.c | 7+++++--
src/blind-linear-gradient.c | 1+
src/blind-matrix-orthoproject.c | 1+
src/blind-matrix-reflect.c | 1+
src/blind-matrix-rotate.c | 1+
src/blind-matrix-scale.c | 1+
src/blind-matrix-shear.c | 1+
src/blind-matrix-translate.c | 1+
src/blind-matrix-transpose.c | 1+
src/blind-mean.c | 5+++--
src/blind-mosaic-corners.c | 4++--
src/blind-mosaic-edges.c | 4++--
src/blind-mosaic.c | 4+++-
src/blind-multiply-matrices.c | 1+
src/blind-norm.c | 3+++
src/blind-premultiply.c | 3+++
src/blind-quaternion-product.c | 3+++
src/blind-radial-gradient.c | 1+
src/blind-rectangle-tessellation.c | 5++++-
src/blind-repeat.c | 11+++++++----
src/blind-set-alpha.c | 30++++++++++++++++--------------
src/blind-set-luma.c | 3+++
src/blind-set-saturation.c | 18++++++++++--------
src/blind-sinc-wave.c | 2++
src/blind-single-colour.c | 3+++
src/blind-spatial-arithm.c | 5++++-
src/blind-spatial-mean.c | 5++++-
src/blind-spectrum.c | 2++
src/blind-spiral-gradient.c | 1+
src/blind-split-chans.c | 2++
src/blind-square-gradient.c | 1+
src/blind-stack.c | 18++++++++++--------
src/blind-temporal-arithm.c | 4+++-
src/blind-temporal-mean.c | 4+++-
src/blind-time-blur.c | 5++++-
src/blind-to-portable.c | 52+++++++++++++++++++++++++++++++++++++++++++---------
src/blind-to-text.c | 5+++++
src/blind-to-video.c | 10++++++++--
src/blind-transition.c | 6+++++-
src/blind-triangle-tessellation.c | 5++++-
src/blind-unpremultiply.c | 3+++
src/blind-vector-projection.c | 3+++
src/common.h | 85++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
src/define-functions.h | 126+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------
src/generate-macros.c | 32++++++++++++++++++++++++++++++++
src/stream.c | 181++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
src/stream.h | 26+++++++++++++++++++++++---
src/util/endian.h | 25+++++++++++++++++++++++++
76 files changed, 892 insertions(+), 167 deletions(-)

diff --git a/TODO b/TODO @@ -34,17 +34,10 @@ blind-preview a graphical tool for previewing the output of a pipeline should display the output for a selected frame or image should have sliders to tune environment variables -blind-from-video: add options to: - * just run ffmpeg just print the output - * convert output from the option above to blind's format, - but stop after a selected number of frames - * like above, but instead of convert, simply read and - print to stdout (up to user to direct to /dev/null - for discarding) - blind-cone-gradient: add ability to make gradient superelliptic +blind-to-text, blind-from-text: support %a, %e, %g, and custom precision -Add [-j jobs] to blind-from-video, blind-to-video, and blind-apply-kernel. +Add [-j jobs] to blind-from-video, blind-to-video, blind-convert, and blind-apply-kernel. long double is slightly faster than long. long double (xyza q) could be added as another format. diff --git a/man/blind-colour-matrix.1 b/man/blind-colour-matrix.1 @@ -55,7 +55,9 @@ CIE Standard Illuminant D65 is used. .BR -F " "\fIpixel-format\fP Select pixel format, see .BR blind-convert (1) -for more information. +for more information. Pixel formats starting with +.BR raw +are not supported. .TP .B -z Parse arguments as CIE XYY instead of CIE XYZ. diff --git a/man/blind-convert.1 b/man/blind-convert.1 @@ -40,6 +40,108 @@ The same colour space as the input stream, but with each subpixel value is stored as a double-precision floating-point number using the local machines endianness. +.TP +.B raw0 +Use output from +.BR ffmpeg (1) +as-is, that is little-endian, 16-bit integer AY'UV. +.TP +.B raw1 +Little-endian, 16-bit integer Y'UVA. +.TP +.B raw2 +Host-endian, 16-bit integer Y'UV. +.TP +.B raw2a +Host-endian, 16-bit integer Y'UVA. +.TP +.B raw3 f +Host-endian, single-precision float-point Y'UV. +.TP +.B raw3 !f +Host-endian, double-precision float-point Y'UV. +.TP +.B raw3 +Host-endian, double-precision float-point Y'UV, +but single-precision float-point if input is +single-precision float-point. +.TP +.B raw3a f +Host-endian, single-precision float-point Y'UVA. +.TP +.B raw3a !f +Host-endian, double-precision float-point Y'UVA. +.TP +.B raw3a +Host-endian, double-precision float-point Y'UVA, +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 +Host-endian, double-precision float-point sR'G'B'. +.TP +.B raw5 +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 +Host-endian, single-precision float-point sR'G'B'A. +.TP +.B raw5a !f +Host-endian, double-precision float-point sR'G'B'A. +.TP +.B raw5a +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 +Host-endian, single-precision float-point sRGB. +.TP +.B raw6 !f +Host-endian, double-precision float-point sRGB. +.TP +.B raw6 +Host-endian, double-precision float-point sRGB, +but single-precision float-point if input is +single-precision float-point. +.TP +.B raw6a f +Host-endian, single-precision float-point sRGBA. +.TP +.B raw6a !f +Host-endian, double-precision float-point sRGBA. +.TP +.B raw6a +Host-endian, double-precision float-point sRGBA, +but single-precision float-point if input is +single-precision float-point. .SH SEE ALSO .BR blind (7) .SH AUTHORS diff --git a/man/blind-coordinate-field.1 b/man/blind-coordinate-field.1 @@ -36,7 +36,9 @@ no processes with an open read end to this process's stdout. .BR -F " "\fIpixel-format\fP Select pixel format, see .BR blind-convert (1) -for more information. +for more information. Pixel formats starting with +.BR raw +are not supported. .TP .BR -w " "\fIwidth\fP The width of the video, in pixels. diff --git a/man/blind-from-video.1 b/man/blind-from-video.1 @@ -13,7 +13,7 @@ blind-from-video - Converts a regular, cooked video to a blind video .IR height ] [-dL] .I input-file -.I output-file +.RI [ output-file ] .SH DESCRIPTION .B blind-from-video converts the video, in the file @@ -34,6 +34,12 @@ It is unspecified what happens if .I input-file does not have exactly one video stream. All non-video streams, such as audio and subtitles are discarded. +.P +If +.B output-file +is omitted, +.RB ' - ' +(stdout) is used. .SH OPTIONS .TP .B -d @@ -44,11 +50,26 @@ 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 .BR blind-convert (1) -for more information. +for more information. Pixel formats starting with +.BR raw , +other than +.BR raw0 , +are not supported. .TP .BR -h " "\fIheight\fP Change the height of the video to @@ -84,6 +105,7 @@ Change the width of the video to .SH SEE ALSO .BR blind (7), .BR blind-to-video (1), +.BR blind-convert (1), .BR blind-split (1), .BR blind-rewrite-head (1) .SH AUTHORS diff --git a/man/blind-rectangle-tessellation.1 b/man/blind-rectangle-tessellation.1 @@ -23,7 +23,9 @@ pixels tall. .BR -F " "\fIpixel-format\fP Select pixel format, see .BR blind-convert (1) -for more information. +for more information. Pixel formats starting with +.BR raw +are not supported. .SH SEE ALSO .BR blind (7), .BR blind-hexagon-tessellation (1), diff --git a/man/blind-repeat.1 b/man/blind-repeat.1 @@ -7,7 +7,7 @@ blind-repeat - Repeat a video .I count | .RB ' inf ') -.I file +.RI [ file ] .SH DESCRIPTION .B blind-repeat write the a video to stdout that is a loop of the @@ -34,6 +34,12 @@ will read stdin into memory; you are highly discouraged from using this unless stdin is a single frame, or known to only be a very small number of frames, is it can potentially use all of the computer's memory. +.P +If +.I file +is omitted, +.RB ' - ' +is used. .SH OPTIONS .TP .B -f diff --git a/man/blind-single-colour.1 b/man/blind-single-colour.1 @@ -55,7 +55,9 @@ no processes with an open read end to this process's stdout. .BR -F " "\fIpixel-format\fP Select pixel format, see .BR blind-convert (1) -for more information. +for more information. Pixel formats starting with +.BR raw +are not supported. .TP .BR -w " "\fIwidth\fP The width of the video, in pixels. diff --git a/man/blind-triangle-tessellation.1 b/man/blind-triangle-tessellation.1 @@ -26,7 +26,9 @@ go from northwest to southeast. .BR -F " "\fIpixel-format\fP Select pixel format, see .BR blind-convert (1) -for more information. +for more information. Pixel formats starting with +.BR raw +are not supported. .SH SEE ALSO .BR blind (7), .BR blind-hexagon-tessellation (1), diff --git a/src/blind-affine-colour.c b/src/blind-affine-colour.c @@ -40,6 +40,10 @@ main(int argc, char *argv[]) eopen_stream(&matrix, argv[0]); SELECT_PROCESS_FUNCTION(&colour); + if (skip_alpha && colour.alpha_chan != -1) + CHECK_CHANS(&colour, == colour.n_chan - 1, == colour.luma_chan); + else + skip_alpha = 0; if (strcmp(colour.pixfmt, matrix.pixfmt)) eprintf("videos use incompatible pixel formats\n"); diff --git a/src/blind-apply-kernel.c b/src/blind-apply-kernel.c @@ -49,6 +49,8 @@ main(int argc, char *argv[]) eopen_stream(&kernel, argv[0]); SELECT_PROCESS_FUNCTION(&colour); + CHECK_ALPHA_CHAN(&colour); + CHECK_N_CHAN(&colour, 4, 4); if (colour.encoding != kernel.encoding || colour.n_chan != kernel.n_chan) eprintf("videos use incompatible pixel formats"); if (per_pixel && !(kernel.width % colour.width || kernel.height % colour.height)) diff --git a/src/blind-apply-palette.c b/src/blind-apply-palette.c @@ -35,6 +35,7 @@ main(int argc, char *argv[]) eopen_stream(&palette, argv[0]); SELECT_PROCESS_FUNCTION(&stream); + CHECK_N_CHAN(&stream, 4, 4); if (strcmp(stream.pixfmt, palette.pixfmt)) eprintf("videos use incompatible pixel formats\n"); diff --git a/src/blind-arithm.c b/src/blind-arithm.c @@ -105,10 +105,15 @@ main(int argc, char *argv[]) frames = streams[i].frames; } + if (streams->alpha) + CHECK_ALPHA(streams); + CHECK_N_CHAN(streams, 1, 3 + !!streams->alpha); if (streams->encoding == DOUBLE) process = get_process_lf(operation); - else + else if (streams->encoding == FLOAT) process = get_process_f(operation); + else + eprintf("pixel format %s is not supported, try xyza\n", streams->pixfmt); tmp = streams->frames, streams->frames = frames; fprint_stream_head(stdout, streams); diff --git a/src/blind-chroma-key.c b/src/blind-chroma-key.c @@ -19,6 +19,8 @@ main(int argc, char *argv[]) eopen_stream(&key, argv[0]); SELECT_PROCESS_FUNCTION(&stream); + CHECK_ALPHA_CHAN(&stream); + CHECK_N_CHAN(&stream, 4, 4); if (strcmp(stream.pixfmt, key.pixfmt)) eprintf("videos use incompatible pixel formats\n"); diff --git a/src/blind-colour-matrix.c b/src/blind-colour-matrix.c @@ -124,12 +124,16 @@ main(int argc, char *argv[]) } } + CHECK_ALPHA_CHAN(&stream); + CHECK_COLOUR_SPACE(&stream, CIEXYZ); if (stream.encoding == DOUBLE) { ewriteall(STDOUT_FILENO, Mlf, sizeof(Mlf), "<stdout>"); - } else { + } else if (stream.encoding == FLOAT) { for (i = 0; i < ELEMENTSOF(Mlf); i++) Mf[i] = (float)Mlf[i]; ewriteall(STDOUT_FILENO, Mf, sizeof(Mf), "<stdout>"); + } else { + eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt); } return 0; diff --git a/src/blind-cone-gradient.c b/src/blind-cone-gradient.c @@ -42,6 +42,7 @@ main(int argc, char *argv[]) eopen_stream(&stream, NULL); SELECT_PROCESS_FUNCTION(&stream); + CHECK_N_CHAN(&stream, 4, 4); if (stream.width > 3 || stream.height > 3 || stream.width * stream.height < 2 || diff --git a/src/blind-coordinate-field.c b/src/blind-coordinate-field.c @@ -46,6 +46,8 @@ main(int argc, char *argv[]) eset_pixel_format(&stream, pixfmt); SELECT_PROCESS_FUNCTION(&stream); + CHECK_N_CHAN(&stream, 4, 4); + fprint_stream_head(stdout, &stream); efflush(stdout, "<stdout>"); process(); diff --git a/src/blind-cross-product.c b/src/blind-cross-product.c @@ -19,6 +19,9 @@ main(int argc, char *argv[]) eopen_stream(&right, argv[0]); SELECT_PROCESS_FUNCTION(&left); + CHECK_ALPHA_CHAN(&left); + CHECK_N_CHAN(&left, 4, 4); + fprint_stream_head(stdout, &left); efflush(stdout, "<stdout>"); process_two_streams(&left, &right, STDOUT_FILENO, "<stdout>", process); diff --git a/src/blind-dissolve.c b/src/blind-dissolve.c @@ -10,10 +10,10 @@ static int reverse = 0; #define PROCESS(TYPE)\ do {\ - size_t i;\ + size_t i = stream->alpha_chan * stream->chan_size;\ TYPE a = fm ? (TYPE)(reverse ? f : fm - f) / fm_##TYPE : (TYPE)0.5;\ - for (i = 0; i < n; i += stream->pixel_size)\ - ((TYPE *)(stream->buf + i))[3] *= a;\ + for (; i < n; i += stream->pixel_size)\ + *(TYPE *)(stream->buf + i) *= a;\ } while (0) static void process_lf(struct stream *stream, size_t n, size_t f) {PROCESS(double);} @@ -38,10 +38,8 @@ main(int argc, char *argv[]) eopen_stream(&stream, NULL); - if (stream.encoding == DOUBLE) - process = process_lf; - else - process = process_f; + SELECT_PROCESS_FUNCTION(&stream); + CHECK_CHANS(&stream, != -1, == stream.luma_chan); if (!stream.frames) eprintf("video's length is not recorded"); diff --git a/src/blind-dual-key.c b/src/blind-dual-key.c @@ -29,6 +29,9 @@ main(int argc, char *argv[]) eopen_stream(&dual, argv[6]); SELECT_PROCESS_FUNCTION(&stream); + CHECK_ALPHA_CHAN(&stream); + CHECK_N_CHAN(&stream, 4, 4); + fprint_stream_head(stdout, &stream); efflush(stdout, "<stdout>"); process_two_streams(&stream, &dual, STDOUT_FILENO, "<stdout>", process); diff --git a/src/blind-extract-alpha.c b/src/blind-extract-alpha.c @@ -20,6 +20,8 @@ main(int argc, char *argv[]) fd = eopen(argv[0], O_WRONLY | O_CREAT | O_TRUNC, 0666); SELECT_PROCESS_FUNCTION(&stream); + CHECK_CHANS(&stream, != -1, == stream.luma_chan); + fprint_stream_head(stdout, &stream); efflush(stdout, "<stdout>"); if (dprint_stream_head(fd, &stream) < 0) @@ -38,7 +40,7 @@ PROCESS(struct stream *stream, int fd, const char *fname) TYPE a, *p, *b; do { n = stream->ptr / stream->pixel_size; - p = (TYPE *)(stream->buf) + stream->n_chan - 1; + p = (TYPE *)(stream->buf) + stream->luma_chan; b = (TYPE *)buf; for (i = 0; i < n; i++, p += stream->n_chan) { a = *p, *p = 1; diff --git a/src/blind-find-rectangle.c b/src/blind-find-rectangle.c @@ -111,18 +111,23 @@ main(int argc, char *argv[]) cache = emalloc2(stream.width + 1, sizeof(*cache)); buf = emalloc(stream.row_size); + if (argc > 3) + CHECK_ALPHA(&stream); + CHECK_N_CHAN(&stream, 1, 3 + !!stream.alpha); if (stream.encoding == DOUBLE) { colour_lf[0] = X; colour_lf[1] = Y; colour_lf[2] = Z; colour_lf[3] = alpha; process(colour_lf); - } else { + } else if (stream.encoding == FLOAT) { colour_f[0] = (float)X; colour_f[1] = (float)Y; colour_f[2] = (float)Z; colour_f[3] = (float)alpha; process(colour_f); + } else { + eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt); } fshut(stdout, "<stdout>"); diff --git a/src/blind-from-portable.c b/src/blind-from-portable.c @@ -1,4 +1,5 @@ /* See LICENSE file for copyright and license details. */ +#define INCLUDE_UINT16 #include "common.h" USAGE("[-s]") @@ -47,7 +48,7 @@ static int strict = 1; return ret;\ } while (0) -#define PROCESS(ITYPE, OTYPE, BITS)\ +#define PROCESS_FLOAT(ITYPE, OTYPE, BITS)\ do {\ size_t i, n;\ ITYPE *ibuf = (ITYPE *)(stream->buf);\ @@ -55,15 +56,19 @@ static int strict = 1; : alloca(sizeof(stream->buf) / sizeof(ITYPE) * sizeof(OTYPE));\ strict *= !USING_BINARY##BITS;\ if (!strict && sizeof(ITYPE) != sizeof(OTYPE))\ - eprintf("-s is required on this machine\n");\ + eprintf("-s is supported not on this machine\n");\ + if (stream->endian == HOST_ENDIAN && !strict) {\ + esend_stream(stream, STDOUT_FILENO, "<stdout>");\ + break;\ + }\ do {\ n = stream->ptr / sizeof(ITYPE);\ if (strict) {\ for (i = 0; i < n; i++)\ - obuf[i] = conv_##OTYPE(le##BITS##toh(ibuf[i]));\ + obuf[i] = conv_##OTYPE(letoh(ibuf[i]));\ } else {\ for (i = 0; i < n; i++)\ - obuf[i] = *(OTYPE *)&(ITYPE){le##BITS##toh(ibuf[i])};\ + obuf[i] = *(OTYPE *)&(ITYPE){letoh(ibuf[i])};\ }\ ewriteall(STDOUT_FILENO, obuf, n * sizeof(OTYPE), "<stdout>");\ n *= sizeof(ITYPE);\ @@ -73,11 +78,32 @@ static int strict = 1; eprintf("%s: incomplete frame\n", stream->file);\ } while (0) +#define PROCESS_INTEGER(TYPE)\ + do {\ + size_t i, n;\ + TYPE *buf = (TYPE *)(stream->buf);\ + if (stream->endian == HOST_ENDIAN) {\ + esend_stream(stream, STDOUT_FILENO, "<stdout>");\ + break;\ + }\ + do {\ + n = stream->ptr / sizeof(TYPE);\ + for (i = 0; i < n; i++)\ + buf[i] = letoh(buf[i]);\ + n *= sizeof(TYPE);\ + ewriteall(STDOUT_FILENO, buf, n, "<stdout>");\ + 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) + static double conv_double(uint64_t portable) {CONV(uint64_t, int64_t, double, 11, 1023, 52);} static float conv_float (uint32_t portable) {CONV(uint32_t, int32_t, float, 8, 127, 23);} -static void process_lf(struct stream *stream) {PROCESS(uint64_t, double, 64);} -static void process_f (struct stream *stream) {PROCESS(uint32_t, float, 32);} +static void process_lf (struct stream *stream) {PROCESS_FLOAT(uint64_t, double, 64);} +static void process_f (struct stream *stream) {PROCESS_FLOAT(uint32_t, float, 32);} +static void process_u16(struct stream *stream) {PROCESS_INTEGER(uint16_t);} int main(int argc, char *argv[]) @@ -97,9 +123,15 @@ main(int argc, char *argv[]) usage(); eopen_stream(&stream, NULL); +#if defined(HOST_ENDIAN_IS_LITTLE_ENDIAN) + if (stream.endian == LITTLE_ENDIAN) + stream.endian = HOST_ENDIAN; +#elif defined(HOST_ENDIAN_IS_BIG_ENDIAN) + if (stream.endian == BIG_ENDIAN) + stream.endian = HOST_ENDIAN; +#endif SELECT_PROCESS_FUNCTION(&stream); - fprint_stream_head(stdout, &stream); efflush(stdout, "<stdout>"); process(&stream); diff --git a/src/blind-from-text.c b/src/blind-from-text.c @@ -1,5 +1,6 @@ /* See LICENSE file for copyright and license details. */ #ifndef TYPE +#define INCLUDE_UINT16 #include "common.h" USAGE("") diff --git a/src/blind-from-video.c b/src/blind-from-video.c @@ -1,7 +1,7 @@ /* See LICENSE file for copyright and license details. */ #include "common.h" -USAGE("[-F pixel-format] [-r frame-rate] [-w width -h height] [-dL] input-file output-file") +USAGE("[-F pixel-format] [-r frame-rate] [-w width -h height] [-dL] input-file [output-file]") static int draft = 0; static void (*convert_segment)(char *buf, size_t n, int fd, const char *file); @@ -153,16 +153,21 @@ convert(const char *infile, int outfd, const char *outfile, size_t width, size_t close(pipe_rw[1]); - for (ptr = 0;;) { - if (!(n = eread(pipe_rw[0], buf + ptr, sizeof(buf) - ptr, "<subprocess>"))) - break; - ptr += n; - n = ptr - (ptr % 8); - convert_segment(buf, n, outfd, outfile); - memmove(buf, buf + n, ptr -= n); + if (convert_segment) { + for (ptr = 0;;) { + if (!(n = eread(pipe_rw[0], buf + ptr, sizeof(buf) - ptr, "<subprocess>"))) + break; + ptr += n; + n = ptr - (ptr % 8); + convert_segment(buf, n, outfd, outfile); + memmove(buf, buf + n, ptr -= n); + } + if (ptr) + eprintf("<subprocess>: incomplete frame\n"); + } else { + while ((n = eread(pipe_rw[0], buf, sizeof(buf), "<subprocess>"))) + ewriteall(outfd, buf, (size_t)n, outfile); } - if (ptr) - eprintf("<subprocess>: incomplete frame\n"); close(pipe_rw[0]); ewaitpid(pid, &status, 0); @@ -208,19 +213,21 @@ main(int argc, char *argv[]) usage(); } ARGEND; - if (argc != 2 || !width != !height) + if (argc < 1 || argc > 2 || !width != !height) usage(); infile = argv[0]; - outfile = argv[1]; + outfile = argv[1] ? argv[1] : "-"; pixfmt = get_pixel_format(pixfmt, "xyza"); if (!strcmp(pixfmt, "xyza")) convert_segment = convert_segment_xyza; else if (!strcmp(pixfmt, "xyza f")) convert_segment = convert_segment_xyzaf; + else if (!strcmp(pixfmt, "raw0")) + convert_segment = NULL; else - eprintf("pixel format %s is not supported, try xyza\n", pixfmt); + eprintf("pixel format %s is not supported, try xyza or raw0 and blind-convert\n", pixfmt); if (!width) get_metadata(infile, &width, &height); diff --git a/src/blind-gauss-blur.c b/src/blind-gauss-blur.c @@ -361,6 +361,8 @@ main(int argc, char *argv[]) eopen_stream(&sigma, argv[0]); SELECT_PROCESS_FUNCTION(&colour); + CHECK_CHANS(&colour, == 3, == (measure_y_only ? 1 : colour.luma_chan)); + CHECK_N_CHAN(&colour, 4, 4); echeck_compat(&colour, &sigma); diff --git a/src/blind-hexagon-tessellation.c b/src/blind-hexagon-tessellation.c @@ -47,10 +47,13 @@ main(int argc, char *argv[]) diameter = etozu_arg("block-diameter", argv[0], 1, SIZE_MAX); eset_pixel_format(&stream, pixfmt); + CHECK_N_CHAN(&stream, 4, 4); if (stream.encoding == DOUBLE) SET_XYZA(double); - else + else if (stream.encoding == FLOAT) SET_XYZA(float); + else + eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt); stream.width = (size_t)((double)diameter * sqrt(3.)); stream.height = diameter * 3 / 2; diff --git a/src/blind-invert-luma.c b/src/blind-invert-luma.c @@ -41,14 +41,14 @@ USAGE("[-iw] mask-stream") }\ } while (0) -static void process_xyza (struct stream *colour, struct stream *mask, size_t n) {PROCESS(double,);} -static void process_xyza_i (struct stream *colour, struct stream *mask, size_t n) {PROCESS(double, 1 -);} -static void process_xyza_w (struct stream *colour, struct stream *mask, size_t n) {PROCESS_W(double,);} -static void process_xyza_iw (struct stream *colour, struct stream *mask, size_t n) {PROCESS_W(double, 1 -);} -static void process_xyzaf (struct stream *colour, struct stream *mask, size_t n) {PROCESS(float,);} -static void process_xyzaf_i (struct stream *colour, struct stream *mask, size_t n) {PROCESS(float, 1 -);} -static void process_xyzaf_w (struct stream *colour, struct stream *mask, size_t n) {PROCESS_W(float,);} -static void process_xyzaf_iw(struct stream *colour, struct stream *mask, size_t n) {PROCESS_W(float, 1 -);} +static void process_lf (struct stream *colour, struct stream *mask, size_t n) {PROCESS(double,);} +static void process_lf_i (struct stream *colour, struct stream *mask, size_t n) {PROCESS(double, 1 -);} +static void process_lf_w (struct stream *colour, struct stream *mask, size_t n) {PROCESS_W(double,);} +static void process_lf_iw(struct stream *colour, struct stream *mask, size_t n) {PROCESS_W(double, 1 -);} +static void process_f (struct stream *colour, struct stream *mask, size_t n) {PROCESS(float,);} +static void process_f_i (struct stream *colour, struct stream *mask, size_t n) {PROCESS(float, 1 -);} +static void process_f_w (struct stream *colour, struct stream *mask, size_t n) {PROCESS_W(float,);} +static void process_f_iw (struct stream *colour, struct stream *mask, size_t n) {PROCESS_W(float, 1 -);} int main(int argc, char *argv[]) @@ -74,12 +74,14 @@ main(int argc, char *argv[]) eopen_stream(&colour, NULL); eopen_stream(&mask, argv[0]); - if (!strcmp(colour.pixfmt, "xyza")) - process = invert ? whitepoint ? process_xyza_iw : process_xyza_i - : whitepoint ? process_xyza_w : process_xyza; - else if (!strcmp(colour.pixfmt, "xyza f")) - process = invert ? whitepoint ? process_xyzaf_iw : process_xyzaf_i - : whitepoint ? process_xyzaf_w : process_xyzaf; + CHECK_ALPHA(&colour); + CHECK_COLOUR_SPACE(&colour, CIEXYZ); + if (colour.encoding == DOUBLE) + process = invert ? whitepoint ? process_lf_iw : process_lf_i + : whitepoint ? process_lf_w : process_lf; + else if (colour.encoding == FLOAT) + process = invert ? whitepoint ? process_f_iw : process_f_i + : whitepoint ? process_f_w : process_f; else eprintf("pixel format %s is not supported, try xyza\n", colour.pixfmt); diff --git a/src/blind-invert-matrix.c b/src/blind-invert-matrix.c @@ -58,11 +58,14 @@ main(int argc, char *argv[]) stream.width = width; efflush(stdout, "<stdout>"); + if (skip_ch[3] && stream.alpha_chan != -1) + CHECK_ALPHA_CHAN(&stream); + CHECK_N_CHAN(&stream, 1, 4); one = alloca(stream.pixel_size); - if (!strcmp(stream.pixfmt, "xyza")) { + if (stream.encoding == DOUBLE) { *(double *)one = 1; process = process_lf; - } else if (!strcmp(stream.pixfmt, "xyza f")) { + } else if (stream.encoding == FLOAT) { *(float *)one = 1; process = process_f; } else { diff --git a/src/blind-linear-gradient.c b/src/blind-linear-gradient.c @@ -37,6 +37,7 @@ main(int argc, char *argv[]) eopen_stream(&stream, NULL); SELECT_PROCESS_FUNCTION(&stream); + CHECK_N_CHAN(&stream, 4, 4); if (stream.width > 2 || stream.height > 2 || stream.width * stream.height != 2) eprintf("<stdin>: each frame must contain exactly 2 pixels\n"); diff --git a/src/blind-matrix-orthoproject.c b/src/blind-matrix-orthoproject.c @@ -29,6 +29,7 @@ main(int argc, char *argv[]) eopen_stream(&stream, NULL); SELECT_PROCESS_FUNCTION(&stream); + CHECK_CHANS(&stream, == 3, == 1); if (stream.width > 2 || stream.height > 2 || stream.width * stream.height != 2) eprintf("<stdin>: each frame must contain exactly 2 pixels\n"); diff --git a/src/blind-matrix-reflect.c b/src/blind-matrix-reflect.c @@ -29,6 +29,7 @@ main(int argc, char *argv[]) eopen_stream(&stream, NULL); SELECT_PROCESS_FUNCTION(&stream); + CHECK_CHANS(&stream, == 3, == 1); if (stream.width > 2 || stream.height > 2 || stream.width * stream.height != 2) eprintf("<stdin>: each frame must contain exactly 2 pixels\n"); diff --git a/src/blind-matrix-rotate.c b/src/blind-matrix-rotate.c @@ -33,6 +33,7 @@ main(int argc, char *argv[]) eopen_stream(&stream, NULL); SELECT_PROCESS_FUNCTION(&stream); + CHECK_CHANS(&stream, == 3, == 1); if (stream.width != 1 || stream.height != 1) eprintf("<stdin>: each frame must contain exactly 1 pixels\n"); diff --git a/src/blind-matrix-scale.c b/src/blind-matrix-scale.c @@ -29,6 +29,7 @@ main(int argc, char *argv[]) eopen_stream(&stream, NULL); SELECT_PROCESS_FUNCTION(&stream); + CHECK_CHANS(&stream, == 3, == 1); if (stream.width > 2 || stream.height > 2 || stream.width * stream.height != 2) eprintf("<stdin>: each frame must contain exactly 2 pixels\n"); diff --git a/src/blind-matrix-shear.c b/src/blind-matrix-shear.c @@ -37,6 +37,7 @@ main(int argc, char *argv[]) eopen_stream(&stream, NULL); SELECT_PROCESS_FUNCTION(&stream); + CHECK_CHANS(&stream, == 3, == 1); if (stream.width > 2 || stream.height > 2 || stream.width * stream.height != 2) eprintf("<stdin>: each frame must contain exactly 2 pixels\n"); diff --git a/src/blind-matrix-translate.c b/src/blind-matrix-translate.c @@ -29,6 +29,7 @@ main(int argc, char *argv[]) eopen_stream(&stream, NULL); SELECT_PROCESS_FUNCTION(&stream); + CHECK_CHANS(&stream, == 3, == 1); if (stream.width > 2 || stream.height > 2 || stream.width * stream.height != 2) eprintf("<stdin>: each frame must contain exactly 2 pixels\n"); diff --git a/src/blind-matrix-transpose.c b/src/blind-matrix-transpose.c @@ -29,6 +29,7 @@ main(int argc, char *argv[]) eopen_stream(&stream, NULL); SELECT_PROCESS_FUNCTION(&stream); + CHECK_CHANS(&stream, == 3, == 1); if (stream.width != 1 || stream.height != 1) eprintf("<stdin>: each frame must contain exactly 1 pixels\n"); diff --git a/src/blind-mean.c b/src/blind-mean.c @@ -109,7 +109,6 @@ main(int argc, char *argv[]) enum method method = ARITHMETIC; int i, two = 0; - ARGBEGIN { case 'd': method = STANDARD_DEVIATION; @@ -171,8 +170,10 @@ main(int argc, char *argv[]) if (streams->encoding == DOUBLE) process = process_functions_lf[method]; - else + else if (streams->encoding == FLOAT) process = process_functions_f[method]; + else + eprintf("pixel format %s is not supported, try xyza\n", streams->pixfmt); tmp = streams->frames, streams->frames = frames; fprint_stream_head(stdout, streams); diff --git a/src/blind-mosaic-corners.c b/src/blind-mosaic-corners.c @@ -59,12 +59,12 @@ main(int argc, char *argv[]) colours[1] = alloca(stream.pixel_size); memset(colours[0], 0, stream.pixel_size); - if (!strcmp(stream.pixfmt, "xyza")) { + if (stream.encoding == DOUBLE) { ((double *)(colours[1]))[0] = (double)1; ((double *)(colours[1]))[1] = (double)1; ((double *)(colours[1]))[2] = (double)1; ((double *)(colours[1]))[3] = (double)1; - } else if (!strcmp(stream.pixfmt, "xyza f")) { + } else if (stream.encoding == FLOAT) { ((float *)(colours[1]))[0] = (float)1; ((float *)(colours[1]))[1] = (float)1; ((float *)(colours[1]))[2] = (float)1; diff --git a/src/blind-mosaic-edges.c b/src/blind-mosaic-edges.c @@ -39,12 +39,12 @@ main(int argc, char *argv[]) colours[1] = alloca(stream.pixel_size); memset(colours[0], 0, stream.pixel_size); - if (!strcmp(stream.pixfmt, "xyza")) { + if (stream.encoding == DOUBLE) { ((double *)(colours[1]))[0] = (double)1; ((double *)(colours[1]))[1] = (double)1; ((double *)(colours[1]))[2] = (double)1; ((double *)(colours[1]))[3] = (double)1; - } else if (!strcmp(stream.pixfmt, "xyza f")) { + } else if (stream.encoding == FLOAT) { ((float *)(colours[1]))[0] = (float)1; ((float *)(colours[1]))[1] = (float)1; ((float *)(colours[1]))[2] = (float)1; diff --git a/src/blind-mosaic.c b/src/blind-mosaic.c @@ -158,8 +158,10 @@ main(int argc, char *argv[]) eopen_stream(&mosaic, argv[0]); SELECT_PROCESS_FUNCTION(&colour); - echeck_compat(&colour, &mosaic); + CHECK_ALPHA(&colour); + CHECK_N_CHAN(&colour, 4, 4); + echeck_compat(&colour, &mosaic); fprint_stream_head(stdout, &colour); efflush(stdout, "<stdout>"); process_each_frame_two_streams(&colour, &mosaic, STDOUT_FILENO, "<stdout>", process); diff --git a/src/blind-multiply-matrices.c b/src/blind-multiply-matrices.c @@ -67,6 +67,7 @@ main(int argc, char *argv[]) } SELECT_PROCESS_FUNCTION(streams); + CHECK_N_CHAN(streams, 1, 4); w = streams->width, streams->width = max_width; h = streams->height, streams->height = max_height; diff --git a/src/blind-norm.c b/src/blind-norm.c @@ -41,6 +41,9 @@ main(int argc, char *argv[]) eopen_stream(&stream, NULL); SELECT_PROCESS_FUNCTION(&stream); + CHECK_ALPHA_CHAN(&stream); + CHECK_N_CHAN(&stream, 4, 4); + fprint_stream_head(stdout, &stream); efflush(stdout, "<stdout>"); process(&stream); diff --git a/src/blind-premultiply.c b/src/blind-premultiply.c @@ -37,6 +37,9 @@ main(int argc, char *argv[]) eopen_stream(&stream, NULL); SELECT_PROCESS_FUNCTION(&stream); + CHECK_CHANS(&stream, == 3, == stream.luma_chan); + CHECK_N_CHAN(&stream, 4, 4); + fprint_stream_head(stdout, &stream); efflush(stdout, "<stdout>"); process(&stream); diff --git a/src/blind-quaternion-product.c b/src/blind-quaternion-product.c @@ -19,6 +19,9 @@ main(int argc, char *argv[]) eopen_stream(&right, argv[0]); SELECT_PROCESS_FUNCTION(&left); + CHECK_ALPHA_CHAN(&left); + CHECK_N_CHAN(&left, 4, 4); + fprint_stream_head(stdout, &left); efflush(stdout, "<stdout>"); process_two_streams(&left, &right, STDOUT_FILENO, "<stdout>", process); diff --git a/src/blind-radial-gradient.c b/src/blind-radial-gradient.c @@ -34,6 +34,7 @@ main(int argc, char *argv[]) eopen_stream(&stream, NULL); SELECT_PROCESS_FUNCTION(&stream); + CHECK_N_CHAN(&stream, 4, 4); if (stream.width > 3 || stream.height > 3 || stream.width * stream.height < 2 || diff --git a/src/blind-rectangle-tessellation.c b/src/blind-rectangle-tessellation.c @@ -47,10 +47,13 @@ main(int argc, char *argv[]) height = etozu_arg("block-height", argv[1], 1, SIZE_MAX); eset_pixel_format(&stream, pixfmt); + CHECK_N_CHAN(&stream, 4, 4); if (stream.encoding == DOUBLE) SET_XYZA(double); - else + else if (stream.encoding == FLOAT) SET_XYZA(float); + else + eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt); stream.width = 2 * width; stream.height = 2 * height; diff --git a/src/blind-repeat.c b/src/blind-repeat.c @@ -1,7 +1,7 @@ /* See LICENSE file for copyright and license details. */ #include "common.h" -USAGE("([-f] count | 'inf') file") +USAGE("([-f] count | 'inf') [file]") static size_t count = 0; static int inf; @@ -76,7 +76,7 @@ main(int argc, char *argv[]) usage(); } ARGEND; - if (argc != 2) + if (argc < 1 || argc > 2) usage(); if ((inf = !strcmp(argv[0], "inf"))) { @@ -87,14 +87,17 @@ main(int argc, char *argv[]) count = etozu_arg("the count", argv[0], 0, SIZE_MAX); } - eopen_stream(&stream, !strcmp(argv[1], "-") ? NULL : argv[1]); + if (argv[1] && !strcmp(argv[1], "-")) + argv[1] = NULL; + + eopen_stream(&stream, argv[1]); if (stream.frames && count > SIZE_MAX / stream.frames) eprintf("%s: video is too long\n", stream.file); stream.frames *= count; fprint_stream_head(stdout, &stream); efflush(stdout, "<stdout>"); - if (!strcmp(argv[1], "-") + if (!argv[1] ? (framewise ? repeat_stdin_framewise() : repeat_stdin()) : (framewise ? repeat_regular_file_framewise(): repeat_regular_file())) if (!inf || errno != EPIPE) diff --git a/src/blind-set-alpha.c b/src/blind-set-alpha.c @@ -6,18 +6,18 @@ USAGE("[-i] alpha-stream") #define PROCESS(TYPE, INV)\ do {\ size_t i;\ - TYPE a;\ - for (i = 0; i < n; i += colour->pixel_size) {\ - a = INV ((TYPE *)(alpha->buf + i))[1];\ - a *= ((TYPE *)(alpha->buf + i))[3];\ - ((TYPE *)(colour->buf + i))[3] *= a;\ - }\ + TYPE *luma = (TYPE *)(alpha->buf) + alpha->luma_chan;\ + TYPE *alph = (TYPE *)(alpha->buf) + alpha->alpha_chan;\ + TYPE *out = (TYPE *)(colour->buf) + colour->alpha_chan;\ + n /= colour->chan_size;\ + for (i = 0; i < n; i += colour->n_chan)\ + out[i] *= (INV luma[i]) * alph[i];\ } while (0) -static void process_xyza (struct stream *colour, struct stream *alpha, size_t n) {PROCESS(double,);} -static void process_xyza_i (struct stream *colour, struct stream *alpha, size_t n) {PROCESS(double, 1 -);} -static void process_xyzaf (struct stream *colour, struct stream *alpha, size_t n) {PROCESS(float,);} -static void process_xyzaf_i(struct stream *colour, struct stream *alpha, size_t n) {PROCESS(float, 1 -);} +static void process_lf (struct stream *colour, struct stream *alpha, size_t n) {PROCESS(double,);} +static void process_lf_i(struct stream *colour, struct stream *alpha, size_t n) {PROCESS(double, 1 -);} +static void process_f (struct stream *colour, struct stream *alpha, size_t n) {PROCESS(float,);} +static void process_f_i (struct stream *colour, struct stream *alpha, size_t n) {PROCESS(float, 1 -);} int main(int argc, char *argv[]) @@ -40,10 +40,12 @@ main(int argc, char *argv[]) eopen_stream(&colour, NULL); eopen_stream(&alpha, argv[0]); - if (!strcmp(colour.pixfmt, "xyza")) - process = invert ? process_xyza_i : process_xyza; - else if (!strcmp(colour.pixfmt, "xyza f")) - process = invert ? process_xyzaf_i : process_xyzaf; + CHECK_CHANS(&colour, != -1, != -1); + CHECK_ALPHA(&colour); + if (colour.encoding == DOUBLE) + process = invert ? process_lf_i : process_lf; + else if (colour.encoding == FLOAT) + process = invert ? process_f_i : process_f; else eprintf("pixel format %s is not supported, try xyza\n", colour.pixfmt); diff --git a/src/blind-set-luma.c b/src/blind-set-luma.c @@ -19,6 +19,9 @@ main(int argc, char *argv[]) eopen_stream(&luma, argv[0]); SELECT_PROCESS_FUNCTION(&colour); + CHECK_CHANS(&colour, == 3, == 1); + CHECK_COLOUR_SPACE(&colour, CIEXYZ); + fprint_stream_head(stdout, &colour); efflush(stdout, "<stdout>"); process_two_streams(&colour, &luma, STDOUT_FILENO, "<stdout>", process); diff --git a/src/blind-set-saturation.c b/src/blind-set-saturation.c @@ -41,10 +41,10 @@ USAGE("[-w] saturation-stream") }\ } while (0) -static void process_xyza (struct stream *colour, struct stream *satur, size_t n) {PROCESS(double);} -static void process_xyza_w (struct stream *colour, struct stream *satur, size_t n) {PROCESS_W(double);} -static void process_xyzaf (struct stream *colour, struct stream *satur, size_t n) {PROCESS(float);} -static void process_xyzaf_w(struct stream *colour, struct stream *satur, size_t n) {PROCESS_W(float);} +static void process_lf (struct stream *colour, struct stream *satur, size_t n) {PROCESS(double);} +static void process_lf_w(struct stream *colour, struct stream *satur, size_t n) {PROCESS_W(double);} +static void process_f (struct stream *colour, struct stream *satur, size_t n) {PROCESS(float);} +static void process_f_w (struct stream *colour, struct stream *satur, size_t n) {PROCESS_W(float);} int main(int argc, char *argv[]) @@ -67,10 +67,12 @@ main(int argc, char *argv[]) eopen_stream(&colour, NULL); eopen_stream(&satur, argv[0]); - if (!strcmp(colour.pixfmt, "xyza")) - process = whitepoint ? process_xyza_w : process_xyza; - else if (!strcmp(colour.pixfmt, "xyza f")) - process = whitepoint ? process_xyzaf_w : process_xyzaf; + CHECK_COLOUR_SPACE(&colour, CIEXYZ); + CHECK_CHANS(&colour, == 3, == 1); + if (colour.encoding == DOUBLE) + process = whitepoint ? process_lf_w : process_lf; + else if (colour.encoding == FLOAT) + process = whitepoint ? process_f_w : process_f; else eprintf("pixel format %s is not supported, try xyza\n", colour.pixfmt); diff --git a/src/blind-sinc-wave.c b/src/blind-sinc-wave.c @@ -35,6 +35,8 @@ main(int argc, char *argv[]) } SELECT_PROCESS_FUNCTION(&stream); + CHECK_CHANS(&stream, == 3, == 1); + CHECK_N_CHAN(&stream, 4, 4); if (have_theta0 && strcmp(stream.pixfmt, theta0.pixfmt)) eprintf("videos use incompatible pixel formats\n"); diff --git a/src/blind-single-colour.c b/src/blind-single-colour.c @@ -59,6 +59,9 @@ main(int argc, char *argv[]) eset_pixel_format(&stream, pixfmt); SELECT_PROCESS_FUNCTION(&stream); + CHECK_N_CHAN(&stream, 4, 4); + if (argc < 3) + CHECK_COLOUR_SPACE(&stream, CIEXYZ); fprint_stream_head(stdout, &stream); efflush(stdout, "<stdout>"); diff --git a/src/blind-spatial-arithm.c b/src/blind-spatial-arithm.c @@ -80,10 +80,13 @@ main(int argc, char *argv[]) eopen_stream(&stream, NULL); echeck_dimensions(&stream, WIDTH | HEIGHT, NULL); + CHECK_N_CHAN(&stream, 4, 4); if (stream.encoding == DOUBLE) process = get_process_lf(argv[0]); - else + else if (stream.encoding == FLOAT) process = get_process_f(argv[0]); + else + eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt); if (DPRINTF_HEAD(STDOUT_FILENO, stream.frames, 1, 1, stream.pixfmt) < 0) eprintf("dprintf:"); diff --git a/src/blind-spatial-mean.c b/src/blind-spatial-mean.c @@ -146,10 +146,13 @@ main(int argc, char *argv[]) eprintf("videos use incompatible pixel formats\n"); } + CHECK_N_CHAN(&stream, 4, 4); if (stream.encoding == DOUBLE) process = process_functions_lf[method]; - else + else if (stream.encoding == FLOAT) process = process_functions_f[method]; + else + eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt); if (DPRINTF_HEAD(STDOUT_FILENO, stream.frames, 1, 1, stream.pixfmt) < 0) eprintf("dprintf:"); diff --git a/src/blind-spectrum.c b/src/blind-spectrum.c @@ -34,6 +34,8 @@ main(int argc, char *argv[]) eopen_stream(&spectrum, argv[0]); SELECT_PROCESS_FUNCTION(&stream); + CHECK_CHANS(&stream, == 3, == (luma ? 1 : stream.luma_chan)); + CHECK_N_CHAN(&stream, 4, 4); if (stream.n_chan != spectrum.n_chan || stream.encoding != spectrum.encoding) eprintf("videos use incompatible pixel formats\n"); diff --git a/src/blind-spiral-gradient.c b/src/blind-spiral-gradient.c @@ -53,6 +53,7 @@ main(int argc, char *argv[]) eopen_stream(&stream, NULL); SELECT_PROCESS_FUNCTION(&stream); + CHECK_N_CHAN(&stream, 4, 4); if (stream.width > 5 || stream.height > 5 || stream.width * stream.height < 2 || diff --git a/src/blind-split-chans.c b/src/blind-split-chans.c @@ -24,6 +24,8 @@ main(int argc, char *argv[]) usage(); eopen_stream(&stream, NULL); + CHECK_ALPHA_CHAN(&stream); + CHECK_N_CHAN(&stream, 4, 4); xfd = eopen(argv[0], O_WRONLY | O_CREAT | O_TRUNC, 0666); yfd = eopen(argv[1], O_WRONLY | O_CREAT | O_TRUNC, 0666); diff --git a/src/blind-square-gradient.c b/src/blind-square-gradient.c @@ -34,6 +34,7 @@ main(int argc, char *argv[]) eopen_stream(&stream, NULL); SELECT_PROCESS_FUNCTION(&stream); + CHECK_N_CHAN(&stream, 4, 4); if (stream.width > 3 || stream.height > 3 || stream.width * stream.height < 2 || diff --git a/src/blind-stack.c b/src/blind-stack.c @@ -33,10 +33,10 @@ USAGE("[-bs] bottom-stream ... top-stream") }\ } while (0) -static void process_xyza (struct stream *streams, size_t n_streams, size_t n) { PROCESS(double, 0); } -static void process_xyza_b (struct stream *streams, size_t n_streams, size_t n) { PROCESS(double, 1); } -static void process_xyzaf (struct stream *streams, size_t n_streams, size_t n) { PROCESS(float, 0); } -static void process_xyzaf_b(struct stream *streams, size_t n_streams, size_t n) { PROCESS(float, 1); } +static void process_lf (struct stream *streams, size_t n_streams, size_t n) { PROCESS(double, 0); } +static void process_lf_b(struct stream *streams, size_t n_streams, size_t n) { PROCESS(double, 1); } +static void process_f (struct stream *streams, size_t n_streams, size_t n) { PROCESS(float, 0); } +static void process_f_b (struct stream *streams, size_t n_streams, size_t n) { PROCESS(float, 1); } int main(int argc, char *argv[]) @@ -72,12 +72,14 @@ main(int argc, char *argv[]) frames = streams[i].frames; } - if (!strcmp(streams->pixfmt, "xyza")) - process = blend ? process_xyza_b : process_xyza; - else if (!strcmp(streams->pixfmt, "xyza f")) - process = blend ? process_xyzaf_b : process_xyzaf; + if (streams->encoding == DOUBLE) + process = blend ? process_lf_b :process_lf; + else if (streams->encoding == FLOAT) + process = blend ? process_f_b : process_f; else eprintf("pixel format %s is not supported, try xyza\n", streams->pixfmt); + CHECK_ALPHA_CHAN(streams); + CHECK_N_CHAN(streams, 4, 4); tmp = streams->frames, streams->frames = frames; fprint_stream_head(stdout, streams); diff --git a/src/blind-temporal-arithm.c b/src/blind-temporal-arithm.c @@ -73,8 +73,10 @@ main(int argc, char *argv[]) if (stream.encoding == DOUBLE) process = get_process_lf(argv[0]); - else + else if (stream.encoding == FLOAT) process = get_process_f(argv[0]); + else + eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt); echeck_dimensions(&stream, WIDTH | HEIGHT, NULL); img = emalloc(stream.frame_size); diff --git a/src/blind-temporal-mean.c b/src/blind-temporal-mean.c @@ -154,8 +154,10 @@ main(int argc, char *argv[]) if (stream.encoding == DOUBLE) process = process_functions_lf[method]; - else + else if (stream.encoding == FLOAT) process = process_functions_f[method]; + else + eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt); stream.frames = 1; echeck_dimensions(&stream, WIDTH | HEIGHT, NULL); diff --git a/src/blind-time-blur.c b/src/blind-time-blur.c @@ -28,6 +28,9 @@ main(int argc, char *argv[]) eopen_stream(&alpha, argv[0]); SELECT_PROCESS_FUNCTION(&colour); + CHECK_CHANS(&colour, == 3, == 1); + CHECK_N_CHAN(&colour, 4, 4); + echeck_compat(&colour, &alpha); fprint_stream_head(stdout, &colour); efflush(stdout, "<stdout>"); @@ -45,7 +48,7 @@ PROCESS(char *output, char *restrict cbuf, char *restrict abuf, pixel_t *restrict clr = (pixel_t *)cbuf; pixel_t *restrict alf = (pixel_t *)abuf; pixel_t *img = (pixel_t *)output; - size_t i, n = colour->frame_size / sizeof(pixel_t); + size_t i, n = colour->width * colour->height; TYPE a1, a2; if (first) { diff --git a/src/blind-to-portable.c b/src/blind-to-portable.c @@ -1,4 +1,5 @@ /* See LICENSE file for copyright and license details. */ +#define INCLUDE_UINT16 #include "common.h" /* Disable warnings in <math.h> */ @@ -9,6 +10,8 @@ USAGE("[-s]") +static int strict = 1; + #define CONV(ITYPE, OTYPE, SOTYPE, EXPONENT, HA2EXPONENT, FRACTION)\ do {\ static int cache_i = 0;\ @@ -62,7 +65,7 @@ USAGE("[-s]") return ret;\ } while (0) -#define PROCESS(ITYPE, OTYPE, BITS)\ +#define PROCESS_FLOAT(ITYPE, OTYPE, BITS)\ do {\ size_t i, n;\ ITYPE *ibuf = (ITYPE *)(stream->buf);\ @@ -70,15 +73,19 @@ USAGE("[-s]") : alloca(sizeof(stream->buf) / sizeof(ITYPE) * sizeof(OTYPE));\ strict *= !USING_BINARY##BITS;\ if (!strict && sizeof(ITYPE) != sizeof(OTYPE))\ - eprintf("-s is required on this machine\n");\ + eprintf("-s is supported not on this machine\n");\ + if (stream->endian == LITTLE_ENDIAN && !strict) {\ + esend_stream(stream, STDOUT_FILENO, "<stdout>");\ + break;\ + }\ do {\ n = stream->ptr / sizeof(ITYPE);\ if (strict) {\ for (i = 0; i < n; i++)\ - obuf[i] = htole##BITS(conv_##ITYPE(ibuf[i]));\ + obuf[i] = htole(conv_##ITYPE(ibuf[i]));\ } else {\ for (i = 0; i < n; i++)\ - obuf[i] = htole##BITS(*(OTYPE *)&ibuf[i]);\ + obuf[i] = htole(*(OTYPE *)&ibuf[i]);\ }\ ewriteall(STDOUT_FILENO, obuf, n * sizeof(OTYPE), "<stdout>");\ n *= sizeof(ITYPE);\ @@ -88,18 +95,38 @@ USAGE("[-s]") eprintf("%s: incomplete frame\n", stream->file);\ } while (0) +#define PROCESS_INTEGER(TYPE)\ + do {\ + size_t i, n;\ + TYPE *buf = (TYPE *)(stream->buf);\ + if (stream->endian == LITTLE_ENDIAN) {\ + esend_stream(stream, STDOUT_FILENO, "<stdout>");\ + break;\ + }\ + do {\ + n = stream->ptr / sizeof(TYPE);\ + for (i = 0; i < n; i++)\ + buf[i] = htole(buf[i]);\ + n *= sizeof(TYPE);\ + ewriteall(STDOUT_FILENO, buf, n, "<stdout>");\ + 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) + 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 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);} +static void process_lf (struct stream *stream) {PROCESS_FLOAT(double, uint64_t, 64);} +static void process_f (struct stream *stream) {PROCESS_FLOAT(float, uint32_t, 32);} +static void process_u16(struct stream *stream) {PROCESS_INTEGER(uint16_t);} int main(int argc, char *argv[]) { struct stream stream; - int strict = 1; - void (*process)(struct stream *stream, int strict); + void (*process)(struct stream *stream); ARGBEGIN { case 's': @@ -113,10 +140,17 @@ main(int argc, char *argv[]) usage(); eopen_stream(&stream, NULL); +#if defined(HOST_ENDIAN_IS_LITTLE_ENDIAN) + if (stream.endian == HOST_ENDIAN) + stream.endian = LITTLE_ENDIAN; +#elif defined(HOST_ENDIAN_IS_BIG_ENDIAN) + if (stream.endian == HOST_ENDIAN) + stream.endian = BIG_ENDIAN; +#endif SELECT_PROCESS_FUNCTION(&stream); fprint_stream_head(stdout, &stream); efflush(stdout, "<stdout>"); - process(&stream, strict); + process(&stream); return 0; } diff --git a/src/blind-to-text.c b/src/blind-to-text.c @@ -1,5 +1,6 @@ /* See LICENSE file for copyright and license details. */ #ifndef TYPE +#define INCLUDE_UINT16 #include "common.h" USAGE("") @@ -32,7 +33,11 @@ PROCESS(struct stream *stream, size_t n) size_t i; TYPE *p = (TYPE *)(stream->buf); for (i = 0, n /= stream->chan_size; i < n; i++) +#ifdef INTEGER_TYPE + printf("%"PRINT_TYPE"%c", (PRINT_CAST)(p[i]), (i + 1) % stream->n_chan ? ' ' : '\n'); +#else printf("%.25"PRINT_TYPE"%c", (PRINT_CAST)(p[i]), (i + 1) % stream->n_chan ? ' ' : '\n'); +#endif } #endif diff --git a/src/blind-to-video.c b/src/blind-to-video.c @@ -51,8 +51,11 @@ main(int argc, char *argv[]) process = process_lf; else if (!strcmp(stream.pixfmt, "xyza f")) process = process_f; + else if (!strcmp(stream.pixfmt, "raw0")) + process = NULL; else - eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt); + eprintf("pixel format %s is not supported, try converting to " + "raw0 or xyza with blind-convert\n", stream.pixfmt); epipe(pipe_rw); pid = efork(); @@ -69,7 +72,10 @@ main(int argc, char *argv[]) close(pipe_rw[0]); fd = pipe_rw[1]; - process_stream(&stream, process); + if (process) + process_stream(&stream, process); + else + esend_stream(&stream, fd, "<subprocess>"); close(fd); ewaitpid(pid, &status, 0); diff --git a/src/blind-transition.c b/src/blind-transition.c @@ -81,10 +81,14 @@ main(int argc, char *argv[]) echeck_compat(&stream, &softness); } + CHECK_ALPHA(&stream); + CHECK_COLOUR_SPACE(&stream, CIEXYZ); if (stream.encoding == DOUBLE) process = process_lf; - else + else if (stream.encoding == FLOAT) process = process_f; + else + eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt); if (!stream.frames) eprintf("video's length is not recorded"); diff --git a/src/blind-triangle-tessellation.c b/src/blind-triangle-tessellation.c @@ -63,10 +63,13 @@ main(int argc, char *argv[]) height = etozu_arg("block-height", argv[1], 1, SIZE_MAX); eset_pixel_format(&stream, pixfmt); + CHECK_N_CHAN(&stream, 4, 4); if (stream.encoding == DOUBLE) SET_XYZA(double); - else + else if (stream.encoding == FLOAT) SET_XYZA(float); + else + eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt); stream.width = 2 * width; stream.height = 2 * height; diff --git a/src/blind-unpremultiply.c b/src/blind-unpremultiply.c @@ -37,6 +37,9 @@ main(int argc, char *argv[]) eopen_stream(&stream, NULL); SELECT_PROCESS_FUNCTION(&stream); + CHECK_CHANS(&stream, == 3, == stream.luma_chan); + CHECK_N_CHAN(&stream, 4, 4); + fprint_stream_head(stdout, &stream); efflush(stdout, "<stdout>"); process(&stream); diff --git a/src/blind-vector-projection.c b/src/blind-vector-projection.c @@ -37,6 +37,9 @@ main(int argc, char *argv[]) eopen_stream(&right, argv[0]); SELECT_PROCESS_FUNCTION(&left); + CHECK_ALPHA_CHAN(&left); + CHECK_N_CHAN(&left, 4, 4); + fprint_stream_head(stdout, &left); efflush(stdout, "<stdout>"); process_two_streams(&left, &right, STDOUT_FILENO, "<stdout>", process); diff --git a/src/common.h b/src/common.h @@ -69,10 +69,89 @@ # define PIPE_BUF BUFSIZ #endif +#ifndef DONT_INCLUDE_FLOAT +# define SELECT_PROCESS_FUNCTION_FLOAT(stream) else if ((stream)->encoding == FLOAT) process = process_f +#else +# define SELECT_PROCESS_FUNCTION_FLOAT(stream) else if (0) +#endif + +#ifndef DONT_INCLUDE_DOUBLE +# define SELECT_PROCESS_FUNCTION_DOUBLE(stream) else if ((stream)->encoding == DOUBLE) process = process_lf +#else +# define SELECT_PROCESS_FUNCTION_DOUBLE(stream) else if (0) +#endif + +#ifdef INCLUDE_LONG_DOUBLE +# define SELECT_PROCESS_FUNCTION_LONG_DOUBLE(stream) else if ((stream)->encoding == LONG_DOUBLE) process = process_llf +#else +# define SELECT_PROCESS_FUNCTION_LONG_DOUBLE(stream) else if (0) +#endif + +#ifdef INCLUDE_UINT8 +# define SELECT_PROCESS_FUNCTION_UINT8(stream) else if ((stream)->encoding == UINT8) process = process_u8 +#else +# define SELECT_PROCESS_FUNCTION_UINT8(stream) else if (0) +#endif + +#ifdef INCLUDE_UINT16 +# define SELECT_PROCESS_FUNCTION_UINT16(stream) else if ((stream)->encoding == UINT16) process = process_u16 +#else +# define SELECT_PROCESS_FUNCTION_UINT16(stream) else if (0) +#endif + +#ifdef INCLUDE_UINT32 +# define SELECT_PROCESS_FUNCTION_UINT32(stream) else if ((stream)->encoding == UINT32) process = process_u32 +#else +# define SELECT_PROCESS_FUNCTION_UINT32(stream) else if (0) +#endif + +#ifdef INCLUDE_UINT64 +# define SELECT_PROCESS_FUNCTION_UINT64(stream) else if ((stream)->encoding == UINT64) process = process_u64 +#else +# define SELECT_PROCESS_FUNCTION_UINT64(stream) else if (0) +#endif + #define SELECT_PROCESS_FUNCTION(stream)\ do {\ - if ((stream)->encoding == DOUBLE)\ - process = process_lf;\ + if ((stream)->endian != HOST_ENDIAN)\ + eprintf("pixel format %s is not supported, try xyza\n", (stream)->pixfmt);\ + SELECT_PROCESS_FUNCTION_FLOAT(stream);\ + SELECT_PROCESS_FUNCTION_DOUBLE(stream);\ + SELECT_PROCESS_FUNCTION_LONG_DOUBLE(stream);\ + SELECT_PROCESS_FUNCTION_UINT8(stream);\ + SELECT_PROCESS_FUNCTION_UINT16(stream);\ + SELECT_PROCESS_FUNCTION_UINT32(stream);\ + SELECT_PROCESS_FUNCTION_UINT64(stream);\ else\ - process = process_f;\ + eprintf("pixel format %s is not supported, try xyza\n", (stream)->pixfmt);\ + } while (0) + +#define CHECK_ALPHA_CHAN(stream)\ + do {\ + if ((stream)->alpha_chan != 3)\ + eprintf("pixel format %s is not supported, try xyza\n", (stream)->pixfmt);\ + } while (0) + +#define CHECK_CHANS(stream, ALPHA, LUMA)\ + do {\ + if (!(((stream)->alpha_chan ALPHA) && ((stream)->luma_chan LUMA)))\ + eprintf("pixel format %s is not supported, try xyza\n", (stream)->pixfmt);\ + } while (0) + +#define CHECK_ALPHA(stream)\ + do {\ + if ((stream)->alpha != UNPREMULTIPLIED)\ + eprintf("pixel format %s is not supported, try xyza\n", (stream)->pixfmt);\ + } while (0) + +#define CHECK_COLOUR_SPACE(stream, colour_space)\ + do {\ + if ((stream)->space != (colour_space))\ + eprintf("pixel format %s is not supported, try xyza\n", (stream)->pixfmt);\ + } while (0) + +#define CHECK_N_CHAN(stream, low, high)\ + do {\ + if ((stream)->n_chan < (low) || (stream)->n_chan > (high))\ + eprintf("pixel format %s is not supported, try xyza\n", (stream)->pixfmt);\ } while (0) diff --git a/src/define-functions.h b/src/define-functions.h @@ -1,25 +1,107 @@ /* See LICENSE file for copyright and license details. */ -#define PROCESS process_lf -#define TYPE double -#define SCAN_TYPE "lf" -#define PRINT_TYPE "lf" -#define PRINT_CAST double -#include FILE -#undef PROCESS -#undef TYPE -#undef SCAN_TYPE -#undef PRINT_TYPE -#undef PRINT_CAST +#ifndef DONT_INCLUDE_FLOAT +# define PROCESS process_lf +# define TYPE double +# define SCAN_TYPE "lf" +# define PRINT_TYPE "lf" +# define PRINT_CAST double +# include FILE +# undef PROCESS +# undef TYPE +# undef SCAN_TYPE +# undef PRINT_TYPE +# undef PRINT_CAST +#endif -#define PROCESS process_f -#define TYPE float -#define SCAN_TYPE "f" -#define PRINT_TYPE "lf" -#define PRINT_CAST double -#include FILE -#undef PROCESS -#undef TYPE -#undef SCAN_TYPE -#undef PRINT_TYPE -#undef PRINT_CAST +#ifndef DONT_INCLUDE_DOUBLE +# define PROCESS process_f +# define TYPE float +# define SCAN_TYPE "f" +# define PRINT_TYPE "lf" +# define PRINT_CAST double +# include FILE +# undef PROCESS +# undef TYPE +# undef SCAN_TYPE +# undef PRINT_TYPE +# undef PRINT_CAST +#endif + +#ifdef INCLUDE_DOUBLE_LONG +# define PROCESS process_llf +# define TYPE long double +# define SCAN_TYPE "Lf" +# define PRINT_TYPE "Lf" +# define PRINT_CAST long double +# include FILE +# undef PROCESS +# undef TYPE +# undef SCAN_TYPE +# undef PRINT_TYPE +# undef PRINT_CAST +#endif + +#ifdef INCLUDE_UINT8 +# define PROCESS process_u8 +# define TYPE uint8_t +# define SCAN_TYPE SCNu8 +# define PRINT_TYPE "u" +# define PRINT_CAST unsigned +# define INTEGER_TYPE +# include FILE +# undef PROCESS +# undef TYPE +# undef SCAN_TYPE +# undef PRINT_TYPE +# undef PRINT_CAST +# undef INTEGER_TYPE +#endif + +#ifdef INCLUDE_UINT16 +# define PROCESS process_u16 +# define TYPE uint16_t +# define SCAN_TYPE SCNu16 +# define PRINT_TYPE "u" +# define PRINT_CAST unsigned +# define INTEGER_TYPE +# include FILE +# undef PROCESS +# undef TYPE +# undef SCAN_TYPE +# undef PRINT_TYPE +# undef PRINT_CAST +# undef INTEGER_TYPE +#endif + +#ifdef INCLUDE_UINT32 +# define PROCESS process_u32 +# define TYPE uint32_t +# define SCAN_TYPE SCNu32 +# define PRINT_TYPE PRIu32 +# define PRINT_CAST uint32_t +# define INTEGER_TYPE +# include FILE +# undef PROCESS +# undef TYPE +# undef SCAN_TYPE +# undef PRINT_TYPE +# undef PRINT_CAST +# undef INTEGER_TYPE +#endif + +#ifdef INCLUDE_UINT64 +# define PROCESS process_u64 +# define TYPE uint64_t +# define SCAN_TYPE SCNu64 +# define PRINT_TYPE PRIu64 +# define PRINT_CAST uint64_t +# define INTEGER_TYPE +# include FILE +# undef PROCESS +# undef TYPE +# undef SCAN_TYPE +# undef PRINT_TYPE +# undef PRINT_CAST +# undef INTEGER_TYPE +#endif diff --git a/src/generate-macros.c b/src/generate-macros.c @@ -1,9 +1,40 @@ +/* See LICENSE file for copyright and license details. */ #include <stdint.h> #include <stdio.h> int main(void) { + char *u16 = (char *)&(uint16_t){0x0001}; + char *u32 = (char *)&(uint32_t){0x00010203}; + char *u64 = (char *)&(uint64_t){0x0001020304050607}; + int le16 = (u16[1] == 0 && u16[0] == 1); + int le32 = (u32[3] == 0 && u32[2] == 1 && u32[1] == 2 && u32[0] == 3); + int le64 = (u64[7] == 0 && u64[6] == 1 && u64[5] == 2 && u64[4] == 3 && + u64[3] == 4 && u64[2] == 5 && u64[1] == 6 && u64[0] == 7); + int be16 = (u16[0] == 0 && u16[1] == 1); + int be32 = (u32[0] == 0 && u32[1] == 1 && u32[2] == 2 && u32[3] == 3); + int be64 = (u64[0] == 0 && u64[1] == 1 && u64[2] == 2 && u64[3] == 3 && + u64[4] == 4 && u64[5] == 5 && u64[6] == 6 && u64[7] == 7); + + if (le16) + printf("#define HOST_ENDIAN_IS_LITTLE_ENDIAN_16\n"); + if (le32) + printf("#define HOST_ENDIAN_IS_LITTLE_ENDIAN_32\n"); + if (le64) + printf("#define HOST_ENDIAN_IS_LITTLE_ENDIAN_64\n"); + if (le16 && le32 && le64) + printf("#define HOST_ENDIAN_IS_LITTLE_ENDIAN\n"); + + if (be16) + printf("#define HOST_ENDIAN_IS_BIG_ENDIAN_16\n"); + if (be32) + printf("#define HOST_ENDIAN_IS_BIG_ENDIAN_32\n"); + if (be64) + printf("#define HOST_ENDIAN_IS_BIG_ENDIAN_64\n"); + if (be16 && be32 && be64) + printf("#define HOST_ENDIAN_IS_BIG_ENDIAN\n"); + if (sizeof(float) == 4) { unsigned long int a, b; a = (unsigned long int)*(uint32_t *)&(float){ (float)(1. / 12.) }; @@ -18,5 +49,6 @@ main(void) printf("#define USING_BINARY64 %i\n", a == 0x3fb5555555555555ULL && b == 0xbfb5555555555555ULL); } + return 0; } diff --git a/src/stream.c b/src/stream.c @@ -95,6 +95,8 @@ enopen_stream(int status, struct stream *stream, const char *file) int 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"); if (strlen(pixfmt) >= sizeof(stream->pixfmt)) @@ -102,27 +104,101 @@ set_pixel_format(struct stream *stream, const char *pixfmt) strcpy(stream->pixfmt, pixfmt); } + stream->n_chan = 4; + stream->alpha = UNPREMULTIPLIED; + stream->encoding = DOUBLE; + stream->endian = HOST_ENDIAN; + stream->alpha_chan = 3; + stream->luma_chan = -1; + 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 if (!strcmp(stream->pixfmt, "raw0")) { + stream->space = YUV_NONLINEAR; + stream->encoding = UINT16; + stream->endian = LITTLE_ENDIAN; + 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; + } else if (!strcmp(stream->pixfmt, "raw2a") || !strcmp(stream->pixfmt, "raw2")) { + stream->space = YUV_NONLINEAR; + stream->alpha = stream->pixfmt[4] == 'a' ? UNPREMULTIPLIED : NO_ALPHA; + stream->encoding = UINT16; + } 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; + } 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->space = SRGB; + stream->alpha = stream->pixfmt[4] == 'a' ? UNPREMULTIPLIED : NO_ALPHA; + stream->encoding = strlen(stream->pixfmt) > 6 ? FLOAT : DOUBLE; } else { return -1; } + if (stream->alpha == NO_ALPHA) { + stream->n_chan -= 1; + stream->alpha_chan = -1; + } + + if (stream->luma_chan == -1) { + switch (stream->space) { + case CIEXYZ: + case CIEXYZ_NONLINEAR: + stream->luma_chan = 1; + break; + case YUV_NONLINEAR: + stream->luma_chan = 0; + break; + default: + break; + } + } + + switch (stream->encoding) { + case DOUBLE: + stream->chan_size = sizeof(double); + break; + case FLOAT: + stream->chan_size = sizeof(float); + break; + case UINT8: + stream->chan_size = sizeof(uint8_t); + break; + case UINT16: + stream->chan_size = sizeof(uint16_t); + break; + case UINT32: + stream->chan_size = sizeof(uint32_t); + break; + case UINT64: + stream->chan_size = sizeof(uint64_t); + break; + default: + abort(); + } + 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; return 0; + +#undef TEST_ENCODING_AGNOSTIC } void @@ -235,30 +311,107 @@ const char * get_pixel_format(const char *specified, const char *current) { enum colour_space space; - enum encoding encoding; + enum alpha alpha = UNPREMULTIPLIED; + enum encoding encoding = DOUBLE; + enum endian endian = HOST_ENDIAN; + int alpha_first = 0; if (!strcmp(current, "xyza")) - space = CIEXYZ, encoding = DOUBLE; + space = CIEXYZ; else if (!strcmp(current, "xyza f")) - space = CIEXYZ, encoding = FLOAT; + 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; else return specified; if (!strcmp(specified, "xyza")) - space = CIEXYZ; - else if (!strcmp(specified, "xyza f")) - return "xyza f"; + 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; else return specified; - if (space == CIEXYZ) + 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"; else return specified; } diff --git a/src/stream.h b/src/stream.h @@ -64,16 +64,33 @@ enum dimension { }; enum colour_space { - CIEXYZ + CIEXYZ, + CIEXYZ_NONLINEAR, + YUV_NONLINEAR, + SRGB_NONLINEAR, + SRGB }; enum alpha { - UNPREMULTIPLIED + NO_ALPHA, + UNPREMULTIPLIED, + PREMULTIPLIED /* not used */ }; enum encoding { FLOAT, - DOUBLE + DOUBLE, + LONG_DOUBLE, /* not used */ + UINT8, /* not used */ + UINT16, + UINT32, /* not used */ + UINT64 /* not used */ +}; + +enum endian { + HOST_ENDIAN, + LITTLE_ENDIAN, + BIG_ENDIAN /* not used */ }; struct stream { @@ -87,6 +104,9 @@ struct stream { enum colour_space space; enum alpha alpha; enum encoding encoding; + enum endian endian; + short int alpha_chan; + short int luma_chan; int fd; size_t ptr; size_t xptr; diff --git a/src/util/endian.h b/src/util/endian.h @@ -9,6 +9,31 @@ #if !defined(HAVE_ENDIAN_H) && !defined(HAVE_SYS_ENDIAN_H) +# if defined(HOST_ENDIAN_IS_LITTLE_ENDIAN_16) +# if !defined(htole16) +# define htole16(x) (x) +# endif +# if !defined(htole16) +# define letoh16(x) (x) +# endif +# endif +# if defined(HOST_ENDIAN_IS_LITTLE_ENDIAN_32) +# if !defined(htole32) +# define htole32(x) (x) +# endif +# if !defined(htole32) +# define letoh32(x) (x) +# endif +# endif +# if defined(HOST_ENDIAN_IS_LITTLE_ENDIAN_64) +# if !defined(htole64) +# define htole16(x) (x) +# endif +# if !defined(htole64) +# define letoh16(x) (x) +# endif +# endif + # if !defined(htole16) # define htole16 blind_htole16 static inline uint16_t