AC-Colour-1.1.1: Data/Colour/Double.hs
{- |
This module provides 'Colour', which stores RGB (red, green, blue)
colour values where each channel is a @Double@. It also provides
arithmetic over such colours, and a few predefined colours.
-}
module Data.Colour.Double where
{- |
The @Colour@ type. Stores a red, a green and a blue component as
strict, unboxed @Double@ values. (So it should be quite efficient
in time and space.) Also provides various class instances for
arithmetic, etc. It is generally assumed that each channel will
have a value somewhere between 0 and 1 at all times.
Note that @(*)@ acts channel-wise. This is usually what is wanted.
-}
data Colour = Colour {red, green, blue :: {-# UNPACK #-} !Double}
deriving (Eq, Ord, Show)
{- |
Apply a function to every channel in a colour. (Mostly used
internally, but exposed here in case it may be useful.)
-}
cmap :: (Double -> Double) -> Colour -> Colour
cmap f (Colour r g b) = Colour (f r) (f g) (f b)
{- |
This is similar to 'Data.List.zipWith'. (Mostly used internally,
but exposed here in case it may be useful.)
-}
czip :: (Double -> Double -> Double) -> Colour -> Colour -> Colour
czip f (Colour r1 g1 b1) (Colour r2 g2 b2) = Colour (f r1 r2) (f g1 g2) (f b1 b2)
{- |
Use a function to collapse a @Colour@ into a @Double@. No
particular order of application is promised.
-}
cfold :: (Double -> Double -> Double) -> Colour -> Double
cfold f (Colour r g b) = f r (f g b)
{- | Turn a @Double@ into a shade of grey. -}
grey :: Double -> Colour
grey x = Colour x x x
{- |
Scale a @Colour@ by a specified amount. (That is, change the
brightness while not affecting the shade.)
-}
cscale :: Double -> Colour -> Colour
cscale x = cmap (x*)
instance Num Colour where
(+) = czip (+)
(-) = czip (-)
(*) = czip (*)
negate = cmap negate
abs = cmap abs
signum = cmap signum
fromInteger = grey . fromInteger
instance Fractional Colour where
(/) = czip (/)
recip = cmap recip
fromRational = grey . fromRational
{- |
Take a @Colour@ and clip all channels to the range 0--1
inclusive. Any value outside that range will be replaced
with the nearest endpoint (i.e., 0 for negative numbers,
1 for positive numbers higher than 1). Values inside
the range are unaffected.
-}
clip :: Colour -> Colour
clip = cmap (min 1 . max 0)
-- | Constant: Black.
cBlack :: Colour
cBlack = Colour 0 0 0
-- | Constant: Red.
cRed :: Colour
cRed = Colour 1 0 0
-- | Constant: Yellow.
cYellow :: Colour
cYellow = Colour 1 1 0
-- | Constant: Green.
cGreen :: Colour
cGreen = Colour 0 1 0
-- | Constant: Cyan.
cCyan :: Colour
cCyan = Colour 0 1 1
-- | Constant: Blue.
cBlue :: Colour
cBlue = Colour 0 0 1
-- | Constant: Magenta.
cMagenta :: Colour
cMagenta = Colour 1 0 1
-- | Constant: White.
cWhite :: Colour
cWhite = Colour 1 1 1