module Data.Colour.Internal where
import Data.List (foldl1')
import qualified Data.Colour.Chan as Chan
import Data.Colour.Chan (Chan(Chan))
data Red = Red
data Green = Green
data Blue = Blue
data Colour a = RGB !(Chan Red a) !(Chan Green a) !(Chan Blue a)
deriving (Colour a -> Colour a -> Bool
(Colour a -> Colour a -> Bool)
-> (Colour a -> Colour a -> Bool) -> Eq (Colour a)
forall a. Eq a => Colour a -> Colour a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Colour a -> Colour a -> Bool
$c/= :: forall a. Eq a => Colour a -> Colour a -> Bool
== :: Colour a -> Colour a -> Bool
$c== :: forall a. Eq a => Colour a -> Colour a -> Bool
Eq)
colourConvert :: (Fractional b, Real a) => Colour a -> Colour b
colourConvert :: Colour a -> Colour b
colourConvert (RGB Chan Red a
r Chan Green a
g Chan Blue a
b) =
Chan Red b -> Chan Green b -> Chan Blue b -> Colour b
forall a. Chan Red a -> Chan Green a -> Chan Blue a -> Colour a
RGB (Chan Red a -> Chan Red b
forall b a p. (Fractional b, Real a) => Chan p a -> Chan p b
Chan.convert Chan Red a
r) (Chan Green a -> Chan Green b
forall b a p. (Fractional b, Real a) => Chan p a -> Chan p b
Chan.convert Chan Green a
g) (Chan Blue a -> Chan Blue b
forall b a p. (Fractional b, Real a) => Chan p a -> Chan p b
Chan.convert Chan Blue a
b)
black :: (Num a) => Colour a
black :: Colour a
black = Chan Red a -> Chan Green a -> Chan Blue a -> Colour a
forall a. Chan Red a -> Chan Green a -> Chan Blue a -> Colour a
RGB Chan Red a
forall a p. Num a => Chan p a
Chan.empty Chan Green a
forall a p. Num a => Chan p a
Chan.empty Chan Blue a
forall a p. Num a => Chan p a
Chan.empty
instance (Num a) => Semigroup (Colour a) where
(RGB Chan Red a
r1 Chan Green a
g1 Chan Blue a
b1) <> :: Colour a -> Colour a -> Colour a
<> (RGB Chan Red a
r2 Chan Green a
g2 Chan Blue a
b2) =
Chan Red a -> Chan Green a -> Chan Blue a -> Colour a
forall a. Chan Red a -> Chan Green a -> Chan Blue a -> Colour a
RGB (Chan Red a
r1 Chan Red a -> Chan Red a -> Chan Red a
forall a p. Num a => Chan p a -> Chan p a -> Chan p a
`Chan.add` Chan Red a
r2) (Chan Green a
g1 Chan Green a -> Chan Green a -> Chan Green a
forall a p. Num a => Chan p a -> Chan p a -> Chan p a
`Chan.add` Chan Green a
g2) (Chan Blue a
b1 Chan Blue a -> Chan Blue a -> Chan Blue a
forall a p. Num a => Chan p a -> Chan p a -> Chan p a
`Chan.add` Chan Blue a
b2)
instance (Num a) => Monoid (Colour a) where
mempty :: Colour a
mempty = Colour a
forall a. Num a => Colour a
black
mconcat :: [Colour a] -> Colour a
mconcat [Colour a]
l = Chan Red a -> Chan Green a -> Chan Blue a -> Colour a
forall a. Chan Red a -> Chan Green a -> Chan Blue a -> Colour a
RGB ([Chan Red a] -> Chan Red a
forall a p. Num a => [Chan p a] -> Chan p a
Chan.sum [Chan Red a]
lr) ([Chan Green a] -> Chan Green a
forall a p. Num a => [Chan p a] -> Chan p a
Chan.sum [Chan Green a]
lg) ([Chan Blue a] -> Chan Blue a
forall a p. Num a => [Chan p a] -> Chan p a
Chan.sum [Chan Blue a]
lb)
where
([Chan Red a]
lr,[Chan Green a]
lg,[Chan Blue a]
lb) = [(Chan Red a, Chan Green a, Chan Blue a)]
-> ([Chan Red a], [Chan Green a], [Chan Blue a])
forall a b c. [(a, b, c)] -> ([a], [b], [c])
unzip3 ((Colour a -> (Chan Red a, Chan Green a, Chan Blue a))
-> [Colour a] -> [(Chan Red a, Chan Green a, Chan Blue a)]
forall a b. (a -> b) -> [a] -> [b]
map Colour a -> (Chan Red a, Chan Green a, Chan Blue a)
forall a. Colour a -> (Chan Red a, Chan Green a, Chan Blue a)
toRGB [Colour a]
l)
toRGB :: Colour a -> (Chan Red a, Chan Green a, Chan Blue a)
toRGB (RGB Chan Red a
r Chan Green a
g Chan Blue a
b) = (Chan Red a
r,Chan Green a
g,Chan Blue a
b)
data Alpha = Alpha
data AlphaColour a = RGBA !(Colour a) !(Chan Alpha a) deriving (AlphaColour a -> AlphaColour a -> Bool
(AlphaColour a -> AlphaColour a -> Bool)
-> (AlphaColour a -> AlphaColour a -> Bool) -> Eq (AlphaColour a)
forall a. Eq a => AlphaColour a -> AlphaColour a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: AlphaColour a -> AlphaColour a -> Bool
$c/= :: forall a. Eq a => AlphaColour a -> AlphaColour a -> Bool
== :: AlphaColour a -> AlphaColour a -> Bool
$c== :: forall a. Eq a => AlphaColour a -> AlphaColour a -> Bool
Eq)
transparent :: (Num a) => AlphaColour a
transparent :: AlphaColour a
transparent = Colour a -> Chan Alpha a -> AlphaColour a
forall a. Colour a -> Chan Alpha a -> AlphaColour a
RGBA (Chan Red a -> Chan Green a -> Chan Blue a -> Colour a
forall a. Chan Red a -> Chan Green a -> Chan Blue a -> Colour a
RGB Chan Red a
forall a p. Num a => Chan p a
Chan.empty Chan Green a
forall a p. Num a => Chan p a
Chan.empty Chan Blue a
forall a p. Num a => Chan p a
Chan.empty) Chan Alpha a
forall a p. Num a => Chan p a
Chan.empty
alphaColourConvert :: (Fractional b, Real a) =>
AlphaColour a -> AlphaColour b
alphaColourConvert :: AlphaColour a -> AlphaColour b
alphaColourConvert (RGBA Colour a
c Chan Alpha a
a) = Colour b -> Chan Alpha b -> AlphaColour b
forall a. Colour a -> Chan Alpha a -> AlphaColour a
RGBA (Colour a -> Colour b
forall b a. (Fractional b, Real a) => Colour a -> Colour b
colourConvert Colour a
c) (Chan Alpha a -> Chan Alpha b
forall b a p. (Fractional b, Real a) => Chan p a -> Chan p b
Chan.convert Chan Alpha a
a)
opaque :: (Num a) => Colour a -> AlphaColour a
opaque :: Colour a -> AlphaColour a
opaque Colour a
c = Colour a -> Chan Alpha a -> AlphaColour a
forall a. Colour a -> Chan Alpha a -> AlphaColour a
RGBA Colour a
c Chan Alpha a
forall a p. Num a => Chan p a
Chan.full
dissolve :: (Num a) => a -> AlphaColour a -> AlphaColour a
dissolve :: a -> AlphaColour a -> AlphaColour a
dissolve a
o (RGBA Colour a
c Chan Alpha a
a) = Colour a -> Chan Alpha a -> AlphaColour a
forall a. Colour a -> Chan Alpha a -> AlphaColour a
RGBA (a -> Colour a -> Colour a
forall (f :: * -> *) a. (ColourOps f, Num a) => a -> f a -> f a
darken a
o Colour a
c) (a -> Chan Alpha a -> Chan Alpha a
forall a p. Num a => a -> Chan p a -> Chan p a
Chan.scale a
o Chan Alpha a
a)
withOpacity :: (Num a) => Colour a -> a -> AlphaColour a
Colour a
c withOpacity :: Colour a -> a -> AlphaColour a
`withOpacity` a
o = Colour a -> Chan Alpha a -> AlphaColour a
forall a. Colour a -> Chan Alpha a -> AlphaColour a
RGBA (a -> Colour a -> Colour a
forall (f :: * -> *) a. (ColourOps f, Num a) => a -> f a -> f a
darken a
o Colour a
c) (a -> Chan Alpha a
forall p a. a -> Chan p a
Chan a
o)
class AffineSpace f where
affineCombo :: (Num a) => [(a,f a)] -> f a -> f a
blend :: (Num a, AffineSpace f) => a -> f a -> f a -> f a
blend :: a -> f a -> f a -> f a
blend a
weight f a
c1 f a
c2 = [(a, f a)] -> f a -> f a
forall (f :: * -> *) a.
(AffineSpace f, Num a) =>
[(a, f a)] -> f a -> f a
affineCombo [(a
weight,f a
c1)] f a
c2
instance AffineSpace Colour where
affineCombo :: [(a, Colour a)] -> Colour a -> Colour a
affineCombo [(a, Colour a)]
l Colour a
z =
(Colour a -> Colour a -> Colour a) -> [Colour a] -> Colour a
forall a. (a -> a -> a) -> [a] -> a
foldl1' Colour a -> Colour a -> Colour a
forall a. Monoid a => a -> a -> a
mappend [a -> Colour a -> Colour a
forall (f :: * -> *) a. (ColourOps f, Num a) => a -> f a -> f a
darken a
w Colour a
a | (a
w,Colour a
a) <- (a
1a -> a -> a
forall a. Num a => a -> a -> a
-a
total,Colour a
z)(a, Colour a) -> [(a, Colour a)] -> [(a, Colour a)]
forall a. a -> [a] -> [a]
:[(a, Colour a)]
l]
where
total :: a
total = [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum ([a] -> a) -> [a] -> a
forall a b. (a -> b) -> a -> b
$ ((a, Colour a) -> a) -> [(a, Colour a)] -> [a]
forall a b. (a -> b) -> [a] -> [b]
map (a, Colour a) -> a
forall a b. (a, b) -> a
fst [(a, Colour a)]
l
instance AffineSpace AlphaColour where
affineCombo :: [(a, AlphaColour a)] -> AlphaColour a -> AlphaColour a
affineCombo [(a, AlphaColour a)]
l AlphaColour a
z =
(AlphaColour a -> AlphaColour a -> AlphaColour a)
-> [AlphaColour a] -> AlphaColour a
forall a. (a -> a -> a) -> [a] -> a
foldl1' AlphaColour a -> AlphaColour a -> AlphaColour a
forall a. Num a => AlphaColour a -> AlphaColour a -> AlphaColour a
rgbaAdd [a -> AlphaColour a -> AlphaColour a
forall a. Num a => a -> AlphaColour a -> AlphaColour a
dissolve a
w AlphaColour a
a | (a
w,AlphaColour a
a) <- (a
1a -> a -> a
forall a. Num a => a -> a -> a
-a
total,AlphaColour a
z)(a, AlphaColour a) -> [(a, AlphaColour a)] -> [(a, AlphaColour a)]
forall a. a -> [a] -> [a]
:[(a, AlphaColour a)]
l]
where
total :: a
total = [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum ([a] -> a) -> [a] -> a
forall a b. (a -> b) -> a -> b
$ ((a, AlphaColour a) -> a) -> [(a, AlphaColour a)] -> [a]
forall a b. (a -> b) -> [a] -> [b]
map (a, AlphaColour a) -> a
forall a b. (a, b) -> a
fst [(a, AlphaColour a)]
l
class ColourOps f where
over :: (Num a) => AlphaColour a -> f a -> f a
darken :: (Num a) => a -> f a -> f a
instance ColourOps Colour where
(RGBA (RGB Chan Red a
r0 Chan Green a
g0 Chan Blue a
b0) (Chan a
a0)) over :: AlphaColour a -> Colour a -> Colour a
`over` (RGB Chan Red a
r1 Chan Green a
g1 Chan Blue a
b1) =
Chan Red a -> Chan Green a -> Chan Blue a -> Colour a
forall a. Chan Red a -> Chan Green a -> Chan Blue a -> Colour a
RGB (Chan Red a -> a -> Chan Red a -> Chan Red a
forall a p. Num a => Chan p a -> a -> Chan p a -> Chan p a
Chan.over Chan Red a
r0 a
a0 Chan Red a
r1)
(Chan Green a -> a -> Chan Green a -> Chan Green a
forall a p. Num a => Chan p a -> a -> Chan p a -> Chan p a
Chan.over Chan Green a
g0 a
a0 Chan Green a
g1)
(Chan Blue a -> a -> Chan Blue a -> Chan Blue a
forall a p. Num a => Chan p a -> a -> Chan p a -> Chan p a
Chan.over Chan Blue a
b0 a
a0 Chan Blue a
b1)
darken :: a -> Colour a -> Colour a
darken a
s (RGB Chan Red a
r Chan Green a
g Chan Blue a
b) = Chan Red a -> Chan Green a -> Chan Blue a -> Colour a
forall a. Chan Red a -> Chan Green a -> Chan Blue a -> Colour a
RGB (a -> Chan Red a -> Chan Red a
forall a p. Num a => a -> Chan p a -> Chan p a
Chan.scale a
s Chan Red a
r)
(a -> Chan Green a -> Chan Green a
forall a p. Num a => a -> Chan p a -> Chan p a
Chan.scale a
s Chan Green a
g)
(a -> Chan Blue a -> Chan Blue a
forall a p. Num a => a -> Chan p a -> Chan p a
Chan.scale a
s Chan Blue a
b)
instance ColourOps AlphaColour where
c0 :: AlphaColour a
c0@(RGBA Colour a
_ a0 :: Chan Alpha a
a0@(Chan a
a0')) over :: AlphaColour a -> AlphaColour a -> AlphaColour a
`over` (RGBA Colour a
c1 Chan Alpha a
a1) =
Colour a -> Chan Alpha a -> AlphaColour a
forall a. Colour a -> Chan Alpha a -> AlphaColour a
RGBA (AlphaColour a
c0 AlphaColour a -> Colour a -> Colour a
forall (f :: * -> *) a.
(ColourOps f, Num a) =>
AlphaColour a -> f a -> f a
`over` Colour a
c1) (Chan Alpha a -> a -> Chan Alpha a -> Chan Alpha a
forall a p. Num a => Chan p a -> a -> Chan p a -> Chan p a
Chan.over Chan Alpha a
a0 a
a0' Chan Alpha a
a1)
darken :: a -> AlphaColour a -> AlphaColour a
darken a
s (RGBA Colour a
c Chan Alpha a
a) = Colour a -> Chan Alpha a -> AlphaColour a
forall a. Colour a -> Chan Alpha a -> AlphaColour a
RGBA (a -> Colour a -> Colour a
forall (f :: * -> *) a. (ColourOps f, Num a) => a -> f a -> f a
darken a
s Colour a
c) Chan Alpha a
a
instance (Num a) => Semigroup (AlphaColour a) where
<> :: AlphaColour a -> AlphaColour a -> AlphaColour a
(<>) = AlphaColour a -> AlphaColour a -> AlphaColour a
forall (f :: * -> *) a.
(ColourOps f, Num a) =>
AlphaColour a -> f a -> f a
over
instance (Num a) => Monoid (AlphaColour a) where
mempty :: AlphaColour a
mempty = AlphaColour a
forall a. Num a => AlphaColour a
transparent
atop :: (Fractional a) => AlphaColour a -> AlphaColour a -> AlphaColour a
atop :: AlphaColour a -> AlphaColour a -> AlphaColour a
atop (RGBA Colour a
c0 (Chan a
a0)) (RGBA Colour a
c1 (Chan a
a1)) =
Colour a -> Chan Alpha a -> AlphaColour a
forall a. Colour a -> Chan Alpha a -> AlphaColour a
RGBA (a -> Colour a -> Colour a
forall (f :: * -> *) a. (ColourOps f, Num a) => a -> f a -> f a
darken a
a1 Colour a
c0 Colour a -> Colour a -> Colour a
forall a. Monoid a => a -> a -> a
`mappend` a -> Colour a -> Colour a
forall (f :: * -> *) a. (ColourOps f, Num a) => a -> f a -> f a
darken (a
1a -> a -> a
forall a. Num a => a -> a -> a
-a
a0) Colour a
c1) (a -> Chan Alpha a
forall p a. a -> Chan p a
Chan a
a1)
quantize :: (RealFrac a1, Integral a, Bounded a) => a1 -> a
quantize :: a1 -> a
quantize a1
x | a1
x a1 -> a1 -> Bool
forall a. Ord a => a -> a -> Bool
<= a -> a1
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
l = a
l
| a -> a1
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
h a1 -> a1 -> Bool
forall a. Ord a => a -> a -> Bool
<= a1
x = a
h
| Bool
otherwise = a1 -> a
forall a b. (RealFrac a, Integral b) => a -> b
round a1
x
where
l :: a
l = a
forall a. Bounded a => a
minBound
h :: a
h = a
forall a. Bounded a => a
maxBound
alphaChannel :: AlphaColour a -> a
alphaChannel :: AlphaColour a -> a
alphaChannel (RGBA Colour a
_ (Chan a
a)) = a
a
colourChannel :: (Fractional a) => AlphaColour a -> Colour a
colourChannel :: AlphaColour a -> Colour a
colourChannel (RGBA Colour a
c (Chan a
a)) = a -> Colour a -> Colour a
forall (f :: * -> *) a. (ColourOps f, Num a) => a -> f a -> f a
darken (a -> a
forall a. Fractional a => a -> a
recip a
a) Colour a
c
rgbaAdd :: AlphaColour a -> AlphaColour a -> AlphaColour a
rgbaAdd (RGBA Colour a
c1 Chan Alpha a
a1) (RGBA Colour a
c2 Chan Alpha a
a2) =
Colour a -> Chan Alpha a -> AlphaColour a
forall a. Colour a -> Chan Alpha a -> AlphaColour a
RGBA (Colour a
c1 Colour a -> Colour a -> Colour a
forall a. Monoid a => a -> a -> a
`mappend` Colour a
c2) (Chan Alpha a
a1 Chan Alpha a -> Chan Alpha a -> Chan Alpha a
forall a p. Num a => Chan p a -> Chan p a -> Chan p a
`Chan.add` Chan Alpha a
a2)