From 6e4400d82549113acced5cd2db55ec92681ebfa7 Mon Sep 17 00:00:00 2001 From: mehbark <terezi@pyrope.net> Date: Tue, 25 Feb 2025 15:41:47 -0500 Subject: [PATCH] feat: (non-l)erping --- mandelbrot.ss | 61 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 41 insertions(+), 20 deletions(-) diff --git a/mandelbrot.ss b/mandelbrot.ss index 33cfe90..2e96a4f 100644 --- a/mandelbrot.ss +++ b/mandelbrot.ss @@ -2,7 +2,7 @@ (export make-ppm mandelbrot! steps make-rgb rgb-r rgb-g rgb-b - number->rgb) + number->rgb rgb-bin rgb-map rgb-lerp) (import (chezscheme)) (define-record-type rgb (fields r g b)) @@ -11,23 +11,29 @@ (make-rgb (bitwise-and #xff (bitwise-arithmetic-shift-right n 16)) (bitwise-and #xff (bitwise-arithmetic-shift-right n 8)) (bitwise-and #xff (bitwise-arithmetic-shift-right n 0)))) -(define rgb+ +(define (rgb-bin +) (case-lambda - [() (make-rgb 0 0 0)] [(a) a] [(a b) (make-rgb (+ (rgb-r a) (rgb-r b)) (+ (rgb-g a) (rgb-g b)) (+ (rgb-b a) (rgb-b b)))] - [rgbs (fold-left rgb+ (rgb+) rgbs)])) + [(a . bs) (fold-left (rgb-bin +) a bs)])) + +(define (rgb-map c f) + (make-rgb (f (rgb-r c)) + (f (rgb-g c)) + (f (rgb-b c)))) (define (rgb-mean . rgbs) (if (null? rgbs) - (rgb+) - (let ([sum (apply rgb+ rgbs)] - [len (length rgbs)]) - (make-rgb (fx/ (rgb-r sum) len) - (fx/ (rgb-g sum) len) - (fx/ (rgb-b sum) len))))) + (make-rgb 0 0 0) + (let* ([sum (apply (rgb-bin +) rgbs)] + [len (length rgbs)] + [scale (lambda (c) (inexact->exact (floor (/ c len))))]) + (rgb-map sum scale)))) + +(define (rgb-lerp i min max) + ((rgb-bin +) min (rgb-map ((rgb-bin -) max min) (lambda (x) (* i x))))) ;; proc : (x y) -> rgb (define (make-ppm path width height proc) @@ -102,7 +108,7 @@ (define (cli-fail) (format (standard-error-port 'line (current-transcoder)) - "usage: ./mandelbrot.ss path width height [color:hex*]\n") + "usage: ./mandelbrot.ss PATH WIDTH HEIGHT [COLOR:hex+|--lerp INTERIOR:hex START:hex END:hex]\n") (exit 1)) (define args (command-line-arguments)) @@ -120,19 +126,34 @@ (cli-fail)) (define (color i) - (define c (floor (* 256 (/ (+ 1 i) steps)))) + (define c + (if (negative? i) + 0 + (floor (* 256 (/ i steps))))) (make-rgb c c c)) (when (< 3 (length args)) - (let* ([stripes - (let* ([colors (cdddr args)] - [nums (map (lambda (n) (string->number n 16)) colors)] - [_ (unless (for-all (lambda (x) (and (integer? x) (<= 0 x))) nums) - (cli-fail))] - [colors (map number->rgb nums)]) - (list->vector colors))] + (let* ([colors (cdddr args)] + [lerp? (equal? "--lerp" (car colors))] + [colors (if lerp? (cdr colors) colors)] + [nums (map (lambda (n) (string->number n 16)) colors)] + [_ (unless (for-all (lambda (x) (and (integer? x) (<= 0 x))) nums) + (cli-fail))] + [stripes (list->vector (map number->rgb nums))] [stripe-count (vector-length stripes)]) - (set! color (lambda (i) (vector-ref stripes (mod i stripe-count)))))) + (when (and lerp? (< stripe-count 3)) + (cli-fail)) + + (set! color + (if lerp? + (lambda (i) + (if (negative? i) + (vector-ref stripes 0) + (rgb-map (rgb-lerp (expt (/ i steps) 1.3) + (vector-ref stripes 1) + (vector-ref stripes 2)) + floor))) + (lambda (i) (vector-ref stripes (mod i stripe-count))))))) (mandelbrot! path width height color -2.2 1.1 -1 1))