/* * fractal * Written in 2020 by Lucas * CC0 1.0 Universal/Public domain - No rights reserved * * To the extent possible under law, the author(s) have dedicated all * copyright and related and neighboring rights to this software to the * public domain worldwide. This software is distributed without any * warranty. You should have received a copy of the CC0 Public Domain * Dedication along with this software. If not, see * . */ /* gepopt visibility for GLIBC */ #if !defined(__OpenBSD__) #define _DEFAULT_SOURCE #endif #include #include #include #include #include #include "palette.h" #include "pnmout.h" #include "util.h" #define CLAMP(x, a, b) ((x) < (a) ? (a) : (x) > (b) ? (b) : (x)) static double bezier3(double t, double p0, double p1, double p2, double p3) { double u = 1.0 - t; return u * u * u * p0 + 3.0 * u * u * t * p1 + 3.0 * u * t * t * p2 + t * t * t * p3; } static double bezier4(double t, double p0, double p1, double p2, double p3) { return (1.0 - t) * bezier3(t, p0, p1, p2, p3) + t * bezier3(t, p1, p2, p3, p0); } struct color * palette_gen(size_t n) { struct color *palette; double p[12] = { drand48(), drand48(), drand48(), drand48(), drand48(), drand48(), drand48(), drand48(), drand48(), drand48(), drand48(), drand48(), }; double r, g, b, t; size_t i; if (!(palette = malloc(n * sizeof(*palette)))) { fprintf(stderr, "out of memory"); exit(1); } for (i = 0; i < n; i++) { t = i / (double)n; r = bezier4(t, p[0], p[3], p[6], p[9]); g = bezier4(t, p[1], p[4], p[7], p[10]); b = bezier4(t, p[2], p[5], p[8], p[11]); palette[i].r = 65535.0 * CLAMP(r, 0.0, 1.0); palette[i].g = 65535.0 * CLAMP(g, 0.0, 1.0); palette[i].b = 65535.0 * CLAMP(b, 0.0, 1.0); } return palette; } static void usage(void) { fprintf(stderr, "Usage: %s palette [-h height] [-w width]\n", xgetprogname()); exit(1); } int palette_main(int argc, char *argv[]) { struct color *palette; char *end; uintmax_t v; unsigned int width, height; int ch, i, j; height = 100; width = 720; while ((ch = getopt(argc, argv, "h:w:")) != -1) switch (ch) { case 'h': errno = 0; v = strtoumax(optarg, &end, 0); if (*end != '\0' || errno != 0 || v == 0 || v > UINT_MAX) { fprintf(stderr, "-h: Invalid value \"%s\"", optarg); exit(1); } height = v; case 'w': errno = 0; v = strtoumax(optarg, &end, 0); if (*end != '\0' || errno != 0 || v == 0 || v > UINT_MAX) { fprintf(stderr, "-w: Invalid value \"%s\"", optarg); exit(1); } width = v; default: usage(); } argc -= optind; argv += optind; if (argc > 1) usage(); palette = palette_gen(width); pnmout_header(stdout, width, height); for (i = 0; i < height; i++) for (j = 0; j < width; j++) pnmout_pixel(stdout, palette[j]); free(palette); return !(fflush(stdout) == 0); }