aboutsummaryrefslogtreecommitdiffstats
path: root/src/blind-radial-gradient.c
diff options
context:
space:
mode:
authorMattias Andrée <maandree@kth.se>2017-07-02 23:58:01 +0200
committerMattias Andrée <maandree@kth.se>2017-07-02 23:58:01 +0200
commite76229ac4f95ac8c6e4e38e60689a09a091e4048 (patch)
treeb2b4925d318d6ac72dadb26125d9be15a679c6bd /src/blind-radial-gradient.c
parentAdd mod to blind-arithm (diff)
downloadblind-e76229ac4f95ac8c6e4e38e60689a09a091e4048.tar.gz
blind-e76229ac4f95ac8c6e4e38e60689a09a091e4048.tar.bz2
blind-e76229ac4f95ac8c6e4e38e60689a09a091e4048.tar.xz
Add gradients
Signed-off-by: Mattias Andrée <maandree@kth.se>
Diffstat (limited to 'src/blind-radial-gradient.c')
-rw-r--r--src/blind-radial-gradient.c128
1 files changed, 128 insertions, 0 deletions
diff --git a/src/blind-radial-gradient.c b/src/blind-radial-gradient.c
new file mode 100644
index 0000000..0c4571c
--- /dev/null
+++ 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;
+}