packages feed

prizm-0.2.0.0: src/Data/Prizm/Color.hs

module Data.Prizm.Color where

import Control.Applicative
import Data.Prizm.Types
import Data.Prizm.Color.CIE as C

pct :: Integer -> Double
pct = (/100) . fromIntegral . (max 0) . (min 100)

pctClamp :: Integer -> Integer
pctClamp i = max (min i 100) 0

-- | Blend two colors using a 50% weighted average.
blend :: (CIEXYZ Double, CIEXYZ Double) -> CIEXYZ Double
blend = blendWeighted 50

-- | Shade a color by blending it using a weight and the color black.
shade :: CIEXYZ Double -> Percent -> CIEXYZ Double
shade c w = blendWeighted (pctClamp w) (CIEXYZ 0.0 0.0 0.0, c)

-- | Tint a color by blending it using a weight and the color white.
tint :: CIEXYZ Double -> Percent -> CIEXYZ Double
tint c w = blendWeighted (pctClamp w) ((CIEXYZ 95.047 100.0 108.883), c)

darken :: CIEXYZ Double -> Percent -> CIEXYZ Double
darken c w =
    let (CIELAB l a b) = C.toLAB c
        l' = l - (l*(pct (pctClamp w)))
    in C.toXYZ (CIELAB l' a b)

lighten :: CIEXYZ Double -> Percent -> CIEXYZ Double
lighten c w =
    let (CIELAB l a b) = C.toLAB c
        l' = l + (l*(pct (pctClamp w)))
    in C.toXYZ (CIELAB l' a b)

-- | Blend using a weighted average for two XYZ colors.
-- 
-- Weight are applied left to right, so if a weight of 25% is
-- supplied, then the color on the left will be multiplied by 25% and
-- the second color will be multiplied by 75%.
blendWeighted :: Percent -> (CIEXYZ Double, CIEXYZ Double) -> CIEXYZ Double
blendWeighted w (a,b) =
    let w' = (pct (pctClamp w))
        a1 = (*w') <$> a
        b1 = (*(1.0 - w')) <$> b
    in (+) <$> a1 <*> b1