diff options
76 files changed, 892 insertions, 167 deletions
@@ -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 index a976260..05ed44a 100644 --- 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 index dd87b78..500ebaa 100644 --- 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 index 371cfec..fe5e0fb 100644 --- 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 index 9172af2..68e355b 100644 --- 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 index 6bcd4c0..75876dc 100644 --- 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 index bbd54b6..f9005af 100644 --- 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 index 2e3d675..4fc72ac 100644 --- 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 index ed0b9a9..6ba58bc 100644 --- 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 index 654345f..f7bda25 100644 --- 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 index 6c00ab7..04a816d 100644 --- 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 index ad5fb4b..6b26736 100644 --- 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 index 4c6ca14..c5d3947 100644 --- 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 index e9e8bcb..222facd 100644 --- 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 index 7387beb..01d3f27 100644 --- 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 index 095c56e..e1b7241 100644 --- 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 index 3b8a7c6..1c87876 100644 --- 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 index 910b49b..4d38cf4 100644 --- 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 index be92c2e..b78121e 100644 --- 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 index 6fa3348..8feb6bf 100644 --- 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 index 49b3947..3d74ece 100644 --- 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 index ac6e843..54cf2cc 100644 --- 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 index c51e2db..e80510b 100644 --- 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 index 2832a9a..328fd23 100644 --- 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 index 07f4bda..8f53af2 100644 --- 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 index 53eaecb..e22fd2e 100644 --- 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 index abb5c7a..377c110 100644 --- 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 index d26f081..e6b8a34 100644 --- 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 index 66b1176..5be63c4 100644 --- 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 index 55711ac..d8e3cf7 100644 --- 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 index 816e76c..f3f70c4 100644 --- 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 index 5dcf89e..2a20cdd 100644 --- 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 index 945205d..946fb3c 100644 --- 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 index 15f27cc..c03f3e2 100644 --- 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 index 8130cba..55b2b1c 100644 --- 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 index 5ae1104..e53f386 100644 --- 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 index 3f19053..8ebb2a0 100644 --- 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 index 8b7e97c..d7c0726 100644 --- 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 index ecb9692..83c33bf 100644 --- 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 index b59dbda..4f05052 100644 --- 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 index a0f36da..3cf40a2 100644 --- 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 index af86311..d99b22a 100644 --- 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 index 303c214..25830c4 100644 --- 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 index c670b60..31135ff 100644 --- 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 index 06a2887..2c3bbe9 100644 --- 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 index a97e474..e2e940f 100644 --- 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 index 2d83222..7ffcb49 100644 --- 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 index e56586d..80ce883 100644 --- 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 index c548673..31c4df4 100644 --- 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 index 2943982..66bf52f 100644 --- 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 index 2c30377..c7e6ebf 100644 --- 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 index 0f999c5..0cda31e 100644 --- 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 index 7e8c348..567a7f5 100644 --- 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 index b63dc89..898a15b 100644 --- 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 index 5511a3f..ab7f2ce 100644 --- 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 index 3ba6191..92763aa 100644 --- 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 index 6ea0601..478b8c8 100644 --- 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 index 305fe98..b475521 100644 --- 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 index 3a754a2..8032476 100644 --- 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 index 29e20b0..c922015 100644 --- 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 index f9f7b51..7b447e6 100644 --- 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 index 4633d75..8a72a27 100644 --- 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 index 6827d26..666c299 100644 --- 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 index 2d9c899..07eee62 100644 --- 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 index 61bd14d..befa3c7 100644 --- 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 index 1c9ef99..5cdffe6 100644 --- 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 index 8463575..758857a 100644 --- 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 index 8d298f0..f806527 100644 --- 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 index d3feced..11d186c 100644 --- 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 index a285846..8d65738 100644 --- 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 index 7d253c0..3972389 100644 --- 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 index 3a44829..029265e 100644 --- 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 index ef87ad5..165c168 100644 --- 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 index b69f9a5..ef57b93 100644 --- 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 index b85c6c6..2d27cba 100644 --- 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 index dfe9e77..1ec9d66 100644 --- 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 |
