packages feed

hcg-minus-0.16: Data/CG/Minus/Colour.hs

-- | Colour related functions
module Data.CG.Minus.Colour where

import Data.Bits {- base -}
import qualified Data.Colour as C {- colour -}
import qualified Data.Colour.SRGB as SRGB {- colour -}
import qualified Data.Colour.RGBSpace.HSL as HSL {- colour -}

-- | Grey 'Colour'.
mk_grey :: (Ord a,Floating a) => a -> C.Colour a
mk_grey x = SRGB.sRGB x x x

-- | Reduce 'Colour' to grey.  Constants are @0.3@, @0.59@ and @0.11@.
to_greyscale :: (Ord a,Floating a) => C.Colour a -> a
to_greyscale c =
    let (SRGB.RGB r g b) = SRGB.toSRGB c
    in r * 0.3 + g * 0.59 + b * 0.11

-- | 'mk_grey' '.' 'to_greyscale'.
to_greyscale_c :: (Ord a,Floating a) => C.Colour a -> C.Colour a
to_greyscale_c = mk_grey . to_greyscale

-- | Discard /alpha/ channel, if possible.
pureColour :: (Ord a, Fractional a) => C.AlphaColour a -> C.Colour a
pureColour c =
    let a = C.alphaChannel c
    in if a > 0
       then C.darken (recip a) (c `C.over` C.black)
       else error "hcg-: transparent has no pure colour"

-- * Tuples

-- > hex_to_rgb24 0xC80815 == (0xC8,0x08,0x15)
hex_to_rgb24 :: (Bits t, Num t) => t -> (t,t,t)
hex_to_rgb24 n = (shiftR (n .&. 0xFF0000) 16,shiftR (n .&. 0x00FF00) 8,n .&. 0x0000FF)

srgb_components :: SRGB.RGB t -> (t,t,t)
srgb_components c = (SRGB.channelRed c,SRGB.channelGreen c,SRGB.channelBlue c)

-- | 'C' to /(red,green,blue)/ tuple.
c_to_rgb :: (Ord t,Floating t) => C.Colour t -> (t,t,t)
c_to_rgb = srgb_components . SRGB.toSRGB

-- | Tuple to 'C', inverse of 'c_to_rgb'.
rgb_to_c :: (Ord t,Floating t) => (t,t,t) -> C.Colour t
rgb_to_c (r,g,b) = SRGB.sRGB r g b

-- > rgb24_to_c ((0xC8,0x08,0x15) :: (Int,Int,Int))
rgb24_to_c :: (Real r,Ord t,Floating t) => (r, r, r) -> C.Colour t
rgb24_to_c (r,g,b) = rgb_to_c (realToFrac r / 255,realToFrac g / 255,realToFrac b / 255)

c_to_hsl :: (Ord t,Floating t) => C.Colour t -> (t,t,t)
c_to_hsl c = HSL.hslView (SRGB.toSRGB c)

hsl_to_c :: (RealFrac t,Floating t) => (t,t,t) -> C.Colour t
hsl_to_c (h,s,l) = rgb_to_c (srgb_components (HSL.hsl h s l))

-- > rgb_to_hsl (1,0,0) == (0,1,0.5)
rgb_to_hsl :: (Ord t,Floating t) => (t,t,t) -> (t,t,t)
rgb_to_hsl = c_to_hsl . rgb_to_c

-- > hsl_to_rgb (0,1,0.5) == (1,0,0)
hsl_to_rgb :: (RealFrac t,Floating t) => (t,t,t) -> (t,t,t)
hsl_to_rgb = c_to_rgb . hsl_to_c

-- | Tuple to 'Ca', inverse of 'c_to_rgba'.
rgba_to_ca :: (Ord t,Floating t) => (t,t,t,t) -> C.AlphaColour t
rgba_to_ca (r,g,b,a) = rgb_to_c (r,g,b) `C.withOpacity` a

rgb_to_ca :: (Ord t,Floating t) => (t,t,t) -> C.AlphaColour t
rgb_to_ca (r,g,b) = rgb_to_c (r,g,b) `C.withOpacity` 1

-- | 'Ca' to /(red,green,blue,alpha)/ tuple
ca_to_rgba :: (Ord t,Floating t) => C.AlphaColour t -> (t,t,t,t)
ca_to_rgba x =
    let x' = SRGB.toSRGB (pureColour x)
    in (SRGB.channelRed x'
       ,SRGB.channelGreen x'
       ,SRGB.channelBlue x'
       ,C.alphaChannel x)

-- | Is the /alpha/ channel zero.
ca_is_transparent :: (Ord t, Num t) => C.AlphaColour t -> Bool
ca_is_transparent x = not (C.alphaChannel x > 0)