module Data.Colour.RGBSpace
(Colour
,RGB(..)
,uncurryRGB, curryRGB
,RGBGamut
,mkRGBGamut, primaries, whitePoint
,inGamut
,TransferFunction(..)
,linearTransferFunction, powerTransferFunction
,inverseTransferFunction
,RGBSpace()
,mkRGBSpace ,gamut, transferFunction
,linearRGBSpace
,rgbUsingSpace
,toRGBUsingSpace
)
where
import Data.Monoid
import Data.Semigroup
import Data.Colour.CIE.Chromaticity
import Data.Colour.Matrix
import Data.Colour.RGB
import Data.Colour.SRGB.Linear
inGamut :: (Ord a, Fractional a) => RGBGamut -> Colour a -> Bool
inGamut :: RGBGamut -> Colour a -> Bool
inGamut RGBGamut
gamut Colour a
c = Bool
r Bool -> Bool -> Bool
&& Bool
g Bool -> Bool -> Bool
&& Bool
b
where
test :: a -> Bool
test a
x = a
0 a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
x Bool -> Bool -> Bool
&& a
x a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
1
RGB Bool
r Bool
g Bool
b = (a -> Bool) -> RGB a -> RGB Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> Bool
forall a. (Ord a, Num a) => a -> Bool
test (RGBGamut -> Colour a -> RGB a
forall a. Fractional a => RGBGamut -> Colour a -> RGB a
toRGBUsingGamut RGBGamut
gamut Colour a
c)
rtf :: (Fractional b, Real a) => [[a]] -> [[b]]
rtf :: [[a]] -> [[b]]
rtf = ([a] -> [b]) -> [[a]] -> [[b]]
forall a b. (a -> b) -> [a] -> [b]
map ((a -> b) -> [a] -> [b]
forall a b. (a -> b) -> [a] -> [b]
map a -> b
forall a b. (Real a, Fractional b) => a -> b
realToFrac)
rgbUsingGamut :: (Fractional a) => RGBGamut -> a -> a -> a -> Colour a
rgbUsingGamut :: RGBGamut -> a -> a -> a -> Colour a
rgbUsingGamut RGBGamut
gamut a
r a
g a
b = a -> a -> a -> Colour a
forall a. Fractional a => a -> a -> a -> Colour a
rgb a
r0 a
g0 a
b0
where
matrix :: [[a]]
matrix = [[Rational]] -> [[a]]
forall b a. (Fractional b, Real a) => [[a]] -> [[b]]
rtf ([[Rational]] -> [[a]]) -> [[Rational]] -> [[a]]
forall a b. (a -> b) -> a -> b
$ [[Rational]] -> [[Rational]] -> [[Rational]]
forall a. Num a => [[a]] -> [[a]] -> [[a]]
matrixMult (RGBGamut -> [[Rational]]
xyz2rgb RGBGamut
sRGBGamut) (RGBGamut -> [[Rational]]
rgb2xyz RGBGamut
gamut)
[a
r0,a
g0,a
b0] = [[a]] -> [a] -> [a]
forall b. Num b => [[b]] -> [b] -> [b]
mult [[a]]
matrix [a
r,a
g,a
b]
toRGBUsingGamut :: (Fractional a) => RGBGamut -> Colour a -> RGB a
toRGBUsingGamut :: RGBGamut -> Colour a -> RGB a
toRGBUsingGamut RGBGamut
gamut Colour a
c = a -> a -> a -> RGB a
forall a. a -> a -> a -> RGB a
RGB a
r a
g a
b
where
RGB a
r0 a
g0 a
b0 = Colour a -> RGB a
forall a. Fractional a => Colour a -> RGB a
toRGB Colour a
c
matrix :: [[a]]
matrix = [[Rational]] -> [[a]]
forall b a. (Fractional b, Real a) => [[a]] -> [[b]]
rtf ([[Rational]] -> [[a]]) -> [[Rational]] -> [[a]]
forall a b. (a -> b) -> a -> b
$ [[Rational]] -> [[Rational]] -> [[Rational]]
forall a. Num a => [[a]] -> [[a]] -> [[a]]
matrixMult (RGBGamut -> [[Rational]]
xyz2rgb RGBGamut
gamut) (RGBGamut -> [[Rational]]
rgb2xyz RGBGamut
sRGBGamut)
[a
r,a
g,a
b] = [[a]] -> [a] -> [a]
forall b. Num b => [[b]] -> [b] -> [b]
mult [[a]]
matrix [a
r0,a
g0,a
b0]
data TransferFunction a = TransferFunction
{ TransferFunction a -> a -> a
transfer :: a -> a
, TransferFunction a -> a -> a
transferInverse :: a -> a
, TransferFunction a -> a
transferGamma :: a }
linearTransferFunction :: (Num a) => TransferFunction a
linearTransferFunction :: TransferFunction a
linearTransferFunction = (a -> a) -> (a -> a) -> a -> TransferFunction a
forall a. (a -> a) -> (a -> a) -> a -> TransferFunction a
TransferFunction a -> a
forall a. a -> a
id a -> a
forall a. a -> a
id a
1
powerTransferFunction :: (Floating a) => a -> TransferFunction a
powerTransferFunction :: a -> TransferFunction a
powerTransferFunction a
gamma =
(a -> a) -> (a -> a) -> a -> TransferFunction a
forall a. (a -> a) -> (a -> a) -> a -> TransferFunction a
TransferFunction (a -> a -> a
forall a. Floating a => a -> a -> a
**a
gamma) (a -> a -> a
forall a. Floating a => a -> a -> a
**(a -> a
forall a. Fractional a => a -> a
recip a
gamma)) a
gamma
inverseTransferFunction :: (Fractional a) => TransferFunction a -> TransferFunction a
inverseTransferFunction :: TransferFunction a -> TransferFunction a
inverseTransferFunction (TransferFunction a -> a
for a -> a
rev a
g) =
(a -> a) -> (a -> a) -> a -> TransferFunction a
forall a. (a -> a) -> (a -> a) -> a -> TransferFunction a
TransferFunction a -> a
rev a -> a
for (a -> a
forall a. Fractional a => a -> a
recip a
g)
instance (Num a) => Semigroup (TransferFunction a) where
<> :: TransferFunction a -> TransferFunction a -> TransferFunction a
(<>) = TransferFunction a -> TransferFunction a -> TransferFunction a
forall a. Monoid a => a -> a -> a
mappend
instance (Num a) => Monoid (TransferFunction a) where
mempty :: TransferFunction a
mempty = TransferFunction a
forall a. Num a => TransferFunction a
linearTransferFunction
(TransferFunction a -> a
f0 a -> a
f1 a
f) mappend :: TransferFunction a -> TransferFunction a -> TransferFunction a
`mappend` (TransferFunction a -> a
g0 a -> a
g1 a
g) =
((a -> a) -> (a -> a) -> a -> TransferFunction a
forall a. (a -> a) -> (a -> a) -> a -> TransferFunction a
TransferFunction (a -> a
f0 (a -> a) -> (a -> a) -> a -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> a
g0) (a -> a
g1 (a -> a) -> (a -> a) -> a -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> a
f1) (a
fa -> a -> a
forall a. Num a => a -> a -> a
*a
g))
data RGBSpace a = RGBSpace { RGBSpace a -> RGBGamut
gamut :: RGBGamut,
RGBSpace a -> TransferFunction a
transferFunction :: TransferFunction a }
mkRGBSpace :: RGBGamut
-> TransferFunction a
-> RGBSpace a
mkRGBSpace :: RGBGamut -> TransferFunction a -> RGBSpace a
mkRGBSpace = RGBGamut -> TransferFunction a -> RGBSpace a
forall a. RGBGamut -> TransferFunction a -> RGBSpace a
RGBSpace
linearRGBSpace :: (Num a) => RGBGamut -> RGBSpace a
linearRGBSpace :: RGBGamut -> RGBSpace a
linearRGBSpace RGBGamut
gamut = RGBGamut -> TransferFunction a -> RGBSpace a
forall a. RGBGamut -> TransferFunction a -> RGBSpace a
RGBSpace RGBGamut
gamut TransferFunction a
forall a. Monoid a => a
mempty
rgbUsingSpace :: (Fractional a) => RGBSpace a -> a -> a -> a -> Colour a
rgbUsingSpace :: RGBSpace a -> a -> a -> a -> Colour a
rgbUsingSpace RGBSpace a
space =
(RGB a -> Colour a) -> a -> a -> a -> Colour a
forall a b. (RGB a -> b) -> a -> a -> a -> b
curryRGB ((a -> a -> a -> Colour a) -> RGB a -> Colour a
forall a b. (a -> a -> a -> b) -> RGB a -> b
uncurryRGB (RGBGamut -> a -> a -> a -> Colour a
forall a. Fractional a => RGBGamut -> a -> a -> a -> Colour a
rgbUsingGamut (RGBSpace a -> RGBGamut
forall a. RGBSpace a -> RGBGamut
gamut RGBSpace a
space)) (RGB a -> Colour a) -> (RGB a -> RGB a) -> RGB a -> Colour a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> a) -> RGB a -> RGB a
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> a
tinv)
where
tinv :: a -> a
tinv = TransferFunction a -> a -> a
forall a. TransferFunction a -> a -> a
transferInverse (RGBSpace a -> TransferFunction a
forall a. RGBSpace a -> TransferFunction a
transferFunction RGBSpace a
space)
toRGBUsingSpace :: (Fractional a) => RGBSpace a -> Colour a -> RGB a
toRGBUsingSpace :: RGBSpace a -> Colour a -> RGB a
toRGBUsingSpace RGBSpace a
space Colour a
c = (a -> a) -> RGB a -> RGB a
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> a
t (RGBGamut -> Colour a -> RGB a
forall a. Fractional a => RGBGamut -> Colour a -> RGB a
toRGBUsingGamut (RGBSpace a -> RGBGamut
forall a. RGBSpace a -> RGBGamut
gamut RGBSpace a
space) Colour a
c)
where
t :: a -> a
t = TransferFunction a -> a -> a
forall a. TransferFunction a -> a -> a
transfer (RGBSpace a -> TransferFunction a
forall a. RGBSpace a -> TransferFunction a
transferFunction RGBSpace a
space)