packages feed

colour 2.3.6 → 2.3.7

raw patch · 6 files changed

+180/−12 lines, 6 filesdep +HUnitdep +test-framework-hunitdep ~QuickCheckdep ~randomPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies added: HUnit, test-framework-hunit

Dependency ranges changed: QuickCheck, random

API changes (from Hackage documentation)

+ Data.Colour.Ok: okLCh :: Floating a => a -> a -> a -> Colour a
+ Data.Colour.Ok: okLChView :: RealFloat a => Colour a -> (a, a, a)
+ Data.Colour.Ok: okLab :: Floating a => a -> a -> a -> Colour a
+ Data.Colour.Ok: okLabView :: Floating a => Colour a -> (a, a, a)
- Data.Colour: class AffineSpace f
+ Data.Colour: class AffineSpace (f :: Type -> Type)
- Data.Colour: class ColourOps f
+ Data.Colour: class ColourOps (f :: Type -> Type)

Files

CHANGELOG view
@@ -1,3 +1,8 @@+New in version 2.3.7:+- Removed uses of head and tail.+- Updated dependencies (for testing).+- Added support for Oklab and Oklch colour spaces from kqr.+ New in version 2.3.6: - Minimum base of 4.13. - Locked down non-colour imports.
Data/Colour.hs view
@@ -34,6 +34,8 @@ -- -- - "Data.Colour.CIE" --+-- - "Data.Colour.Ok"+-- -- Colours can be specified in a generic 'Data.Colour.RGBSpace.RGBSpace' -- by using --
+ Data/Colour/Ok.hs view
@@ -0,0 +1,125 @@+{-+Copyright (c) 2008, 2009, 2026+Russell O'Connor, Christoffer Stjernlöf++Permission is hereby granted, free of charge, to any person obtaining a copy+of this software and associated documentation files (the "Software"), to deal+in the Software without restriction, including without limitation the rights+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+copies of the Software, and to permit persons to whom the Software is+furnished to do so, subject to the following conditions:++The above copyright notice and this permission notice shall be included in+all copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN+THE SOFTWARE.+-}+-- | Functions for converting 'Colour' values to and from the Oklab space, and+-- convenience functions for the derived Oklch space.+-- See <https://bottosson.github.io/posts/oklab/>.+module Data.Colour.Ok+ (okLab, okLabView+ ,okLCh, okLChView+ )+where++import Data.Complex (Complex((:+)), magnitude, mkPolar, phase)+import Data.Fixed (mod')++import Data.Colour.CIE+import Data.Colour.CIE.Illuminant+import Data.Colour.Matrix++-- |Returns the Oklab coordinates of a colour, which is a+-- perceptually uniform colour space inspired by CIELAB+-- but which handles blue hues more accurately.+--+-- A white point is not specified because Oklab assumes+-- a standard 'd65' daylight illuminant.+okLabView :: Floating a => Colour a -> (a,a,a)+okLabView colour = (l,a,b)+ where+  (x,y,z) = cieXYZView colour+  lms = mult okM1 [x,y,z]+  cbrt v = signum v * (abs v)**(1/3)+  lms' = map cbrt lms+  [l,a,b] = mult (inverse okM2inv) lms'++-- |Returns the colour for given Oklab coordinates, which+-- is a perceptually uniform colour space inspired by+-- CIELAB but which handles blue hues more accurately.+--+-- A white point is not specified because Oklab assumes+-- a standard 'd65' daylight illuminant.+okLab :: Floating a => a -- ^L* coordinate (lightness)+                    -> a -- ^a* coordinate+                    -> a -- ^b* coordinate+                    -> Colour a+okLab l a b = cieXYZ x y z+ where+  lms' = mult okM2inv [l, a, b]+  lms = map (**3) lms'+  [x,y,z] = mult (inverse okM1) lms++-- |Returns the Oklab LCh coordinates of a colour. The+-- lightness coordinate is the same as in Oklab, while+-- the chroma C and hue h are the (a,b)-coordinates+-- expressed in polar form.+okLChView :: RealFloat a => Colour a -> (a,a,a)+okLChView colour = (l,c, h `mod'` 360)+ where+  (l,a,b) = okLabView colour+  z = a :+ b+  c = magnitude z+  h = phase z * 180 / pi++-- |Constructs a colour from a lightness, chroma, and+-- hue given in LCh polar coordinates correspondong to+-- an Oklab coordinate.+okLCh :: Floating a => a -- ^L* coordinate (lightness)+                    -> a -- ^C* coordinate (chroma)+                    -> a -- ^h* coordinate (hue)+                    -> Colour a+okLCh l c h = okLab l a b+ where+  (a :+ b) = mkPolar c (h * pi / 180)++--------------------------------------------------------------------------+{- not for export -}++-- |Converts XYZ coordinates to approximate human cone responses.+-- See <https://github.com/color-js/color.js/blob/6b487db289f7c41b78d2933d9cb83bf8c06f3c5e/scripts/oklab_matrix_maker.py>+oklms ::  Fractional a => Chromaticity a -- ^White point+                       -> [[a]]+oklms white_ch = zipWith f m0 lmsWhite+ where+  white = chromaColour white_ch 1.0+  (xw,yw,zw) = cieXYZView white+  lmsWhite = mult m0 [xw, yw, zw]+  f v w = (/w) <$> v+  m0 = [[0.77849780, 0.34399940, -0.12249720]+       ,[0.03303601, 0.93076195, 0.03620204]+       ,[0.05092917, 0.27933344, 0.66973739]+       ]++-- |The M1 matrix from the Oklab specification. This converts XYZ coordinates+-- to approximate human cone responses.+okM1 :: Fractional a => [[a]]+okM1 = oklms d65++-- |The inverse M2 matrix from the Oklab specification. This converts+-- perceptually uniform LAB coordinates into+-- non-linearly-transformed (l', m', s') coordinates.+-- See <https://github.com/color-js/color.js/blob/6b487db289f7c41b78d2933d9cb83bf8c06f3c5e/scripts/oklab_matrix_maker.py>+okM2inv :: Fractional a => [[a]]+okM2inv =+ [[1.0, 0.3963377774, 0.2158037573]+ ,[1.0, -0.1055613458, -0.0638541728]+ ,[1.0, -0.0894841775, -1.2914855480]+ ]
Data/Colour/SRGB.hs view
@@ -110,11 +110,11 @@ -- |Read a colour in hexadecimal form, e.g. \"#00aaff\" or \"00aaff\" sRGB24reads :: (Ord b, Floating b) => ReadS (Colour b) sRGB24reads "" = []-sRGB24reads x =+sRGB24reads x@(hdx : tlx) =   [(sRGB24 a b c, c0)   |(a,a0) <- readPair x', (b,b0) <- readPair a0, (c,c0) <- readPair b0]  where-  x' | head x == '#' = tail x+  x' | hdx == '#' = tlx      | otherwise = x   readPair [] = []   readPair [_] = []@@ -124,11 +124,9 @@  -- |Read a colour in hexadecimal form, e.g. \"#00aaff\" or \"00aaff\" sRGB24read :: (Ord b, Floating b) => String -> (Colour b)-sRGB24read x | length rx /= 1 || not (null (snd (head rx))) =-  error "Data.Colour.SRGB.sRGB24read: no parse"-             | otherwise = fst (head rx)- where-  rx = sRGB24reads x+sRGB24read x = case sRGB24reads x of+  [(x,"")] -> x+  _ -> error "Data.Colour.SRGB.sRGB24read: no parse"  -- |The sRGB colour space sRGBSpace :: (Ord a, Floating a) => RGBSpace a
Tests.hs view
@@ -23,13 +23,16 @@ -} module Main where +import Data.Fixed (Milli, resolution) import Data.Word (Word8) import Control.Monad (liftM, liftM2, liftM3) import Test.QuickCheck ( Arbitrary, CoArbitrary, Gen, Property                        , (==>), arbitrary, choose, coarbitrary, forAll                        )+import Test.HUnit (Assertion, (@?=)) import Test.Framework (defaultMain, defaultMainWithOpts, testGroup) import Test.Framework.Providers.QuickCheck2 (testProperty)+import Test.Framework.Providers.HUnit (testCase)  import Data.Colour.Matrix import Data.Colour@@ -37,6 +40,7 @@ import Data.Colour.SRGB.Linear import Data.Colour.CIE import Data.Colour.CIE.Illuminant (d65)+import Data.Colour.Ok import Data.Colour.Names --import Data.Colour.HDTV as HDTV --import qualified Data.Colour.SDTV as SDTV@@ -161,6 +165,18 @@   (l,a,b) = cieLABView wp c   cc = toSRGB24 +prop_toFromOklab :: DColour -> Bool+prop_toFromOklab c = cc (okLab l a b) == cc c+ where+  (l,a,b) = okLabView c+  cc = toSRGB24++prop_toFromOklch :: DColour -> Bool+prop_toFromOklch c = cc (okLCh l a b) == cc c+ where+  (l,a,b) = okLChView c+  cc = toSRGB24+ {- prop_fromToY'CbCr709 :: Word8 -> Word8 -> Word8 -> Bool prop_fromToY'CbCr709 y' cb cr =@@ -286,6 +302,21 @@     snd (properFraction ((h0-h1)/360)::(Integer,Rational)) == 0     && s0 == s1 && v0 == v1 +-- |Pairs of XYZ and LAB colours provided for verification in the Oklab+-- specification.+case_xyzToOklab :: Assertion+case_xyzToOklab = do+ xyzToOklab 0.950 1.000 1.089 @?= [ 1.000, 0.000, 0.000]+ xyzToOklab 1.000 0.000 0.000 @?= [ 0.450, 1.236,-0.019]+ xyzToOklab 0.000 1.000 0.000 @?= [ 0.922,-0.671, 0.263]+ xyzToOklab 0.000 0.000 1.000 @?= [ 0.153,-1.415,-0.449]+ where+  xyzToOklab x y z = rounded (okLabView (cieXYZ x y z))+  rounded (l,a,b) = map roundFixed [l,a,b] :: [Milli]+  roundFixed x = result+    where+     result = fromRational $ toRational x + (0.5/fromInteger (resolution result))+ tests = [ testProperty "matrix-mult" prop_matrixMult         , testProperty "RGB-to-from" prop_toFromRGB         , testProperty "RGB-from-to" prop_fromToRGB@@ -294,6 +325,8 @@         , testProperty "sRGB-to-from" prop_toFromSRGB         , testProperty "sRGB-from-to" prop_fromToSRGB         , testProperty "cieLAB-to-from" (prop_toFromLAB d65)+        , testProperty "Oklab-to-from" prop_toFromOklab+        , testProperty "Oklch-to-from" prop_toFromOklch --        , testProperty "Y'CbCr-709-from-to" prop_fromToY'CbCr709 --        , testProperty "Y'CbCr-601-from-to" prop_fromToY'CbCr601         , testProperty "dissolve-id" prop_disolveId@@ -326,6 +359,7 @@         , testProperty "fromToHSL" prop_fromToHSL         , testProperty "toFromHSV" prop_toFromHSV         , testProperty "fromToHSV" prop_fromToHSV+        , testCase "example-xyz-oklab-pairs" case_xyzToOklab         ]  main = defaultMain tests
colour.cabal view
@@ -1,5 +1,5 @@ Name:                colour-Version:             2.3.6+Version:             2.3.7 Cabal-Version:       >= 1.10 License:             MIT License-file:        LICENSE@@ -13,7 +13,7 @@                      Colours can be blended and composed.                      Various colour spaces are supported.                      A module of colour names ("Data.Colour.Names") is provided.-Tested-with:         GHC == 8.8.4+Tested-with:         GHC == 9.10.3 data-files:          README CHANGELOG  Library@@ -28,6 +28,7 @@                      Data.Colour.RGBSpace.HSL                      Data.Colour.RGBSpace.HSV                      Data.Colour.Names+                     Data.Colour.Ok   Other-Modules:     Data.Colour.Internal                      Data.Colour.Chan                      Data.Colour.RGB@@ -39,15 +40,18 @@   main-is:           Tests.hs   build-depends: base >= 4.13 && < 5,                  colour,-                 QuickCheck >= 2.5 && < 2.15,-                 random >= 1.0 && < 1.2,+                 QuickCheck >= 2.5 && < 2.16,+                 random >= 1.0 && < 1.3,                  test-framework >= 0.8 && < 0.9,-                 test-framework-quickcheck2 >= 0.3 && < 0.4+                 test-framework-quickcheck2 >= 0.3 && < 0.4,+                 test-framework-hunit >= 0.3 && < 0.4,+                 HUnit >= 1.4 && <1.7   Other-Modules:   Data.Colour                    Data.Colour.SRGB                    Data.Colour.SRGB.Linear                    Data.Colour.CIE                    Data.Colour.CIE.Illuminant+                   Data.Colour.Ok                    Data.Colour.RGBSpace                    Data.Colour.RGBSpace.HSL                    Data.Colour.RGBSpace.HSV