prizm 0.2.1.0 → 0.3.0.0
raw patch · 9 files changed
+239/−79 lines, 9 filesdep +test-framework-hunit
Dependencies added: test-framework-hunit
Files
- CHANGES +11/−0
- prizm.cabal +6/−2
- src/Data/Prizm/Color/CIE.hs +8/−75
- src/Data/Prizm/Color/CIE/LAB.hs +64/−0
- src/Data/Prizm/Color/CIE/LAB.hs-boot +6/−0
- src/Data/Prizm/Color/CIE/LCH.hs +48/−0
- src/Data/Prizm/Color/CIE/LCH.hs-boot +6/−0
- src/Data/Prizm/Color/CIE/XYZ.hs +85/−0
- tests/QC/SRGB.hs +5/−2
CHANGES view
@@ -1,3 +1,14 @@+0.3.0.0+=======++- Separated the CIE representations out into their own modules so that+ I could implement their own convenience functions to go to/from all+ of the other different representations without arduous function+ chaining. Particularly for HEX/RGB -> LCH (involves around 5+ function calls!).+- Removed the Angle package.+- Fixed the tests to accomodate the API changes.+ 0.2.1.0 =======
prizm.cabal view
@@ -1,5 +1,5 @@ Name: prizm-Version: 0.2.1.0+Version: 0.3.0.0 Synopsis: A haskell library for computing with colors Description: Prizm can convert between many different color@@ -39,6 +39,9 @@ Data.Prizm.Color.Transform Data.Prizm.Color.SRGB Data.Prizm.Color.CIE+ Data.Prizm.Color.CIE.XYZ+ Data.Prizm.Color.CIE.LAB+ Data.Prizm.Color.CIE.LCH Data.Prizm.Color.Matrices.RGB Data.Prizm.Color.Matrices.XYZ @@ -62,4 +65,5 @@ base >= 4, QuickCheck >= 2.5, test-framework >= 0.8,- test-framework-quickcheck2 >= 0.3.0+ test-framework-quickcheck2 >= 0.3.0,+ test-framework-hunit >= 0.3.0
src/Data/Prizm/Color/CIE.hs view
@@ -1,27 +1,11 @@ module Data.Prizm.Color.CIE (- toRGB-, toRGBMatrix-, toLAB-, toXYZ-, toLCH-, lchToLAB+ v1+, v2+, refWhite+, transformXYZ ) where -import Control.Applicative--import Data.Angle--import Data.Prizm.Types-import Data.Prizm.Color.SRGB (clamp)-import Data.Prizm.Color.Transform-import Data.Prizm.Color.Matrices.XYZ---- 2deg observer, d65 illuminant--- [x,y,z]-refWhite :: [Double]-refWhite = [95.047, 100.000, 108.883]- -- | exact rational of the "0.008856" value. v1 :: Double v1 = (6/29) ** 3@@ -30,63 +14,12 @@ v2 :: Double v2 = 1/3 * ((29/6) ** 2) --- | @transformRGB@ transform an XYZ integer to be computed against--- the xyzToRGB matrix.-transformRGB :: Double -> Integer-transformRGB v | v > 0.0031308 = min (round ((1.055 * (v ** (1 / 2.4)) - 0.055) * 255)) 255- | otherwise = min (round ((12.92 * v) * 255)) 255--transformLAB :: Double -> Double-transformLAB v | v > v1 = v ** (1/3)- | otherwise = (v2 * v) + (16 / 116)--transformLCH :: Double -> Double-transformLCH v | v > 0 = (v / pi) * 180- | otherwise = 360 - ((abs v) / pi) * 180+-- 2deg observer, d65 illuminant+-- [x,y,z]+refWhite :: [Double]+refWhite = [95.047, 100.000, 108.883] transformXYZ :: Double -> Double transformXYZ v | cv > v1 = cv | otherwise = (v - 16 / 116) / v2 where cv = v**3---- | @toRGB@ convert a CIE color to an SRGB color.--- --- Once I've implemented CIE L*a*b -> XYZ and vice-versa functions--- then I'll introduce the type exhaustively here to handle any CIE--- color -> SRGB conversion.-toRGB :: CIEXYZ Double -> RGB Integer-toRGB = (toRGBMatrix d65SRGB)--toRGBMatrix :: XYZtoRGB -> CIEXYZ Double -> RGB Integer-toRGBMatrix (XYZtoRGB m) (CIEXYZ x y z) =- let t = ZipList ((/100) <$> [x,y,z])- [r,g,b] = (transformRGB) <$> ((zipTransform t) <$> m)- in (clamp) <$> RGB r g b--toLAB :: CIEXYZ Double -> CIELAB Double-toLAB (CIEXYZ x y z) =- let v = getZipList $ ZipList ((/) <$> [x,y,z]) <*> ZipList refWhite- [tx,ty,tz] = (transformLAB) <$> v- l = (116 * ty) - 16- a = 500 * (tx - ty)- b = 200 * (ty - tz)- in CIELAB l a b--toLCH :: CIELAB Double -> CIELCH Double-toLCH (CIELAB l a b) =- let h = transformLCH (atan2 b a)- c = sqrt ((a^2) + (b^2))- in CIELCH l c h--lchToLAB :: CIELCH Double -> CIELAB Double-lchToLAB (CIELCH l c h) =- let v = h * pi / 180- in CIELAB l ((cos v)*c) ((sin v)*c)--toXYZ :: CIELAB Double -> CIEXYZ Double-toXYZ (CIELAB l a b) =- let y = (l + 16) / 116- x = a / 500 + y- z = y - b / 200- [nx,ny,nz] = getZipList $ ((*) <$> ZipList ((transformXYZ) <$> [x,y,z])) <*> ZipList refWhite- in CIEXYZ nx ny nz
+ src/Data/Prizm/Color/CIE/LAB.hs view
@@ -0,0 +1,64 @@+module Data.Prizm.Color.CIE.LAB+(+ toLCH+, toXYZ+, toRGB+, toHex+, fromXYZ+, fromRGB+, fromHex+, fromLCH+) where++import Control.Applicative++import Data.Prizm.Types+import Data.Prizm.Color.CIE (refWhite, transformXYZ)++import qualified Data.Prizm.Color.SRGB as S+import qualified Data.Prizm.Color.CIE.XYZ as X+import {-# SOURCE #-} qualified Data.Prizm.Color.CIE.LCH as LC++transformLCH :: Double -> Double+transformLCH v | v > 0 = (v / pi) * 180+ | otherwise = 360 - ((abs v) / pi) * 180++-- | @toLCH@ convert a LAB color to the LCH representation.+toLCH :: CIELAB Double -> CIELCH Double+toLCH (CIELAB l a b) =+ let h = transformLCH (atan2 b a)+ c = sqrt ((a^2) + (b^2))+ in CIELCH l c h++-- | @fromLCH@ convert a LCH color to the LAB representation.+fromLCH :: CIELCH Double -> CIELAB Double+fromLCH = LC.toLAB++-- | @toXYZ@ convert a LAB color to the XYZ representation.+toXYZ :: CIELAB Double -> CIEXYZ Double+toXYZ (CIELAB l a b) =+ let y = (l + 16) / 116+ x = a / 500 + y+ z = y - b / 200+ [nx,ny,nz] = getZipList $ ((*) <$> ZipList ((transformXYZ) <$> [x,y,z])) <*> ZipList refWhite+ in CIEXYZ nx ny nz++-- | @fromXYZ@ convert an XYZ color straight to LAB.+fromXYZ :: CIEXYZ Double -> CIELAB Double+fromXYZ = X.toLAB++-- | @toRGB@ convenience function for converting straight to RGB.+toRGB :: CIELAB Double -> RGB Integer+toRGB = X.toRGB . toXYZ++-- | @fromRGB@ convenience function for converting to LAB from RGB.+fromRGB :: RGB Integer -> CIELAB Double+fromRGB = X.toLAB . S.toXYZ++-- | @toHex@ convenience function for converting straight to HEX.+toHex :: CIELAB Double -> Hex+toHex = X.toHex . toXYZ++-- | @fromHex@ convenience function for converting to LAB from HEX.+fromHex :: Hex -> CIELAB Double+fromHex = X.toLAB . X.fromHex
+ src/Data/Prizm/Color/CIE/LAB.hs-boot view
@@ -0,0 +1,6 @@+module Data.Prizm.Color.CIE.LAB where++import Data.Prizm.Types++toXYZ :: CIELAB Double -> CIEXYZ Double+toLCH :: CIELAB Double -> CIELCH Double
+ src/Data/Prizm/Color/CIE/LCH.hs view
@@ -0,0 +1,48 @@+module Data.Prizm.Color.CIE.LCH+(+ toRGB+, toLAB+, toXYZ+, toHex+, fromRGB+, fromHex+, fromLAB+, fromXYZ+) where++import Data.Prizm.Types++import qualified Data.Prizm.Color.CIE.LAB as LB+import qualified Data.Prizm.Color.CIE.XYZ as X++-- | @toLAB@ convert an LCH color to a LAB representation.+toLAB :: CIELCH Double -> CIELAB Double+toLAB (CIELCH l c h) =+ let v = h * pi / 180+ in CIELAB l ((cos v)*c) ((sin v)*c)++-- | @fromLAB@ convenience function for converting from LAB to LCH.+fromLAB :: CIELAB Double -> CIELCH Double+fromLAB = LB.toLCH++-- | @toXYZ@ convert from LCH to XYZ.+toXYZ :: CIELCH Double -> CIEXYZ Double+toXYZ = LB.toXYZ . toLAB++-- | @fromXYZ@ convert from XYZ to LCH.+fromXYZ :: CIEXYZ Double -> CIELCH Double+fromXYZ = X.toLCH++-- | @toRGB@ convert from LCH to RGB.+toRGB :: CIELCH Double -> RGB Integer+toRGB = X.toRGB . toXYZ++-- | @fromRGB@ convert from RGB to LCH.+fromRGB :: RGB Integer -> CIELCH Double+fromRGB = fromLAB . LB.fromRGB++toHex :: CIELCH Double -> Hex+toHex = LB.toHex . toLAB++fromHex :: Hex -> CIELCH Double+fromHex = LB.toLCH . LB.fromHex
+ src/Data/Prizm/Color/CIE/LCH.hs-boot view
@@ -0,0 +1,6 @@+module Data.Prizm.Color.CIE.LCH where++import Data.Prizm.Types++toXYZ :: CIELCH Double -> CIEXYZ Double+toLAB :: CIELCH Double -> CIELAB Double
+ src/Data/Prizm/Color/CIE/XYZ.hs view
@@ -0,0 +1,85 @@+module Data.Prizm.Color.CIE.XYZ+(+ toRGB+, toRGBMatrix+, toLAB+, toLCH+, toHex+, fromRGB+, fromHex+, fromLAB+, fromLCH+) where++import Control.Applicative++import Data.Prizm.Types++import Data.Prizm.Color.Transform+import Data.Prizm.Color.Matrices.XYZ+import Data.Prizm.Color.CIE (v1, v2, refWhite)++import qualified Data.Prizm.Color.SRGB as S+import {-# SOURCE #-} qualified Data.Prizm.Color.CIE.LAB as LB+import {-# SOURCE #-} qualified Data.Prizm.Color.CIE.LCH as LC+++-- | @transformRGB@ transform an XYZ integer to be computed against+-- the xyzToRGB matrix.+transformRGB :: Double -> Integer+transformRGB v | v > 0.0031308 = min (round ((1.055 * (v ** (1 / 2.4)) - 0.055) * 255)) 255+ | otherwise = min (round ((12.92 * v) * 255)) 255++transformLAB :: Double -> Double+transformLAB v | v > v1 = v ** (1/3)+ | otherwise = (v2 * v) + (16 / 116)++-- | @toRGB@ convert a CIE color to an SRGB color.+-- +-- This function uses the default d65 illuminant matrix.+toRGB :: CIEXYZ Double -> RGB Integer+toRGB = (toRGBMatrix d65SRGB)++-- | @toRGBMatrix@ convert an XYZ color to an SRGB color using a+-- provided matrix.+toRGBMatrix :: XYZtoRGB -> CIEXYZ Double -> RGB Integer+toRGBMatrix (XYZtoRGB m) (CIEXYZ x y z) =+ let t = ZipList ((/100) <$> [x,y,z])+ [r,g,b] = (transformRGB) <$> ((zipTransform t) <$> m)+ in (S.clamp) <$> RGB r g b++-- | @fromRGB@ convenience function for converting to XYZ from RGB.+fromRGB :: RGB Integer -> CIEXYZ Double+fromRGB = S.toXYZ++-- | @toHex@ convenience function for converting XYZ straight to HEX.+toHex :: CIEXYZ Double -> Hex+toHex = S.toHex . toRGB++-- | @fromHex@ convenience function for converting to XYZ from HEX.+fromHex :: Hex -> CIEXYZ Double+fromHex = S.toXYZ . S.fromHex++-- | @toLAB@ convert an XYZ color to a LAB color.+-- +-- This function uses the default reference white (2deg observer, d65+-- illuminant).+toLAB :: CIEXYZ Double -> CIELAB Double+toLAB (CIEXYZ x y z) =+ let v = getZipList $ ZipList ((/) <$> [x,y,z]) <*> ZipList refWhite+ [tx,ty,tz] = (transformLAB) <$> v+ l = (116 * ty) - 16+ a = 500 * (tx - ty)+ b = 200 * (ty - tz)+ in CIELAB l a b++-- | @fromLAB@ convenience function for converting to XYZ from LAB.+fromLAB :: CIELAB Double -> CIEXYZ Double+fromLAB = LB.toXYZ++-- | @toLCH@ convenience function for converting XYZ straight to LAB.+toLCH :: CIEXYZ Double -> CIELCH Double+toLCH = LB.toLCH . toLAB++fromLCH :: CIELCH Double -> CIEXYZ Double+fromLCH = LC.toXYZ
tests/QC/SRGB.hs view
@@ -10,13 +10,16 @@ import Control.Monad import Data.Prizm.Color.SRGB as S-import Data.Prizm.Color.CIE as C+import Data.Prizm.Color.CIE.XYZ as X import Data.Prizm.Types instance Arbitrary (RGB Integer) where arbitrary = liftM3 RGB (choose (0, 255)) (choose (0, 255)) (choose (0, 255)) -rgb2XYZ v = C.toRGB(S.toXYZ v) == v+rgb2XYZ :: RGB Integer -> Bool+rgb2XYZ v = X.toRGB(S.toXYZ v) == v++rgb2HEX :: RGB Integer -> Bool rgb2HEX v = S.fromHex(S.toHex v) == v tests = [