packages feed

AC-Colour 1.1.3 → 1.1.4

raw patch · 6 files changed

+132/−34 lines, 6 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Data.Colour.Nonlinear: Colour8_sRGB :: Colour8 -> Colour8_sRGB
+ Data.Colour.Nonlinear: Colour_sRGB :: Colour -> Colour_sRGB
+ Data.Colour.Nonlinear: cdemote_sRGB :: Colour_sRGB -> Colour8_sRGB
+ Data.Colour.Nonlinear: colour_from_sRGB :: Colour_sRGB -> Colour
+ Data.Colour.Nonlinear: colour_to_sRGB :: Colour -> Colour_sRGB
+ Data.Colour.Nonlinear: cpromote_sRGB :: Colour8_sRGB -> Colour_sRGB
+ Data.Colour.Nonlinear: instance Eq Colour8_sRGB
+ Data.Colour.Nonlinear: instance Eq Colour_sRGB
+ Data.Colour.Nonlinear: instance Ord Colour8_sRGB
+ Data.Colour.Nonlinear: instance Ord Colour_sRGB
+ Data.Colour.Nonlinear: instance Show Colour8_sRGB
+ Data.Colour.Nonlinear: instance Show Colour_sRGB
+ Data.Colour.Nonlinear: newtype Colour8_sRGB
+ Data.Colour.Nonlinear: newtype Colour_sRGB

Files

AC-Colour.cabal view
@@ -1,6 +1,6 @@ Cabal-Version: >= 1.6
 Name:          AC-Colour
-Version:       1.1.3
+Version:       1.1.4
 Stability:     Experimental
 Synopsis:      Efficient RGB colour types.
 
@@ -10,12 +10,12 @@   both @Double@ and @Word8@ channel types. It implements
   efficient conversions between the two (GHC-specific),
   and general arithmetic over colours.
-
+  .
   Changes:
-
-  * Added (linear) colour map support.
-
-  * Added pack/unpack functions.
+  .
+  * Added sRGB support.
+  .
+  * Minor documentation improvements.
 
 Category:      Data, Math, Numerical, Graphics
 License:       BSD3
@@ -23,9 +23,15 @@ Author:        Andrew Coppin
 Maintainer:    MathematicalOrchid@hotmail.com
 Build-Type:    Simple
-Tested-With:   GHC == 6.10.3
+Tested-With:   GHC == 7.0.2
 
 Library
-  Exposed-modules: Data.Colour.Double, Data.Colour.Map, Data.Colour.Word8, Data.Colour.FastFloor, Data.Colour
+  Exposed-modules:
+    Data.Colour.Double
+    Data.Colour.Map
+    Data.Colour.Word8
+    Data.Colour.Nonlinear
+    Data.Colour.FastFloor
+    Data.Colour
   Build-Depends:   base >= 4 && < 5, ghc-prim >= 0.1.0.0 && < 0.3
   HS-Source-Dirs:  .
Data/Colour.hs view
@@ -8,6 +8,11 @@   However, full arithmetic on 'Colour8' is supported anyway,
   in case anybody wants to work that way. It is slightly less
   efficient and flexible, however.
+
+  Note that most colour values from external sources are typically
+  colour values in the non-linear sRGB colour space, rather than the
+  linear RGB values handled here. See "Data.Colour.Nonlinear" for
+  conversion functions.
 -}
 
 module Data.Colour
