packages feed

Color 0.3.3 → 0.4.0

raw patch · 65 files changed

+1290/−228 lines, 65 filesdep −doctestdep ~QuickCheckdep ~basePVP ok

version bump matches the API change (PVP)

Dependencies removed: doctest

Dependency ranges changed: QuickCheck, base

API changes (from Hackage documentation)

- Graphics.Color.Adaptation: data family Adaptation t it ir e :: Type;
- Graphics.Color.Algebra.Binary: instance Data.Bits.Bits Graphics.Color.Algebra.Binary.Bit
- Graphics.Color.Space.RGB.Alternative.YCbCr: instance (Data.Typeable.Internal.Typeable cs, Graphics.Color.Model.Internal.ColorModel (cs 'Graphics.Color.Space.RGB.Internal.NonLinear) e, Graphics.Color.Algebra.Elevator.Elevator e) => GHC.Show.Show (Graphics.Color.Model.Internal.Color (Graphics.Color.Space.RGB.Alternative.YCbCr.Y'CbCr cs) e)
- Graphics.Color.Space.RGB.Luma: instance forall k (cs :: Graphics.Color.Space.RGB.Internal.Linearity -> *) (i :: k) e. (Data.Typeable.Internal.Typeable cs, Graphics.Color.Space.Internal.Illuminant i, Graphics.Color.Space.Internal.ColorSpace (cs 'Graphics.Color.Space.RGB.Internal.Linear) i e, Graphics.Color.Space.Internal.ColorSpace (cs 'Graphics.Color.Space.RGB.Internal.NonLinear) i e, Graphics.Color.Space.RGB.Luma.Luma cs, Graphics.Color.Space.RGB.Internal.RedGreenBlue cs i) => Graphics.Color.Space.Internal.ColorSpace (Graphics.Color.Space.RGB.Luma.Y' cs) i e
+ Graphics.Color.Adaptation: data Adaptation t it ir e :: Type;
+ Graphics.Color.Algebra.Binary: instance GHC.Bits.Bits Graphics.Color.Algebra.Binary.Bit
+ Graphics.Color.Model: channelColors :: ColorModel cs e => Proxy (Color cs e) -> NonEmpty (V3 Word8)
+ Graphics.Color.Model: channelCount :: ColorModel cs e => Proxy (Color cs e) -> Word8
+ Graphics.Color.Model: channelNames :: ColorModel cs e => Proxy (Color cs e) -> NonEmpty String
+ Graphics.Color.Model: channelRgbColors :: ColorModel cs e => Proxy (Color cs e) -> NonEmpty (Color RGB Word8)
+ Graphics.Color.Model: type ChannelCount cs :: Nat;
+ Graphics.Color.Model: type Components cs e :: Type;
+ Graphics.Color.Space: Weights :: V3 e -> Weights e
+ Graphics.Color.Space: [unWeights] :: Weights e -> V3 e
+ Graphics.Color.Space: applyGrayscale :: ColorSpace cs i e => Color cs e -> (Color X e -> Color X e) -> Color cs e
+ Graphics.Color.Space: channelColors :: ColorModel cs e => Proxy (Color cs e) -> NonEmpty (V3 Word8)
+ Graphics.Color.Space: channelCount :: ColorModel cs e => Proxy (Color cs e) -> Word8
+ Graphics.Color.Space: channelNames :: ColorModel cs e => Proxy (Color cs e) -> NonEmpty String
+ Graphics.Color.Space: data X
+ Graphics.Color.Space: grayscale :: ColorSpace cs i e => Color cs e -> Color X e
+ Graphics.Color.Space: newtype Weights e
+ Graphics.Color.Space: pattern ColorX :: e -> Color X e
+ Graphics.Color.Space: pattern ColorXA :: e -> e -> Color (Alpha X) e
+ Graphics.Color.Space: replaceGrayscale :: ColorSpace cs i e => Color cs e -> Color X e -> Color cs e
+ Graphics.Color.Space: rgb2y :: forall e e'. (Elevator e', Elevator e, RealFloat e) => Color RGB e' -> Weights e -> Color X e
+ Graphics.Color.Space: type BaseModel cs :: Type;
+ Graphics.Color.Space: type ChannelCount cs :: Nat;
+ Graphics.Color.Space: type Components cs e :: Type;
+ Graphics.Color.Space: type Temperature i :: n;
+ Graphics.Color.Space: unY :: Color (Y i) e -> e
+ Graphics.Color.Space.CIE1976.LAB: ft :: RealFloat a => a -> a
+ Graphics.Color.Space.CIE1976.LAB: ift :: (Fractional a, Ord a) => a -> a
+ Graphics.Color.Space.CIE1976.LAB: lab2xyz :: forall i a e. (Illuminant i, Elevator e, Elevator a, RealFloat a) => Color (LAB i) e -> Color (XYZ i) a
+ Graphics.Color.Space.CIE1976.LAB: xyz2lab :: forall i a e. (Illuminant i, Elevator a, Elevator e, RealFloat e) => Color (XYZ i) a -> Color (LAB i) e
+ Graphics.Color.Space.DIN99: data DIN99 (i :: k)
+ Graphics.Color.Space.DIN99: deltaE :: (Floating e, Illuminant i, Elevator e) => Color (LAB i) e -> Color (LAB i) e -> e
+ Graphics.Color.Space.DIN99: instance GHC.Classes.Eq Graphics.Color.Space.DIN99.DINMethod
+ Graphics.Color.Space.DIN99: instance GHC.Classes.Ord Graphics.Color.Space.DIN99.DINMethod
+ Graphics.Color.Space.DIN99: instance GHC.Enum.Bounded Graphics.Color.Space.DIN99.DINMethod
+ Graphics.Color.Space.DIN99: instance GHC.Enum.Enum Graphics.Color.Space.DIN99.DINMethod
+ Graphics.Color.Space.DIN99: instance GHC.Generics.Generic Graphics.Color.Space.DIN99.DINMethod
+ Graphics.Color.Space.DIN99: instance GHC.Read.Read Graphics.Color.Space.DIN99.DINMethod
+ Graphics.Color.Space.DIN99: instance GHC.Show.Show Graphics.Color.Space.DIN99.DINMethod
+ Graphics.Color.Space.DIN99: instance forall k (i :: k) e. (Graphics.Color.Space.Internal.Illuminant i, Graphics.Color.Algebra.Elevator.Elevator e) => GHC.Show.Show (Graphics.Color.Model.Internal.Color (Graphics.Color.Space.DIN99.DIN99 i) e)
+ Graphics.Color.Space.DIN99: instance forall k (i :: k) e. (Graphics.Color.Space.Internal.Illuminant i, Graphics.Color.Algebra.Elevator.Elevator e) => Graphics.Color.Model.Internal.ColorModel (Graphics.Color.Space.DIN99.DIN99 i) e
+ Graphics.Color.Space.DIN99: instance forall k (i :: k) e. (Graphics.Color.Space.Internal.Illuminant i, Graphics.Color.Algebra.Elevator.Elevator e, GHC.Float.RealFloat e) => Graphics.Color.Space.Internal.ColorSpace (Graphics.Color.Space.DIN99.DIN99 i) i e
+ Graphics.Color.Space.DIN99: instance forall k (i :: k). Data.Foldable.Foldable (Graphics.Color.Model.Internal.Color (Graphics.Color.Space.DIN99.DIN99 i))
+ Graphics.Color.Space.DIN99: instance forall k (i :: k). Data.Traversable.Traversable (Graphics.Color.Model.Internal.Color (Graphics.Color.Space.DIN99.DIN99 i))
+ Graphics.Color.Space.DIN99: instance forall k (i :: k). GHC.Base.Applicative (Graphics.Color.Model.Internal.Color (Graphics.Color.Space.DIN99.DIN99 i))
+ Graphics.Color.Space.DIN99: instance forall k (i :: k). GHC.Base.Functor (Graphics.Color.Model.Internal.Color (Graphics.Color.Space.DIN99.DIN99 i))
+ Graphics.Color.Space.DIN99: instance forall k e (i :: k). Foreign.Storable.Storable e => Foreign.Storable.Storable (Graphics.Color.Model.Internal.Color (Graphics.Color.Space.DIN99.DIN99 i) e)
+ Graphics.Color.Space.DIN99: instance forall k e (i :: k). GHC.Classes.Eq e => GHC.Classes.Eq (Graphics.Color.Model.Internal.Color (Graphics.Color.Space.DIN99.DIN99 i) e)
+ Graphics.Color.Space.DIN99: instance forall k e (i :: k). GHC.Classes.Ord e => GHC.Classes.Ord (Graphics.Color.Model.Internal.Color (Graphics.Color.Space.DIN99.DIN99 i) e)
+ Graphics.Color.Space.DIN99: pattern ColorDIN99 :: e -> e -> e -> Color (DIN99 i) e
+ Graphics.Color.Space.DIN99: pattern DIN99 :: () => V3 e -> Color (DIN99 i) e
+ Graphics.Color.Space.RGB: Weights :: V3 e -> Weights e
+ Graphics.Color.Space.RGB: [unWeights] :: Weights e -> V3 e
+ Graphics.Color.Space.RGB: applyGrayscale :: ColorSpace cs i e => Color cs e -> (Color X e -> Color X e) -> Color cs e
+ Graphics.Color.Space.RGB: channelColors :: ColorModel cs e => Proxy (Color cs e) -> NonEmpty (V3 Word8)
+ Graphics.Color.Space.RGB: channelCount :: ColorModel cs e => Proxy (Color cs e) -> Word8
+ Graphics.Color.Space.RGB: channelNames :: ColorModel cs e => Proxy (Color cs e) -> NonEmpty String
+ Graphics.Color.Space.RGB: data X
+ Graphics.Color.Space.RGB: grayscale :: ColorSpace cs i e => Color cs e -> Color X e
+ Graphics.Color.Space.RGB: newtype Weights e
+ Graphics.Color.Space.RGB: pattern ColorX :: e -> Color X e
+ Graphics.Color.Space.RGB: pattern ColorXA :: e -> e -> Color (Alpha X) e
+ Graphics.Color.Space.RGB: replaceGrayscale :: ColorSpace cs i e => Color cs e -> Color X e -> Color cs e
+ Graphics.Color.Space.RGB: rgb2y :: forall e e'. (Elevator e', Elevator e, RealFloat e) => Color RGB e' -> Weights e -> Color X e
+ Graphics.Color.Space.RGB: rgbLinearApplyGrayscale :: forall cs i e. ColorSpace (cs 'Linear) i e => Color (cs 'Linear) e -> (Color X e -> Color X e) -> Color (cs 'Linear) e
+ Graphics.Color.Space.RGB: rgbLinearGrayscale :: forall cs i e. ColorSpace (cs 'Linear) i e => Color (cs 'Linear) e -> Color X e
+ Graphics.Color.Space.RGB: rgbNonLinearApplyGrayscale :: forall cs i e. (RedGreenBlue cs i, ColorSpace (cs 'NonLinear) i e) => Color (cs 'NonLinear) e -> (Color X e -> Color X e) -> Color (cs 'NonLinear) e
+ Graphics.Color.Space.RGB: rgbNonLinearGrayscale :: forall cs i e. (RedGreenBlue cs i, ColorSpace (cs 'NonLinear) i e) => Color (cs 'NonLinear) e -> Color X e
+ Graphics.Color.Space.RGB: type BaseModel cs :: Type;
+ Graphics.Color.Space.RGB: type ChannelCount cs :: Nat;
+ Graphics.Color.Space.RGB: type Components cs e :: Type;
+ Graphics.Color.Space.RGB: type Temperature i :: n;
+ Graphics.Color.Space.RGB: unY :: Color (Y i) e -> e
+ Graphics.Color.Space.RGB.Alternative: Weights :: V3 e -> Weights e
+ Graphics.Color.Space.RGB.Alternative: [unWeights] :: Weights e -> V3 e
+ Graphics.Color.Space.RGB.Alternative: applyGrayscale :: ColorSpace cs i e => Color cs e -> (Color X e -> Color X e) -> Color cs e
+ Graphics.Color.Space.RGB.Alternative: channelColors :: ColorModel cs e => Proxy (Color cs e) -> NonEmpty (V3 Word8)
+ Graphics.Color.Space.RGB.Alternative: channelCount :: ColorModel cs e => Proxy (Color cs e) -> Word8
+ Graphics.Color.Space.RGB.Alternative: channelNames :: ColorModel cs e => Proxy (Color cs e) -> NonEmpty String
+ Graphics.Color.Space.RGB.Alternative: data X
+ Graphics.Color.Space.RGB.Alternative: grayscale :: ColorSpace cs i e => Color cs e -> Color X e
+ Graphics.Color.Space.RGB.Alternative: newtype Weights e
+ Graphics.Color.Space.RGB.Alternative: pattern ColorX :: e -> Color X e
+ Graphics.Color.Space.RGB.Alternative: pattern ColorXA :: e -> e -> Color (Alpha X) e
+ Graphics.Color.Space.RGB.Alternative: replaceGrayscale :: ColorSpace cs i e => Color cs e -> Color X e -> Color cs e
+ Graphics.Color.Space.RGB.Alternative: rgb2y :: forall e e'. (Elevator e', Elevator e, RealFloat e) => Color RGB e' -> Weights e -> Color X e
+ Graphics.Color.Space.RGB.Alternative: rgbLinearApplyGrayscale :: forall cs i e. ColorSpace (cs 'Linear) i e => Color (cs 'Linear) e -> (Color X e -> Color X e) -> Color (cs 'Linear) e
+ Graphics.Color.Space.RGB.Alternative: rgbLinearGrayscale :: forall cs i e. ColorSpace (cs 'Linear) i e => Color (cs 'Linear) e -> Color X e
+ Graphics.Color.Space.RGB.Alternative: rgbNonLinearApplyGrayscale :: forall cs i e. (RedGreenBlue cs i, ColorSpace (cs 'NonLinear) i e) => Color (cs 'NonLinear) e -> (Color X e -> Color X e) -> Color (cs 'NonLinear) e
+ Graphics.Color.Space.RGB.Alternative: rgbNonLinearGrayscale :: forall cs i e. (RedGreenBlue cs i, ColorSpace (cs 'NonLinear) i e) => Color (cs 'NonLinear) e -> Color X e
+ Graphics.Color.Space.RGB.Alternative: type BaseModel cs :: Type;
+ Graphics.Color.Space.RGB.Alternative: type ChannelCount cs :: Nat;
+ Graphics.Color.Space.RGB.Alternative: type Components cs e :: Type;
+ Graphics.Color.Space.RGB.Alternative: type Temperature i :: n;
+ Graphics.Color.Space.RGB.Alternative: unY :: Color (Y i) e -> e
+ Graphics.Color.Space.RGB.Alternative.YCbCr: instance (Data.Typeable.Internal.Typeable cs, Graphics.Color.Model.Internal.ColorModel (cs 'Graphics.Color.Space.RGB.Internal.NonLinear) e) => GHC.Show.Show (Graphics.Color.Model.Internal.Color (Graphics.Color.Space.RGB.Alternative.YCbCr.Y'CbCr cs) e)
+ Graphics.Color.Space.RGB.ITU.Rec601: applyGrayscaleRec601 :: forall cs i e. (RedGreenBlue cs i, ColorSpace (cs 'NonLinear) i e) => Color (cs 'NonLinear) e -> (Color X e -> Color X e) -> Color (cs 'NonLinear) e
+ Graphics.Color.Space.RGB.ITU.Rec601: rec601ToYcbcr :: (RedGreenBlue cs i, RealFloat e) => Color (cs 'NonLinear) e -> Color YCbCr e
+ Graphics.Color.Space.RGB.ITU.Rec601: ycbcrToRec601 :: (RedGreenBlue cs i, RealFloat e) => Color YCbCr e -> Color (cs 'NonLinear) e
+ Graphics.Color.Space.RGB.Luma: instance forall k (cs :: Graphics.Color.Space.RGB.Internal.Linearity -> *) (i :: k) e. (Data.Typeable.Internal.Typeable cs, Graphics.Color.Space.Internal.ColorSpace (cs 'Graphics.Color.Space.RGB.Internal.Linear) i e, Graphics.Color.Space.Internal.ColorSpace (cs 'Graphics.Color.Space.RGB.Internal.NonLinear) i e, Graphics.Color.Space.RGB.Luma.Luma cs, Graphics.Color.Space.RGB.Internal.RedGreenBlue cs i) => Graphics.Color.Space.Internal.ColorSpace (Graphics.Color.Space.RGB.Luma.Y' cs) i e
+ Graphics.Pixel.ColorSpace: applyGrayscalePixel :: ColorSpace cs i e => Pixel cs e -> (Pixel X e -> Pixel X e) -> Pixel cs e
+ Graphics.Pixel.ColorSpace: grayscalePixel :: ColorSpace cs i e => Pixel cs e -> Pixel X e
+ Graphics.Pixel.ColorSpace: pattern PixelX :: e -> Pixel X e
+ Graphics.Pixel.ColorSpace: replaceGrayscalePixel :: ColorSpace cs i e => Pixel cs e -> Pixel X e -> Pixel cs e
- Graphics.Color.Model: type family Components cs e :: Type;
+ Graphics.Color.Model: type family Opaque cs
- Graphics.Color.Space: type family Temperature i :: n;
+ Graphics.Color.Space: type family Opaque cs
- Graphics.Color.Space.RGB: type family Temperature i :: n;
+ Graphics.Color.Space.RGB: type family Opaque cs
- Graphics.Color.Space.RGB.Alternative: type family Temperature i :: n;
+ Graphics.Color.Space.RGB.Alternative: type family Opaque cs
- Graphics.Pixel.ColorSpace: pattern PixelSRGB :: e -> e -> e -> Pixel (SRGB 'NonLinear) e
+ Graphics.Pixel.ColorSpace: pattern PixelSRGB :: forall e l. e -> e -> e -> Pixel (SRGB l) e
- Graphics.Pixel.ColorSpace: pattern PixelSRGBA :: e -> e -> e -> e -> Pixel (Alpha (SRGB 'NonLinear)) e
+ Graphics.Pixel.ColorSpace: pattern PixelSRGBA :: e -> e -> e -> e -> Pixel (Alpha (SRGB l)) e

Files

CHANGELOG.md view
@@ -1,5 +1,14 @@ # Changelog for Color +## 0.4.0++* Addition of `DIN99` color space.+* Scale `L*a*b*` color space to `[0, 1]` range from the more common `[0, 100]` for+  consistency.+* Addition of: `toGrayscale`, `applyGrayscale` and `replaceGrayscale`.+* Addition of: `ChannelCount`, `channelCount`, `channelNames` and `channelColors`+* Remove `RealFloat` constraint from `ColorSpace` for `Y'`+ ## 0.3.3  Addition of `SVG` colors
Color.cabal view
@@ -1,5 +1,5 @@ name:                Color-version:             0.3.3+version:             0.4.0 synopsis:            Color spaces and conversions between them description:         Please see the README on GitHub at <https://github.com/lehins/Color#readme> homepage:            https://github.com/lehins/Color@@ -7,11 +7,11 @@ license-file:        LICENSE author:              Alexey Kuleshevich maintainer:          alexey@kuleshevi.ch-copyright:           2019-2021 Alexey Kuleshevich+copyright:           2019-2025 Alexey Kuleshevich category:            Graphics extra-source-files:  README.md-                   , CHANGELOG.md-extra-doc-files:     files/*.svg+extra-doc-files:     CHANGELOG.md+                   , files/*.svg                    , files/svg/*.png cabal-version:       1.18 build-type:          Simple@@ -19,7 +19,13 @@                     , GHC == 8.6.5                     , GHC == 8.8.6                     , GHC == 8.10.7-                    , GHC == 9.0.1+                    , GHC == 9.0.2+                    , GHC == 9.2.8+                    , GHC == 9.4.8+                    , GHC == 9.6.6+                    , GHC == 9.8.4+                    , GHC == 9.10.1+                    , GHC == 9.12.1  library   hs-source-dirs:      src@@ -44,6 +50,7 @@                      , Graphics.Color.Space.CIE1976.LAB.LCH                      , Graphics.Color.Space.CIE1976.LUV                      , Graphics.Color.Space.CIE1976.LUV.LCH+                     , Graphics.Color.Space.DIN99                      , Graphics.Color.Space.RGB                      , Graphics.Color.Space.RGB.CIERGB                      , Graphics.Color.Space.RGB.AdobeRGB@@ -96,7 +103,8 @@   ghc-options:         -Wall                        -Wincomplete-record-updates                        -Wincomplete-uni-patterns-                       -Wredundant-constraints+  if impl(ghc < 9.0) || impl(ghc >= 9.6)+    ghc-options:   -Wredundant-constraints  test-suite tests   type:               exitcode-stdio-1.0@@ -159,25 +167,6 @@                       -threaded                       -freduction-depth=0 -test-suite doctests-  type:             exitcode-stdio-1.0-  hs-source-dirs:   tests-  main-is:          doctests.hs-  build-depends: base-  if impl(ghc >= 8.2) && impl(ghc < 8.10)-    build-depends: doctest >=0.16-                 , QuickCheck-                 , Color-                 , JuicyPixels-  default-language:    Haskell2010-  ghc-options:        -Wall-                      -Wincomplete-record-updates-                      -Wincomplete-uni-patterns-                      -Wredundant-constraints-                      -fno-warn-orphans-                      -threaded-- benchmark conversion   type:                exitcode-stdio-1.0   hs-source-dirs:      bench@@ -191,6 +180,19 @@                      , colour                      , deepseq                      , random+  default-language:    Haskell2010++benchmark ycbcr+  type:                exitcode-stdio-1.0+  hs-source-dirs:      bench+  main-is:             YCbCr.hs+  ghc-options:         -Wall+                       -threaded+                       -O2+  build-depends:       base+                     , criterion+                     , Color+                     , deepseq   default-language:    Haskell2010  source-repository head
LICENSE view
@@ -1,4 +1,4 @@-Copyright Alexey Kuleshevich (c) 2019-2020+Copyright Alexey Kuleshevich (c) 2019-2025  All rights reserved. 
README.md view
@@ -38,6 +38,7 @@   * `Y'` - luma   * `CIE XYZ`   * `CIE L*a*b*`+  * `DIN99`   * `RGB`:      * `sRGB` - both standardized and derived@@ -72,6 +73,73 @@   * RAL   * SVG +## Example++Here is a short example how this library can be used. Here we assume a GHCi session that+can be started like so:++```shell+$ stack ghci --package Color+```++### Perceived lightness++Let's say we need find the perceived lightness as described in [this StackOverflow+answer](https://stackoverflow.com/questions/596216/formula-to-determine-perceived-brightness-of-rgb-color/56678483#56678483)+for an RGB triple `(128, 255, 65) :: (Word8, Word8, Word8)`.++Before we can attempt getting the lightness we need to do these two things:++1. Figure out what is the color space of the `RGB` triplet? In particular the `Illuminant`+   and the `Linearity` of the `RGB` color space.+2. Convert your `RGB` color to [`CIE+   L*a*b*`](https://en.wikipedia.org/wiki/CIELAB_color_space) and then we can get the `L*`+   out, which is the perceived lightness.++More often than not an RGB image will be encoded in non-linear sRGB color space with 8 bits+per channel, so we'll use that for this example:++```haskell+ghci> :set -XDataKinds+ghci> import Graphics.Color.Space+ghci> let rgb8 = ColorSRGB 128 255 65 :: Color (SRGB 'NonLinear) Word8+ghci> print rgb8+<SRGB 'NonLinear:(128,255, 65)>+```++Before we convert `sRGB` to `CIE L*a*b*` color space we need to increase the precision to+`Double`, because for now `Word8` is not supported by the `LAB` color space implementation:++```haskell+ghci> let rgb = toDouble <$> rgb8+ghci> print rgb+<SRGB 'NonLinear:( 0.5019607843137255, 1.0000000000000000, 0.2549019607843137)>+```++In order to convert to another color space without changing the `Illuminant` we can use+`convertColor` function. So here is how we convert to CIELAB and extract the perceived+lightness `L*`:++```haskell+ghci> let lab@(ColorLAB l _ _) = convertColor rgb :: Color (LAB D65) Double+ghci> lab+<LAB * D65:(90.0867507593648500,-65.7999116680496000,74.4643898323530600)>+ghci> l+90.08675075936485+```++### Color adaptation++When a change of `Illuminant` is also needed during color space conversion we can use+`convert` function++```haskell+ghci> import Graphics.Color.Adaptation (convert)+ghci> import qualified Graphics.Color.Illuminant.CIE1964 as CIE1964+ghci> let lab@(ColorLAB l _ _) = convert rgb :: Color (LAB 'CIE1964.D50) Double+ghci> lab+<LAB CIE1964 'D50:(90.2287735564601500,-59.3846969983265500,72.9304679742930800)>+```  ## External resources 
+ bench/YCbCr.hs view
@@ -0,0 +1,71 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE ScopedTypeVariables #-}+module Main where++import Criterion.Main+import Control.DeepSeq+import qualified Graphics.Color.Model as CM+import Graphics.Color.Space+import Graphics.Color.Space.RGB.ITU.Rec601+import Graphics.Color.Space.RGB.ITU.Rec709+import Data.Coerce++main :: IO ()+main = do+  defaultMain+    [ bgroup+        "toYCbCr"+        [ toYCbCrBench (CM.ColorRGB 0.1 0.2 0.3 :: Color CM.RGB Float) "Float"+        , toYCbCrBench (CM.ColorRGB 0.1 0.2 0.3 :: Color CM.RGB Double) "Double"+        ]+    , bgroup+        "fromYCbCr"+        [ fromYCbCrBench (CM.ColorYCbCr 0.1 0.2 0.3 :: Color CM.YCbCr Float) "Float"+        , fromYCbCrBench (CM.ColorYCbCr 0.1 0.2 0.3 :: Color CM.YCbCr Double) "Double"+        ]+    ]+++toYCbCrBench ::+     forall e. (Elevator e, NFData e)+  => Color CM.RGB e+  -> String+  -> Benchmark+toYCbCrBench rgb tyName =+  bgroup+    tyName+    [ bgroup+        "Standard"+        [ bench "SRGB" $+          nf (fromBaseSpace :: Color (SRGB 'NonLinear) e -> Color (Y'CbCr SRGB) e) (mkColorRGB rgb)+        , bench "Rec601" $+          nf+            (fromBaseSpace :: Color (BT601_625 'NonLinear) e -> Color (Y'CbCr BT601_625) e)+            (mkColorRGB rgb)+        , bench "Rec709" $+          nf (fromBaseSpace :: Color (BT709 'NonLinear) e -> Color (Y'CbCr BT709) e) (mkColorRGB rgb)+        ]+    ]++fromYCbCrBench ::+     forall e. (Elevator e, NFData e)+  => Color CM.YCbCr e+  -> String+  -> Benchmark+fromYCbCrBench ycbcr tyName =+  bgroup+    tyName+    [ bgroup+        "Standard"+        [ bench "SRGB" $+          nf (toBaseSpace :: Color (Y'CbCr SRGB) e -> Color (SRGB 'NonLinear) e) (coerce ycbcr)+        , bench "Rec601" $+          nf+            (toBaseSpace :: Color (Y'CbCr BT601_625) e -> Color (BT601_625 'NonLinear) e)+            (coerce ycbcr)+        , bench "Rec709" $+          nf (toBaseSpace :: Color (Y'CbCr BT709) e -> Color (BT709 'NonLinear) e) (coerce ycbcr)+        ]+    ]
src/Graphics/Color/Adaptation.hs view
@@ -1,6 +1,6 @@ -- | -- Module      : Graphics.Color.Adaptation--- Copyright   : (c) Alexey Kuleshevich 2019-2020+-- Copyright   : (c) Alexey Kuleshevich 2019-2025 -- License     : BSD3 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru> -- Stability   : experimental
src/Graphics/Color/Adaptation/Internal.hs view
@@ -4,9 +4,10 @@ {-# LANGUAGE PolyKinds #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-} -- | -- Module      : Graphics.Color.Adaptation.Internal--- Copyright   : (c) Alexey Kuleshevich 2019-2020+-- Copyright   : (c) Alexey Kuleshevich 2019-2025 -- License     : BSD3 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru> -- Stability   : experimental
src/Graphics/Color/Adaptation/VonKries.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-}@@ -5,10 +6,15 @@ {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeFamilies #-}+#if __GLASGOW_HASKELL__ >= 906+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE PolyKinds #-}+#else {-# LANGUAGE TypeInType #-}+#endif -- | -- Module      : Graphics.Color.Adaptation.VonKries--- Copyright   : (c) Alexey Kuleshevich 2018-2020+-- Copyright   : (c) Alexey Kuleshevich 2018-2025 -- License     : BSD3 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru> -- Stability   : experimental
src/Graphics/Color/Algebra.hs view
@@ -4,7 +4,7 @@ {-# LANGUAGE ScopedTypeVariables #-} -- | -- Module      : Graphics.Color.Algebra--- Copyright   : (c) Alexey Kuleshevich 2019-2020+-- Copyright   : (c) Alexey Kuleshevich 2019-2025 -- License     : BSD3 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru> -- Stability   : experimental@@ -33,9 +33,11 @@  import Data.Typeable import Foreign.Ptr-import Control.Applicative import Foreign.Storable import Graphics.Color.Algebra.Elevator+#if MIN_VERSION_base(4,10,0) && !MIN_VERSION_base(4,18,0)+import Control.Applicative (liftA2)+#endif   --------
src/Graphics/Color/Algebra/Binary.hs view
@@ -8,7 +8,7 @@ {-# LANGUAGE TypeFamilies #-} -- | -- Module      : Graphics.Color.Algebra.Binary--- Copyright   : (c) Alexey Kuleshevich 2018-2020+-- Copyright   : (c) Alexey Kuleshevich 2018-2025 -- License     : BSD3 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru> -- Stability   : experimental@@ -31,7 +31,7 @@ import Foreign.Storable import Graphics.Color.Algebra.Elevator import Prelude hiding (map)-+import Data.Coerce  -- | Under the hood, binary pixels are backed by `Word8`, but can only take -- values of @0@ or @1@. Use `zero`\/`one` to construct a bit and `on`\/`off` to@@ -43,35 +43,32 @@   show (Bit 0) = "0"   show _       = "1" +cf :: (Word8 -> Word8) -> Bit -> Bit+cf = coerce +cf2 :: (Word8 -> Word8 -> Word8) -> Bit -> Bit -> Bit+cf2 = coerce+ instance Bits Bit where-  (Bit 0) .&. _       = Bit 0-  (Bit 1) .&. (Bit 1) = Bit 1-  _       .&. (Bit 0) = Bit 0-  _       .&. _       = Bit 1+  (.&.) = cf2 (.&.)   {-# INLINE (.&.) #-}-  (Bit 1) .|. _       = Bit 1-  (Bit 0) .|. (Bit 0) = Bit 0-  _       .|. _       = Bit 1+  (.|.) = cf2 (.|.)   {-# INLINE (.|.) #-}-  (Bit 0) `xor` (Bit 0) = Bit 0-  (Bit 1) `xor` (Bit 1) = Bit 0-  _       `xor` _       = Bit 1+  xor = cf2 xor   {-# INLINE xor #-}-  complement (Bit 0) = Bit 1-  complement       _ = Bit 0+  complement = cf complement   {-# INLINE complement #-}   shift !b 0 = b   shift  _ _ = Bit 0   {-# INLINE shift #-}   rotate !b _ = b   {-# INLINE rotate #-}-  zeroBits = Bit 0+  zeroBits = zero   {-# INLINE zeroBits #-}-  bit 0 = Bit 1-  bit _ = Bit 0+  bit 0 = one+  bit _ = zero   {-# INLINE bit #-}-  testBit (Bit 1) 0 = True+  testBit (Bit b) 0 = b /= 0   testBit _       _ = False   {-# INLINE testBit #-}   bitSizeMaybe _ = Just 1@@ -119,24 +116,23 @@   zero :: Bit-zero = Bit 0+zero = coerce (0x00 :: Word8) {-# INLINE zero #-}  one :: Bit-one = Bit 1+one = coerce (0xff :: Word8) {-# INLINE one #-}   -- | Values: @0@ and @1@ instance Elevator Bit where-  minValue = Bit 0+  minValue = Bit 0x00   {-# INLINE minValue #-}-  maxValue = Bit 1+  maxValue = Bit 0xff   {-# INLINE maxValue #-}   toShowS (Bit 0) = ('0':)   toShowS _       = ('1':)-  toWord8 (Bit 0) = 0-  toWord8 _       = maxBound+  toWord8 = coerce   {-# INLINE toWord8 #-}   toWord16 (Bit 0) = 0   toWord16 _       = maxBound@@ -153,10 +149,10 @@   toRealFloat (Bit 0) = 0   toRealFloat _       = 1   {-# INLINE toRealFloat #-}-  fromRealFloat 0 = Bit 0-  fromRealFloat _ = Bit 1+  fromRealFloat 0 = zero+  fromRealFloat _ = one   {-# INLINE fromRealFloat #-}-  (//) (Bit x) (Bit y) = Bit (x `div` y)+  (//) = cf2 div   {-# INLINE (//) #-}  @@ -167,9 +163,9 @@   -- 0 - 1 = 0   -- 1 - 0 = 1   -- 1 - 1 = 0-  (Bit 0) - (Bit 0) = Bit 0-  _       - (Bit 0) = Bit 1-  _       - _       = Bit 0+  (Bit 0) - (Bit 0) = zero+  _       - (Bit 0) = one+  _       - _       = zero   {-# INLINE (-) #-}   (*) = (.&.)   {-# INLINE (*) #-}@@ -177,8 +173,8 @@   {-# INLINE abs #-}   signum      = id   {-# INLINE signum #-}-  fromInteger 0 = Bit 0-  fromInteger _ = Bit 1+  fromInteger 0 = zero+  fromInteger _ = one   {-# INLINE fromInteger #-}  -- | Unboxing of a `Bit`.
src/Graphics/Color/Algebra/Elevator.hs view
@@ -5,7 +5,7 @@ {-# LANGUAGE ScopedTypeVariables #-} -- | -- Module      : Graphics.Color.Algebra.Elevator--- Copyright   : (c) Alexey Kuleshevich 2018-2020+-- Copyright   : (c) Alexey Kuleshevich 2018-2025 -- License     : BSD3 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru> -- Stability   : experimental@@ -135,7 +135,9 @@  -- | Differs from `fromIntegral` due to: [GHC #17782](https://gitlab.haskell.org/ghc/ghc/issues/17782) ----- >>> fromIntegral (maxBound :: Word64) :: Double+-- This is the value for ghc < 9.2+--+-- > fromIntegral (maxBound :: Word64) :: Double -- 1.844674407370955e19 -- maxWord64 :: Double
src/Graphics/Color/Illuminant/CIE1931.hs view
@@ -4,7 +4,7 @@ {-# LANGUAGE DataKinds #-} -- | -- Module      : Graphics.Color.Illuminant.CIE1931--- Copyright   : (c) Alexey Kuleshevich 2019-2020+-- Copyright   : (c) Alexey Kuleshevich 2019-2025 -- License     : BSD3 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru> -- Stability   : experimental
src/Graphics/Color/Illuminant/CIE1964.hs view
@@ -3,7 +3,7 @@ {-# LANGUAGE TypeFamilies #-} -- | -- Module      : Graphics.Color.Illuminant.CIE1964--- Copyright   : (c) Alexey Kuleshevich 2019-2020+-- Copyright   : (c) Alexey Kuleshevich 2019-2025 -- License     : BSD3 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru> -- Stability   : experimental
src/Graphics/Color/Illuminant/ICC/PCS.hs view
@@ -4,7 +4,7 @@ {-# LANGUAGE DataKinds #-} -- | -- Module      : Graphics.Color.Illuminant.ICC.PCS--- Copyright   : (c) Alexey Kuleshevich 2019-2020+-- Copyright   : (c) Alexey Kuleshevich 2019-2025 -- License     : BSD3 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru> -- Stability   : experimental
src/Graphics/Color/Illuminant/ITU/Rec470.hs view
@@ -4,7 +4,7 @@ {-# LANGUAGE DataKinds #-} -- | -- Module      : Graphics.Color.Illuminant.ITU.Rec470--- Copyright   : (c) Alexey Kuleshevich 2019-2020+-- Copyright   : (c) Alexey Kuleshevich 2019-2025 -- License     : BSD3 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru> -- Stability   : experimental
src/Graphics/Color/Illuminant/ITU/Rec601.hs view
@@ -4,7 +4,7 @@ {-# LANGUAGE DataKinds #-} -- | -- Module      : Graphics.Color.Illuminant.ITU.Rec601--- Copyright   : (c) Alexey Kuleshevich 2019-2020+-- Copyright   : (c) Alexey Kuleshevich 2019-2025 -- License     : BSD3 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru> -- Stability   : experimental
src/Graphics/Color/Illuminant/Wikipedia.hs view
@@ -4,7 +4,7 @@ {-# LANGUAGE DataKinds #-} -- | -- Module      : Graphics.Color.Illuminant.Wikipedia--- Copyright   : (c) Alexey Kuleshevich 2019-2020+-- Copyright   : (c) Alexey Kuleshevich 2019-2025 -- License     : BSD3 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru> -- Stability   : experimental
src/Graphics/Color/Model.hs view
@@ -1,6 +1,6 @@ -- | -- Module      : Graphics.Color.Model--- Copyright   : (c) Alexey Kuleshevich 2018-2020+-- Copyright   : (c) Alexey Kuleshevich 2018-2025 -- License     : BSD3 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru> -- Stability   : experimental@@ -8,6 +8,7 @@ -- module Graphics.Color.Model   ( ColorModel(..)+  , channelRgbColors   -- * Alpha   , Alpha   , Opaque@@ -50,3 +51,13 @@ import Graphics.Color.Model.RGB import Graphics.Color.Model.X import Graphics.Color.Model.YCbCr+import Data.Coerce+import Data.Proxy+import Data.List.NonEmpty++-- | Uses `channelColors` to produce actual `RGB` colors for each+-- channel. Useful for plotting.+--+-- @0.4.0+channelRgbColors :: ColorModel cs e => Proxy (Color cs e) -> NonEmpty (Color RGB Word8)+channelRgbColors = coerce . channelColors
src/Graphics/Color/Model/CMYK.hs view
@@ -1,14 +1,15 @@-{-# LANGUAGE StandaloneDeriving #-}-{-# LANGUAGE PatternSynonyms #-} {-# LANGUAGE BangPatterns #-}+{-# LANGUAGE DataKinds #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE PatternSynonyms #-} {-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE TypeFamilies #-} -- | -- Module      : Graphics.Color.Model.CMYK--- Copyright   : (c) Alexey Kuleshevich 2018-2020+-- Copyright   : (c) Alexey Kuleshevich 2018-2025 -- License     : BSD3 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru> -- Stability   : experimental@@ -25,6 +26,7 @@   , rgb2cmyk   ) where +import Data.List.NonEmpty import Foreign.Storable import Graphics.Color.Model.Internal import Graphics.Color.Model.RGB@@ -55,6 +57,14 @@ -- | `CMYK` color model instance Elevator e => ColorModel CMYK e where   type Components CMYK e = (e, e, e, e)+  type ChannelCount CMYK = 4+  channelCount _ = 4+  {-# INLINE channelCount #-}+  channelNames _ = "Cyan" :| ["Magenta", "Yellow", "Key"]+  channelColors _ = V3 0x00 0xff 0xff :|+                  [ V3 0xff 0x00 0xff+                  , V3 0xff 0xff 0x00+                  , V3 0xff 0xff 0xff ]   toComponents (ColorCMYK c m y k) = (c, m, y, k)   {-# INLINE toComponents #-}   fromComponents (c, m, y, k) = ColorCMYK c m y k@@ -69,7 +79,7 @@ instance Applicative (Color CMYK) where   pure !e = ColorCMYK e e e e   {-# INLINE pure #-}-  (ColorCMYK fc fm fy fk) <*> (ColorCMYK c m y k) = ColorCMYK (fc c) (fm m) (fy y) (fk k)+  ColorCMYK fc fm fy fk <*> ColorCMYK c m y k = ColorCMYK (fc c) (fm m) (fy y) (fk k)   {-# INLINE (<*>) #-}  -- | `CMYK` color model
src/Graphics/Color/Model/HSI.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE BangPatterns #-}+{-# LANGUAGE DataKinds #-} {-# LANGUAGE DeriveTraversable #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-}@@ -11,7 +12,7 @@ {-# LANGUAGE ViewPatterns #-} -- | -- Module      : Graphics.Color.Model.HSI--- Copyright   : (c) Alexey Kuleshevich 2018-2020+-- Copyright   : (c) Alexey Kuleshevich 2018-2025 -- License     : BSD3 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru> -- Stability   : experimental@@ -23,12 +24,13 @@   , pattern ColorHSI   , pattern ColorHSIA   , pattern ColorH360SI-  , Color+  , Color(..)   , ColorModel(..)   , hsi2rgb   , rgb2hsi   ) where +import Data.List.NonEmpty import Foreign.Storable import Graphics.Color.Model.Internal import Graphics.Color.Model.RGB@@ -85,6 +87,11 @@ -- | `HSI` color model instance Elevator e => ColorModel HSI e where   type Components HSI e = (e, e, e)+  type ChannelCount HSI = 3+  channelCount _ = 3+  {-# INLINE channelCount #-}+  channelNames _ = "Hue" :| ["Saturation", "Intensity"]+  channelColors _ = V3 0x94 0x00 0xd3 :| [V3 0xff 0x8c 0x00, V3 0x00 0xce 0xd1]   toComponents (ColorHSI h s i) = (h, s, i)   {-# INLINE toComponents #-}   fromComponents (h, s, i) = ColorHSI h s i
src/Graphics/Color/Model/HSL.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE BangPatterns #-}+{-# LANGUAGE DataKinds #-} {-# LANGUAGE DeriveTraversable #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-}@@ -11,7 +12,7 @@ {-# LANGUAGE ViewPatterns #-} -- | -- Module      : Graphics.Color.Model.HSL--- Copyright   : (c) Alexey Kuleshevich 2018-2020+-- Copyright   : (c) Alexey Kuleshevich 2018-2025 -- License     : BSD3 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru> -- Stability   : experimental@@ -23,13 +24,14 @@   , pattern ColorHSL   , pattern ColorHSLA   , pattern ColorH360SL-  , Color+  , Color(..)   , ColorModel(..)   , hc2rgb   , hsl2rgb   , rgb2hsl   ) where +import Data.List.NonEmpty import Foreign.Storable import Graphics.Color.Model.HSV (hc2rgb) import Graphics.Color.Model.Internal@@ -86,6 +88,11 @@ -- | `HSL` color model instance Elevator e => ColorModel HSL e where   type Components HSL e = (e, e, e)+  type ChannelCount HSL = 3+  channelCount _ = 3+  {-# INLINE channelCount #-}+  channelNames _ = "Hue" :| ["Saturation", "Lightness"]+  channelColors _ = V3 0x94 0x00 0xd3 :| [V3 0xff 0x8c 0x00, V3 0xaf 0xee 0xee]   toComponents (ColorHSL h s l) = (h, s, l)   {-# INLINE toComponents #-}   fromComponents (h, s, l) = ColorHSL h s l@@ -104,9 +111,11 @@   where     !max' = max r (max g b)     !min' = min r (min g b)-    !h' | max' == r = (    (g - b) / (max' - min')) / 6-        | max' == g = (2 + (b - r) / (max' - min')) / 6-        | max' == b = (4 + (r - g) / (max' - min')) / 6+    !c' = max' - min'+    !h' | c'   == 0 = 0+        | max' == r = (    (g - b) / c') / 6+        | max' == g = (2 + (b - r) / c') / 6+        | max' == b = (4 + (r - g) / c') / 6         | otherwise = 0     !h       | h' < 0 = h' + 1
src/Graphics/Color/Model/HSV.hs view
@@ -1,8 +1,9 @@-{-# LANGUAGE DeriveTraversable #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE BangPatterns #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE DeriveTraversable #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE PatternSynonyms #-} {-# LANGUAGE ScopedTypeVariables #-}@@ -11,7 +12,7 @@ {-# LANGUAGE ViewPatterns #-} -- | -- Module      : Graphics.Color.Model.HSV--- Copyright   : (c) Alexey Kuleshevich 2018-2020+-- Copyright   : (c) Alexey Kuleshevich 2018-2025 -- License     : BSD3 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru> -- Stability   : experimental@@ -23,13 +24,14 @@   , pattern ColorHSV   , pattern ColorHSVA   , pattern ColorH360SV-  , Color+  , Color(..)   , ColorModel(..)   , hc2rgb   , hsv2rgb   , rgb2hsv   ) where +import Data.List.NonEmpty import Foreign.Storable import Graphics.Color.Model.Internal import Graphics.Color.Model.RGB@@ -85,6 +87,11 @@ -- | `HSV` color model instance Elevator e => ColorModel HSV e where   type Components HSV e = (e, e, e)+  type ChannelCount HSV = 3+  channelCount _ = 3+  {-# INLINE channelCount #-}+  channelNames _ = "Hue" :| ["Saturation", "Value"]+  channelColors _ = V3 0x94 0x00 0xd3 :| [V3 0xff 0x8c 0x00, V3 0x5f 0x9e 0x90]   toComponents (ColorHSV h s v) = (h, s, v)   {-# INLINE toComponents #-}   fromComponents (h, s, v) = ColorHSV h s v@@ -120,15 +127,17 @@   where     !max' = max r (max g b)     !min' = min r (min g b)-    !h' | max' == r = (    (g - b) / (max' - min')) / 6-        | max' == g = (2 + (b - r) / (max' - min')) / 6-        | max' == b = (4 + (r - g) / (max' - min')) / 6+    !c' = max' - min'+    !h' | c'   == 0 = 0+        | max' == r = (    (g - b) / c') / 6+        | max' == g = (2 + (b - r) / c') / 6+        | max' == b = (4 + (r - g) / c') / 6         | otherwise = 0     !h       | h' < 0 = h' + 1       | otherwise = h'     !s       | max' == 0 = 0-      | otherwise = (max' - min') / max'+      | otherwise = c' / max'     !v = max' {-# INLINE rgb2hsv #-}
src/Graphics/Color/Model/Internal.hs view
@@ -4,10 +4,11 @@ {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-} {-# LANGUAGE UndecidableInstances #-} -- | -- Module      : Graphics.Color.Model.Internal--- Copyright   : (c) Alexey Kuleshevich 2018-2020+-- Copyright   : (c) Alexey Kuleshevich 2018-2025 -- License     : BSD3 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru> -- Stability   : experimental@@ -43,10 +44,11 @@   , VU.Vector(V_Color)   ) where -import Control.Applicative+import qualified Control.Applicative as A+import Data.List.NonEmpty as NE import Control.DeepSeq (NFData(rnf), deepseq) import Data.Default.Class (Default(..))-import Data.Foldable+import Data.Foldable as F import Data.Kind import Data.Typeable import qualified Data.Vector.Generic as V@@ -75,12 +77,30 @@       ) =>       ColorModel cs e where   type Components cs e :: Type+  type ChannelCount cs :: Nat   -- | Convert a Color to a representation suitable for storage as an unboxed   -- element, usually a tuple of channels.   toComponents :: Color cs e -> Components cs e   -- | Convert from an elemnt representation back to a Color.   fromComponents :: Components cs e -> Color cs e +  -- | Number of channels in the color model (eg. RGB has three).+  --+  -- @since 0.4.0+  channelCount :: Proxy (Color cs e) -> Word8++  -- | Textual name for each of the channels+  --+  -- @since 0.4.0+  channelNames :: Proxy (Color cs e) -> NonEmpty String++  -- | Some non-white 8bit sRGB values for each of the channels that might or+  -- might not have some meaningful visual relation to the actual channel+  -- names. This is useful for plotting values.+  --+  -- @since 0.4.0+  channelColors :: Proxy (Color cs e) -> NonEmpty (V3 Word8)+   -- | Display the @cs@ portion of the pixel. Color itself will not be evaluated.   --   -- @since 0.1.0@@ -94,11 +114,11 @@   instance ColorModel cs e => Num (Color cs e) where-  (+)         = liftA2 (+)+  (+)         = A.liftA2 (+)   {-# INLINE (+) #-}-  (-)         = liftA2 (-)+  (-)         = A.liftA2 (-)   {-# INLINE (-) #-}-  (*)         = liftA2 (*)+  (*)         = A.liftA2 (*)   {-# INLINE (*) #-}   abs         = fmap abs   {-# INLINE abs #-}@@ -109,7 +129,7 @@   instance (ColorModel cs e, Fractional e) => Fractional (Color cs e) where-  (/)          = liftA2 (/)+  (/)          = A.liftA2 (/)   {-# INLINE (/) #-}   recip        = fmap recip   {-# INLINE recip #-}@@ -219,7 +239,7 @@   where     t = asProxy px showsColorModelName     channels =-      case toList px of+      case F.toList px of         [] -> id         (x:xs) -> foldl' (\facc y -> facc . (channelSeparator :) . toShowS y) (toShowS x) xs @@ -357,6 +377,12 @@ instance (ColorModel cs e, cs ~ Opaque (Alpha cs)) =>          ColorModel (Alpha cs) e where   type Components (Alpha cs) e = (Components cs e, e)+  type ChannelCount (Alpha cs) = 1 + ChannelCount cs+  channelCount _ = 1 + channelCount (Proxy :: Proxy (Color cs e))+  {-# INLINE channelCount #-}+  channelNames _ = channelNames (Proxy :: Proxy (Color cs e)) <> ("Alpha" :| [])+  channelColors _ =+    channelColors (Proxy :: Proxy (Color cs e)) <> (V3 0xe6 0xe6 0xfa :| []) -- <- lavander   toComponents (Alpha px a) = (toComponents px, a)   {-# INLINE toComponents #-}   fromComponents (pxc, a) = Alpha (fromComponents pxc) a
src/Graphics/Color/Model/LCH.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE BangPatterns #-}+{-# LANGUAGE DataKinds #-} {-# LANGUAGE DeriveTraversable #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-}@@ -13,14 +14,15 @@   -- * Constructors for an LCH color model.   , pattern ColorLCH   , pattern ColorLCHA-  , Color+  , Color(..)   , ColorModel(..)   , lch2lxy   , lxy2lch   ) where -import Data.Complex ( Complex(..), polar, mkPolar )-import Data.Fixed ( mod' )+import Data.Complex (Complex(..), polar, mkPolar)+import Data.Fixed (mod')+import Data.List.NonEmpty import Foreign.Storable import Graphics.Color.Model.Internal @@ -68,6 +70,14 @@ -- | `LCH` color model instance Elevator e => ColorModel LCH e where   type Components LCH e = (e, e, e)+  type ChannelCount LCH = 3+  channelCount _ = 3+  {-# INLINE channelCount #-}+  channelNames _ = "Luminance" :| ["Chroma", "Hue"]+  channelColors _ = V3 0x80 0x80 0x80 :|+                  [ V3 0xff 0x00 0xff+                  , V3 0xcc 0xff 0x33+                  ]   toComponents (ColorLCH l c h) = (l, c, h)   {-# INLINE toComponents #-}   fromComponents (l, c, h) = ColorLCH l c h
src/Graphics/Color/Model/RGB.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE DataKinds #-} {-# LANGUAGE DeriveTraversable #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-}@@ -10,7 +11,7 @@ {-# LANGUAGE TypeFamilies #-} -- | -- Module      : Graphics.Color.Model.RGB--- Copyright   : (c) Alexey Kuleshevich 2018-2020+-- Copyright   : (c) Alexey Kuleshevich 2018-2025 -- License     : BSD3 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru> -- Stability   : experimental@@ -26,6 +27,7 @@   , ColorModel(..)   ) where +import Data.List.NonEmpty import Foreign.Storable import Graphics.Color.Algebra import Graphics.Color.Model.Internal@@ -58,6 +60,14 @@ -- | `RGB` color model instance Elevator e => ColorModel RGB e where   type Components RGB e = (e, e, e)+  type ChannelCount RGB = 3+  channelCount _ = 3+  {-# INLINE channelCount #-}+  channelNames _ = "Red" :| ["Green", "Blue"]+  channelColors _ = V3 0xff 0x00 0x00 :|+                  [ V3 0x00 0xff 0x00+                  , V3 0x00 0x00 0xff+                  ]   toComponents (ColorRGB r g b) = (r, g, b)   {-# INLINE toComponents #-}   fromComponents (r, g, b) = ColorRGB r g b
src/Graphics/Color/Model/X.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE BangPatterns #-}+{-# LANGUAGE DataKinds #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-}@@ -9,7 +10,7 @@ {-# LANGUAGE TypeFamilies #-} -- | -- Module      : Graphics.Color.Model.X--- Copyright   : (c) Alexey Kuleshevich 2018-2020+-- Copyright   : (c) Alexey Kuleshevich 2018-2025 -- License     : BSD3 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru> -- Stability   : experimental@@ -25,6 +26,7 @@   , rgb2y   ) where +import Data.List.NonEmpty import Data.Coerce import Foreign.Storable import Graphics.Color.Model.Internal@@ -65,6 +67,11 @@ -- | `X` color model instance Elevator e => ColorModel X e where   type Components X e = e+  type ChannelCount X = 1+  channelCount _ = 1+  {-# INLINE channelCount #-}+  channelNames _ = "Gray" :| []+  channelColors _ = V3 0x80 0x80 0x80 :| []   toComponents (X y) = y   {-# INLINE toComponents #-}   fromComponents = X
src/Graphics/Color/Model/YCbCr.hs view
@@ -13,7 +13,7 @@ {-# LANGUAGE UndecidableInstances #-} -- | -- Module      : Graphics.Color.Model.YCbCr--- Copyright   : (c) Alexey Kuleshevich 2018-2020+-- Copyright   : (c) Alexey Kuleshevich 2018-2025 -- License     : BSD3 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru> -- Stability   : experimental@@ -28,6 +28,7 @@   , ycbcr2rgb   ) where +import Data.List.NonEmpty import Foreign.Storable import Graphics.Color.Model.Internal import Graphics.Color.Model.RGB@@ -72,6 +73,11 @@ -- | `YCbCr` color model instance Elevator e => ColorModel YCbCr e where   type Components YCbCr e = (e, e, e)+  type ChannelCount YCbCr = 3+  channelCount _ = 3+  {-# INLINE channelCount #-}+  channelNames _ = "Luma" :| ["Blue Chroma Diff", "Red Chroma Diff"]+  channelColors _ = V3 0x80 0x80 0x80 :| [V3 0x00 0x00 0x80, V3 0x8b 0x00 0x00]   toComponents (ColorYCbCr y cb cr) = (y, cb, cr)   {-# INLINE toComponents #-}   fromComponents (y, cb, cr) = ColorYCbCr y cb cr
src/Graphics/Color/Space.hs view
@@ -2,7 +2,7 @@ {-# LANGUAGE ScopedTypeVariables #-} -- | -- Module      : Graphics.Color.Space--- Copyright   : (c) Alexey Kuleshevich 2018-2020+-- Copyright   : (c) Alexey Kuleshevich 2018-2025 -- License     : BSD3 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru> -- Stability   : experimental
src/Graphics/Color/Space/CIE1931/RGB.hs view
@@ -11,7 +11,7 @@ {-# LANGUAGE TypeFamilies #-} -- | -- Module      : Graphics.Color.Space.CIE1931.RGB--- Copyright   : (c) Alexey Kuleshevich 2018-2020+-- Copyright   : (c) Alexey Kuleshevich 2018-2025 -- License     : BSD3 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru> -- Stability   : experimental@@ -60,6 +60,11 @@ -- | `CIERGB` color space instance (Typeable l, Elevator e) => ColorModel (CIERGB l) e where   type Components (CIERGB l) e = (e, e, e)+  type ChannelCount (CIERGB l) = 3+  channelCount _ = 3+  {-# INLINE channelCount #-}+  channelNames _ = channelNames (Proxy :: Proxy (Color CM.RGB e))+  channelColors _ = channelColors (Proxy :: Proxy (Color CM.RGB e))   toComponents = toComponents . unColorRGB   {-# INLINE toComponents #-}   fromComponents = mkColorRGB . fromComponents@@ -74,6 +79,10 @@   {-# INLINE fromBaseSpace #-}   luminance = rgbLinearLuminance . castLinearity . fmap toRealFloat   {-# INLINE luminance #-}+  grayscale = toBaseModel . fmap fromDouble . luminance+  {-# INLINE grayscale #-}+  applyGrayscale c f = castLinearity (rgbLinearApplyGrayscale (castLinearity c) f)+  {-# INLINE applyGrayscale #-}   toColorXYZ = rgbLinear2xyz . fmap toRealFloat . castLinearity   {-# INLINE toColorXYZ #-}   fromColorXYZ xyz = castLinearity (fromRealFloat <$> xyz2rgbLinear @CIERGB xyz)@@ -94,4 +103,4 @@ -- @since 0.2.0 castLinearity :: Color (CIERGB l') e -> Color (CIERGB l) e castLinearity = coerce-+{-# INLINE castLinearity #-}
src/Graphics/Color/Space/CIE1931/XYZ.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE PatternSynonyms #-} -- | -- Module      : Graphics.Color.Space.CIE1931.XYZ--- Copyright   : (c) Alexey Kuleshevich 2019-2020+-- Copyright   : (c) Alexey Kuleshevich 2019-2025 -- License     : BSD3 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru> -- Stability   : experimental
src/Graphics/Color/Space/CIE1976/LAB.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE BangPatterns #-}+{-# LANGUAGE DataKinds #-} {-# LANGUAGE DeriveTraversable #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-}@@ -11,7 +12,7 @@ {-# LANGUAGE TypeFamilies #-} -- | -- Module      : Graphics.Color.Space.CIE1976.LAB--- Copyright   : (c) Alexey Kuleshevich 2018-2020+-- Copyright   : (c) Alexey Kuleshevich 2018-2025 -- License     : BSD3 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru> -- Stability   : experimental@@ -23,8 +24,16 @@   , pattern ColorLAB   , pattern ColorLABA   , LAB+    -- * Helpers+    -- ** XYZ to L*a*b*+  , xyz2lab+  , ft+    -- ** L*a*b* to XYZ+  , lab2xyz+  , ift   ) where +import Data.List.NonEmpty import Foreign.Storable import Graphics.Color.Model.Internal import Graphics.Color.Space.Internal@@ -34,6 +43,52 @@ --------------  -- | [CIE L*a*b*](https://en.wikipedia.org/wiki/CIELAB_color_space) color space+--+-- It is customary to have CIELAB color channels to be in range of [0, 100], however in+-- this library all values for consistency are kept in a [0, 1] range for floating point+-- precision.+--+-- Conversion from `XYZ` (`xyz2lab`):+--+-- \[+-- \begin{align}+--   L^\star &= 1.16 \  f\!\left(\frac{Y}{Y_{\mathrm{n}}}\right) - 0.16\\+--   a^\star &= 5.0 \left(f\!\left(\frac{X}{X_{\mathrm{n}}}\right) - f\!\left(\frac{Y}{Y_{\mathrm{n}}}\right)\right)\\+--   b^\star &= 2.0 \left(f\!\left(\frac{Y}{Y_{\mathrm{n}}}\right) - f\!\left(\frac{Z}{Z_{\mathrm{n}}}\right)\right)+-- \end{align}+-- \]+--+-- Where `ft` is defined as:+--+-- \[+-- \begin{align}+--   f(t) &= \begin{cases}+--     \sqrt[3]{t} & \text{if } t > \delta^3 \\+--     \dfrac{t}{3 \delta^2} + \frac{4}{29} & \text{otherwise}+--   \end{cases} \\+--   \delta &= \tfrac{6}{29}+-- \end{align}+-- \]+--+-- Conversion to `XYZ` (`lab2xyz`):+--+-- \[+-- \begin{align}+--   X &= X_{\mathrm{n}} f^{-1}\left(\frac{L^\star+0.16}{1.16} + \frac{a^\star}{5.0}\right)\\+--   Y &= Y_{\mathrm{n}} f^{-1}\left(\frac{L^\star+0.16}{1.16}\right)\\+--   Z &= Z_{\mathrm{n}} f^{-1}\left(\frac{L^\star+0.16}{1.16} - \frac{b^\star}{2.0}\right)\\+-- \end{align}+-- \]+--+-- Where `ift` is defined as:+--+-- \[+-- f^{-1}(t) = \begin{cases}+--   t^3 & \text{if } t > \delta \\+--   3\delta^2\left(t - \tfrac{4}{29}\right) & \text{otherwise}+-- \end{cases}+-- \]+-- data LAB (i :: k)  -- | Color in CIE L*a*b* color space@@ -77,6 +132,14 @@ -- | CIE1976 `LAB` color space instance (Illuminant i, Elevator e) => ColorModel (LAB i) e where   type Components (LAB i) e = (e, e, e)+  type ChannelCount (LAB i) = 3+  channelCount _ = 3+  {-# INLINE channelCount #-}+  channelNames _ = "L*" :| ["a*", "b*"]+  channelColors _ = V3 0x80 0x80 0x80 :| -- gray+                  [ V3 0x00 0x64 0x00    -- dark green+                  , V3 0x00 0x00 0x8b    -- dark blue+                  ]   toComponents (ColorLAB l' a' b') = (l', a', b')   {-# INLINE toComponents #-}   fromComponents (l', a', b') = ColorLAB l' a' b'@@ -91,6 +154,10 @@   {-# INLINE fromBaseSpace #-}   luminance (ColorLAB l' _ _) = Y (ift (scaleLightness l'))   {-# INLINE luminance #-}+  grayscale (ColorLAB l' _ _) = X l'+  {-# INLINE grayscale #-}+  replaceGrayscale (ColorLAB _ a' b') (X l') = ColorLAB l' a' b'+  {-# INLINE replaceGrayscale #-}   toColorXYZ = lab2xyz   {-# INLINE toColorXYZ #-}   fromColorXYZ = xyz2lab@@ -102,22 +169,22 @@   -> Color (XYZ i) a lab2xyz (ColorLAB l' a' b') = ColorXYZ x y z   where-    !(ColorXYZ wx _ wz) = whitePointTristimulus :: Color (XYZ i) a+    ColorXYZ wx _ wz = whitePointTristimulus :: Color (XYZ i) a     !l = scaleLightness l'-    !x = wx * ift (l + toRealFloat a' / 500)+    !x = wx * ift (l + toRealFloat a' / 5)     !y = ift l-    !z = wz * ift (l - toRealFloat b' / 200)+    !z = wz * ift (l - toRealFloat b' / 2) {-# INLINE lab2xyz #-}  scaleLightness :: (Elevator e, Elevator a, RealFloat a) => e -> a-scaleLightness l' = (toRealFloat l' + 16) / 116+scaleLightness l' = (toRealFloat l' + 0.16) / 1.16 {-# INLINE scaleLightness #-}  ift :: (Fractional a, Ord a) => a -> a ift t   | t > 6 / 29 = t ^ (3 :: Int)   | otherwise = (108 / 841) * (t - 4 / 29)-+{-# INLINE ift #-}   xyz2lab ::@@ -126,13 +193,13 @@   -> Color (LAB i) e xyz2lab (ColorXYZ x y z) = ColorLAB l' a' b'   where-    !(ColorXYZ wx _ wz) = whitePointTristimulus :: Color (XYZ i) e+    ColorXYZ wx _ wz = whitePointTristimulus :: Color (XYZ i) e     !fx = ft (toRealFloat x / wx)     !fy = ft (toRealFloat y)     !fz = ft (toRealFloat z / wz)-    !l' = 116 * fy - 16-    !a' = 500 * (fx - fy)-    !b' = 200 * (fy - fz)+    !l' = 1.16 * fy - 0.16+    !a' = 5 * (fx - fy)+    !b' = 2 * (fy - fz) {-# INLINE xyz2lab #-}  ft :: RealFloat a => a -> a
src/Graphics/Color/Space/CIE1976/LAB/LCH.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE DataKinds #-} {-# LANGUAGE DeriveTraversable #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-}@@ -5,10 +6,11 @@ {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE PatternSynonyms #-} {-# LANGUAGE PolyKinds #-}+{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE UndecidableInstances #-}-{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE ViewPatterns #-}  -- | -- Module: Graphics.Color.Space.CIE1976.LAB.LCH@@ -20,6 +22,7 @@   , Color(LCHab)   ) where +import Data.List.NonEmpty import Data.Coerce import Data.Proxy import Foreign.Storable@@ -73,9 +76,17 @@ -- | CIE1976 `LCHab` color space instance (Illuminant i, Elevator e, ColorModel (LAB i) e) => ColorModel (LCHab i) e where   type Components (LCHab i) e = (e, e, e)-  toComponents = toComponents . coerce+  type ChannelCount (LCHab i) = 3+  channelCount _ = 3+  {-# INLINE channelCount #-}+  channelNames _ = "L" :| ["Cab", "Hab"]+  channelColors _ = V3 0x80 0x80 0x80 :|+                  [ V3 0x99 0xff 0x99+                  , V3 0x66 0x66 0xff+                  ]+  toComponents (LCHab lch) = toComponents lch   {-# INLINE toComponents #-}-  fromComponents = coerce . fromComponents+  fromComponents = LCHab . fromComponents   {-# INLINE fromComponents #-}   showsColorModelName _ =     ("LCH-"++) . showsColorModelName (Proxy :: Proxy (Color (LAB i) e))@@ -83,9 +94,13 @@ instance (Illuminant i, Elevator e, ColorSpace (LAB i) i e) => ColorSpace (LCHab i) i e where   type BaseModel (LCHab i) = CM.LCH   type BaseSpace (LCHab i) = LAB i-  toBaseSpace = fmap fromDouble . fromComponents . CM.lch2lxy . fmap toDouble . coerce+  toBaseSpace (LCHab lch) = fmap fromDouble . fromComponents . CM.lch2lxy . fmap toDouble $ lch   {-# INLINE toBaseSpace #-}-  fromBaseSpace = coerce . fmap fromDouble . CM.lxy2lch . toComponents . fmap toDouble+  fromBaseSpace = LCHab . fmap fromDouble . CM.lxy2lch . toComponents . fmap toDouble   {-# INLINE fromBaseSpace #-}   luminance = luminance . toBaseSpace   {-# INLINE luminance #-}+  grayscale (coerce -> V3 l _ _) = X l+  {-# INLINE grayscale #-}+  replaceGrayscale (coerce -> V3 _ c h) (X l) = coerce (V3 l c h)+  {-# INLINE replaceGrayscale #-}
src/Graphics/Color/Space/CIE1976/LUV.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE BangPatterns #-}+{-# LANGUAGE DataKinds #-} {-# LANGUAGE DeriveTraversable #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-}@@ -9,6 +10,7 @@ {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE ViewPatterns #-} -- | -- Module      : Graphics.Color.Space.CIE1976.LUV --@@ -20,6 +22,8 @@   , LUV   ) where +import Data.Coerce+import Data.List.NonEmpty import Foreign.Storable import Graphics.Color.Model.Internal import Graphics.Color.Space.Internal@@ -72,6 +76,14 @@ -- | CIE1976 `LUV` color space instance (Illuminant i, Elevator e) => ColorModel (LUV i) e where   type Components (LUV i) e = (e, e, e)+  type ChannelCount (LUV i) = 3+  channelCount _ = 3+  {-# INLINE channelCount #-}+  channelNames _ = "L" :| ["U", "V"]+  channelColors _ = V3 0x80 0x80 0x80 :|+                  [ V3 0x00 0xff 0xff+                  , V3 0x00 0x00 0x00+                  ]   toComponents (ColorLUV l' u' v') = (l', u', v')   {-# INLINE toComponents #-}   fromComponents (l', u', v') = ColorLUV l' u' v'@@ -86,6 +98,10 @@   {-# INLINE fromBaseSpace #-}   luminance (ColorLUV l' _ _) = Y (ift (scaleLightness l'))   {-# INLINE luminance #-}+  grayscale (coerce -> V3 l _ _) = X l+  {-# INLINE grayscale #-}+  replaceGrayscale (coerce -> V3 _ c h) (X l) = coerce (V3 l c h)+  {-# INLINE replaceGrayscale #-}   toColorXYZ = luv2xyz   {-# INLINE toColorXYZ #-}   fromColorXYZ = xyz2luv
src/Graphics/Color/Space/CIE1976/LUV/LCH.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE DataKinds #-} {-# LANGUAGE DeriveTraversable #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-}@@ -9,6 +10,7 @@ {-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE ViewPatterns #-}  -- | -- Module: Graphics.Color.Space.CIE1976.LUV.LCH@@ -20,6 +22,7 @@   , Color(LCHuv)   ) where +import Data.List.NonEmpty import Data.Coerce import Data.Proxy import Foreign.Storable@@ -73,9 +76,17 @@ -- | CIE1976 `LCHuv` color space instance (Illuminant i, Elevator e, ColorModel (LUV i) e) => ColorModel (LCHuv i) e where   type Components (LCHuv i) e = (e, e, e)-  toComponents = toComponents . coerce+  type ChannelCount (LCHuv i) = 3+  channelCount _ = 3+  {-# INLINE channelCount #-}+  channelNames _ = "L" :| ["Cuv", "Huv"]+  channelColors _ = V3 0x80 0x80 0x80 :|+                  [ V3 0x99 0x00 0x99+                  , V3 0x99 0xcc 0x00+                  ]+  toComponents (LCHuv lch) =  toComponents lch   {-# INLINE toComponents #-}-  fromComponents = coerce . fromComponents+  fromComponents = LCHuv . fromComponents   {-# INLINE fromComponents #-}   showsColorModelName _ =     ("LCH-"++) . showsColorModelName (Proxy :: Proxy (Color (LUV i) e))@@ -83,9 +94,13 @@ instance (Illuminant i, Elevator e, ColorSpace (LUV i) i e) => ColorSpace (LCHuv i) i e where   type BaseModel (LCHuv i) = CM.LCH   type BaseSpace (LCHuv i) = LUV i-  toBaseSpace = fmap fromDouble . fromComponents . CM.lch2lxy . fmap toDouble . coerce+  toBaseSpace (LCHuv lch) = fmap fromDouble . fromComponents . CM.lch2lxy . fmap toDouble $ lch   {-# INLINE toBaseSpace #-}-  fromBaseSpace = coerce . fmap fromDouble . CM.lxy2lch . toComponents . fmap toDouble+  fromBaseSpace = LCHuv . fmap fromDouble . CM.lxy2lch . toComponents . fmap toDouble   {-# INLINE fromBaseSpace #-}   luminance = luminance . toBaseSpace   {-# INLINE luminance #-}+  grayscale (coerce -> V3 l _ _) = X l+  {-# INLINE grayscale #-}+  replaceGrayscale (coerce -> V3 _ c h) (X l) = coerce (V3 l c h)+  {-# INLINE replaceGrayscale #-}
+ src/Graphics/Color/Space/DIN99.hs view
@@ -0,0 +1,192 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveTraversable #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE Strict #-}+{-# LANGUAGE TypeFamilies #-}++module Graphics.Color.Space.DIN99+  ( pattern DIN99,+    pattern ColorDIN99,+    DIN99,+    deltaE,+  )+where++import Data.List.NonEmpty+import Foreign.Storable+import GHC.Generics (Generic)+import Graphics.Color.Model.Internal+import Graphics.Color.Space.Internal+import Graphics.Color.Space.CIE1976.LAB++data DIN99 (i :: k)++-- | Color in DIN99 color space+newtype instance Color (DIN99 i) e = DIN99 (V3 e)++pattern ColorDIN99 :: e -> e -> e -> Color (DIN99 i) e+pattern ColorDIN99 l' a' b' = DIN99 (V3 l' a' b')++{-# COMPLETE ColorDIN99 #-}++-- | `DIN99` color space+deriving instance Eq e => Eq (Color (DIN99 i) e)++-- | `DIN99` color space+deriving instance Ord e => Ord (Color (DIN99 i) e)++-- | `DIN99` color space+deriving instance Functor (Color (DIN99 i))++-- | `DIN99` color space+deriving instance Applicative (Color (DIN99 i))++-- | `DIN99` color space+deriving instance Foldable (Color (DIN99 i))++-- | `DIN99` color space+deriving instance Traversable (Color (DIN99 i))++-- | `DIN99` color space+deriving instance Storable e => Storable (Color (DIN99 i) e)++-- | `DIN99` color space+instance (Illuminant i, Elevator e) => Show (Color (DIN99 i) e) where+  showsPrec _ = showsColorModel++instance (Illuminant i, Elevator e) => ColorModel (DIN99 i) e where+  type Components (DIN99 i) e = (e, e, e)+  type ChannelCount (DIN99 i) = 3+  channelCount _ = 3+  {-# INLINE channelCount #-}+  channelNames _ = "L*" :| ["a*", "b*"] -- DIN99 is base on Lab color space+  channelColors _ = V3 0x80 0x80 0x80 :| -- gray+                  [ V3 0x00 0x64 0x00    -- dark green+                  , V3 0x00 0x00 0x8b    -- dark blue+                  ]+  toComponents (ColorDIN99 l' a' b') = (l', a', b')+  {-# INLINE toComponents #-}+  fromComponents (l', a', b') = ColorDIN99 l' a' b'+  {-# INLINE fromComponents #-}++instance (Illuminant i, Elevator e, RealFloat e) => ColorSpace (DIN99 (i :: k)) i e where+  type BaseModel (DIN99 i) = DIN99 i+  type BaseSpace (DIN99 i) = DIN99 i+  toBaseSpace = id+  {-# INLINE toBaseSpace #-}+  fromBaseSpace = id+  {-# INLINE fromBaseSpace #-}+  luminance = luminance . dinToLAB DIN99Method+  {-# INLINE luminance #-}+  grayscale (ColorDIN99 l' _ _) = X l'+  {-# INLINE grayscale #-}+  replaceGrayscale (ColorDIN99 _ a' b') (X l') = ColorDIN99 l' a' b'+  {-# INLINE replaceGrayscale #-}+  toColorXYZ = toColorXYZ . dinToLAB DIN99Method+  {-# INLINE toColorXYZ #-}+  fromColorXYZ = labToDIN DIN99Method . fromColorXYZ+  {-# INLINE fromColorXYZ #-}++kE :: RealFloat a => a+kE = 1++kCH :: RealFloat a => a+kCH = 1++data DINMethod+  = ASTMD2244_07Method+  | DIN99Method+  | DIN99bMethod+  | DIN99cMethod+  | DIN99dMethod+  deriving (Eq, Show, Read, Ord, Bounded, Enum, Generic)++fromDINMethod ::+  ( Fractional a,+    Fractional b,+    Fractional c,+    Fractional d,+    Fractional f,+    Fractional g,+    Fractional h,+    Fractional e+  ) =>+  DINMethod ->+  (a, b, c, d, e, f, g, h)+fromDINMethod ASTMD2244_07Method =+  (105.509, 0.0158, 16.0, 0.7, 1, 9 / 200, 0.0, 9 / 200)+fromDINMethod DIN99Method = (105.509, 0.0158, 16.0, 0.7, 1, 9 / 200, 0.0, 9 / 200)+fromDINMethod DIN99bMethod = (303.67, 0.0039, 26.0, 0.83, 23.0, 0.075, 26.0, 1)+fromDINMethod DIN99cMethod = (317.65, 0.0037, 0.0, 0.94, 23.0, 0.066, 0.0, 1)+fromDINMethod DIN99dMethod = (325.22, 0.0036, 50.0, 1.14, 22.5, 0.06, 50.0, 1)++radians :: Floating a => a -> a+radians x = pi / 180 * x++-- | deltaE distance in DIN99 is the perceptually-uniform distance between+-- two points in the space. Otherwise known as euclidean distance.+deltaE ::+  (Floating e, Illuminant i, Elevator e) =>+  Color (LAB i) e ->+  Color (LAB i) e ->+  e+deltaE a b = sqrt $ sum ((a - b) ** 2)++-- | Bidirectional @DIN99@ @DIN99@ conversion as implemented in Python+-- [colour](https://github.com/colour-science/colour/blob/c3735e5d0ad67443022ece0b42b575e040eb61d1/colour/models/din99.py#L79) package.+--+-- >>> import Graphics.Color.Illuminant.Wikipedia as W+-- >>> labToDIN DIN99Method (ColorLAB 41.527874 52.638584 26.92318 :: Color (LAB 'W.D65) Float)+-- <DIN99 Degree2 'D65:(53.22821400,28.41634600, 3.89839500)>+-- >>> dinToLAB DIN99Method (ColorDIN99 53.228218 28.416348 3.8983955 :: Color (DIN99 'W.D65) Float)+-- <LAB Degree2 'D65:(41.52787800,52.63859000,26.92318300)>+labToDIN ::+  (RealFloat e) =>+  DINMethod ->+  Color (LAB i) e ->+  Color (DIN99 i) e+labToDIN m (ColorLAB l a b) = ColorDIN99 l_99 a_99 b_99+  where+    cos_c = cos $ radians c_3+    sin_c = sin $ radians c_3+    e = cos_c * a + sin_c * b+    f = c_4 * (- sin_c * a + cos_c * b)+    g' = sqrt (e ** 2 + f ** 2)+    h_ef = atan2 f e + radians c_7+    c_99 = c_5 * log (1 + c_6 * g') / (c_8 * kCH * kE)+    a_99 = c_99 * cos h_ef+    b_99 = c_99 * sin h_ef+    l_99 = c_1 * log (1 + c_2 * l) * kE+    (c_1, c_2, c_3, c_4, c_5, c_6, c_7, c_8) = fromDINMethod m++dinToLAB ::+  RealFloat e =>+  DINMethod ->+  Color (DIN99 i) e ->+  Color (LAB i) e+dinToLAB m (ColorDIN99 l_99 a_99 b_99) = ColorLAB l a b+  where+    expm1 x = exp x - 1+    cos' = cos (radians c_3)+    sin' = sin (radians c_3)++    h_99 = atan2 b_99 a_99 - radians c_7++    c_99 = sqrt (a_99 ** 2 + b_99 ** 2)+    g' = expm1 (c_8 / c_5 * c_99 * kCH * kE) / c_6++    e = g' * cos h_99+    f = g' * sin h_99++    a = e * cos' - f / c_4 * sin'+    b = e * sin' + f / c_4 * cos'+    l = expm1 (l_99 * kE / c_1) / c_2+    (c_1, c_2, c_3, c_4, c_5, c_6, c_7, c_8) = fromDINMethod m
src/Graphics/Color/Space/Internal.hs view
@@ -11,11 +11,12 @@ {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-} {-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE ViewPatterns #-} -- | -- Module      : Graphics.Color.Space.Internal--- Copyright   : (c) Alexey Kuleshevich 2018-2020+-- Copyright   : (c) Alexey Kuleshevich 2018-2025 -- License     : BSD3 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru> -- Stability   : experimental@@ -50,6 +51,7 @@   , whitePointTristimulus   , CCT(..)   , Y+  , unY   , pattern Y   , pattern YA   , XYZ@@ -61,20 +63,23 @@   , showsColorModel   , module Graphics.Color.Algebra.Binary   , module Graphics.Color.Algebra.Elevator+  , module Graphics.Color.Model.X   ) where +import Data.Coerce+import Data.Kind+import Data.List.NonEmpty+import Data.Typeable import Foreign.Storable+import GHC.TypeNats import Graphics.Color.Algebra.Binary import Graphics.Color.Algebra.Elevator import Graphics.Color.Model.Internal-import qualified Graphics.Color.Model.X as CM-import Data.Typeable-import Data.Coerce-import GHC.TypeNats-import Data.Kind+import Graphics.Color.Model.X  class (Illuminant i, ColorModel (BaseModel cs) e, ColorModel cs e) =>   ColorSpace cs (i :: k) e | cs -> i where+  {-# MINIMAL toBaseSpace, fromBaseSpace, luminance, grayscale, (replaceGrayscale|applyGrayscale) #-}    type BaseModel cs :: Type @@ -96,11 +101,50 @@   toBaseSpace :: ColorSpace (BaseSpace cs) i e => Color cs e -> Color (BaseSpace cs) e   fromBaseSpace :: ColorSpace (BaseSpace cs) i e => Color (BaseSpace cs) e -> Color cs e -  -- | Get the relative luminance of a color+  -- | Get the relative luminance of a color. This is different from `grayscale` in that+  -- it will produce achromatic color that is no longer dependent on the source color   --   -- @since 0.1.0   luminance :: (Elevator a, RealFloat a) => Color cs e -> Color (Y i) a +  -- | Drop chromatic information and get only the grayscale information from+  -- the color. Without knowledge of the source color the produced value is+  -- inconsequential, becaus each class of color spaces has its own notion of+  -- grayscale (luma, luminocity, in linear or non-linear form, etc.)+  --+  -- /Warning/ - This method is still experimental. Use at your own risk.+  --+  -- @since 0.4.0+  grayscale :: Color cs e -> Color X e++  -- | Replace the grayscale information, leaving the chromatic portion of the coloer+  -- intact.+  --+  -- Property that this function must obide:+  --+  -- > replaceGrayscale c y = applyGrayscale c (const y)+  --+  -- /Warning/ - This method is still experimental. Use at your own risk.+  --+  -- @since 0.4.0+  replaceGrayscale :: Color cs e -> Color X e -> Color cs e+  replaceGrayscale c y = applyGrayscale c (const y)+  {-# INLINE replaceGrayscale #-}++  -- | Apply a function to the grayscale portion of the color leaving chromaticity+  -- intact. The meaning of "grayscale" is very much specific to the color space it is being+  -- applied to.+  --+  -- Property that this function must obide:+  --+  -- > applyGrayscale c f = replaceGrayscale c (f (grayscale c))+  --+  -- @since 0.4.0+  applyGrayscale :: Color cs e -> (Color X e -> Color X e) -> Color cs e+  applyGrayscale c f = replaceGrayscale c (f (grayscale c))+  {-# INLINE applyGrayscale #-}++   toColorXYZ :: (Elevator a, RealFloat a) => Color cs e -> Color (XYZ i) a   default toColorXYZ ::     (ColorSpace (BaseSpace cs) i e, Elevator a, RealFloat a) => Color cs e -> Color (XYZ i) a@@ -132,6 +176,10 @@   {-# INLINE fromColorXYZ #-}   luminance = luminance . dropAlpha   {-# INLINE luminance #-}+  grayscale = grayscale . dropAlpha+  {-# INLINE grayscale #-}+  replaceGrayscale c x = modifyOpaque (`replaceGrayscale` x) c+  {-# INLINE replaceGrayscale #-}   toBaseSpace = modifyOpaque toBaseSpace   {-# INLINE toBaseSpace #-}   fromBaseSpace = modifyOpaque fromBaseSpace@@ -326,6 +374,11 @@ -- | CIE1931 `XYZ` color space instance (Illuminant i, Elevator e) => ColorModel (XYZ (i :: k)) e where   type Components (XYZ i) e = (e, e, e)+  type ChannelCount (XYZ i) = 3+  channelCount _ = 3+  {-# INLINE channelCount #-}+  channelNames _ = "X" :| ["Y", "Z"]+  channelColors _ = V3 0xff 0xff 0xff :| [V3 0x80 0x80 0x80, V3 0x2f 0x4f 0x4f]   toComponents (ColorXYZ x y z) = (x, y, z)   {-# INLINE toComponents #-}   fromComponents (x, y, z) = ColorXYZ x y z@@ -340,6 +393,10 @@   fromBaseSpace = id   luminance (ColorXYZ _ y _) = Y (toRealFloat y)   {-# INLINE luminance #-}+  grayscale (ColorXYZ _ y _) = X y+  {-# INLINE grayscale #-}+  replaceGrayscale (ColorXYZ x _ z) (X y) = ColorXYZ x y z+  {-# INLINE replaceGrayscale #-}   toColorXYZ (ColorXYZ x y z) = ColorXYZ (toRealFloat x) (toRealFloat y) (toRealFloat z)   {-# INLINE toColorXYZ #-}   fromColorXYZ (ColorXYZ x y z) = ColorXYZ (fromRealFloat x) (fromRealFloat y) (fromRealFloat z)@@ -398,6 +455,11 @@ -- | CIE xyY color space instance (Illuminant i, Elevator e) => ColorModel (CIExyY (i :: k)) e where   type Components (CIExyY i) e = (e, e)+  type ChannelCount (CIExyY i) = 2+  channelCount _ = 2+  {-# INLINE channelCount #-}+  channelNames _ = "x" :| ["y"]+  channelColors _ = V3 0xbd 0xb7 0x6b :| [V3 0xf0 0xe6 0x8c]   toComponents (CIExyY (V2 x y)) = (x, y)   {-# INLINE toComponents #-}   fromComponents (x, y) = CIExyY (V2 x y)@@ -405,7 +467,7 @@   showsColorModelName _ = showsType (Proxy :: Proxy (CIExyY i))  -- | CIE xyY color space-instance (Illuminant i, Elevator e) => ColorSpace (CIExyY (i :: k)) i e where+instance (Illuminant i, RealFloat e, Elevator e) => ColorSpace (CIExyY (i :: k)) i e where   type BaseModel (CIExyY i) = CIExyY i   toBaseModel = id   fromBaseModel = id@@ -413,6 +475,14 @@   fromBaseSpace = id   luminance _ = Y 1   {-# INLINE luminance #-}+  grayscale _ = X 1+  {-# INLINE grayscale #-}+  replaceGrayscale xy y =+    fromColorXYZ (replaceGrayscale (toColorXYZ xy) y :: Color (XYZ i) e)+  {-# INLINE replaceGrayscale #-}+  applyGrayscale xy f =+    fromColorXYZ (applyGrayscale (toColorXYZ xy) f :: Color (XYZ i) e)+  {-# INLINE applyGrayscale #-}   toColorXYZ xy = ColorXYZ (x / y) 1 ((1 - x - y) / y)     where ColorCIExy x y = toRealFloat <$> xy   {-# INLINE toColorXYZ #-}@@ -423,7 +493,6 @@   {-# INLINE fromColorXYZ #-}  - ------------- --- Y --- -------------@@ -432,16 +501,21 @@ data Y (i :: k)  -- | Luminance `Y`-newtype instance Color (Y i) e = Luminance (CM.Color CM.X e)+newtype instance Color (Y i) e = Luminance (Color X e) +-- | Get the luminance value+unY :: Color (Y i) e -> e+unY = coerce+{-# INLINE unY #-}+ -- | Constructor for @Y@ with alpha channel. pattern Y :: e -> Color (Y i) e-pattern Y y = Luminance (CM.X y)+pattern Y y = Luminance (X y) {-# COMPLETE Y #-}  -- | Constructor for @Y@ with alpha channel. pattern YA :: e -> e -> Color (Alpha (Y i)) e-pattern YA y a = Alpha (Luminance (CM.X y)) a+pattern YA y a = Alpha (Luminance (X y)) a {-# COMPLETE YA #-}  -- | `Y` - relative luminance of a color space@@ -467,6 +541,11 @@ -- | `Y` - relative luminance of a color space instance (Illuminant i, Elevator e) => ColorModel (Y i) e where   type Components (Y i) e = e+  type ChannelCount (Y i) = 1+  channelCount _ = 1+  {-# INLINE channelCount #-}+  channelNames _ = "Luminance" :| []+  channelColors _ = V3 0x80 0x80 0x80 :| []   toComponents = coerce   {-# INLINE toComponents #-}   fromComponents = coerce@@ -475,16 +554,22 @@  -- | CIE1931 `XYZ` color space instance (Illuminant i, Elevator e) => ColorSpace (Y i) i e where-  type BaseModel (Y i) = CM.X+  type BaseModel (Y i) = X   toBaseSpace = id   fromBaseSpace = id   luminance = fmap toRealFloat   {-# INLINE luminance #-}+  grayscale = coerce+  {-# INLINE grayscale #-}+  applyGrayscale c f = coerce (f (coerce c))+  {-# INLINE applyGrayscale #-}+  replaceGrayscale _ = coerce+  {-# INLINE replaceGrayscale #-}   toColorXYZ (Y y) = ColorXYZ 0 (toRealFloat y) 0   {-# INLINE toColorXYZ #-}   fromColorXYZ (ColorXYZ _ y _) = Y (fromRealFloat y)   {-# INLINE fromColorXYZ #-}  {-# RULES-"luminance :: RealFloat a => Color Y a -> Color Y a" luminance = id+"luminance :: RealFloat a => Color (Y i) a -> Color (Y i) a" luminance = id  #-}
src/Graphics/Color/Space/RGB.hs view
@@ -1,6 +1,6 @@ -- | -- Module      : Graphics.Color.Space.RGB--- Copyright   : (c) Alexey Kuleshevich 2019-2020+-- Copyright   : (c) Alexey Kuleshevich 2019-2025 -- License     : BSD3 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru> -- Stability   : experimental
src/Graphics/Color/Space/RGB/AdobeRGB.hs view
@@ -7,11 +7,12 @@ {-# LANGUAGE NegativeLiterals #-} {-# LANGUAGE PatternSynonyms #-} {-# LANGUAGE PolyKinds #-}+{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE TypeFamilies #-} -- | -- Module      : Graphics.Color.Space.RGB.AdobeRGB--- Copyright   : (c) Alexey Kuleshevich 2019-2020+-- Copyright   : (c) Alexey Kuleshevich 2019-2025 -- License     : BSD3 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru> -- Stability   : experimental@@ -112,6 +113,11 @@ -- | `AdobeRGB` color space instance (Typeable l, Elevator e) => ColorModel (AdobeRGB l) e where   type Components (AdobeRGB l) e = (e, e, e)+  type ChannelCount (AdobeRGB l) = 3+  channelCount _ = 3+  {-# INLINE channelCount #-}+  channelNames _ = channelNames (Proxy :: Proxy (Color CM.RGB e))+  channelColors _ = channelColors (Proxy :: Proxy (Color CM.RGB e))   toComponents = toComponents . unColorRGB   {-# INLINE toComponents #-}   fromComponents = mkColorRGB . fromComponents@@ -126,6 +132,10 @@   {-# INLINE fromBaseSpace #-}   luminance = rgbLinearLuminance . fmap toRealFloat   {-# INLINE luminance #-}+  grayscale = rgbLinearGrayscale+  {-# INLINE grayscale #-}+  applyGrayscale = rgbLinearApplyGrayscale+  {-# INLINE applyGrayscale #-}   toColorXYZ = rgbLinear2xyz . fmap toRealFloat   {-# INLINE toColorXYZ #-}   fromColorXYZ = fmap fromRealFloat . xyz2rgbLinear@@ -140,6 +150,10 @@   {-# INLINE fromBaseSpace #-}   luminance = rgbLuminance . fmap toRealFloat   {-# INLINE luminance #-}+  grayscale = rgbNonLinearGrayscale+  {-# INLINE grayscale #-}+  applyGrayscale = rgbNonLinearApplyGrayscale+  {-# INLINE applyGrayscale #-}   toColorXYZ = rgb2xyz . fmap toRealFloat   {-# INLINE toColorXYZ #-}   fromColorXYZ = fmap fromRealFloat . xyz2rgb
src/Graphics/Color/Space/RGB/Alternative.hs view
@@ -1,6 +1,6 @@ -- | -- Module      : Graphics.Color.Space.RGB.Alternative--- Copyright   : (c) Alexey Kuleshevich 2019-2020+-- Copyright   : (c) Alexey Kuleshevich 2019-2025 -- License     : BSD3 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru> -- Stability   : experimental
src/Graphics/Color/Space/RGB/Alternative/CMYK.hs view
@@ -12,7 +12,7 @@ {-# LANGUAGE UndecidableInstances #-} -- | -- Module      : Graphics.Color.Space.RGB.Alternative.CMYK--- Copyright   : (c) Alexey Kuleshevich 2019-2020+-- Copyright   : (c) Alexey Kuleshevich 2019-2025 -- License     : BSD3 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru> -- Stability   : experimental@@ -78,6 +78,11 @@ -- | `CMYK` representation for some (@`RedGreenBlue` cs i@) color space instance ColorModel cs e => ColorModel (CMYK cs) e where   type Components (CMYK cs) e = (e, e, e, e)+  type ChannelCount (CMYK cs) = 4+  channelCount _ = 4+  {-# INLINE channelCount #-}+  channelNames _ = channelNames (Proxy :: Proxy (Color CM.CMYK e))+  channelColors _ = channelColors (Proxy :: Proxy (Color CM.CMYK e))   toComponents = toComponents . coerce   {-# INLINE toComponents #-}   fromComponents = coerce . fromComponents@@ -96,6 +101,10 @@   {-# INLINE fromBaseSpace #-}   luminance = luminance . toBaseSpace   {-# INLINE luminance #-}+  grayscale = grayscale . toBaseSpace+  {-# INLINE grayscale #-}+  applyGrayscale c f = fromBaseSpace (applyGrayscale (toBaseSpace c) f)+  {-# INLINE applyGrayscale #-}   @@ -109,6 +118,10 @@   {-# INLINE fromBaseSpace #-}   luminance = luminance . toBaseSpace   {-# INLINE luminance #-}+  grayscale = grayscale . toBaseSpace+  {-# INLINE grayscale #-}+  applyGrayscale c f = fromBaseSpace (applyGrayscale (toBaseSpace c) f)+  {-# INLINE applyGrayscale #-}  -- | `CMYK` representation for `AdobeRGB` color space instance ColorSpace (AdobeRGB l) D65 e => ColorSpace (CMYK (AdobeRGB l)) D65 e where@@ -120,6 +133,10 @@   {-# INLINE fromBaseSpace #-}   luminance = luminance . toBaseSpace   {-# INLINE luminance #-}+  grayscale = grayscale . toBaseSpace+  {-# INLINE grayscale #-}+  applyGrayscale c f = fromBaseSpace (applyGrayscale (toBaseSpace c) f)+  {-# INLINE applyGrayscale #-}  -- | `CMYK` representation for `Rec470.BT470_525` color space instance ColorSpace (Rec470.BT470_525 l) D65 e => ColorSpace (CMYK (Rec470.BT470_525 l)) D65 e where@@ -131,6 +148,10 @@   {-# INLINE fromBaseSpace #-}   luminance = luminance . toBaseSpace   {-# INLINE luminance #-}+  grayscale = grayscale . toBaseSpace+  {-# INLINE grayscale #-}+  applyGrayscale c f = fromBaseSpace (applyGrayscale (toBaseSpace c) f)+  {-# INLINE applyGrayscale #-}  -- | `CMYK` representation for `Rec470.BT470_625` color space instance ColorSpace (Rec470.BT470_625 l) D65 e => ColorSpace (CMYK (Rec470.BT470_625 l)) D65 e where@@ -142,6 +163,10 @@   {-# INLINE fromBaseSpace #-}   luminance = luminance . toBaseSpace   {-# INLINE luminance #-}+  grayscale = grayscale . toBaseSpace+  {-# INLINE grayscale #-}+  applyGrayscale c f = fromBaseSpace (applyGrayscale (toBaseSpace c) f)+  {-# INLINE applyGrayscale #-}  -- | `CMYK` representation for `BT601_525` color space instance ColorSpace (BT601_525 l) D65 e => ColorSpace (CMYK (BT601_525 l)) D65 e where@@ -153,6 +178,10 @@   {-# INLINE fromBaseSpace #-}   luminance = luminance . toBaseSpace   {-# INLINE luminance #-}+  grayscale = grayscale . toBaseSpace+  {-# INLINE grayscale #-}+  applyGrayscale c f = fromBaseSpace (applyGrayscale (toBaseSpace c) f)+  {-# INLINE applyGrayscale #-}  -- | `CMYK` representation for `BT601_625` color space instance ColorSpace (BT601_625 l) D65 e => ColorSpace (CMYK (BT601_625 l)) D65 e where@@ -164,6 +193,10 @@   {-# INLINE fromBaseSpace #-}   luminance = luminance . toBaseSpace   {-# INLINE luminance #-}+  grayscale = grayscale . toBaseSpace+  {-# INLINE grayscale #-}+  applyGrayscale c f = fromBaseSpace (applyGrayscale (toBaseSpace c) f)+  {-# INLINE applyGrayscale #-}  -- | `CMYK` representation for `BT709` color space instance ColorSpace (BT709 l) D65 e => ColorSpace (CMYK (BT709 l)) D65 e where@@ -175,3 +208,7 @@   {-# INLINE fromBaseSpace #-}   luminance = luminance . toBaseSpace   {-# INLINE luminance #-}+  grayscale = grayscale . toBaseSpace+  {-# INLINE grayscale #-}+  applyGrayscale c f = fromBaseSpace (applyGrayscale (toBaseSpace c) f)+  {-# INLINE applyGrayscale #-}
src/Graphics/Color/Space/RGB/Alternative/HSI.hs view
@@ -13,7 +13,7 @@ {-# LANGUAGE ViewPatterns #-} -- | -- Module      : Graphics.Color.Space.RGB.Alternative.HSI--- Copyright   : (c) Alexey Kuleshevich 2019-2020+-- Copyright   : (c) Alexey Kuleshevich 2019-2025 -- License     : BSD3 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru> -- Stability   : experimental@@ -83,9 +83,14 @@ -- | `HSI` representation for some (@`RedGreenBlue` cs i@) color space instance ColorModel cs e => ColorModel (HSI cs) e where   type Components (HSI cs) e = (e, e, e)-  toComponents = toComponents . coerce+  type ChannelCount (HSI cs) = 3+  channelCount _ = 3+  {-# INLINE channelCount #-}+  channelNames _ = channelNames (Proxy :: Proxy (Color CM.HSI e))+  channelColors _ = channelColors (Proxy :: Proxy (Color CM.HSI e))+  toComponents = toComponents . (coerce :: Color (HSI cs) e -> Color CM.HSI e)   {-# INLINE toComponents #-}-  fromComponents = coerce . fromComponents+  fromComponents = (coerce :: Color CM.HSI e -> Color (HSI cs) e) . fromComponents   {-# INLINE fromComponents #-}   showsColorModelName _ = ("HSI-" ++) . showsColorModelName (Proxy :: Proxy (Color cs e)) @@ -94,9 +99,13 @@ instance (ColorSpace (cs l) i e, RedGreenBlue cs i) => ColorSpace (HSI (cs l)) i e where   type BaseModel (HSI (cs l)) = CM.HSI   type BaseSpace (HSI (cs l)) = cs l-  toBaseSpace = mkColorRGB . fmap fromDouble . CM.hsi2rgb . fmap toDouble . coerce+  toBaseSpace = mkColorRGB . fmap fromDouble . CM.hsi2rgb . fmap toDouble . toBaseModel   {-# INLINE toBaseSpace #-}-  fromBaseSpace = coerce . fmap fromDouble . CM.rgb2hsi . fmap toDouble . unColorRGB+  fromBaseSpace = fromBaseModel . fmap fromDouble . CM.rgb2hsi . fmap toDouble . unColorRGB   {-# INLINE fromBaseSpace #-}   luminance = luminance . toBaseSpace   {-# INLINE luminance #-}+  grayscale (coerce -> V3 _ _ i) = X i+  {-# INLINE grayscale #-}+  replaceGrayscale (coerce -> V3 h s _) (X i) = coerce (V3 h s i)+  {-# INLINE replaceGrayscale #-}
src/Graphics/Color/Space/RGB/Alternative/HSL.hs view
@@ -13,7 +13,7 @@ {-# LANGUAGE ViewPatterns #-} -- | -- Module      : Graphics.Color.Space.RGB.Alternative.HSL--- Copyright   : (c) Alexey Kuleshevich 2019-2020+-- Copyright   : (c) Alexey Kuleshevich 2019-2025 -- License     : BSD3 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru> -- Stability   : experimental@@ -82,9 +82,14 @@ -- | `HSL` representation for some (@`RedGreenBlue` cs i@) color space instance ColorModel cs e => ColorModel (HSL cs) e where   type Components (HSL cs) e = (e, e, e)-  toComponents = toComponents . coerce+  type ChannelCount (HSL cs) = 3+  channelCount _ = 3+  {-# INLINE channelCount #-}+  channelNames _ = channelNames (Proxy :: Proxy (Color CM.HSL e))+  channelColors _ = channelColors (Proxy :: Proxy (Color CM.HSL e))+  toComponents = toComponents . (coerce :: Color (HSL cs) e -> Color CM.HSL e)   {-# INLINE toComponents #-}-  fromComponents = coerce . fromComponents+  fromComponents = (coerce :: Color CM.HSL e -> Color (HSL cs) e) . fromComponents   {-# INLINE fromComponents #-}   showsColorModelName _ = ("HSL-" ++) . showsColorModelName (Proxy :: Proxy (Color cs e)) @@ -93,9 +98,13 @@ instance (ColorSpace (cs l) i e, RedGreenBlue cs i) => ColorSpace (HSL (cs l)) i e where   type BaseModel (HSL (cs l)) = CM.HSL   type BaseSpace (HSL (cs l)) = cs l-  toBaseSpace = mkColorRGB . fmap fromDouble . CM.hsl2rgb . fmap toDouble . coerce+  toBaseSpace = mkColorRGB . fmap fromDouble . CM.hsl2rgb . fmap toDouble . toBaseModel   {-# INLINE toBaseSpace #-}-  fromBaseSpace = coerce . fmap fromDouble . CM.rgb2hsl . fmap toDouble . unColorRGB+  fromBaseSpace = fromBaseModel . fmap fromDouble . CM.rgb2hsl . fmap toDouble . unColorRGB   {-# INLINE fromBaseSpace #-}   luminance = luminance . toBaseSpace   {-# INLINE luminance #-}+  grayscale (coerce -> V3 _ _ l) = X l+  {-# INLINE grayscale #-}+  replaceGrayscale (coerce -> V3 h s _) (X l) = coerce (V3 h s l)+  {-# INLINE replaceGrayscale #-}
src/Graphics/Color/Space/RGB/Alternative/HSV.hs view
@@ -13,7 +13,7 @@ {-# LANGUAGE ViewPatterns #-} -- | -- Module      : Graphics.Color.Space.RGB.Alternative.HSV--- Copyright   : (c) Alexey Kuleshevich 2019-2020+-- Copyright   : (c) Alexey Kuleshevich 2019-2025 -- License     : BSD3 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru> -- Stability   : experimental@@ -82,9 +82,14 @@ -- | `HSV` representation for some (@`RedGreenBlue` cs i@) color space instance ColorModel cs e => ColorModel (HSV cs) e where   type Components (HSV cs) e = (e, e, e)-  toComponents = toComponents . coerce+  type ChannelCount (HSV cs) = 3+  channelCount _ = 3+  {-# INLINE channelCount #-}+  channelNames _ = channelNames (Proxy :: Proxy (Color CM.HSV e))+  channelColors _ = channelColors (Proxy :: Proxy (Color CM.HSV e))+  toComponents = toComponents . (coerce :: Color (HSV cs) e -> Color CM.HSV e)   {-# INLINE toComponents #-}-  fromComponents = coerce . fromComponents+  fromComponents = (coerce :: Color CM.HSV e -> Color (HSV cs) e) . fromComponents   {-# INLINE fromComponents #-}   showsColorModelName _ = ("HSV-" ++) . showsColorModelName (Proxy :: Proxy (Color cs e)) @@ -93,9 +98,13 @@ instance (ColorSpace (cs l) i e, RedGreenBlue cs i) => ColorSpace (HSV (cs l)) i e where   type BaseModel (HSV (cs l)) = CM.HSV   type BaseSpace (HSV (cs l)) = cs l-  toBaseSpace = mkColorRGB . fmap fromDouble . CM.hsv2rgb . fmap toDouble . coerce+  toBaseSpace = mkColorRGB . fmap fromDouble . CM.hsv2rgb . fmap toDouble . toBaseModel   {-# INLINE toBaseSpace #-}-  fromBaseSpace = coerce . fmap fromDouble . CM.rgb2hsv . fmap toDouble . unColorRGB+  fromBaseSpace = fromBaseModel . fmap fromDouble . CM.rgb2hsv . fmap toDouble . unColorRGB   {-# INLINE fromBaseSpace #-}   luminance = luminance . toBaseSpace   {-# INLINE luminance #-}+  grayscale (coerce -> V3 _ _ v) = X v+  {-# INLINE grayscale #-}+  replaceGrayscale (coerce -> V3 h s _) (X v) = coerce (V3 h s v)+  {-# INLINE replaceGrayscale #-}
src/Graphics/Color/Space/RGB/Alternative/YCbCr.hs view
@@ -11,9 +11,10 @@ {-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE ViewPatterns #-} -- | -- Module      : Graphics.Color.Space.RGB.Alternative.YCbCr--- Copyright   : (c) Alexey Kuleshevich 2019-2020+-- Copyright   : (c) Alexey Kuleshevich 2019-2025 -- License     : BSD3 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru> -- Stability   : experimental@@ -59,7 +60,7 @@ deriving instance Traversable (Color (Y'CbCr cs)) deriving instance Storable e => Storable (Color (Y'CbCr cs) e) -instance (Typeable cs, ColorModel (cs 'NonLinear) e, Elevator e) => Show (Color (Y'CbCr cs) e) where+instance (Typeable cs, ColorModel (cs 'NonLinear) e) => Show (Color (Y'CbCr cs) e) where   showsPrec _ = showsColorModel  -- | Constructor for an RGB color space in an alternative Y'CbCr color model@@ -75,6 +76,11 @@  instance (Typeable cs, ColorModel (cs 'NonLinear) e, Elevator e) => ColorModel (Y'CbCr cs) e where   type Components (Y'CbCr cs) e = (e, e, e)+  type ChannelCount (Y'CbCr cs) = 3+  channelCount _ = 3+  {-# INLINE channelCount #-}+  channelNames _ = channelNames (Proxy :: Proxy (Color CM.YCbCr e))+  channelColors _ = channelColors (Proxy :: Proxy (Color CM.YCbCr e))   toComponents (ColorY'CbCr y cb cr) = (y, cb, cr)   {-# INLINE toComponents #-}   fromComponents (y, cb, cr) = ColorY'CbCr y cb cr@@ -91,6 +97,10 @@   {-# INLINE fromBaseSpace #-}   luminance = luminance . toBaseSpace   {-# INLINE luminance #-}+  grayscale (coerce -> V3 y' _ _) = X y'+  {-# INLINE grayscale #-}+  replaceGrayscale (coerce -> V3 _ cb cr) (X y') = coerce (V3 y' cb cr)+  {-# INLINE replaceGrayscale #-}  instance Elevator e => ColorSpace (Y'CbCr BT601_525) D65 e where   type BaseModel (Y'CbCr BT601_525) = CM.YCbCr@@ -101,6 +111,10 @@   {-# INLINE fromBaseSpace #-}   luminance = luminance . toBaseSpace   {-# INLINE luminance #-}+  grayscale (coerce -> V3 y' _ _) = X y'+  {-# INLINE grayscale #-}+  replaceGrayscale (coerce -> V3 _ cb cr) (X y') = coerce (V3 y' cb cr)+  {-# INLINE replaceGrayscale #-}  instance Elevator e => ColorSpace (Y'CbCr BT601_625) D65 e where   type BaseModel (Y'CbCr BT601_625) = CM.YCbCr@@ -111,6 +125,10 @@   {-# INLINE fromBaseSpace #-}   luminance = luminance . toBaseSpace   {-# INLINE luminance #-}+  grayscale (coerce -> V3 y' _ _) = X y'+  {-# INLINE grayscale #-}+  replaceGrayscale (coerce -> V3 _ cb cr) (X y') = coerce (V3 y' cb cr)+  {-# INLINE replaceGrayscale #-}  instance Elevator e => ColorSpace (Y'CbCr BT709) D65 e where   type BaseModel (Y'CbCr BT709) = CM.YCbCr@@ -121,6 +139,10 @@   {-# INLINE fromBaseSpace #-}   luminance = luminance . toBaseSpace   {-# INLINE luminance #-}+  grayscale (coerce -> V3 y' _ _) = X y'+  {-# INLINE grayscale #-}+  replaceGrayscale (coerce -> V3 _ cb cr) (X y') = coerce (V3 y' cb cr)+  {-# INLINE replaceGrayscale #-}  instance (Typeable cs, Luma (cs i), ColorSpace (cs i 'NonLinear) i e, RedGreenBlue (cs i) i) =>          ColorSpace (Y'CbCr (cs i)) i e where@@ -132,6 +154,10 @@   {-# INLINE fromBaseSpace #-}   luminance = luminance . toBaseSpace   {-# INLINE luminance #-}+  grayscale (coerce -> V3 y' _ _) = X y'+  {-# INLINE grayscale #-}+  replaceGrayscale (coerce -> V3 _ cb cr) (X y') = coerce (V3 y' cb cr)+  {-# INLINE replaceGrayscale #-}   -- | This conversion is only correct for sRGB and Rec601. Source: ITU-T Rec. T.871@@ -139,13 +165,7 @@ -- @since 0.1.3 ycbcr2srgb ::      (RedGreenBlue cs i, RealFloat e) => Color (Y'CbCr cs) e -> Color (cs 'NonLinear) e-ycbcr2srgb (ColorY'CbCr y' cb cr) = ColorRGB r' g' b'-  where-    !cb05 = cb - 0.5-    !cr05 = cr - 0.5-    !r' = clamp01 (y'                   + 1.402    * cr05)-    !g' = clamp01 (y' - 0.344136 * cb05 - 0.714136 * cr05)-    !b' = clamp01 (y' + 1.772    * cb05)+ycbcr2srgb = ycbcrToRec601 . coerce {-# INLINE ycbcr2srgb #-}  -- | This conversion is only correct for sRGB and Rec601. Source: ITU-T Rec. T.871@@ -153,11 +173,7 @@ -- @since 0.1.3 srgb2ycbcr ::      (RedGreenBlue cs i, RealFloat e) => Color (cs 'NonLinear) e -> Color (Y'CbCr cs) e-srgb2ycbcr (ColorRGB r' g' b') = ColorY'CbCr y' cb cr-  where-    !y' =          0.299 * r' +    0.587 * g' +    0.114 * b'-    !cb = 0.5 - 0.168736 * r' - 0.331264 * g' +      0.5 * b'-    !cr = 0.5 +      0.5 * r' - 0.418688 * g' - 0.081312 * b'+srgb2ycbcr = coerce . rec601ToYcbcr {-# INLINE srgb2ycbcr #-}  -- | Convert any RGB color space that has `Luma` specified to `Y'CbCr`
src/Graphics/Color/Space/RGB/CIERGB.hs view
@@ -1,6 +1,6 @@ -- | -- Module      : Graphics.Color.Space.RGB.Derived.CIERGB--- Copyright   : (c) Alexey Kuleshevich 2020+-- Copyright   : (c) Alexey Kuleshevich 2020-2025 -- License     : BSD3 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru> -- Stability   : experimental
src/Graphics/Color/Space/RGB/Derived/AdobeRGB.hs view
@@ -11,7 +11,7 @@ {-# LANGUAGE TypeFamilies #-} -- | -- Module      : Graphics.Color.Space.RGB.Derived.AdobeRGB--- Copyright   : (c) Alexey Kuleshevich 2019-2020+-- Copyright   : (c) Alexey Kuleshevich 2019-2025 -- License     : BSD3 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru> -- Stability   : experimental@@ -58,6 +58,11 @@ -- | `AdobeRGB` color space (derived) instance (Typeable l, Illuminant i, Elevator e) => ColorModel (AdobeRGB (i :: k) l) e where   type Components (AdobeRGB i l) e = (e, e, e)+  type ChannelCount (AdobeRGB i l) = 3+  channelCount _ = 3+  {-# INLINE channelCount #-}+  channelNames _ = channelNames (Proxy :: Proxy (Color CM.RGB e))+  channelColors _ = channelColors (Proxy :: Proxy (Color CM.RGB e))   toComponents = toComponents . unColorRGB   {-# INLINE toComponents #-}   fromComponents = mkColorRGB . fromComponents@@ -72,6 +77,10 @@   {-# INLINE fromBaseSpace #-}   luminance = rgbLinearLuminance . fmap toRealFloat   {-# INLINE luminance #-}+  grayscale = rgbLinearGrayscale+  {-# INLINE grayscale #-}+  applyGrayscale = rgbLinearApplyGrayscale+  {-# INLINE applyGrayscale #-}   toColorXYZ = rgbLinear2xyz . fmap toRealFloat   {-# INLINE toColorXYZ #-}   fromColorXYZ = fmap fromRealFloat . xyz2rgbLinear@@ -86,6 +95,10 @@   {-# INLINE fromBaseSpace #-}   luminance = rgbLuminance . fmap toRealFloat   {-# INLINE luminance #-}+  grayscale = rgbNonLinearGrayscale+  {-# INLINE grayscale #-}+  applyGrayscale = rgbNonLinearApplyGrayscale+  {-# INLINE applyGrayscale #-}   toColorXYZ = rgb2xyz . fmap toRealFloat   {-# INLINE toColorXYZ #-}   fromColorXYZ = fmap fromRealFloat . xyz2rgb
src/Graphics/Color/Space/RGB/Derived/CIERGB.hs view
@@ -11,7 +11,7 @@ {-# LANGUAGE TypeFamilies #-} -- | -- Module      : Graphics.Color.Space.RGB.Derived.CIERGB--- Copyright   : (c) Alexey Kuleshevich 2018-2020+-- Copyright   : (c) Alexey Kuleshevich 2018-2025 -- License     : BSD3 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru> -- Stability   : experimental@@ -60,6 +60,11 @@ -- | `CIERGB` color space (derived) instance (Typeable l, Illuminant i, Elevator e) => ColorModel (CIERGB (i :: k) l) e where   type Components (CIERGB i l) e = (e, e, e)+  type ChannelCount (CIERGB i l) = 3+  channelCount _ = 3+  {-# INLINE channelCount #-}+  channelNames _ = channelNames (Proxy :: Proxy (Color CM.RGB e))+  channelColors _ = channelColors (Proxy :: Proxy (Color CM.RGB e))   toComponents = toComponents . unColorRGB   {-# INLINE toComponents #-}   fromComponents = mkColorRGB . fromComponents@@ -74,6 +79,10 @@   {-# INLINE fromBaseSpace #-}   luminance = rgbLinearLuminance . castLinearity . fmap toRealFloat   {-# INLINE luminance #-}+  grayscale = toBaseModel . fmap fromDouble . luminance+  {-# INLINE grayscale #-}+  applyGrayscale c f = castLinearity (rgbLinearApplyGrayscale (castLinearity c) f)+  {-# INLINE applyGrayscale #-}   toColorXYZ = rgbLinear2xyz . fmap toRealFloat . castLinearity   {-# INLINE toColorXYZ #-}   fromColorXYZ xyz = castLinearity (fromRealFloat <$> xyz2rgbLinear @(CIERGB i) xyz)
src/Graphics/Color/Space/RGB/Derived/SRGB.hs view
@@ -11,7 +11,7 @@ {-# LANGUAGE TypeFamilies #-} -- | -- Module      : Graphics.Color.Space.RGB.Derived.SRGB--- Copyright   : (c) Alexey Kuleshevich 2019-2020+-- Copyright   : (c) Alexey Kuleshevich 2019-2025 -- License     : BSD3 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru> -- Stability   : experimental@@ -21,6 +21,7 @@   ( SRGB   ) where +import Data.Coerce import Data.Typeable import Foreign.Storable import Graphics.Color.Model.Internal@@ -29,7 +30,7 @@ import Graphics.Color.Space.RGB.Internal import Graphics.Color.Space.RGB.Luma import qualified Graphics.Color.Space.RGB.SRGB as SRGB-+import Graphics.Color.Space.RGB.ITU.Rec601 (applyGrayscaleRec601)  -- | The most common @sRGB@ color space with an arbitrary illuminant data SRGB (i :: k) (l :: Linearity)@@ -59,6 +60,11 @@ -- | `SRGB` color space (derived) instance (Typeable l, Illuminant i, Elevator e) => ColorModel (SRGB (i :: k) l) e where   type Components (SRGB i l) e = (e, e, e)+  type ChannelCount (SRGB i l) = 3+  channelCount _ = 3+  {-# INLINE channelCount #-}+  channelNames _ = channelNames (Proxy :: Proxy (Color CM.RGB e))+  channelColors _ = channelColors (Proxy :: Proxy (Color CM.RGB e))   toComponents = toComponents . unColorRGB   {-# INLINE toComponents #-}   fromComponents = mkColorRGB . fromComponents@@ -73,6 +79,10 @@   {-# INLINE fromBaseSpace #-}   luminance = rgbLinearLuminance . fmap toRealFloat   {-# INLINE luminance #-}+  grayscale = rgbLinearGrayscale+  {-# INLINE grayscale #-}+  applyGrayscale = rgbLinearApplyGrayscale+  {-# INLINE applyGrayscale #-}   toColorXYZ = rgbLinear2xyz . fmap toRealFloat   {-# INLINE toColorXYZ #-}   fromColorXYZ = fmap fromRealFloat . xyz2rgbLinear@@ -88,6 +98,10 @@   {-# INLINE fromBaseSpace #-}   luminance = rgbLuminance . fmap toRealFloat   {-# INLINE luminance #-}+  grayscale = fmap fromDouble . coerce . rgbLuma @_ @_ @_ @Double+  {-# INLINE grayscale #-}+  applyGrayscale = applyGrayscaleRec601+  {-# INLINE applyGrayscale #-}   toColorXYZ = rgb2xyz . fmap toRealFloat   {-# INLINE toColorXYZ #-}   fromColorXYZ = fmap fromRealFloat . xyz2rgb
src/Graphics/Color/Space/RGB/ITU/Rec470.hs view
@@ -6,11 +6,12 @@ {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE PatternSynonyms #-} {-# LANGUAGE PolyKinds #-}+{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE TypeFamilies #-} -- | -- Module      : Graphics.Color.Space.RGB.ITU.Rec470--- Copyright   : (c) Alexey Kuleshevich 2019-2020+-- Copyright   : (c) Alexey Kuleshevich 2019-2025 -- License     : BSD3 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru> -- Stability   : experimental@@ -63,6 +64,11 @@ -- | ITU-R BT.470 (525) color space instance (Typeable l, Elevator e) => ColorModel (BT470_525 l) e where   type Components (BT470_525 l) e = (e, e, e)+  type ChannelCount (BT470_525 l) = 3+  channelCount _ = 3+  {-# INLINE channelCount #-}+  channelNames _ = channelNames (Proxy :: Proxy (Color CM.RGB e))+  channelColors _ = channelColors (Proxy :: Proxy (Color CM.RGB e))   toComponents = toComponents . unColorRGB   {-# INLINE toComponents #-}   fromComponents = mkColorRGB . fromComponents@@ -77,6 +83,10 @@   {-# INLINE fromBaseSpace #-}   luminance = rgbLinearLuminance . fmap toRealFloat   {-# INLINE luminance #-}+  grayscale = rgbLinearGrayscale+  {-# INLINE grayscale #-}+  applyGrayscale = rgbLinearApplyGrayscale+  {-# INLINE applyGrayscale #-}   toColorXYZ = rgbLinear2xyz . fmap toRealFloat   {-# INLINE toColorXYZ #-}   fromColorXYZ = fmap fromRealFloat . xyz2rgbLinear@@ -91,6 +101,10 @@   {-# INLINE fromBaseSpace #-}   luminance = rgbLuminance . fmap toRealFloat   {-# INLINE luminance #-}+  grayscale = rgbNonLinearGrayscale+  {-# INLINE grayscale #-}+  applyGrayscale = rgbNonLinearApplyGrayscale+  {-# INLINE applyGrayscale #-}   toColorXYZ = rgb2xyz . fmap toRealFloat   {-# INLINE toColorXYZ #-}   fromColorXYZ = fmap fromRealFloat . xyz2rgb@@ -137,6 +151,11 @@ -- | ITU-R BT.470 (625) color space instance (Typeable l, Elevator e) => ColorModel (BT470_625 l) e where   type Components (BT470_625 l) e = (e, e, e)+  type ChannelCount (BT470_625 l) = 3+  channelCount _ = 3+  {-# INLINE channelCount #-}+  channelNames _ = channelNames (Proxy :: Proxy (Color CM.RGB e))+  channelColors _ = channelColors (Proxy :: Proxy (Color CM.RGB e))   toComponents = toComponents . unColorRGB   {-# INLINE toComponents #-}   fromComponents = mkColorRGB . fromComponents@@ -151,6 +170,10 @@   {-# INLINE fromBaseSpace #-}   luminance = rgbLinearLuminance . fmap toRealFloat   {-# INLINE luminance #-}+  grayscale = rgbLinearGrayscale+  {-# INLINE grayscale #-}+  applyGrayscale = rgbLinearApplyGrayscale+  {-# INLINE applyGrayscale #-}   toColorXYZ = rgbLinear2xyz . fmap toRealFloat   {-# INLINE toColorXYZ #-}   fromColorXYZ = fmap fromRealFloat . xyz2rgbLinear@@ -165,6 +188,10 @@   {-# INLINE fromBaseSpace #-}   luminance = rgbLuminance . fmap toRealFloat   {-# INLINE luminance #-}+  grayscale = rgbNonLinearGrayscale+  {-# INLINE grayscale #-}+  applyGrayscale = rgbNonLinearApplyGrayscale+  {-# INLINE applyGrayscale #-}   toColorXYZ = rgb2xyz . fmap toRealFloat   {-# INLINE toColorXYZ #-}   fromColorXYZ = fmap fromRealFloat . xyz2rgb
src/Graphics/Color/Space/RGB/ITU/Rec601.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE BangPatterns #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE DeriveTraversable #-} {-# LANGUAGE FlexibleContexts #-}@@ -6,12 +7,13 @@ {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE PatternSynonyms #-} {-# LANGUAGE PolyKinds #-}+{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeFamilies #-} -- | -- Module      : Graphics.Color.Space.RGB.ITU.Rec601--- Copyright   : (c) Alexey Kuleshevich 2019-2020+-- Copyright   : (c) Alexey Kuleshevich 2019-2025 -- License     : BSD3 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru> -- Stability   : experimental@@ -23,13 +25,18 @@   , pattern BT601_625   , BT601_625   , D65+  , ycbcrToRec601+  , rec601ToYcbcr+  , applyGrayscaleRec601   ) where +import Data.Coerce import Data.Typeable import Foreign.Storable import Graphics.Color.Illuminant.ITU.Rec601 import Graphics.Color.Model.Internal import qualified Graphics.Color.Model.RGB as CM+import qualified Graphics.Color.Model.YCbCr as CM import Graphics.Color.Space.Internal import Graphics.Color.Space.RGB.Internal import Graphics.Color.Space.RGB.ITU.Rec470 (BT470_625)@@ -68,6 +75,11 @@ -- | ITU-R BT.601 (525) color space instance  (Typeable l, Elevator e) => ColorModel (BT601_525 l) e where   type Components (BT601_525 l) e = (e, e, e)+  type ChannelCount (BT601_525 l) = 3+  channelCount _ = 3+  {-# INLINE channelCount #-}+  channelNames _ = channelNames (Proxy :: Proxy (Color CM.RGB e))+  channelColors _ = channelColors (Proxy :: Proxy (Color CM.RGB e))   toComponents = toComponents . unColorRGB   {-# INLINE toComponents #-}   fromComponents = mkColorRGB . fromComponents@@ -82,6 +94,10 @@   {-# INLINE fromBaseSpace #-}   luminance = rgbLinearLuminance . fmap toRealFloat   {-# INLINE luminance #-}+  grayscale = rgbLinearGrayscale+  {-# INLINE grayscale #-}+  applyGrayscale = rgbLinearApplyGrayscale+  {-# INLINE applyGrayscale #-}   toColorXYZ = rgbLinear2xyz . fmap toRealFloat   {-# INLINE toColorXYZ #-}   fromColorXYZ = fmap fromRealFloat . xyz2rgbLinear@@ -97,6 +113,10 @@   {-# INLINE fromBaseSpace #-}   luminance = rgbLuminance . fmap toRealFloat   {-# INLINE luminance #-}+  grayscale = fmap fromDouble . coerce . rgbLuma @_ @_ @_ @Double+  {-# INLINE grayscale #-}+  applyGrayscale = applyGrayscaleRec601+  {-# INLINE applyGrayscale #-}   toColorXYZ = rgb2xyz . fmap toRealFloat   {-# INLINE toColorXYZ #-}   fromColorXYZ = fmap fromRealFloat . xyz2rgb@@ -143,6 +163,11 @@ -- | ITU-R BT.601 (625) color space instance (Typeable l, Elevator e) => ColorModel (BT601_625 l) e where   type Components (BT601_625 l) e = (e, e, e)+  type ChannelCount (BT601_625 l) = 3+  channelCount _ = 3+  {-# INLINE channelCount #-}+  channelNames _ = channelNames (Proxy :: Proxy (Color CM.RGB e))+  channelColors _ = channelColors (Proxy :: Proxy (Color CM.RGB e))   toComponents = toComponents . unColorRGB   {-# INLINE toComponents #-}   fromComponents = mkColorRGB . fromComponents@@ -157,6 +182,10 @@   {-# INLINE fromBaseSpace #-}   luminance = rgbLinearLuminance . fmap toRealFloat   {-# INLINE luminance #-}+  grayscale = rgbLinearGrayscale+  {-# INLINE grayscale #-}+  applyGrayscale = rgbLinearApplyGrayscale+  {-# INLINE applyGrayscale #-}   toColorXYZ = rgbLinear2xyz . fmap toRealFloat   {-# INLINE toColorXYZ #-}   fromColorXYZ = fmap fromRealFloat . xyz2rgbLinear@@ -171,6 +200,10 @@   {-# INLINE fromBaseSpace #-}   luminance = rgbLuminance . fmap toRealFloat   {-# INLINE luminance #-}+  grayscale = fmap fromDouble . coerce . rgbLuma @_ @_ @_ @Double+  {-# INLINE grayscale #-}+  applyGrayscale = applyGrayscaleRec601+  {-# INLINE applyGrayscale #-}   toColorXYZ = rgb2xyz . fmap toRealFloat   {-# INLINE toColorXYZ #-}   fromColorXYZ = fmap fromRealFloat . xyz2rgb@@ -231,3 +264,45 @@ inv0018 :: (Ord a, Floating a) => a inv0018 = transferRec601 0.018 -- ~ 0.081 +++-- | This conversion is correct only for sRGB and Rec601. Source: ITU-T Rec. T.871+--+-- @since 0.1.3+ycbcrToRec601 ::+     (RedGreenBlue cs i, RealFloat e)+  => Color CM.YCbCr e+  -> Color (cs 'NonLinear) e+ycbcrToRec601 (CM.ColorYCbCr y' cb cr) = mkColorRGB (CM.ColorRGB r' g' b')+  where+    !cb05 = cb - 0.5+    !cr05 = cr - 0.5+    !r' = clamp01 (y'                   + 1.402    * cr05)+    !g' = clamp01 (y' - 0.344136 * cb05 - 0.714136 * cr05)+    !b' = clamp01 (y' + 1.772    * cb05)+{-# INLINE ycbcrToRec601 #-}++-- | This conversion is correct only for sRGB and Rec601. Source: ITU-T Rec. T.871+--+-- @since 0.1.3+rec601ToYcbcr :: (RedGreenBlue cs i, RealFloat e) => Color (cs 'NonLinear) e -> Color CM.YCbCr e+rec601ToYcbcr rgb = CM.ColorYCbCr y' cb cr+  where+    CM.ColorRGB r' g' b' = unColorRGB rgb+    !y' =          0.299 * r' +    0.587 * g' +    0.114 * b'+    !cb = 0.5 - 0.168736 * r' - 0.331264 * g' +      0.5 * b'+    !cr = 0.5 +      0.5 * r' - 0.418688 * g' - 0.081312 * b'+{-# INLINE rec601ToYcbcr #-}+++applyGrayscaleRec601 ::+     forall cs i e. (RedGreenBlue cs i, ColorSpace (cs 'NonLinear) i e)+  => Color (cs 'NonLinear) e+  -> (Color X e -> Color X e)+  -> Color (cs 'NonLinear) e+applyGrayscaleRec601 rgb f =+  case rec601ToYcbcr (toDouble <$> rgb) of+    (CM.ColorYCbCr y' cb cr :: Color CM.YCbCr Double) ->+      fromDouble <$>+      ycbcrToRec601 (CM.ColorYCbCr (toDouble (coerce (f (X (fromDouble y'))) :: e)) cb cr)+{-# INLINE applyGrayscaleRec601 #-}
src/Graphics/Color/Space/RGB/ITU/Rec709.hs view
@@ -6,12 +6,13 @@ {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE PatternSynonyms #-} {-# LANGUAGE PolyKinds #-}+{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeFamilies #-} -- | -- Module      : Graphics.Color.Space.RGB.ITU.Rec709--- Copyright   : (c) Alexey Kuleshevich 2019-2020+-- Copyright   : (c) Alexey Kuleshevich 2019-2025 -- License     : BSD3 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru> -- Stability   : experimental@@ -59,6 +60,11 @@ -- | ITU-R BT.709 color space instance (Typeable l, Elevator e) => ColorModel (BT709 l) e where   type Components (BT709 l) e = (e, e, e)+  type ChannelCount (BT709 l) = 3+  channelCount _ = 3+  {-# INLINE channelCount #-}+  channelNames _ = channelNames (Proxy :: Proxy (Color CM.RGB e))+  channelColors _ = channelColors (Proxy :: Proxy (Color CM.RGB e))   toComponents = toComponents . unColorRGB   {-# INLINE toComponents #-}   fromComponents = mkColorRGB . fromComponents@@ -73,6 +79,10 @@   {-# INLINE fromBaseSpace #-}   luminance = rgbLinearLuminance . fmap toRealFloat   {-# INLINE luminance #-}+  grayscale = rgbLinearGrayscale+  {-# INLINE grayscale #-}+  applyGrayscale = rgbLinearApplyGrayscale+  {-# INLINE applyGrayscale #-}   toColorXYZ = rgbLinear2xyz . fmap toRealFloat   {-# INLINE toColorXYZ #-}   fromColorXYZ = fmap fromRealFloat . xyz2rgbLinear@@ -87,6 +97,10 @@   {-# INLINE fromBaseSpace #-}   luminance = rgbLuminance . fmap toRealFloat   {-# INLINE luminance #-}+  grayscale = rgbNonLinearGrayscale+  {-# INLINE grayscale #-}+  applyGrayscale = rgbNonLinearApplyGrayscale+  {-# INLINE applyGrayscale #-}   toColorXYZ = rgb2xyz . fmap toRealFloat   {-# INLINE toColorXYZ #-}   fromColorXYZ = fmap fromRealFloat . xyz2rgb
src/Graphics/Color/Space/RGB/Internal.hs view
@@ -18,7 +18,7 @@ {-# LANGUAGE ViewPatterns #-} -- | -- Module      : Graphics.Color.Space.RGB.Internal--- Copyright   : (c) Alexey Kuleshevich 2019-2020+-- Copyright   : (c) Alexey Kuleshevich 2019-2025 -- License     : BSD3 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru> -- Stability   : experimental@@ -39,6 +39,10 @@   , xyz2rgbLinear   , rgbLuminance   , rgbLinearLuminance+  , rgbLinearGrayscale+  , rgbLinearApplyGrayscale+  , rgbNonLinearGrayscale+  , rgbNonLinearApplyGrayscale   , NPM(..)   , npmApply   , npmDerive@@ -219,6 +223,44 @@   Y (m3x3row1 (unNPM (npm :: NPM cs e)) `dotProduct` coerce (unColorRGB px)) {-# INLINE rgbLinearLuminance #-} +rgbLinearGrayscale ::+     forall cs i e. (ColorSpace (cs 'Linear) i e)+  => Color (cs 'Linear) e+  -> Color X e+rgbLinearGrayscale = ColorX . fromDouble . unY . luminance+{-# INLINE rgbLinearGrayscale #-}+++rgbLinearApplyGrayscale ::+     forall cs i e. (ColorSpace (cs 'Linear) i e)+  => Color (cs 'Linear) e+  -> (Color X e -> Color X e)+  -> Color (cs 'Linear) e+rgbLinearApplyGrayscale rgb f =+  case toColorXYZ rgb of+    ColorXYZ x y z ->+      fromColorXYZ (ColorXYZ x (toDouble (coerce (f (X (fromDouble y))) :: e)) z)+{-# INLINE rgbLinearApplyGrayscale #-}+++rgbNonLinearApplyGrayscale ::+     forall cs i e. (RedGreenBlue cs i, ColorSpace (cs 'NonLinear) i e)+  => Color (cs 'NonLinear) e+  -> (Color X e -> Color X e)+  -> Color (cs 'NonLinear) e+rgbNonLinearApplyGrayscale rgb f =+  case toColorXYZ rgb of+    ColorXYZ x y z ->+      let y' = itransfer @_ @cs (toDouble (coerce (f (X (fromDouble (transfer @_ @cs y)))) :: e))+      in fromColorXYZ (ColorXYZ x y' z)+{-# INLINE rgbNonLinearApplyGrayscale #-}++rgbNonLinearGrayscale ::+     forall cs i e. (RedGreenBlue cs i, ColorSpace (cs 'NonLinear) i e)+  => Color (cs 'NonLinear) e+  -> Color X e+rgbNonLinearGrayscale = ColorX . fromDouble . (transfer @_ @cs) . unY . luminance+{-# INLINE rgbNonLinearGrayscale #-}  rgbLuminance ::      (RedGreenBlue cs i, ColorSpace (cs 'Linear) i e, RealFloat e)
src/Graphics/Color/Space/RGB/Luma.hs view
@@ -14,7 +14,7 @@ {-# LANGUAGE UndecidableInstances #-} -- | -- Module      : Graphics.Color.Space.RGB.Luma--- Copyright   : (c) Alexey Kuleshevich 2018-2020+-- Copyright   : (c) Alexey Kuleshevich 2018-2025 -- License     : BSD3 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru> -- Stability   : experimental@@ -36,6 +36,7 @@  import Data.Coerce import Data.Kind+import Data.List.NonEmpty import Data.Typeable import Foreign.Storable import Graphics.Color.Model.Internal@@ -92,6 +93,11 @@ -- | `Y'` - as a color model instance (Typeable cs, Elevator e) => ColorModel (Y' cs) e where   type Components (Y' cs) e = e+  type ChannelCount (Y' cs) = 1+  channelCount _ = 1+  {-# INLINE channelCount #-}+  channelNames _ = "Luma" :| []+  channelColors _ = V3 0x80 0x80 0x80 :| []   toComponents (Y' y) = y   {-# INLINE toComponents #-}   fromComponents = Y'@@ -99,7 +105,6 @@   instance ( Typeable cs-         , Illuminant i          , ColorSpace (cs 'Linear) i e          , ColorSpace (cs 'NonLinear) i e          , Luma cs@@ -112,6 +117,12 @@   {-# INLINE toBaseSpace #-}   fromBaseSpace = fmap fromDouble . rgbLuma   {-# INLINE fromBaseSpace #-}+  grayscale = coerce+  {-# INLINE grayscale #-}+  applyGrayscale c f = coerce (f (coerce c))+  {-# INLINE applyGrayscale #-}+  replaceGrayscale _ = coerce+  {-# INLINE replaceGrayscale #-}   luminance = luminance . fmap (fromDouble :: Double -> e) . toBaseLinearSpace . fmap toDouble   {-# INLINE luminance #-}   toColorXYZ = toColorXYZ . fmap (fromDouble :: Double -> e) . toBaseLinearSpace . fmap toDouble
src/Graphics/Color/Space/RGB/SRGB.hs view
@@ -7,12 +7,13 @@ {-# LANGUAGE NegativeLiterals #-} {-# LANGUAGE PatternSynonyms #-} {-# LANGUAGE PolyKinds #-}+{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeFamilies #-} -- | -- Module      : Graphics.Color.Space.RGB.SRGB--- Copyright   : (c) Alexey Kuleshevich 2019-2020+-- Copyright   : (c) Alexey Kuleshevich 2019-2025 -- License     : BSD3 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru> -- Stability   : experimental@@ -36,6 +37,7 @@ import qualified Graphics.Color.Model.RGB as CM import Graphics.Color.Space.Internal import Graphics.Color.Space.RGB.Internal+import Graphics.Color.Space.RGB.ITU.Rec601 (applyGrayscaleRec601) import Graphics.Color.Space.RGB.ITU.Rec709 (BT709, D65) import Graphics.Color.Space.RGB.Luma @@ -122,6 +124,11 @@ -- | `SRGB` color space instance (Typeable l, Elevator e) => ColorModel (SRGB l) e where   type Components (SRGB l) e = (e, e, e)+  type ChannelCount (SRGB l) = 3+  channelCount _ = 3+  {-# INLINE channelCount #-}+  channelNames _ = channelNames (Proxy :: Proxy (Color CM.RGB e))+  channelColors _ = channelColors (Proxy :: Proxy (Color CM.RGB e))   toComponents = toComponents . unColorRGB   {-# INLINE toComponents #-}   fromComponents = mkColorRGB . fromComponents@@ -136,6 +143,10 @@   {-# INLINE fromBaseSpace #-}   luminance = rgbLinearLuminance . fmap toRealFloat   {-# INLINE luminance #-}+  grayscale = rgbLinearGrayscale+  {-# INLINE grayscale #-}+  applyGrayscale = rgbLinearApplyGrayscale+  {-# INLINE applyGrayscale #-}   toColorXYZ = rgbLinear2xyz . fmap toRealFloat   {-# INLINE toColorXYZ #-}   fromColorXYZ = fmap fromRealFloat . xyz2rgbLinear@@ -151,6 +162,10 @@   {-# INLINE fromBaseSpace #-}   luminance = rgbLuminance . fmap toRealFloat   {-# INLINE luminance #-}+  grayscale = fmap fromDouble . coerce . rgbLuma @_ @_ @_ @Double+  {-# INLINE grayscale #-}+  applyGrayscale = applyGrayscaleRec601+  {-# INLINE applyGrayscale #-}   toColorXYZ = rgb2xyz . fmap toRealFloat   {-# INLINE toColorXYZ #-}   fromColorXYZ = fmap fromRealFloat . xyz2rgb
src/Graphics/Color/Standard.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE MultiParamTypeClasses #-} -- | -- Module      : Graphics.Color.Standard--- Copyright   : (c) Alexey Kuleshevich 2021+-- Copyright   : (c) Alexey Kuleshevich 2021-2025 -- License     : BSD3 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru> -- Stability   : experimental
src/Graphics/Color/Standard/Internal.hs view
@@ -2,7 +2,7 @@ {-# LANGUAGE MultiParamTypeClasses #-} -- | -- Module      : Graphics.Color.Standard.Internal--- Copyright   : (c) Alexey Kuleshevich 2019-2021+-- Copyright   : (c) Alexey Kuleshevich 2019-2025 -- License     : BSD3 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru> -- Stability   : experimental
src/Graphics/Color/Standard/RAL.hs view
@@ -1,13 +1,19 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE NegativeLiterals #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeFamilies #-}+#if __GLASGOW_HASKELL__ >= 906+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE PolyKinds #-}+#else {-# LANGUAGE TypeInType #-}+#endif -- | -- Module      : Graphics.Color.Standard.RAL--- Copyright   : (c) Alexey Kuleshevich 2019-2020+-- Copyright   : (c) Alexey Kuleshevich 2019-2025 -- License     : BSD3 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru> -- Stability   : experimental@@ -475,7 +481,7 @@     :: ColorSpace cs i e => Color cs e  ral :: ColorSpace cs i e => Float -> Float -> Float -> Color cs e-ral l' a' b' = convert (ColorLAB l' a' b' :: Color (LAB D50) Float)+ral l' a' b' = convert (ColorLAB (l' / 100) (a' / 100) (b' / 100) :: Color (LAB D50) Float)  greenBeige = ral 76.022 -0.366 27.636 beige = ral 73.595 5.518 26.95
src/Graphics/Color/Standard/SVG.hs view
@@ -4,7 +4,7 @@ {-# LANGUAGE MultiParamTypeClasses #-} -- | -- Module      : Graphics.Color.Standard.SVG--- Copyright   : (c) Alexey Kuleshevich 2021+-- Copyright   : (c) Alexey Kuleshevich 2021-2025 -- License     : BSD3 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru> -- Stability   : experimental@@ -26,7 +26,7 @@ -- >>> import Graphics.Color.Space.CIE1976.LAB -- >>> import Graphics.Color.Illuminant.CIE1931 -- >>> color (SVG :: SVG "aqua") :: Color (LAB 'D65) Float--- <LAB CIE1931 'D65:(91.11637000,-48.08154700,-14.12457300)>+-- <LAB CIE1931 'D65:( 0.91116370,-0.48081547,-0.14124572)> -- data SVG (n :: Symbol) = SVG 
src/Graphics/Pixel.hs view
@@ -4,7 +4,7 @@ {-# LANGUAGE TypeFamilies #-} -- | -- Module      : Graphics.Pixel--- Copyright   : (c) Alexey Kuleshevich 2019-2020+-- Copyright   : (c) Alexey Kuleshevich 2019-2025 -- License     : BSD3 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru> -- Stability   : experimental
src/Graphics/Pixel/ColorSpace.hs view
@@ -4,18 +4,19 @@ {-# LANGUAGE PatternSynonyms #-} {-# LANGUAGE PolyKinds #-} {-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-} {-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE ViewPatterns #-} -- | -- Module      : Graphics.Pixel.ColorSpace--- Copyright   : (c) Alexey Kuleshevich 2019-2020+-- Copyright   : (c) Alexey Kuleshevich 2019-2025 -- License     : BSD3 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru> -- Stability   : experimental -- Portability : non-portable -- module Graphics.Pixel.ColorSpace-  ( Pixel(Pixel, PixelY, PixelXYZ, PixelLAB, PixelRGB, PixelHSI, PixelHSL, PixelHSV,+  ( Pixel(Pixel, PixelX, PixelY, PixelXYZ, PixelLAB, PixelRGB, PixelHSI, PixelHSL, PixelHSV,       PixelCMYK, PixelY'CbCr, PixelY', PixelYA, PixelXYZA, PixelLABA, PixelRGBA, PixelHSIA, PixelHSLA,       PixelHSVA, PixelCMYKA, PixelY'CbCrA, PixelY'A)   , liftPixel@@ -28,6 +29,10 @@   , fromPixelXYZ   , toPixelBaseSpace   , fromPixelBaseSpace+  -- * Grayscale+  , grayscalePixel+  , applyGrayscalePixel+  , replaceGrayscalePixel   -- ** Color model   , toPixelBaseModel   , fromPixelBaseModel@@ -56,13 +61,14 @@ import Graphics.Color.Algebra.Binary import qualified Graphics.Color.Model.RGB as CM import Graphics.Color.Space+import Graphics.Pixel (pattern PixelX) import Graphics.Pixel.Internal  -- | Convert a pixel from one color space to any other. -- -- >>> :set -XDataKinds -- >>> :set -XTypeApplications--- >>> px = PixelSRGB @Float 0.0 0.5 1.0+-- >>> px = PixelSRGB @Float @'NonLinear 0.0 0.5 1.0 -- >>> px -- <SRGB 'NonLinear:( 0.00000000, 0.50000000, 1.00000000)> -- >>> convertPixel @(AdobeRGB 'NonLinear) @_ @Word8 px@@ -79,14 +85,14 @@ -- | Constructor for a pixel in @sRGB@ color space -- -- @since 0.1.0-pattern PixelSRGB :: e -> e -> e -> Pixel (SRGB 'NonLinear) e+pattern PixelSRGB :: forall e l. e -> e -> e -> Pixel (SRGB l) e pattern PixelSRGB r g b = Pixel (SRGB (CM.ColorRGB r g b)) {-# COMPLETE PixelSRGB #-}  -- | Constructor for a pixel in @sRGB@ color space with Alpha channel -- -- @since 0.1.0-pattern PixelSRGBA :: e -> e -> e -> e -> Pixel (Alpha (SRGB 'NonLinear)) e+pattern PixelSRGBA :: e -> e -> e -> e -> Pixel (Alpha (SRGB l)) e pattern PixelSRGBA r g b a = Pixel (Alpha (SRGB (CM.ColorRGB r g b)) a) {-# COMPLETE PixelSRGBA #-} @@ -319,13 +325,37 @@ toPixelBaseSpace = liftPixel toBaseSpace {-# INLINE toPixelBaseSpace #-} --- | Covert a color space of a pixel into it's alternative representation. Example AdobeRGB to HSI.+-- | Covert a color space of a pixel into its alternative representation. Example AdobeRGB to HSI. -- -- @since 0.1.0 fromPixelBaseSpace ::      (ColorSpace cs i e, bcs ~ BaseSpace cs, ColorSpace bcs i e) => Pixel bcs e -> Pixel cs e fromPixelBaseSpace = liftPixel fromBaseSpace {-# INLINE fromPixelBaseSpace #-}++-- | Drop chroma information from a pixel. Same as `grayscale` for `Color`+--+-- @since 0.4.0+grayscalePixel :: ColorSpace cs i e => Pixel cs e -> Pixel X e+grayscalePixel = liftPixel grayscale+{-# INLINE grayscalePixel #-}+++-- | Apply a function to grayscale information of a pixel leaving chroma untouched. Same+-- as `applyGrayscale` for `Color`+--+-- @since 0.4.0+applyGrayscalePixel :: ColorSpace cs i e => Pixel cs e -> (Pixel X e -> Pixel X e) -> Pixel cs e+applyGrayscalePixel c f = coerce (applyGrayscale (coerce c) (coerce f))+{-# INLINE applyGrayscalePixel #-}++-- | Replace grayscale information in a pixel leaving chroma untouched. Same as+-- `replaceGrayscale` for `Color`+--+-- @since 0.4.0+replaceGrayscalePixel :: ColorSpace cs i e => Pixel cs e -> Pixel X e -> Pixel cs e+replaceGrayscalePixel c e = coerce (replaceGrayscale (coerce c) (coerce e))+{-# INLINE replaceGrayscalePixel #-}   -- -- | Constructor for a pixel in @sRGB@ color space with 8-bits per channel
src/Graphics/Pixel/Internal.hs view
@@ -8,7 +8,7 @@ {-# OPTIONS_HADDOCK hide, not-home #-} -- | -- Module      : Graphics.Pixel.Internal--- Copyright   : (c) Alexey Kuleshevich 2019-2020+-- Copyright   : (c) Alexey Kuleshevich 2019-2025 -- License     : BSD3 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru> -- Stability   : experimental
tests/Graphics/Color/Model/Common.hs view
@@ -46,6 +46,7 @@ import Test.HUnit (assertBool) import Test.Massiv.Array.Mutable import Test.QuickCheck+import GHC.TypeLits  instance (Random e, ColorModel cs e, Arbitrary (Color cs e)) => Arbitrary (Color (Alpha cs) e) where   arbitrary = addAlpha <$> arbitrary <*> arbitraryElevator@@ -68,7 +69,7 @@   expectSameLength xs ys   zipWithM_ f xs ys -expectSameLength :: Foldable t => t a1 -> t a2 -> IO ()+expectSameLength :: (HasCallStack, Foldable t) => t a1 -> t a2 -> IO () expectSameLength xs ys =   unless (length xs == length ys) $   expectationFailure $ "List lengths mismatch: " ++ show (length xs) ++ "/=" ++ show (length ys)@@ -154,7 +155,7 @@   epsilonEq ::-     (Show a, RealFloat a)+     (HasCallStack, Show a, RealFloat a)   => a -- ^ Epsilon, a maximum tolerated error. Sign is ignored.   -> a -- ^ Expected result.   -> a -- ^ Tested value.@@ -162,7 +163,8 @@ epsilonEq epsilon x y = property $ epsilonExpect epsilon x y  epsilonEqDouble ::-     Double -- ^ Expected result.+     HasCallStack+  => Double -- ^ Expected result.   -> Double -- ^ Tested value.   -> Property epsilonEqDouble = epsilonEq epsilon@@ -178,22 +180,26 @@     epsilon = 1e-6  -epsilonEqColor :: (ColorModel cs e, RealFloat e) => Color cs e -> Color cs e -> Property+epsilonEqColor ::+     (HasCallStack, ColorModel cs e, RealFloat e) => Color cs e -> Color cs e -> Property epsilonEqColor = epsilonEqColorTol epsilon   where     epsilon = 1e-11 -epsilonEqColorDouble :: ColorModel cs Double => Color cs Double -> Color cs Double -> Property+epsilonEqColorDouble ::+     (HasCallStack, ColorModel cs Double) => Color cs Double -> Color cs Double -> Property epsilonEqColorDouble = epsilonEqColorTol epsilon   where     epsilon = 1e-12 -epsilonEqColorFloat :: ColorModel cs Float => Color cs Float -> Color cs Float -> Property+epsilonEqColorFloat ::+     (HasCallStack, ColorModel cs Float) => Color cs Float -> Color cs Float -> Property epsilonEqColorFloat = epsilonEqColorTol epsilon   where     epsilon = 1e-6 -epsilonEqColorTol :: (ColorModel cs e, RealFloat e) => e -> Color cs e -> Color cs e -> Property+epsilonEqColorTol ::+     (HasCallStack, ColorModel cs e, RealFloat e) => e -> Color cs e -> Color cs e -> Property epsilonEqColorTol epsilon x y = property $ epsilonColorExpect epsilon x y   --conjoin $ F.toList $ liftA2 (epsilonEq epsilon) x y @@ -218,6 +224,7 @@      , Function (Components cs e)      , CoArbitrary (Components cs e)      , Arbitrary (Color cs e)+     , KnownNat (ChannelCount cs)      )   => String   -> Spec@@ -225,6 +232,12 @@   describe "ColorModel" $ do     toFromComponentsSpec @cs @e     it "Model Name" $ showsColorModelName (Proxy :: Proxy (Color cs e)) "" `shouldStartWith` name+    it "ChannelCount" $ do+      let px = Proxy :: Proxy (Color cs e)+          count = channelCount px+      count `shouldBe` fromInteger (natVal (Proxy :: Proxy (ChannelCount cs)))+      length (channelNames px)  `shouldBe` fromIntegral count+      length (channelColors px)  `shouldBe` fromIntegral count     modifyMaxSuccess (`div` 10) $ describe "Array" $ do       describe "Storable" $         mutableSpec @S @Ix1 @(Color cs e)
tests/Graphics/Color/Space/CIE1976/LABSpec.hs view
@@ -24,11 +24,12 @@   colorSpaceLenientSpec @(LAB 'D65) @Double 1e-10   describe "Same as colour package" $ do     prop "lab2srgb" $ \lab@(ColorLAB l' a' b' :: Color (LAB 'W.D65) Double) ->-      case Colour.toSRGB (Colour.cieLAB Colour.d65 l' a' b') of+      case Colour.toSRGB (Colour.cieLAB Colour.d65 (l' * 100) (a' * 100) (b' * 100)) of         Colour.RGB r g b ->           (convertColor lab :: Color (D.SRGB 'W.D65 'NonLinear) Double)           `epsilonEqColorDouble` ColorRGB r g b     prop "srgb2xlab" $ \rgb@(ColorRGB r g b :: Color (D.SRGB 'W.D65 'NonLinear) Double) ->       case Colour.cieLABView Colour.d65 (Colour.sRGB r g b) of         (l', a', b') ->-          convertColor rgb `epsilonEqColorDouble` (ColorLAB l' a' b' :: Color (LAB 'W.D65) Double)+          convertColor rgb `epsilonEqColorDouble`+          (ColorLAB (l' / 100) (a' / 100) (b' / 100) :: Color (LAB 'W.D65) Double)
tests/Graphics/Color/Space/Common.hs view
@@ -16,11 +16,15 @@   , prop_toFromBaseSpace   ) where +import Data.Coerce import Graphics.Color.Space import Graphics.Color.Model.Common +instance (Elevator e, Random e) => Arbitrary (Color X e) where+  arbitrary = coerce $ arbitraryElevator @e+ instance (Elevator e, Random e) => Arbitrary (Color (Y i) e) where-  arbitrary = Y <$> arbitraryElevator+  arbitrary = coerce $ arbitraryElevator @e  instance (Elevator e, Random e) => Arbitrary (Color (XYZ i) e) where   arbitrary = ColorXYZ <$> arbitraryElevator <*> arbitraryElevator <*> arbitraryElevator@@ -67,6 +71,44 @@   -> Property prop_toFromBaseModel c = c === fromBaseModel (toBaseModel c) +prop_toApplyGrayscale ::+     forall cs e i. (ColorSpace cs i e, RealFloat e)+  => e+  -> Color cs e+  -> Property+prop_toApplyGrayscale epsilon c = epsilonEqColorTol epsilon c $ applyGrayscale c id++prop_toReplaceGrayscale ::+     forall cs e i. (ColorSpace cs i e, RealFloat e)+  => e+  -> Color cs e+  -> Property+prop_toReplaceGrayscale epsilon c =+  epsilonEqColorTol epsilon c (replaceGrayscale c (grayscale c))++prop_toApplyGrayscaleAsReplace ::+     forall cs e i. (ColorSpace cs i e, RealFloat e)+  => e+  -> Color cs e+  -> Fun (Color X e) (Color X e)+  -> Property+prop_toApplyGrayscaleAsReplace epsilon c f =+  epsilonEqColorTol+    epsilon+    (applyGrayscale c (applyFun f))+    (replaceGrayscale c (applyFun f (grayscale c)))+++prop_toReplaceGrayscaleAsApply ::+     forall cs e i. (ColorSpace cs i e, RealFloat e)+  => e+  -> Color cs e+  -> Color X e+  -> Property+prop_toReplaceGrayscaleAsApply epsilon c y =+  epsilonEqColorTol epsilon (replaceGrayscale c y) (applyGrayscale c (const y))++ colorSpaceCommonSpec ::      forall cs e i.      (Arbitrary (Color cs e), ColorSpace cs i e)@@ -88,7 +130,14 @@  colorSpaceLenientSpec ::      forall cs e i.-     (Arbitrary (Color cs e), ColorSpace (BaseSpace cs) i e, ColorSpace cs i e, RealFloat e)+     ( Arbitrary (Color cs e)+     , ColorSpace (BaseSpace cs) i e+     , ColorSpace cs i e+     , RealFloat e+     , Function e+     , Random e+     , CoArbitrary e+     )   => e   -> Spec colorSpaceLenientSpec tol =@@ -96,3 +145,7 @@   in colorSpaceCommonSpec @cs @e @i $ do        prop ("toFromBaseSpace " ++ tolStr) $ prop_toFromBaseSpaceLenient @cs @e @i tol        prop ("toFromColorXYZ " ++ tolStr) $ prop_toFromLenientColorXYZ @cs @e @i tol+       prop ("toReplaceGrayscale " ++ tolStr) $ prop_toReplaceGrayscale @cs @e @i tol+       prop ("toReplaceGrayscaleAsApply " ++ tolStr) $ prop_toReplaceGrayscaleAsApply @cs @e @i tol+       prop ("toApplyGrayscale" ++ tolStr) $ prop_toApplyGrayscale @cs @e @i tol+       prop ("toApplyGrayscaleAsReplace" ++ tolStr) $ prop_toApplyGrayscaleAsReplace @cs @e @i tol
− tests/doctests.hs
@@ -1,16 +0,0 @@-{-# LANGUAGE CPP #-}-module Main where--#if __GLASGOW_HASKELL__ >= 802 && __GLASGOW_HASKELL__ < 810--import Test.DocTest (doctest)--main :: IO ()-main = doctest ["src"]--#else--main :: IO ()-main = putStrLn "\nDoctests are not supported for older ghc version\n"--#endif