commit 83169cdcb60716016e096d5433cd7de1beacf26b
parent c53860987a368f8e2f80c722c7b0bd48631e69f9
Author: MikoĊaj Lenczewski <mblenczewski@gmail.com>
Date: Sun, 19 Jan 2025 12:50:22 +0000
Implement hsv smooth colouring
Diffstat:
2 files changed, 42 insertions(+), 10 deletions(-)
diff --git a/src/main.c b/src/main.c
@@ -16,7 +16,7 @@ static void
usage(char *prog)
{
fprintf(stderr, "Usage: %s [-hv] [-r <xres>x<yres> ] [-i <maxiters>] "
- "[-p mono|gray|hist|smooth ] [-o <out.bmp>]\n",
+ "[-p basic|mono|gray|hist|smooth ] [-o <out.bmp>]\n",
prog);
fprintf(stderr, "\t-h : display help information\n");
@@ -66,7 +66,9 @@ parse_opts(int argc, char **argv, struct opts *opts)
break;
case 'p':
- if (strcmp(optarg, "mono") == 0) {
+ if (strcmp(optarg, "basic") == 0) {
+ opts->palette = PALETTE_BASIC;
+ } else if (strcmp(optarg, "mono") == 0) {
opts->palette = PALETTE_MONOCHROME;
} else if (strcmp(optarg, "gray") == 0) {
opts->palette = PALETTE_GRAYSCALE;
@@ -139,32 +141,61 @@ point(float x, float y, uint32_t max_iters, float *out)
#define CLAMP(v, v0, v1) MIN(MAX((v), (v0)), (v1))
static inline uint32_t
+hsv_to_rgb(float hue, float sat, float val)
+{
+ float h = fmodf(hue, 360.0);
+
+ float hp = h / 60.0;
+ float c = val * sat;
+ float x = c * (1 - fabsf(fmodf(hp, 2.0) - 1));
+
+ float rgb[3] = {0};
+
+ if (0 <= hp && hp < 1) { rgb[0] = c; rgb[1] = x; }
+ else if (1 <= hp && hp < 2) { rgb[0] = x; rgb[1] = c; }
+ else if (2 <= hp && hp < 3) { rgb[1] = c; rgb[2] = x; }
+ else if (3 <= hp && hp < 4) { rgb[1] = x; rgb[2] = c; }
+ else if (4 <= hp && hp < 5) { rgb[0] = x; rgb[2] = c; }
+ else if (5 <= hp && hp < 6) { rgb[0] = c; rgb[2] = x; }
+
+ float m = val - c;
+ rgb[0] += m;
+ rgb[1] += m;
+ rgb[2] += m;
+
+ return pixel(rgb[0] * 255, rgb[1] * 255, rgb[2] * 255, 255);
+}
+
+static inline uint32_t
palette(float abs2, uint32_t iters, uint32_t max_iters, enum palette_type type)
{
float f = (float) iters / max_iters;
+ float smooth_iters = (iters + 1) - (logf(logf(sqrtf(abs2))) / M_LN2);
+ float sf = CLAMP(smooth_iters / max_iters, 0.0f, 1.0f);
+ float v = 255 * (1 - sf);
switch (type) {
- case PALETTE_MONOCHROME:
+ case PALETTE_BASIC:
return (iters == max_iters) ? pixel(0, 0, 0, 255)
: pixel(255, 255, 255, 255);
- case PALETTE_GRAYSCALE:
+ case PALETTE_MONOCHROME:
return (iters == max_iters) ? pixel(0, 0, 0, 255)
: pixel(f * 255, f * 255, f * 255, 255);
+ case PALETTE_GRAYSCALE:
+ return (iters == max_iters) ? pixel(0, 0, 0, 255) : pixel(v, v, v, 255);
+
case PALETTE_HISTOGRAM: {
// TODO: actually implement histogram colouring
-
return (iters == max_iters) ? pixel(0, 0, 0, 255)
: pixel(f * 255, f * 255, f * 255, 255);
} break;
case PALETTE_SMOOTH: {
- float smooth_iters = (iters + 1) - (logf(logf(sqrtf(abs2))) / M_LN2);
- float sf = CLAMP(smooth_iters / max_iters, 0.0f, 1.0f);
- float v = 255 * (1 - sf);
-
- return (iters == max_iters) ? pixel(0, 0, 0, 255) : pixel(v, v, v, 255);
+ float hue = 0.95 + 20 * smooth_iters;
+ return (iters == max_iters) ? pixel(0, 0, 0, 255)
+ : hsv_to_rgb(hue, 0.8, 1.0);
} break;
}
}
diff --git a/src/mandelbrot.h b/src/mandelbrot.h
@@ -18,6 +18,7 @@
*/
enum palette_type {
+ PALETTE_BASIC,
PALETTE_MONOCHROME,
PALETTE_GRAYSCALE,
PALETTE_HISTOGRAM,