module Data.Colour.CIE
(Colour
,cieXYZ, cieXYZView, luminance
,toCIEXYZ
,Chromaticity
,mkChromaticity, chromaCoords
,chromaX, chromaY, chromaZ
,chromaConvert
,chromaColour
,lightness, cieLABView, cieLAB
)
where
import Data.List
import Data.Colour
import Data.Colour.RGB
import Data.Colour.SRGB.Linear
import Data.Colour.CIE.Chromaticity
import Data.Colour.Matrix
cieXYZ :: (Fractional a) => a -> a -> a -> Colour a
cieXYZ x y z = rgb r g b
where
[r,g,b] = mult matrix [x,y,z]
matrix = map (map fromRational) xyz2rgb709
cieXYZView :: (Fractional a) => Colour a -> (a,a,a)
cieXYZView c = (x,y,z)
where
RGB r g b = toRGB c
[x,y,z] = mult matrix [r,g,b]
matrix = map (map fromRational) rgb7092xyz
{-# DEPRECATED toCIEXYZ "`toCIEXYZ' has been renamed `cieXYZView'" #-}
toCIEXYZ x = cieXYZView x
luminance :: (Fractional a) => Colour a -> a
luminance c = y
where
(x,y,z) = toCIEXYZ c
instance AffineSpace Chromaticity where
affineCombo l z =
foldl1' chromaAdd [chromaScale w a | (w,a) <- (1-total,z):l]
where
total = sum $ map fst l
(Chroma x0 y0) `chromaAdd` (Chroma x1 y1) = Chroma (x0+x1) (y0+y1)
s `chromaScale` (Chroma x y) = Chroma (s*x) (s*y)
chromaColour :: (Fractional a) =>
Chromaticity a
-> a
-> Colour a
chromaColour ch y = cieXYZ (s*ch_x) y (s*ch_z)
where
(ch_x, ch_y, ch_z) = chromaCoords ch
s = y/ch_y
lightness :: (Ord a, Floating a) => Chromaticity a
-> Colour a -> a
lightness white_ch c | (6/29)^3 < y' = 116*y'**(1/3) - 16
| otherwise = (29/3)^3*y'
where
white = chromaColour white_ch 1.0
y' = (luminance c/luminance white)
cieLABView :: (Ord a, Floating a) => Chromaticity a
-> Colour a -> (a,a,a)
cieLABView white_ch c = (lightness white_ch c, a, b)
where
white = chromaColour white_ch 1.0
(x,y,z) = toCIEXYZ c
(xn,yn,zn) = toCIEXYZ white
(fx, fy, fz) = (f (x/xn), f (y/yn), f (z/zn))
a = 500*(fx - fy)
b = 200*(fy - fz)
f x | (6/29)^3 < x = x**(1/3)
| otherwise = 841/108*x + 4/29
cieLAB :: (Ord a, Floating a) => Chromaticity a
-> a
-> a
-> a
-> Colour a
cieLAB white_ch l a b = cieXYZ (xn*transform fx)
(yn*transform fy)
(zn*transform fz)
where
white = chromaColour white_ch 1.0
(xn,yn,zn) = toCIEXYZ white
fx = fy + a/500
fy = (l + 16)/116
fz = fy - b/200
delta = 6/29
transform fa | fa > delta = fa^3
| otherwise = (fa - 16/116)*3*delta^2
cieLuv :: (Ord a, Floating a) => Chromaticity a
-> Colour a -> (a,a,a)
cieLuv white_ch c = (l, 13*l*(u'-un'), 13*l*(v'-vn'))
where
white = chromaColour white_ch 1.0
(u', v') = u'v' c
(un', vn') = u'v' white
l = lightness white_ch c
u'v' :: (Ord a, Floating a) => Colour a -> (a,a)
u'v' c = (4*x/(x+15*y+3*z), 9*y/(x+15*y+3*z))
where
(x,y,z) = toCIEXYZ c
rgb7092xyz = (rgb2xyz sRGBGamut)
xyz2rgb709 = inverse rgb7092xyz