commit e76229ac4f95ac8c6e4e38e60689a09a091e4048
parent c91c5cb8e892f1c19c970cef033cc03c9f47f98a
Author: Mattias Andrée <maandree@kth.se>
Date: Sun, 2 Jul 2017 23:58:01 +0200
Add gradients
Signed-off-by: Mattias Andrée <maandree@kth.se>
Diffstat:
14 files changed, 1267 insertions(+), 0 deletions(-)
diff --git a/Makefile b/Makefile
@@ -9,7 +9,9 @@ BIN =\
blind-colour-srgb\
blind-compress\
blind-concat\
+ blind-cone-gradient\
blind-convert\
+ blind-coordinate-field\
blind-crop\
blind-cross-product\
blind-cut\
@@ -17,6 +19,7 @@ BIN =\
blind-disperse\
blind-dissolve\
blind-dot-product\
+ blind-double-sinus-wave\
blind-extend\
blind-find-rectangle\
blind-flip\
@@ -29,26 +32,35 @@ BIN =\
blind-gauss-blur\
blind-interleave\
blind-invert-luma\
+ blind-linear-gradient\
blind-make-kernel\
blind-next-frame\
blind-norm\
blind-quaternion-product\
blind-premultiply\
+ blind-radial-gradient\
blind-read-head\
blind-repeat\
blind-reverse\
blind-rewrite-head\
+ blind-round-wave\
+ blind-sawtooth-wave\
blind-set-alpha\
blind-set-luma\
blind-set-saturation\
blind-single-colour\
+ blind-sinc-wave\
+ blind-sinus-wave\
blind-skip-pattern\
+ blind-spiral-gradient\
blind-split\
blind-split-cols\
blind-split-rows\
+ blind-square-gradient\
blind-stack\
blind-tee\
blind-time-blur\
+ blind-triangular-wave\
blind-to-image\
blind-to-named\
blind-to-portable\
diff --git a/src/blind-cone-gradient.c b/src/blind-cone-gradient.c
@@ -0,0 +1,126 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+USAGE("[-a | -s] -w width -h height")
+
+static int anticlockwise = 0;
+static int symmetric = 0;
+static size_t width = 0;
+static size_t height = 0;
+static int with_multiplier = 0;
+
+
+#define PROCESS(TYPE, SUFFIX)\
+ static void\
+ process_##SUFFIX(struct stream *stream)\
+ {\
+ typedef TYPE pixel_t[4];\
+ pixel_t buf[BUFSIZ / sizeof(pixel_t)];\
+ TYPE *params, x1, y1, x2, y2;\
+ TYPE x, y, u, v, m = 1;\
+ size_t ix, iy, ptr = 0;\
+ for (;;) {\
+ while (stream->ptr < stream->frame_size) {\
+ if (!eread_stream(stream, stream->frame_size - stream->ptr)) {\
+ ewriteall(STDOUT_FILENO, buf, ptr * sizeof(*buf), "<stdout>");\
+ return;\
+ }\
+ }\
+ params = (TYPE *)stream->buf;\
+ x1 = (params)[0];\
+ y1 = (params)[1];\
+ x2 = (params)[4];\
+ y2 = (params)[5];\
+ if (with_multiplier)\
+ m = (params)[9];\
+ memmove(stream->buf, stream->buf + stream->frame_size,\
+ stream->ptr -= stream->frame_size);\
+ \
+ x2 -= x1;\
+ y2 -= y1;\
+ u = atan2(y2, x2);\
+ \
+ for (iy = 0; iy < height; iy++) {\
+ y = (TYPE)iy - y1;\
+ for (ix = 0; ix < width; ix++) {\
+ x = (TYPE)ix - x1;\
+ v = atan2(y, x);\
+ v -= u;\
+ v += 2 * (TYPE)M_PI;\
+ v = mod(v, 2 * (TYPE)M_PI);\
+ v /= 2 * (TYPE)M_PI;\
+ if (anticlockwise)\
+ v = 1 - v;\
+ v *= m;\
+ if (symmetric) {\
+ v = mod(2 * v, (TYPE)2);\
+ if (v > 1)\
+ v = 2 - v;\
+ }\
+ buf[ptr][0] = buf[ptr][1] = buf[ptr][2] = buf[ptr][3] = v;\
+ if (++ptr == ELEMENTSOF(buf)) {\
+ ewriteall(STDOUT_FILENO, buf, sizeof(buf), "<stdout>");\
+ ptr = 0;\
+ }\
+ }\
+ }\
+ }\
+ }
+
+PROCESS(double, lf)
+PROCESS(float, f)
+
+
+int
+main(int argc, char *argv[])
+{
+ struct stream stream;
+ void (*process)(struct stream *stream);
+
+ ARGBEGIN {
+ case 'a':
+ if (symmetric)
+ usage();
+ anticlockwise = 1;
+ break;
+ case 's':
+ if (anticlockwise)
+ usage();
+ symmetric = 1;
+ break;
+ case 'w':
+ width = etozu_flag('w', UARGF(), 1, SIZE_MAX);
+ break;
+ case 'h':
+ height = etozu_flag('h', UARGF(), 1, SIZE_MAX);
+ break;
+ default:
+ usage();
+ } ARGEND;
+
+ if (!width || !height || argc)
+ usage();
+
+ eopen_stream(&stream, NULL);
+
+ if (!strcmp(stream.pixfmt, "xyza"))
+ process = process_lf;
+ else if (!strcmp(stream.pixfmt, "xyza f"))
+ process = process_f;
+ else
+ eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt);
+
+ if (stream.width > 3 || stream.height > 3 ||
+ stream.width * stream.height < 2 ||
+ stream.width * stream.height > 3)
+ eprintf("<stdin>: each frame must contain exactly 2 or 3 pixels\n");
+
+ with_multiplier = stream.width * stream.height == 3;
+
+ stream.width = width;
+ stream.height = height;
+ fprint_stream_head(stdout, &stream);
+ efflush(stdout, "<stdout>");
+ process(&stream);
+ return 0;
+}
diff --git a/src/blind-coordinate-field.c b/src/blind-coordinate-field.c
@@ -0,0 +1,77 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+USAGE("[-f frames | -f 'inf'] [-F pixel-format] -w width -h height")
+
+static struct stream stream = { .width = 0, .height = 0, .frames = 1 };
+static int inf = 0;
+
+#define PROCESS(TYPE)\
+ do {\
+ TYPE buf[4] = {0, 0, 0, 0};\
+ size_t x, y;\
+ \
+ while (inf || stream.frames--) {\
+ for (y = 0; y < stream.height; y++) {\
+ buf[1] = (TYPE)y;\
+ for (x = 0; x < stream.width; x++) {\
+ buf[0] = (TYPE)x;\
+ if (write(STDOUT_FILENO, buf, sizeof(buf)) < 0)\
+ eprintf("write <stdout>:");\
+ }\
+ }\
+ }\
+ } while (0)
+
+static void process_lf(void) {PROCESS(double);}
+static void process_f(void) {PROCESS(float);}
+
+int
+main(int argc, char *argv[])
+{
+ char *arg;
+ const char *pixfmt = "xyza";
+ void (*process)(void);
+
+ ARGBEGIN {
+ case 'f':
+ arg = UARGF();
+ if (!strcmp(arg, "inf"))
+ inf = 1, stream.frames = 0;
+ else
+ stream.frames = etozu_flag('f', arg, 1, SIZE_MAX);
+ break;
+ case 'F':
+ pixfmt = UARGF();
+ break;
+ case 'w':
+ stream.width = etozu_flag('w', UARGF(), 1, SIZE_MAX);
+ break;
+ case 'h':
+ stream.height = etozu_flag('h', UARGF(), 1, SIZE_MAX);
+ break;
+ default:
+ usage();
+ } ARGEND;
+
+ if (!stream.width || !stream.height || argc)
+ usage();
+
+ if (inf)
+ einf_check_fd(STDOUT_FILENO, "<stdout>");
+
+ pixfmt = get_pixel_format(pixfmt, "xyza");
+ if (!strcmp(pixfmt, "xyza"))
+ process = process_lf;
+ else if (!strcmp(pixfmt, "xyza f"))
+ process = process_f;
+ else
+ eprintf("pixel format %s is not supported, try xyza\n", pixfmt);
+
+ strcpy(stream.pixfmt, pixfmt);
+ fprint_stream_head(stdout, &stream);
+ efflush(stdout, "<stdout>");
+
+ process();
+ return 0;
+}
diff --git a/src/blind-double-sinus-wave.c b/src/blind-double-sinus-wave.c
@@ -0,0 +1,94 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+USAGE("[-e]")
+
+static int equal = 0;
+
+
+#define PROCESS(TYPE, SUFFIX)\
+ static void\
+ process_##SUFFIX(struct stream *stream)\
+ {\
+ size_t i, n;\
+ TYPE x, y, z, a;\
+ do {\
+ n = stream->ptr / stream->pixel_size;\
+ if (equal) {\
+ for (i = 0; i < n; i++) {\
+ a = ((TYPE *)(stream->buf))[4 * i + 3];\
+ a = posmod(a, (TYPE)2);\
+ a = a > 1 ? 2 - a : a;\
+ a = 1 - (sin(a * (2 * (TYPE)M_PI)) + 1) / 2;\
+ ((TYPE *)(stream->buf))[4 * i + 0] = a;\
+ ((TYPE *)(stream->buf))[4 * i + 1] = a;\
+ ((TYPE *)(stream->buf))[4 * i + 2] = a;\
+ ((TYPE *)(stream->buf))[4 * i + 3] = a;\
+ }\
+ } else {\
+ for (i = 0; i < n; i++) {\
+ x = ((TYPE *)(stream->buf))[4 * i + 0];\
+ y = ((TYPE *)(stream->buf))[4 * i + 1];\
+ z = ((TYPE *)(stream->buf))[4 * i + 2];\
+ a = ((TYPE *)(stream->buf))[4 * i + 3];\
+ x = posmod(x, (TYPE)1);\
+ y = posmod(y, (TYPE)1);\
+ z = posmod(z, (TYPE)1);\
+ a = posmod(a, (TYPE)1);\
+ x = x > 1 ? 2 - x : x;\
+ y = y > 1 ? 2 - y : y;\
+ z = z > 1 ? 2 - z : z;\
+ a = a > 1 ? 2 - a : a;\
+ x = 1 - (sin(x * (2 * (TYPE)M_PI)) + 1) / 2;\
+ y = 1 - (sin(y * (2 * (TYPE)M_PI)) + 1) / 2;\
+ z = 1 - (sin(z * (2 * (TYPE)M_PI)) + 1) / 2;\
+ a = 1 - (sin(a * (2 * (TYPE)M_PI)) + 1) / 2;\
+ ((TYPE *)(stream->buf))[4 * i + 0] = x;\
+ ((TYPE *)(stream->buf))[4 * i + 1] = y;\
+ ((TYPE *)(stream->buf))[4 * i + 2] = z;\
+ ((TYPE *)(stream->buf))[4 * i + 3] = a;\
+ }\
+ }\
+ n *= stream->pixel_size;\
+ ewriteall(STDOUT_FILENO, stream->buf, n, "<stdout>");\
+ memmove(stream->buf, stream->buf + n, stream->ptr -= n);\
+ } while (eread_stream(stream, SIZE_MAX));\
+ if (stream->ptr)\
+ eprintf("%s: incomplete frame\n", stream->file);\
+ }
+
+PROCESS(double, lf)
+PROCESS(float, f)
+
+
+int
+main(int argc, char *argv[])
+{
+ struct stream stream;
+ void (*process)(struct stream *stream);
+
+ ARGBEGIN {
+ case 'e':
+ equal = 1;
+ break;
+ default:
+ usage();
+ } ARGEND;
+
+ if (argc)
+ usage();
+
+ eopen_stream(&stream, NULL);
+
+ if (!strcmp(stream.pixfmt, "xyza"))
+ process = process_lf;
+ else if (!strcmp(stream.pixfmt, "xyza f"))
+ process = process_f;
+ else
+ eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt);
+
+ fprint_stream_head(stdout, &stream);
+ efflush(stdout, "<stdout>");
+ process(&stream);
+ return 0;
+}
diff --git a/src/blind-linear-gradient.c b/src/blind-linear-gradient.c
@@ -0,0 +1,101 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+USAGE("[-b] -w width -h height")
+
+static int bilinear = 0;
+static size_t width = 0;
+static size_t height = 0;
+
+
+#define PROCESS(TYPE, SUFFIX)\
+ static void\
+ process_##SUFFIX(struct stream *stream)\
+ {\
+ typedef TYPE pixel_t[4];\
+ pixel_t buf[BUFSIZ / sizeof(pixel_t)];\
+ TYPE *params, x1, y1, x2, y2, norm2;\
+ TYPE x, y;\
+ size_t ix, iy, ptr = 0;\
+ for (;;) {\
+ while (stream->ptr < stream->frame_size) {\
+ if (!eread_stream(stream, stream->frame_size - stream->ptr)) {\
+ ewriteall(STDOUT_FILENO, buf, ptr * sizeof(*buf), "<stdout>");\
+ return;\
+ }\
+ }\
+ params = (TYPE *)stream->buf;\
+ x1 = (params)[0];\
+ y1 = (params)[1];\
+ x2 = (params)[4];\
+ y2 = (params)[5];\
+ memmove(stream->buf, stream->buf + stream->frame_size,\
+ stream->ptr -= stream->frame_size);\
+ \
+ x2 -= x1;\
+ y2 -= y1;\
+ norm2 = x2 * x2 + y2 * y2;\
+ \
+ for (iy = 0; iy < height; iy++) {\
+ y = (TYPE)iy - y1;\
+ for (ix = 0; ix < width; ix++) {\
+ x = (TYPE)ix - x1;\
+ x = (x * x2 + y * y2) / norm2;\
+ if (bilinear)\
+ x = abs(x);\
+ buf[ptr][0] = buf[ptr][1] = buf[ptr][2] = buf[ptr][3] = x;\
+ if (++ptr == ELEMENTSOF(buf)) {\
+ ewriteall(STDOUT_FILENO, buf, sizeof(buf), "<stdout>");\
+ ptr = 0;\
+ }\
+ }\
+ }\
+ }\
+ }
+
+PROCESS(double, lf)
+PROCESS(float, f)
+
+
+int
+main(int argc, char *argv[])
+{
+ struct stream stream;
+ void (*process)(struct stream *stream);
+
+ ARGBEGIN {
+ case 'b':
+ bilinear = 1;
+ break;
+ case 'w':
+ width = etozu_flag('w', UARGF(), 1, SIZE_MAX);
+ break;
+ case 'h':
+ height = etozu_flag('h', UARGF(), 1, SIZE_MAX);
+ break;
+ default:
+ usage();
+ } ARGEND;
+
+ if (!width || !height || argc)
+ usage();
+
+ eopen_stream(&stream, NULL);
+
+ if (!strcmp(stream.pixfmt, "xyza"))
+ process = process_lf;
+ else if (!strcmp(stream.pixfmt, "xyza f"))
+ process = process_f;
+ else
+ eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt);
+
+ if (stream.width > 2 || stream.height > 2 || stream.width * stream.height != 2)
+ eprintf("<stdin>: each frame must contain exactly 2 pixels\n");
+
+ stream.width = width;
+ stream.height = height;
+ fprint_stream_head(stdout, &stream);
+ efflush(stdout, "<stdout>");
+ process(&stream);
+ return 0;
+}
diff --git a/src/blind-radial-gradient.c b/src/blind-radial-gradient.c
@@ -0,0 +1,128 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+USAGE("-w width -h height")
+
+static size_t width = 0;
+static size_t height = 0;
+static int with_params;
+
+
+#define PROCESS(TYPE, SUFFIX)\
+ static void\
+ process_##SUFFIX(struct stream *stream)\
+ {\
+ typedef TYPE pixel_t[4];\
+ pixel_t buf[BUFSIZ / sizeof(pixel_t)];\
+ TYPE *params, x1, y1, x2, y2, norm, rd = 1, pe = 2, re = 2, e = 0.5;\
+ TYPE x, y, p, r, rx, ry;\
+ size_t ix, iy, ptr = 0;\
+ for (;;) {\
+ while (stream->ptr < stream->frame_size) {\
+ if (!eread_stream(stream, stream->frame_size - stream->ptr)) {\
+ ewriteall(STDOUT_FILENO, buf, ptr * sizeof(*buf), "<stdout>");\
+ return;\
+ }\
+ }\
+ params = (TYPE *)stream->buf;\
+ x1 = (params)[0];\
+ y1 = (params)[1];\
+ x2 = (params)[4];\
+ y2 = (params)[5];\
+ if (with_params) {\
+ pe = (params)[8];\
+ re = (params)[9];\
+ rd = (params)[10];\
+ e = 1 / sqrt(pe * re);\
+ }\
+ memmove(stream->buf, stream->buf + stream->frame_size,\
+ stream->ptr -= stream->frame_size);\
+ \
+ x2 -= x1;\
+ y2 -= y1;\
+ norm = sqrt(x2 * x2 + y2 * y2);\
+ \
+ if (!with_params) {\
+ for (iy = 0; iy < height; iy++) {\
+ y = (TYPE)iy - y1;\
+ y *= y;\
+ for (ix = 0; ix < width; ix++) {\
+ x = (TYPE)ix - x1;\
+ x = sqrt(x * x + y) / norm;\
+ buf[ptr][0] = buf[ptr][1] = buf[ptr][2] = buf[ptr][3] = x;\
+ if (++ptr == ELEMENTSOF(buf)) {\
+ ewriteall(STDOUT_FILENO, buf, sizeof(buf), "<stdout>");\
+ ptr = 0;\
+ }\
+ }\
+ }\
+ } else {\
+ for (iy = 0; iy < height; iy++) {\
+ y = (TYPE)iy - y1;\
+ for (ix = 0; ix < width; ix++) {\
+ x = (TYPE)ix - x1;\
+ p = (x * x2 + y * y2) / norm;\
+ rx = x - p * x2 / norm;\
+ ry = y - p * y2 / norm;\
+ r = sqrt(rx * rx + ry * ry) / rd;\
+ p = pow(abs(p / norm), pe);\
+ r = pow(abs(r / norm), re);\
+ x = pow(p + r, e);\
+ buf[ptr][0] = buf[ptr][1] = buf[ptr][2] = buf[ptr][3] = x;\
+ if (++ptr == ELEMENTSOF(buf)) {\
+ ewriteall(STDOUT_FILENO, buf, sizeof(buf), "<stdout>");\
+ ptr = 0;\
+ }\
+ }\
+ }\
+ }\
+ }\
+ }
+
+PROCESS(double, lf)
+PROCESS(float, f)
+
+
+int
+main(int argc, char *argv[])
+{
+ struct stream stream;
+ void (*process)(struct stream *stream);
+
+ ARGBEGIN {
+ case 'w':
+ width = etozu_flag('w', UARGF(), 1, SIZE_MAX);
+ break;
+ case 'h':
+ height = etozu_flag('h', UARGF(), 1, SIZE_MAX);
+ break;
+ default:
+ usage();
+ } ARGEND;
+
+ if (!width || !height || argc)
+ usage();
+
+ eopen_stream(&stream, NULL);
+
+ if (!strcmp(stream.pixfmt, "xyza"))
+ process = process_lf;
+ else if (!strcmp(stream.pixfmt, "xyza f"))
+ process = process_f;
+ else
+ eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt);
+
+ if (stream.width > 3 || stream.height > 3 ||
+ stream.width * stream.height < 2 ||
+ stream.width * stream.height > 3)
+ eprintf("<stdin>: each frame must contain exactly 2 pixels\n");
+
+ with_params = stream.width * stream.height == 3;
+
+ stream.width = width;
+ stream.height = height;
+ fprint_stream_head(stdout, &stream);
+ efflush(stdout, "<stdout>");
+ process(&stream);
+ return 0;
+}
diff --git a/src/blind-round-wave.c b/src/blind-round-wave.c
@@ -0,0 +1,89 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+USAGE("[-e]")
+
+static int equal = 0;
+
+
+#define PROCESS(TYPE, SUFFIX)\
+ static void\
+ process_##SUFFIX(struct stream *stream)\
+ {\
+ size_t i, n;\
+ TYPE x, y, z, a;\
+ do {\
+ n = stream->ptr / stream->pixel_size;\
+ if (equal) {\
+ for (i = 0; i < n; i++) {\
+ a = ((TYPE *)(stream->buf))[4 * i + 3];\
+ a = mod(a + 1, (TYPE)4) - 1;\
+ a = a < 1 ? 1 - a * a / 2 : (a - 2) * (a - 2) / 2;\
+ ((TYPE *)(stream->buf))[4 * i + 0] = a;\
+ ((TYPE *)(stream->buf))[4 * i + 1] = a;\
+ ((TYPE *)(stream->buf))[4 * i + 2] = a;\
+ ((TYPE *)(stream->buf))[4 * i + 3] = a;\
+ }\
+ } else {\
+ for (i = 0; i < n; i++) {\
+ x = ((TYPE *)(stream->buf))[4 * i + 0];\
+ y = ((TYPE *)(stream->buf))[4 * i + 1];\
+ z = ((TYPE *)(stream->buf))[4 * i + 2];\
+ a = ((TYPE *)(stream->buf))[4 * i + 3];\
+ x = mod(x + 1, (TYPE)4) - 1;\
+ y = mod(y + 1, (TYPE)4) - 1;\
+ z = mod(z + 1, (TYPE)4) - 1;\
+ a = mod(a + 1, (TYPE)4) - 1;\
+ x = x < 1 ? 1 - x * x / 2 : (x - 2) * (x - 2) / 2;\
+ y = y < 1 ? 1 - y * y / 2 : (y - 2) * (y - 2) / 2;\
+ z = z < 1 ? 1 - z * z / 2 : (z - 2) * (z - 2) / 2;\
+ a = a < 1 ? 1 - a * a / 2 : (a - 2) * (a - 2) / 2;\
+ ((TYPE *)(stream->buf))[4 * i + 0] = x;\
+ ((TYPE *)(stream->buf))[4 * i + 1] = y;\
+ ((TYPE *)(stream->buf))[4 * i + 2] = z;\
+ ((TYPE *)(stream->buf))[4 * i + 3] = a;\
+ }\
+ }\
+ n *= stream->pixel_size;\
+ ewriteall(STDOUT_FILENO, stream->buf, n, "<stdout>");\
+ memmove(stream->buf, stream->buf + n, stream->ptr -= n);\
+ } while (eread_stream(stream, SIZE_MAX));\
+ if (stream->ptr)\
+ eprintf("%s: incomplete frame\n", stream->file);\
+ }
+
+PROCESS(double, lf)
+PROCESS(float, f)
+
+
+int
+main(int argc, char *argv[])
+{
+ struct stream stream;
+ void (*process)(struct stream *stream);
+
+ ARGBEGIN {
+ case 'e':
+ equal = 1;
+ break;
+ default:
+ usage();
+ } ARGEND;
+
+ if (argc)
+ usage();
+
+ eopen_stream(&stream, NULL);
+
+ if (!strcmp(stream.pixfmt, "xyza"))
+ process = process_lf;
+ else if (!strcmp(stream.pixfmt, "xyza f"))
+ process = process_f;
+ else
+ eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt);
+
+ fprint_stream_head(stdout, &stream);
+ efflush(stdout, "<stdout>");
+ process(&stream);
+ return 0;
+}
diff --git a/src/blind-sawtooth-wave.c b/src/blind-sawtooth-wave.c
@@ -0,0 +1,84 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+USAGE("[-e]")
+
+static int equal = 0;
+
+
+#define PROCESS(TYPE, SUFFIX)\
+ static void\
+ process_##SUFFIX(struct stream *stream)\
+ {\
+ size_t i, n;\
+ TYPE x, y, z, a;\
+ do {\
+ n = stream->ptr / stream->pixel_size;\
+ if (equal) {\
+ for (i = 0; i < n; i++) {\
+ a = ((TYPE *)(stream->buf))[4 * i + 3];\
+ a = posmod(a, (TYPE)1);\
+ ((TYPE *)(stream->buf))[4 * i + 0] = a;\
+ ((TYPE *)(stream->buf))[4 * i + 1] = a;\
+ ((TYPE *)(stream->buf))[4 * i + 2] = a;\
+ ((TYPE *)(stream->buf))[4 * i + 3] = a;\
+ }\
+ } else {\
+ for (i = 0; i < n; i++) {\
+ x = ((TYPE *)(stream->buf))[4 * i + 0];\
+ y = ((TYPE *)(stream->buf))[4 * i + 1];\
+ z = ((TYPE *)(stream->buf))[4 * i + 2];\
+ a = ((TYPE *)(stream->buf))[4 * i + 3];\
+ x = posmod(x, (TYPE)1);\
+ y = posmod(y, (TYPE)1);\
+ z = posmod(z, (TYPE)1);\
+ a = posmod(a, (TYPE)1);\
+ ((TYPE *)(stream->buf))[4 * i + 0] = x;\
+ ((TYPE *)(stream->buf))[4 * i + 1] = y;\
+ ((TYPE *)(stream->buf))[4 * i + 2] = z;\
+ ((TYPE *)(stream->buf))[4 * i + 3] = a;\
+ }\
+ }\
+ n *= stream->pixel_size;\
+ ewriteall(STDOUT_FILENO, stream->buf, n, "<stdout>");\
+ memmove(stream->buf, stream->buf + n, stream->ptr -= n);\
+ } while (eread_stream(stream, SIZE_MAX));\
+ if (stream->ptr)\
+ eprintf("%s: incomplete frame\n", stream->file);\
+ }
+
+PROCESS(double, lf)
+PROCESS(float, f)
+
+
+int
+main(int argc, char *argv[])
+{
+ struct stream stream;
+ void (*process)(struct stream *stream);
+
+ ARGBEGIN {
+ case 'e':
+ equal = 1;
+ break;
+ default:
+ usage();
+ } ARGEND;
+
+ if (argc)
+ usage();
+
+ eopen_stream(&stream, NULL);
+
+ if (!strcmp(stream.pixfmt, "xyza"))
+ process = process_lf;
+ else if (!strcmp(stream.pixfmt, "xyza f"))
+ process = process_f;
+ else
+ eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt);
+
+ fprint_stream_head(stdout, &stream);
+ efflush(stdout, "<stdout>");
+ process(&stream);
+ return 0;
+}
diff --git a/src/blind-sinc-wave.c b/src/blind-sinc-wave.c
@@ -0,0 +1,114 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+USAGE("[-e] [theta0-stream]")
+
+static int equal = 0;
+
+
+#define PROCESS(TYPE, SUFFIX)\
+ static void\
+ process_##SUFFIX(struct stream *grad, struct stream *theta0)\
+ {\
+ size_t i, n, m = 0;\
+ TYPE *theta0xyza;\
+ TYPE x, theta0x = 0;\
+ TYPE y, theta0y = 0;\
+ TYPE z, theta0z = 0;\
+ TYPE a, theta0a = 0;\
+ echeck_dimensions(grad, WIDTH | HEIGHT, NULL);\
+ do {\
+ if (!m) {\
+ m = grad->frame_size;\
+ if (theta0) {\
+ while (theta0->ptr < theta0->frame_size)\
+ if (!eread_stream(theta0, theta0->frame_size - theta0->ptr))\
+ return;\
+ theta0xyza = (TYPE *)theta0->buf;\
+ theta0x = (theta0xyza)[0];\
+ theta0y = (theta0xyza)[1];\
+ theta0z = (theta0xyza)[2];\
+ theta0a = (theta0xyza)[3];\
+ memmove(theta0->buf, theta0->buf + theta0->frame_size,\
+ theta0->ptr -= theta0->frame_size);\
+ }\
+ }\
+ n = MIN(grad->ptr, m) / grad->pixel_size;\
+ if (equal) {\
+ for (i = 0; i < n; i++) {\
+ a = ((TYPE *)(grad->buf))[4 * i + 3];\
+ a = (a ? sin(a + theta0y) / a : sin(a + theta0y)) / 2 + 0.5;\
+ ((TYPE *)(grad->buf))[4 * i + 0] = a;\
+ ((TYPE *)(grad->buf))[4 * i + 1] = a;\
+ ((TYPE *)(grad->buf))[4 * i + 2] = a;\
+ ((TYPE *)(grad->buf))[4 * i + 3] = a;\
+ }\
+ } else {\
+ for (i = 0; i < n; i++) {\
+ x = ((TYPE *)(grad->buf))[4 * i + 0];\
+ y = ((TYPE *)(grad->buf))[4 * i + 1];\
+ z = ((TYPE *)(grad->buf))[4 * i + 2];\
+ a = ((TYPE *)(grad->buf))[4 * i + 3];\
+ x = (x ? sin(x + theta0x) / x : sin(x + theta0x)) / 2 + 0.5;\
+ y = (y ? sin(y + theta0y) / y : sin(y + theta0y)) / 2 + 0.5;\
+ z = (z ? sin(z + theta0z) / z : sin(z + theta0z)) / 2 + 0.5;\
+ a = (a ? sin(a + theta0a) / a : sin(a + theta0a)) / 2 + 0.5;\
+ ((TYPE *)(grad->buf))[4 * i + 0] = x;\
+ ((TYPE *)(grad->buf))[4 * i + 1] = y;\
+ ((TYPE *)(grad->buf))[4 * i + 2] = z;\
+ ((TYPE *)(grad->buf))[4 * i + 3] = a;\
+ }\
+ }\
+ n *= grad->pixel_size;\
+ m -= n;\
+ ewriteall(STDOUT_FILENO, grad->buf, n, "<stdout>");\
+ memmove(grad->buf, grad->buf + n, grad->ptr -= n);\
+ } while (eread_stream(grad, SIZE_MAX));\
+ if (grad->ptr)\
+ eprintf("%s: incomplete frame\n", grad->file);\
+ }
+
+PROCESS(double, lf)
+PROCESS(float, f)
+
+
+int
+main(int argc, char *argv[])
+{
+ struct stream stream, theta0;
+ int have_theta0;
+ void (*process)(struct stream *grad, struct stream *theta0);
+
+ ARGBEGIN {
+ case 'e':
+ equal = 1;
+ break;
+ default:
+ usage();
+ } ARGEND;
+
+ if (argc > 1)
+ usage();
+
+ eopen_stream(&stream, NULL);
+ if ((have_theta0 = argc == 1)) {
+ eopen_stream(&theta0, argv[0]);
+ if (theta0.width != 1 || theta0.height != 1)
+ eprintf("theta0-stream must be of dimension 1x1\n");
+ }
+
+ if (!strcmp(stream.pixfmt, "xyza"))
+ process = process_lf;
+ else if (!strcmp(stream.pixfmt, "xyza f"))
+ process = process_f;
+ else
+ eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt);
+
+ if (have_theta0 && strcmp(stream.pixfmt, theta0.pixfmt))
+ eprintf("videos use incompatible pixel formats\n");
+
+ fprint_stream_head(stdout, &stream);
+ efflush(stdout, "<stdout>");
+ process(&stream, have_theta0 ? &theta0 : NULL);
+ return 0;
+}
diff --git a/src/blind-sinus-wave.c b/src/blind-sinus-wave.c
@@ -0,0 +1,94 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+USAGE("[-e]")
+
+static int equal = 0;
+
+
+#define PROCESS(TYPE, SUFFIX)\
+ static void\
+ process_##SUFFIX(struct stream *stream)\
+ {\
+ size_t i, n;\
+ TYPE x, y, z, a;\
+ do {\
+ n = stream->ptr / stream->pixel_size;\
+ if (equal) {\
+ for (i = 0; i < n; i++) {\
+ a = ((TYPE *)(stream->buf))[4 * i + 3];\
+ a = posmod(a, (TYPE)2);\
+ a = a > 1 ? 2 - a : a;\
+ a = 1 - (cos(a * (TYPE)M_PI) + 1) / 2;\
+ ((TYPE *)(stream->buf))[4 * i + 0] = a;\
+ ((TYPE *)(stream->buf))[4 * i + 1] = a;\
+ ((TYPE *)(stream->buf))[4 * i + 2] = a;\
+ ((TYPE *)(stream->buf))[4 * i + 3] = a;\
+ }\
+ } else {\
+ for (i = 0; i < n; i++) {\
+ x = ((TYPE *)(stream->buf))[4 * i + 0];\
+ y = ((TYPE *)(stream->buf))[4 * i + 1];\
+ z = ((TYPE *)(stream->buf))[4 * i + 2];\
+ a = ((TYPE *)(stream->buf))[4 * i + 3];\
+ x = posmod(x, (TYPE)1);\
+ y = posmod(y, (TYPE)1);\
+ z = posmod(z, (TYPE)1);\
+ a = posmod(a, (TYPE)1);\
+ x = x > 1 ? 2 - x : x;\
+ y = y > 1 ? 2 - y : y;\
+ z = z > 1 ? 2 - z : z;\
+ a = a > 1 ? 2 - a : a;\
+ x = 1 - (cos(x * (TYPE)M_PI) + 1) / 2;\
+ y = 1 - (cos(y * (TYPE)M_PI) + 1) / 2;\
+ z = 1 - (cos(z * (TYPE)M_PI) + 1) / 2;\
+ a = 1 - (cos(a * (TYPE)M_PI) + 1) / 2;\
+ ((TYPE *)(stream->buf))[4 * i + 0] = x;\
+ ((TYPE *)(stream->buf))[4 * i + 1] = y;\
+ ((TYPE *)(stream->buf))[4 * i + 2] = z;\
+ ((TYPE *)(stream->buf))[4 * i + 3] = a;\
+ }\
+ }\
+ n *= stream->pixel_size;\
+ ewriteall(STDOUT_FILENO, stream->buf, n, "<stdout>");\
+ memmove(stream->buf, stream->buf + n, stream->ptr -= n);\
+ } while (eread_stream(stream, SIZE_MAX));\
+ if (stream->ptr)\
+ eprintf("%s: incomplete frame\n", stream->file);\
+ }
+
+PROCESS(double, lf)
+PROCESS(float, f)
+
+
+int
+main(int argc, char *argv[])
+{
+ struct stream stream;
+ void (*process)(struct stream *stream);
+
+ ARGBEGIN {
+ case 'e':
+ equal = 1;
+ break;
+ default:
+ usage();
+ } ARGEND;
+
+ if (argc)
+ usage();
+
+ eopen_stream(&stream, NULL);
+
+ if (!strcmp(stream.pixfmt, "xyza"))
+ process = process_lf;
+ else if (!strcmp(stream.pixfmt, "xyza f"))
+ process = process_f;
+ else
+ eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt);
+
+ fprint_stream_head(stdout, &stream);
+ efflush(stdout, "<stdout>");
+ process(&stream);
+ return 0;
+}
diff --git a/src/blind-spiral-gradient.c b/src/blind-spiral-gradient.c
@@ -0,0 +1,134 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+USAGE("[-al] -w width -h height")
+
+static int anticlockwise = 0;
+static int logarithmic = 0;
+static size_t width = 0;
+static size_t height = 0;
+static int with_params;
+
+
+#define PROCESS(TYPE, SUFFIX)\
+ static void\
+ process_##SUFFIX(struct stream *stream)\
+ {\
+ typedef TYPE pixel_t[4];\
+ pixel_t buf[BUFSIZ / sizeof(pixel_t)];\
+ TYPE *params, x1, y1, x2, y2, b, r, u, v;\
+ TYPE x, y, a = 0, e = 1, p = 1, k = 1, ep = 1;\
+ size_t ix, iy, ptr = 0;\
+ for (;;) {\
+ while (stream->ptr < stream->frame_size) {\
+ if (!eread_stream(stream, stream->frame_size - stream->ptr)) {\
+ ewriteall(STDOUT_FILENO, buf, ptr * sizeof(*buf), "<stdout>");\
+ return;\
+ }\
+ }\
+ params = (TYPE *)stream->buf;\
+ x1 = (params)[0];\
+ y1 = (params)[1];\
+ x2 = (params)[4];\
+ y2 = (params)[5];\
+ if (with_params) {\
+ a = (params)[8];\
+ e = (params)[9];\
+ p = (params)[10];\
+ k = (params)[11];\
+ ep = 1 / (e * p);\
+ }\
+ memmove(stream->buf, stream->buf + stream->frame_size,\
+ stream->ptr -= stream->frame_size);\
+ \
+ x2 -= x1;\
+ y2 -= y1;\
+ u = atan2(y2, x2);\
+ b = sqrt(x2 * x2 + y2 * y2);\
+ if (logarithmic)\
+ b = log(b);\
+ b /= pow(2 * (TYPE)M_PI, e);\
+ \
+ for (iy = 0; iy < height; iy++) {\
+ y = (TYPE)iy - y1;\
+ for (ix = 0; ix < width; ix++) {\
+ x = (TYPE)ix - x1;\
+ v = atan2(y, x);\
+ if (anticlockwise)\
+ v = 1 - v;\
+ v -= u;\
+ v += 4 * (TYPE)M_PI;\
+ v = mod(v, 2 * (TYPE)M_PI);\
+ r = sqrt(x * x + y * y);\
+ r -= a;\
+ if (!logarithmic) {\
+ r = pow(r / b, ep);\
+ r = (r - v) / (2 * (TYPE)M_PI);\
+ } else if (r) {\
+ r = log(r / k);\
+ r = pow(r / b, ep);\
+ r = (r - v) / (2 * (TYPE)M_PI);\
+ }\
+ buf[ptr][0] = buf[ptr][1] = buf[ptr][2] = buf[ptr][3] = r;\
+ if (++ptr == ELEMENTSOF(buf)) {\
+ ewriteall(STDOUT_FILENO, buf, sizeof(buf), "<stdout>");\
+ ptr = 0;\
+ }\
+ }\
+ }\
+ }\
+ }
+
+PROCESS(double, lf)
+PROCESS(float, f)
+
+
+int
+main(int argc, char *argv[])
+{
+ struct stream stream;
+ void (*process)(struct stream *stream);
+
+ ARGBEGIN {
+ case 'a':
+ anticlockwise = 1;
+ break;
+ case 'l':
+ logarithmic = 1;
+ break;
+ case 'w':
+ width = etozu_flag('w', UARGF(), 1, SIZE_MAX);
+ break;
+ case 'h':
+ height = etozu_flag('h', UARGF(), 1, SIZE_MAX);
+ break;
+ default:
+ usage();
+ } ARGEND;
+
+ if (!width || !height || argc)
+ usage();
+
+ eopen_stream(&stream, NULL);
+
+ if (!strcmp(stream.pixfmt, "xyza"))
+ process = process_lf;
+ else if (!strcmp(stream.pixfmt, "xyza f"))
+ process = process_f;
+ else
+ eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt);
+
+ if (stream.width > 3 || stream.height > 3 ||
+ stream.width * stream.height < 2 ||
+ stream.width * stream.height > 3)
+ eprintf("<stdin>: each frame must contain exactly 2 or 3 pixels\n");
+
+ with_params = stream.width * stream.height == 3;
+
+ stream.width = width;
+ stream.height = height;
+ fprint_stream_head(stdout, &stream);
+ efflush(stdout, "<stdout>");
+ process(&stream);
+ return 0;
+}
diff --git a/src/blind-square-gradient.c b/src/blind-square-gradient.c
@@ -0,0 +1,109 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+USAGE("-w width -h height")
+
+static size_t width = 0;
+static size_t height = 0;
+static int with_multiplier;
+
+
+#define PROCESS(TYPE, SUFFIX)\
+ static void\
+ process_##SUFFIX(struct stream *stream)\
+ {\
+ typedef TYPE pixel_t[4];\
+ pixel_t buf[BUFSIZ / sizeof(pixel_t)];\
+ TYPE *params, x1, y1, x2, y2, norm, rd = 1; \
+ TYPE x, y, p, r, rx, ry;\
+ size_t ix, iy, ptr = 0;\
+ for (;;) {\
+ while (stream->ptr < stream->frame_size) {\
+ if (!eread_stream(stream, stream->frame_size - stream->ptr)) {\
+ ewriteall(STDOUT_FILENO, buf, ptr * sizeof(*buf), "<stdout>");\
+ return;\
+ }\
+ }\
+ params = (TYPE *)stream->buf;\
+ x1 = (params)[0];\
+ y1 = (params)[1];\
+ x2 = (params)[4];\
+ y2 = (params)[5];\
+ if (with_multiplier)\
+ rd = (params)[9];\
+ memmove(stream->buf, stream->buf + stream->frame_size,\
+ stream->ptr -= stream->frame_size);\
+ \
+ x2 -= x1;\
+ y2 -= y1;\
+ norm = sqrt(x2 * x2 + y2 * y2);\
+ x2 /= norm;\
+ y2 /= norm;\
+ \
+ for (iy = 0; iy < height; iy++) {\
+ y = (TYPE)iy - y1;\
+ for (ix = 0; ix < width; ix++) {\
+ x = (TYPE)ix - x1;\
+ p = x * x2 + y * y2;\
+ rx = x - p * x2;\
+ ry = y - p * y2;\
+ r = sqrt(rx * rx + ry * ry) / rd;\
+ p = abs(p);\
+ x = MAX(p, r) / norm;\
+ buf[ptr][0] = buf[ptr][1] = buf[ptr][2] = buf[ptr][3] = x;\
+ if (++ptr == ELEMENTSOF(buf)) {\
+ ewriteall(STDOUT_FILENO, buf, sizeof(buf), "<stdout>");\
+ ptr = 0;\
+ }\
+ }\
+ }\
+ }\
+ }
+
+PROCESS(double, lf)
+PROCESS(float, f)
+
+
+int
+main(int argc, char *argv[])
+{
+ struct stream stream;
+ void (*process)(struct stream *stream);
+
+ ARGBEGIN {
+ case 'w':
+ width = etozu_flag('w', UARGF(), 1, SIZE_MAX);
+ break;
+ case 'h':
+ height = etozu_flag('h', UARGF(), 1, SIZE_MAX);
+ break;
+ default:
+ usage();
+ } ARGEND;
+
+ if (!width || !height || argc)
+ usage();
+
+ eopen_stream(&stream, NULL);
+
+ if (!strcmp(stream.pixfmt, "xyza"))
+ process = process_lf;
+ else if (!strcmp(stream.pixfmt, "xyza f"))
+ process = process_f;
+ else
+ eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt);
+
+ if (stream.width > 3 || stream.height > 3 ||
+ stream.width * stream.height < 2 ||
+ stream.width * stream.height > 3)
+ eprintf("<stdin>: each frame must contain exactly 2 or 3 pixels\n");
+
+ with_multiplier = stream.width * stream.height == 3;
+
+ stream.width = width;
+ stream.height = height;
+ fprint_stream_head(stdout, &stream);
+ efflush(stdout, "<stdout>");
+ process(&stream);
+ return 0;
+}
diff --git a/src/blind-triangular-wave.c b/src/blind-triangular-wave.c
@@ -0,0 +1,101 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+USAGE("[-es]")
+
+static int equal = 0;
+static int spiral = 0;
+
+
+#define PROCESS(TYPE, SUFFIX)\
+ static void\
+ process_##SUFFIX(struct stream *stream)\
+ {\
+ size_t i, n;\
+ TYPE x, y, z, a;\
+ do {\
+ n = stream->ptr / stream->pixel_size;\
+ if (equal) {\
+ for (i = 0; i < n; i++) {\
+ a = ((TYPE *)(stream->buf))[4 * i + 3];\
+ a = posmod(a, (TYPE)2);\
+ a = a > 1 ? 2 - a : a;\
+ if (spiral)\
+ a = (a > 0.5 ? 1 - a : a) * 2;\
+ ((TYPE *)(stream->buf))[4 * i + 0] = a;\
+ ((TYPE *)(stream->buf))[4 * i + 1] = a;\
+ ((TYPE *)(stream->buf))[4 * i + 2] = a;\
+ ((TYPE *)(stream->buf))[4 * i + 3] = a;\
+ }\
+ } else {\
+ for (i = 0; i < n; i++) {\
+ x = ((TYPE *)(stream->buf))[4 * i + 0];\
+ y = ((TYPE *)(stream->buf))[4 * i + 1];\
+ z = ((TYPE *)(stream->buf))[4 * i + 2];\
+ a = ((TYPE *)(stream->buf))[4 * i + 3];\
+ x = posmod(x, (TYPE)2);\
+ y = posmod(y, (TYPE)2);\
+ z = posmod(z, (TYPE)2);\
+ a = posmod(a, (TYPE)2);\
+ x = x > 1 ? 2 - x : x;\
+ y = y > 1 ? 2 - y : y;\
+ z = z > 1 ? 2 - z : z;\
+ a = a > 1 ? 2 - a : a;\
+ if (spiral) {\
+ x = (x > 0.5 ? 1 - x : x) * 2;\
+ y = (y > 0.5 ? 1 - y : y) * 2;\
+ z = (z > 0.5 ? 1 - z : z) * 2;\
+ a = (a > 0.5 ? 1 - a : a) * 2;\
+ }\
+ ((TYPE *)(stream->buf))[4 * i + 0] = x;\
+ ((TYPE *)(stream->buf))[4 * i + 1] = y;\
+ ((TYPE *)(stream->buf))[4 * i + 2] = z;\
+ ((TYPE *)(stream->buf))[4 * i + 3] = a;\
+ }\
+ }\
+ n *= stream->pixel_size;\
+ ewriteall(STDOUT_FILENO, stream->buf, n, "<stdout>");\
+ memmove(stream->buf, stream->buf + n, stream->ptr -= n);\
+ } while (eread_stream(stream, SIZE_MAX));\
+ if (stream->ptr)\
+ eprintf("%s: incomplete frame\n", stream->file);\
+ }
+
+PROCESS(double, lf)
+PROCESS(float, f)
+
+
+int
+main(int argc, char *argv[])
+{
+ struct stream stream;
+ void (*process)(struct stream *stream);
+
+ ARGBEGIN {
+ case 'e':
+ equal = 1;
+ break;
+ case 's':
+ spiral = 1;
+ break;
+ default:
+ usage();
+ } ARGEND;
+
+ if (argc)
+ usage();
+
+ eopen_stream(&stream, NULL);
+
+ if (!strcmp(stream.pixfmt, "xyza"))
+ process = process_lf;
+ else if (!strcmp(stream.pixfmt, "xyza f"))
+ process = process_f;
+ else
+ eprintf("pixel format %s is not supported, try xyza\n", stream.pixfmt);
+
+ fprint_stream_head(stdout, &stream);
+ efflush(stdout, "<stdout>");
+ process(&stream);
+ return 0;
+}
diff --git a/src/video-math.h b/src/video-math.h
@@ -59,6 +59,7 @@ posmodf(float a, float b)
#define pow(...) MATH_GENERIC_N(pow, __VA_ARGS__)
#define log2(...) MATH_GENERIC_1(log2, __VA_ARGS__)
+#define log(...) MATH_GENERIC_1(log, __VA_ARGS__)
#define abs(...) MATH_GENERIC_1(fabs, __VA_ARGS__)
#define sqrt(...) MATH_GENERIC_1(sqrt, __VA_ARGS__)
#define exp(...) MATH_GENERIC_1(exp, __VA_ARGS__)
@@ -68,6 +69,9 @@ posmodf(float a, float b)
#define nnpow(...) MATH_GENERIC_N(nnpow, __VA_ARGS__)
#define mod(...) MATH_GENERIC_N(fmod, __VA_ARGS__)
#define posmod(...) MATH_GENERIC_N(posmod, __VA_ARGS__)
+#define cos(...) MATH_GENERIC_1(cos, __VA_ARGS__)
+#define sin(...) MATH_GENERIC_1(sin, __VA_ARGS__)
+#define atan2(...) MATH_GENERIC_N(atan2, __VA_ARGS__)
#define srgb_encode(...) BLIND_GENERIC_1(srgb_encode, __VA_ARGS__)
#define srgb_decode(...) BLIND_GENERIC_1(srgb_decode, __VA_ARGS__)