137 lines
2.9 KiB
C
137 lines
2.9 KiB
C
/*
|
|
* 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
|
|
* <http://creativecommons.org/publicdomain/zero/1.0/>.
|
|
*/
|
|
/* gepopt visibility for GLIBC */
|
|
#if !defined(__OpenBSD__)
|
|
#define _DEFAULT_SOURCE
|
|
#endif
|
|
|
|
#include <errno.h>
|
|
#include <inttypes.h>
|
|
#include <limits.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
|
|
#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);
|
|
}
|