Data/Colour/Double.hs view
@@ -1,19 +1,24 @@ {- |
-  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.
+  This module provides 'Colour', which stores linear 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.
+  The main colour type. It stores three channels (red, green and
+  blue) as linear 'Double' values normally ranging from 0 to 1.
+  (0 represents minimum intensity, 1 represents maximum. Black is
+  therefore @Colour 0 0 0@ and white is @Colour 1 1 1@.)
 
-  Note that @(*)@ acts channel-wise. This is usually what is wanted.
+  The channel values are stored as strict, unboxed fields, so
+  operating on @Colour@s should be quite efficient in time and space.
+
+  The 'Num' and 'Fractional' instances provide arithmetic for
+  @Colour@s. Note that @(*)@ acts channel-wise; this is usually what
+  is wanted.
 -}
 data Colour = Colour {red, green, blue :: {-# UNPACK #-} !Double}
   deriving (Eq, Ord, Show)
@@ -74,9 +79,11 @@ clip :: Colour -> Colour
 clip = cmap (min 1 . max 0)
 
+-- | Convert a 'Colour' into a tuple.
 unpack :: Colour -> (Double, Double, Double)
 unpack (Colour r g b) = (r, g, b)
 
+-- | Convert a tuple into a 'Colour'.
 pack :: (Double, Double, Double) -> Colour
 pack (r, g, b) = Colour r g b
 
Data/Colour/Map.hs view
@@ -5,8 +5,13 @@ 
 module Data.Colour.Map
     (
+      -- * Utility
       range_cycle,
+
+      -- * Simple colour range
       ColourMap, colour_map,
+
+      -- * Repeating colour range
       FullColourMap (..), full_colour_map
     )
   where
@@ -71,8 +76,11 @@     in (1-k) `cscale` c0 + k `cscale` c1
 
 {- |
-  This is a colour map with has optional repeating behaviour
-  using 'range_cycle' above.
+  This is a colour map with has optional repeating behaviour using
+  'range_cycle' above.
+
+  Notice that the parameter range that gets repeated need not cover
+  the entire range of the underlying 'ColourMap'.
 -}
 data FullColourMap =
   SimpleMap                    ColourMap | -- ^ Colour map which does not repeat.
+ Data/Colour/Nonlinear.hs view
@@ -0,0 +1,62 @@+{- |
+  Support for the \"sRGB\" colour space.
+
+  This colour space is the /de facto/ standard colour space for
+  computer data, unless some more specific colour space is explicitly
+  specified. Unless you know differently, any image data received
+  from the outside world is probably sRGB, and and data output is
+  probably expected to be sRGB.
+
+  Unfortunately, sRGB is a non-linear colour space, so it is not
+  feasible to perform arithmetic in it directly. (The sRGB colour
+  space basically standardises the defective non-linear behaviour of
+  obsolete CRT display technology.)
+-}
+
+module Data.Colour.Nonlinear where
+
+import Data.Word (Word8) -- For Haddock.
+
+import Data.Colour
+
+-- * Types
+
+{- |
+  Type for holding sRGB colour values (with 'Double' components).
+
+  The standard 'Colour' type is for /linear/ RGB values. This type
+  is for sRGB colours, which are non-linear.
+-}
+newtype Colour_sRGB = Colour_sRGB Colour deriving (Eq, Ord, Show)
+
+{- |
+  Type for holding sRGB colour values (with 'Word8' components).
+
+  The standard 'Colour8' type is for /linear/ RGB values. This type
+  is for sRGB colours, which are non-linear.
+-}
+newtype Colour8_sRGB = Colour8_sRGB Colour8 deriving (Eq, Ord, Show)
+
+-- * Conversions
+
+-- | Convert a linear RGB value into a non-linear sRGB value.
+colour_to_sRGB :: Colour -> Colour_sRGB
+colour_to_sRGB (Colour r g b) = Colour_sRGB (Colour (f r) (f g) (f b))
+  where
+    f :: Double -> Double
+    f x = if x <= 0.0031308 then 12.92 * x else 1.055 * (x ** (1 / 2.4)) - 0.055
+
+-- | Convert from 'Double' components to 'Word8' components.
+cdemote_sRGB :: Colour_sRGB -> Colour8_sRGB
+cdemote_sRGB (Colour_sRGB c) = Colour8_sRGB (cdemote c)
+
+-- | Convert from 'Word8' components to 'Double' components.
+cpromote_sRGB :: Colour8_sRGB -> Colour_sRGB
+cpromote_sRGB (Colour8_sRGB c) = Colour_sRGB (cpromote c)
+
+-- | Convert a non-linear sRGB value into a linear RGB value.
+colour_from_sRGB :: Colour_sRGB -> Colour
+colour_from_sRGB (Colour_sRGB (Colour r g b)) = Colour (f r) (f g) (f b)
+  where
+    f :: Double -> Double
+    f x = if x <= 0.04045 then x / 12.92 else ((x + 0.055)/1.055) ** 2.4
Data/Colour/Word8.hs view
@@ -1,13 +1,18 @@ {- |
-  This module provides 'Colour8', which stores RGB (red, green, blue)
-  colour values where each channel is a @Word8@. It also provides
-  arithmetic over such colours, and a few predefined colours.
+  This module provides 'Colour8', which stores linear RGB (red,
+  green, blue) colour values where each channel is a @Word8@. It also
+  provides arithmetic over such colours, and a few predefined
+  colours.
 
   It is the general intention that \"most\" work will be done with
-  "Data.Colour.Double", with values converted to @Colour8@ only
-  as a final step. However, full arithmetic is supported anyway,
-  in case anybody wants to work that way. It is slightly less
-  efficient and flexible, however.
+  "Data.Colour.Double", with values converted to @Colour8@ only as a
+  final step. However, full arithmetic is supported anyway, in case
+  anybody wants to work that way. It is slightly less efficient and
+  flexible, however.
+
+  Beware that \"most\" RGB data found in external sources is in the
+  (non-linear) sRGB colour space, not the /linear/ RGB colour space
+  used here. See "Data.Colour.Nonlinear" for conversion functions.
 -}
 
 module Data.Colour.Word8 where
@@ -15,15 +20,18 @@ import Data.Word
 
 {- |
-  The @Colour@ type. Stores a red, a green and a blue component as
-  strict, unboxed @Word8@ values. (So it should be quite efficient
-  in time and space.) Also provides various class instances for
-  arithmetic, etc.
+  The integral colour. It stores three channels (red, green and
+  blue) as linear 'Word8' values ranging from 0 to 255. (0 represents
+  minimum intensity, 255 represents maximum. Black is therefore
+  @Colour8 0 0 0@ and white is @Colour8 255 255 255@.)
 
-  Note that 0x00 is assumed to mean zero, and 0xFF to mean one.
-  That means that @(*)@ is slightly slower than you might expect
-  due to the extra steps required for renormalisation; @(+)@ and
-  @(-)@ are still efficient, however.
+  The channel values are stored as strict, unboxed fields, so
+  operating on @Colour8@s should be quite efficient in time and
+  space.
+
+  The 'Num' and 'Fractional' instances provide arithmetic for
+  @Colour8@s. Note that @(*)@ acts channel-wise; this is usually what
+  is wanted.
 -}
 data Colour8 = Colour8 {red8, green8, blue8 :: {-# UNPACK #-} !Word8}
   deriving (Eq, Ord, Show)
@@ -72,9 +80,11 @@   signum = c8map signum
   fromInteger = grey8 . fromInteger
 
+-- | Convert a 'Colour8' to a tuple.
 unpack8 :: Colour8 -> (Word8, Word8, Word8)
 unpack8 (Colour8 r g b) = (r,g,b)
 
+-- | Convert a tuple to a 'Colour8'.
 pack8 :: (Word8, Word8, Word8) -> Colour8
 pack8 (r,g,b) = Colour8 r g b