racket/collects/images/private/flomap-effects.rkt

107 lines
4.4 KiB
Racket
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#lang typed/racket/base
(require racket/math racket/match racket/list
"flonum.rkt"
"flomap-struct.rkt"
"flomap-stats.rkt"
"flomap-pointwise.rkt"
"flomap-blur.rkt"
"flomap-composite.rkt"
"flomap-resize.rkt"
"flomap-transform.rkt")
(provide flomap-shadow flomap-outline
flomap-whirl-morph)
(: colorize-alpha (flomap (U (Vectorof Real) FlVector) -> flomap))
(define (colorize-alpha fm vs)
(match-define (flomap _ 1 w h) fm)
(fm* fm (make-flomap* w h vs)))
(: shadow-color (Integer (Option (U (Vectorof Real) FlVector)) -> (U (Vectorof Real) FlVector)))
(define (shadow-color c color)
(cond [color color]
[else (define vs (make-flvector c))
(flvector-set! vs 0 1.0)
vs]))
(: flomap-shadow (case-> (flomap Real -> flomap)
(flomap Real (Option (U (Vectorof Real) FlVector)) -> flomap)))
(define flomap-shadow
(case-lambda
[(fm σ) (flomap-shadow fm σ #f)]
[(fm σ color)
(define c (flomap-components fm))
(cond [(= c 0) (raise-type-error 'flomap-shadow "flomap with at least one component" fm)]
[(= c 1) (flomap-blur fm σ)]
[else (colorize-alpha (flomap-blur (flomap-ref-component fm 0) σ)
(shadow-color c color))])]))
(: flomap-outline (case-> (flomap Real -> flomap)
(flomap Real (Option (U (Vectorof Real) FlVector)) -> flomap)))
(define flomap-outline
(case-lambda
[(fm amt) (flomap-outline fm amt #f)]
[(fm amt color)
(define c (flomap-components fm))
(unless (c . > . 0)
(raise-type-error 'flomap-outline "flomap with at least one component" fm))
(let ([amt (real->double-flonum amt)])
(define σ (* 0.5 (max 1.0 amt)))
(define ceiling-amt (fl->fx (ceiling amt)))
(define test-size (fx* 2 (fx+ 1 ceiling-amt)))
(define test-mid (fxquotient test-size 2))
(define alpha-fm (flomap-ref-component fm 0))
(define-values (a-min a-max) (flomap-extreme-values alpha-fm))
(define a-size (- a-max a-min))
(define test-fm (inline-build-flomap 1 test-size 1
(λ (k x y i) (if (x . fx>= . test-mid) a-max a-min))))
(define blur-test-fm (flomap-blur-x test-fm σ))
(define v-min (flomap-bilinear-ref blur-test-fm 0 (+ 0.5 (- test-mid amt 1.0)) 0.5))
(define v-max (flomap-bilinear-ref blur-test-fm 0 (+ 0.5 (- test-mid amt)) 0.5))
(define av-scale (/ a-size (- v-max v-min)))
(let* ([outline-fm (flomap-blur alpha-fm σ)]
[outline-fm ((inline-flomap-lift
(λ (v) (+ a-min (max 0.0 (min a-size (* av-scale (- v v-min)))))))
outline-fm)]
[outline-fm ((inline-flomap-lift2
'subtract-alpha
(λ (o a) (if (= a 1.0) 0.0 (/ (- o a) (- 1.0 a)))))
outline-fm alpha-fm)])
(define color-vs (shadow-color c color))
(colorize-alpha outline-fm color-vs)))]))
(define blend-start 1/3)
(define blend-end 2/3)
(: flomap-whirl-morph (flomap flomap -> (Real -> flomap)))
(define (flomap-whirl-morph fm1 fm2)
(define w (max (flomap-width fm1) (flomap-width fm2)))
(define h (max (flomap-height fm1) (flomap-height fm2)))
(let ([fm1 (flomap-cc-crop fm1 w h)]
[fm2 (flomap-cc-crop fm2 w h)])
(define: (whirled-fm1 [t : Real]) : flomap
(define t1 (sqr t))
(define trans1
(flomap-transform-compose (flomap-rotate-transform (* t1 (* -1 pi)))
(flomap-whirl-transform (* t1 (* -8 pi)))))
(flomap-transform fm1 trans1 0 0 w h))
(define: (whirled-fm2 [t : Real]) : flomap
(define t2 (sqr (- 1 t)))
(define trans2
(flomap-transform-compose (flomap-rotate-transform (* t2 (* 1 pi)))
(flomap-whirl-transform (* t2 (* 8 pi)))))
(flomap-transform fm2 trans2 0 0 w h))
(λ (t)
(cond [(t . <= . 0) fm1]
[(t . >= . 1) fm2]
[else
(cond [(t . <= . blend-start) (whirled-fm1 t)]
[(t . >= . blend-end) (whirled-fm2 t)]
[else
(define b (/ (- t blend-start) (- blend-end blend-start)))
(fm+ (fm* (- 1 b) (whirled-fm1 t)) (fm* b (whirled-fm2 t)))])]))))