module Data.Colour.RGB where
import Data.List (elemIndex, transpose)
import Data.Colour.Matrix
import Data.Colour.CIE.Chromaticity
data RGB a = RGB {RGB a -> a
channelRed :: !a
,RGB a -> a
channelGreen :: !a
,RGB a -> a
channelBlue :: !a
} deriving (RGB a -> RGB a -> Bool
(RGB a -> RGB a -> Bool) -> (RGB a -> RGB a -> Bool) -> Eq (RGB a)
forall a. Eq a => RGB a -> RGB a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: RGB a -> RGB a -> Bool
$c/= :: forall a. Eq a => RGB a -> RGB a -> Bool
== :: RGB a -> RGB a -> Bool
$c== :: forall a. Eq a => RGB a -> RGB a -> Bool
Eq, Int -> RGB a -> ShowS
[RGB a] -> ShowS
RGB a -> String
(Int -> RGB a -> ShowS)
-> (RGB a -> String) -> ([RGB a] -> ShowS) -> Show (RGB a)
forall a. Show a => Int -> RGB a -> ShowS
forall a. Show a => [RGB a] -> ShowS
forall a. Show a => RGB a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [RGB a] -> ShowS
$cshowList :: forall a. Show a => [RGB a] -> ShowS
show :: RGB a -> String
$cshow :: forall a. Show a => RGB a -> String
showsPrec :: Int -> RGB a -> ShowS
$cshowsPrec :: forall a. Show a => Int -> RGB a -> ShowS
Show, ReadPrec [RGB a]
ReadPrec (RGB a)
Int -> ReadS (RGB a)
ReadS [RGB a]
(Int -> ReadS (RGB a))
-> ReadS [RGB a]
-> ReadPrec (RGB a)
-> ReadPrec [RGB a]
-> Read (RGB a)
forall a. Read a => ReadPrec [RGB a]
forall a. Read a => ReadPrec (RGB a)
forall a. Read a => Int -> ReadS (RGB a)
forall a. Read a => ReadS [RGB a]
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [RGB a]
$creadListPrec :: forall a. Read a => ReadPrec [RGB a]
readPrec :: ReadPrec (RGB a)
$creadPrec :: forall a. Read a => ReadPrec (RGB a)
readList :: ReadS [RGB a]
$creadList :: forall a. Read a => ReadS [RGB a]
readsPrec :: Int -> ReadS (RGB a)
$creadsPrec :: forall a. Read a => Int -> ReadS (RGB a)
Read)
instance Functor RGB where
fmap :: (a -> b) -> RGB a -> RGB b
fmap a -> b
f (RGB a
r a
g a
b) = b -> b -> b -> RGB b
forall a. a -> a -> a -> RGB a
RGB (a -> b
f a
r) (a -> b
f a
g) (a -> b
f a
b)
instance Applicative RGB where
pure :: a -> RGB a
pure a
c = a -> a -> a -> RGB a
forall a. a -> a -> a -> RGB a
RGB a
c a
c a
c
(RGB a -> b
fr a -> b
fg a -> b
fb) <*> :: RGB (a -> b) -> RGB a -> RGB b
<*> (RGB a
r a
g a
b) = b -> b -> b -> RGB b
forall a. a -> a -> a -> RGB a
RGB (a -> b
fr a
r) (a -> b
fg a
g) (a -> b
fb a
b)
uncurryRGB :: (a -> a -> a -> b) -> RGB a -> b
uncurryRGB :: (a -> a -> a -> b) -> RGB a -> b
uncurryRGB a -> a -> a -> b
f (RGB a
r a
g a
b) = a -> a -> a -> b
f a
r a
g a
b
curryRGB :: (RGB a -> b) -> a -> a -> a -> b
curryRGB :: (RGB a -> b) -> a -> a -> a -> b
curryRGB RGB a -> b
f a
r a
g a
b = RGB a -> b
f (a -> a -> a -> RGB a
forall a. a -> a -> a -> RGB a
RGB a
r a
g a
b)
data RGBGamut = RGBGamut {RGBGamut -> RGB (Chromaticity Rational)
primaries :: !(RGB (Chromaticity Rational))
,RGBGamut -> Chromaticity Rational
whitePoint :: !(Chromaticity Rational)
} deriving (RGBGamut -> RGBGamut -> Bool
(RGBGamut -> RGBGamut -> Bool)
-> (RGBGamut -> RGBGamut -> Bool) -> Eq RGBGamut
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: RGBGamut -> RGBGamut -> Bool
$c/= :: RGBGamut -> RGBGamut -> Bool
== :: RGBGamut -> RGBGamut -> Bool
$c== :: RGBGamut -> RGBGamut -> Bool
Eq)
instance Show RGBGamut where
showsPrec :: Int -> RGBGamut -> ShowS
showsPrec Int
d RGBGamut
gamut = Bool -> ShowS -> ShowS
showParen (Int
d Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
app_prec) ShowS
showStr
where
showStr :: ShowS
showStr = String -> ShowS
showString String
"mkRGBGamut"
ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
" " ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> RGB (Chromaticity Rational) -> ShowS
forall a. Show a => Int -> a -> ShowS
showsPrec (Int
app_precInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) (RGBGamut -> RGB (Chromaticity Rational)
primaries RGBGamut
gamut))
ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
" " ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> Chromaticity Rational -> ShowS
forall a. Show a => Int -> a -> ShowS
showsPrec (Int
app_precInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) (RGBGamut -> Chromaticity Rational
whitePoint RGBGamut
gamut))
instance Read RGBGamut where
readsPrec :: Int -> ReadS RGBGamut
readsPrec Int
d String
r = Bool -> ReadS RGBGamut -> ReadS RGBGamut
forall a. Bool -> ReadS a -> ReadS a
readParen (Int
d Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
app_prec)
(\String
r -> [(RGB (Chromaticity Rational) -> Chromaticity Rational -> RGBGamut
mkRGBGamut RGB (Chromaticity Rational)
p Chromaticity Rational
w,String
t)
|(String
"mkRGBGamut",String
s) <- ReadS String
lex String
r
,(RGB (Chromaticity Rational)
p,String
s0) <- Int -> ReadS (RGB (Chromaticity Rational))
forall a. Read a => Int -> ReadS a
readsPrec (Int
app_precInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) String
s
,(Chromaticity Rational
w,String
t) <- Int -> ReadS (Chromaticity Rational)
forall a. Read a => Int -> ReadS a
readsPrec (Int
app_precInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) String
s0]) String
r
mkRGBGamut :: RGB (Chromaticity Rational)
-> Chromaticity Rational
-> RGBGamut
mkRGBGamut :: RGB (Chromaticity Rational) -> Chromaticity Rational -> RGBGamut
mkRGBGamut = RGB (Chromaticity Rational) -> Chromaticity Rational -> RGBGamut
RGBGamut
primaryMatrix :: (Fractional a) => (RGB (Chromaticity a)) -> [[a]]
primaryMatrix :: RGB (Chromaticity a) -> [[a]]
primaryMatrix RGB (Chromaticity a)
p =
[[a
xr, a
xg, a
xb]
,[a
yr, a
yg, a
yb]
,[a
zr, a
zg, a
zb]]
where
RGB (a
xr, a
yr, a
zr)
(a
xg, a
yg, a
zg)
(a
xb, a
yb, a
zb) = (Chromaticity a -> (a, a, a))
-> RGB (Chromaticity a) -> RGB (a, a, a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Chromaticity a -> (a, a, a)
forall a. Fractional a => Chromaticity a -> (a, a, a)
chromaCoords RGB (Chromaticity a)
p
rgb2xyz :: RGBGamut -> [[Rational]]
rgb2xyz :: RGBGamut -> [[Rational]]
rgb2xyz RGBGamut
space =
[[Rational]] -> [[Rational]]
forall a. [[a]] -> [[a]]
transpose ((Rational -> [Rational] -> [Rational])
-> [Rational] -> [[Rational]] -> [[Rational]]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith ((Rational -> Rational) -> [Rational] -> [Rational]
forall a b. (a -> b) -> [a] -> [b]
map ((Rational -> Rational) -> [Rational] -> [Rational])
-> (Rational -> Rational -> Rational)
-> Rational
-> [Rational]
-> [Rational]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
(*)) [Rational]
as ([[Rational]] -> [[Rational]]
forall a. [[a]] -> [[a]]
transpose [[Rational]]
matrix))
where
(Rational
xn, Rational
yn, Rational
zn) = Chromaticity Rational -> (Rational, Rational, Rational)
forall a. Fractional a => Chromaticity a -> (a, a, a)
chromaCoords (RGBGamut -> Chromaticity Rational
whitePoint RGBGamut
space)
matrix :: [[Rational]]
matrix = RGB (Chromaticity Rational) -> [[Rational]]
forall a. Fractional a => RGB (Chromaticity a) -> [[a]]
primaryMatrix (RGBGamut -> RGB (Chromaticity Rational)
primaries RGBGamut
space)
as :: [Rational]
as = [[Rational]] -> [Rational] -> [Rational]
forall b. Num b => [[b]] -> [b] -> [b]
mult ([[Rational]] -> [[Rational]]
forall a. Fractional a => [[a]] -> [[a]]
inverse [[Rational]]
matrix) [Rational
xnRational -> Rational -> Rational
forall a. Fractional a => a -> a -> a
/Rational
yn, Rational
1, Rational
znRational -> Rational -> Rational
forall a. Fractional a => a -> a -> a
/Rational
yn]
xyz2rgb :: RGBGamut -> [[Rational]]
xyz2rgb :: RGBGamut -> [[Rational]]
xyz2rgb = [[Rational]] -> [[Rational]]
forall a. Fractional a => [[a]] -> [[a]]
inverse ([[Rational]] -> [[Rational]])
-> (RGBGamut -> [[Rational]]) -> RGBGamut -> [[Rational]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RGBGamut -> [[Rational]]
rgb2xyz
hslsv :: (Fractional a, Ord a) => RGB a -> (a,a,a,a,a)
hslsv :: RGB a -> (a, a, a, a, a)
hslsv (RGB a
r a
g a
b) | a
mx a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
mn = (a
0,a
0,a
mx,a
0 ,a
mx)
| Bool
otherwise = (a
h,a
s,a
l ,a
s0,a
mx)
where
mx :: a
mx = [a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum [a
r,a
g,a
b]
mn :: a
mn = [a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
minimum [a
r,a
g,a
b]
l :: a
l = (a
mxa -> a -> a
forall a. Num a => a -> a -> a
+a
mn)a -> a -> a
forall a. Fractional a => a -> a -> a
/a
2
s :: a
s | a
l a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
0.5 = (a
mxa -> a -> a
forall a. Num a => a -> a -> a
-a
mn)a -> a -> a
forall a. Fractional a => a -> a -> a
/(a
mxa -> a -> a
forall a. Num a => a -> a -> a
+a
mn)
| Bool
otherwise = (a
mxa -> a -> a
forall a. Num a => a -> a -> a
-a
mn)a -> a -> a
forall a. Fractional a => a -> a -> a
/(a
2a -> a -> a
forall a. Num a => a -> a -> a
-(a
mxa -> a -> a
forall a. Num a => a -> a -> a
+a
mn))
s0 :: a
s0 = (a
mxa -> a -> a
forall a. Num a => a -> a -> a
-a
mn)a -> a -> a
forall a. Fractional a => a -> a -> a
/a
mx
[a
x,a
y,a
z] = Int -> [a] -> [a]
forall a. Int -> [a] -> [a]
take Int
3 ([a] -> [a]) -> [a] -> [a]
forall a b. (a -> b) -> a -> b
$ (a -> Bool) -> [a] -> [a]
forall a. (a -> Bool) -> [a] -> [a]
dropWhile (a -> a -> Bool
forall a. Eq a => a -> a -> Bool
/=a
mx) [a
r,a
g,a
b,a
r,a
g]
Just Int
o = a -> [a] -> Maybe Int
forall a. Eq a => a -> [a] -> Maybe Int
elemIndex a
mx [a
r,a
g,a
b]
h0 :: a
h0 = a
60a -> a -> a
forall a. Num a => a -> a -> a
*(a
ya -> a -> a
forall a. Num a => a -> a -> a
-a
z)a -> a -> a
forall a. Fractional a => a -> a -> a
/(a
mxa -> a -> a
forall a. Num a => a -> a -> a
-a
mn) a -> a -> a
forall a. Num a => a -> a -> a
+ a
120a -> a -> a
forall a. Num a => a -> a -> a
*(Int -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
o)
h :: a
h | a
h0 a -> a -> Bool
forall a. Ord a => a -> a -> Bool
< a
0 = a
h0 a -> a -> a
forall a. Num a => a -> a -> a
+ a
360
| Bool
otherwise = a
h0
hue :: (Fractional a, Ord a) => RGB a -> a
hue :: RGB a -> a
hue RGB a
rgb = a
h
where
(a
h,a
_,a
_,a
_,a
_) = RGB a -> (a, a, a, a, a)
forall a. (Fractional a, Ord a) => RGB a -> (a, a, a, a, a)
hslsv RGB a
rgb
mod1 :: p -> p
mod1 p
x | p
pf p -> p -> Bool
forall a. Ord a => a -> a -> Bool
< p
0 = p
pfp -> p -> p
forall a. Num a => a -> a -> a
+p
1
| Bool
otherwise = p
pf
where
(Integer
_,p
pf) = p -> (Integer, p)
forall a b. (RealFrac a, Integral b) => a -> (b, a)
properFraction p
x