mandelbrot

mandelbrot.git
git clone git://git.lenczewski.org/mandelbrot.git
Log | Files | Refs

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:
Msrc/main.c | 51+++++++++++++++++++++++++++++++++++++++++----------
Msrc/mandelbrot.h | 1+
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,