{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DefaultSignatures #-}
{-# LANGUAGE DeriveTraversable #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE ViewPatterns #-}
-- |
-- Module      : Graphics.Color.Space.RGB.Internal
-- Copyright   : (c) Alexey Kuleshevich 2019-2020
-- License     : BSD3
-- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru>
-- Stability   : experimental
-- Portability : non-portable
--
module Graphics.Color.Space.RGB.Internal
  ( pattern ColorRGB
  , pattern ColorRGBA
  , RedGreenBlue(..)
  , Linearity(..)
  , ecctf
  , dcctf
  , Gamut(..)
  , coerceGamut
  , rgb2xyz
  , rgbLinear2xyz
  , xyz2rgb
  , xyz2rgbLinear
  , rgbLuminance
  , rgbLinearLuminance
  , NPM(..)
  , npmApply
  , npmDerive
  , INPM(..)
  , inpmApply
  , inpmDerive
  , rgbColorGamut
  , pixelWhitePoint
  , gamutWhitePoint
  , module Graphics.Color.Space.Internal
  ) where

import Data.Coerce
import Graphics.Color.Algebra
import qualified Graphics.Color.Model.RGB as CM
import Graphics.Color.Space.Internal
import Data.Kind

data Linearity = Linear | NonLinear

class Illuminant i => RedGreenBlue (cs :: Linearity -> Type) (i :: k) | cs -> i where
  -- | RGB primaries that are defined for the RGB color space, while point is defined by
  -- the __@i@__ type parameter
  gamut :: RealFloat e => Gamut cs i e

  -- | @since 0.3.0
  transfer :: RealFloat e => e -> e

  -- | @since 0.3.0
  itransfer :: RealFloat e => e -> e

  -- | Normalized primary matrix for this RGB color space. Default implementation derives
  -- it from `chromaticity`
  npm :: (ColorSpace (cs 'Linear) i e, RealFloat e) => NPM cs e
  npm = Gamut cs i e -> NPM cs e
forall k (cs :: Linearity -> *) (i :: k) e.
(ColorSpace (cs 'Linear) i e, RealFloat e) =>
Gamut cs i e -> NPM cs e
npmDerive Gamut cs i e
forall k (cs :: Linearity -> *) (i :: k) e.
(RedGreenBlue cs i, RealFloat e) =>
Gamut cs i e
gamut
  {-# INLINE npm #-}

  -- | Inverse normalized primary matrix for this RGB color space. Default implementation
  -- derives it from `chromaticity`
  inpm :: (ColorSpace (cs 'Linear) i e, RealFloat e) => INPM cs e
  inpm = Gamut cs i e -> INPM cs e
forall k (cs :: Linearity -> *) (i :: k) e.
(ColorSpace (cs 'Linear) i e, RealFloat e) =>
Gamut cs i e -> INPM cs e
inpmDerive Gamut cs i e
forall k (cs :: Linearity -> *) (i :: k) e.
(RedGreenBlue cs i, RealFloat e) =>
Gamut cs i e
gamut
  {-# INLINE inpm #-}

  -- | Lift RGB color model into a RGB color space
  mkColorRGB :: Color CM.RGB e -> Color (cs l) e
  default mkColorRGB ::
    Coercible (Color CM.RGB e) (Color (cs l) e) => Color CM.RGB e -> Color (cs l) e
  mkColorRGB = Color RGB e -> Color (cs l) e
coerce

  -- | Drop RGB color space down to the RGB color model
  unColorRGB :: Color (cs l) e -> Color CM.RGB e
  default unColorRGB ::
    Coercible (Color (cs l) e) (Color CM.RGB e) => Color (cs l) e -> Color CM.RGB e
  unColorRGB = Color (cs l) e -> Color RGB e
coerce

-- | This function allows for creating a completely mismatched color space spec. Make
-- sure you know what you are doing, if you need to use it.
--
-- @since 0.3.0
coerceGamut :: Gamut cs' i' e -> Gamut cs i e
coerceGamut :: Gamut cs' i' e -> Gamut cs i e
coerceGamut (Gamut Primary i' e
r Primary i' e
g Primary i' e
b) = Primary i e -> Primary i e -> Primary i e -> Gamut cs i e
forall k (cs :: Linearity -> *) (i :: k) e.
Primary i e -> Primary i e -> Primary i e -> Gamut cs i e
Gamut (Primary i' e -> Primary i e
coerce Primary i' e
r) (Primary i' e -> Primary i e
coerce Primary i' e
g) (Primary i' e -> Primary i e
coerce Primary i' e
b)


-- | RGB color space gamut specification.
data Gamut (cs :: Linearity -> Type) i e = Gamut
  { Gamut cs i e -> Primary i e
gamutRedPrimary   :: !(Primary i e)
  , Gamut cs i e -> Primary i e
gamutGreenPrimary :: !(Primary i e)
  , Gamut cs i e -> Primary i e
gamutBluePrimary  :: !(Primary i e)
  }
deriving instance Eq e => Eq (Gamut cs i e)

instance (RealFloat e, Elevator e, Illuminant i) => Show (Gamut cs i e) where
  show :: Gamut cs i e -> String
show Gamut {Primary i e
gamutBluePrimary :: Primary i e
gamutGreenPrimary :: Primary i e
gamutRedPrimary :: Primary i e
gamutBluePrimary :: forall (cs :: Linearity -> *) k (i :: k) e.
Gamut cs i e -> Primary i e
gamutGreenPrimary :: forall (cs :: Linearity -> *) k (i :: k) e.
Gamut cs i e -> Primary i e
gamutRedPrimary :: forall (cs :: Linearity -> *) k (i :: k) e.
Gamut cs i e -> Primary i e
..} =
    [String] -> String
unlines
      [ String
"Gamut:"
      , String
"  Red:   " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Chromaticity i e -> String
forall a. Show a => a -> String
show (Primary i e -> Chromaticity i e
forall k (i :: k) e. Primary i e -> Chromaticity i e
primaryChromaticity Primary i e
gamutRedPrimary)
      , String
"  Green: " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Chromaticity i e -> String
forall a. Show a => a -> String
show (Primary i e -> Chromaticity i e
forall k (i :: k) e. Primary i e -> Chromaticity i e
primaryChromaticity Primary i e
gamutGreenPrimary)
      , String
"  Blue:  " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Chromaticity i e -> String
forall a. Show a => a -> String
show (Primary i e -> Chromaticity i e
forall k (i :: k) e. Primary i e -> Chromaticity i e
primaryChromaticity Primary i e
gamutBluePrimary)
      ]

-- | Get the `WhitePoint` of chromaticity. `Chromaticity` itself isn't actually evaluated,
-- its type carries enough information for this operation.
--
-- @since 0.1.0
gamutWhitePoint ::
     forall cs e i. (RedGreenBlue cs i, RealFloat e)
  => Gamut cs i e
  -> WhitePoint i e
gamutWhitePoint :: Gamut cs i e -> WhitePoint i e
gamutWhitePoint Gamut cs i e
_ = WhitePoint i e
forall k (i :: k) e. (Illuminant i, RealFloat e) => WhitePoint i e
whitePoint
{-# INLINE gamutWhitePoint #-}


-- | Encoding color component transfer function (forward). Also known as opto-electronic
-- transfer function (OETF / OECF).
--
-- @since 0.1.0
ecctf ::
     forall cs e i. (RedGreenBlue cs i, RealFloat e)
  => Color (cs 'Linear) e
  -> Color (cs 'NonLinear) e
ecctf :: Color (cs 'Linear) e -> Color (cs 'NonLinear) e
ecctf = Color RGB e -> Color (cs 'NonLinear) e
forall k (cs :: Linearity -> *) (i :: k) e (l :: Linearity).
RedGreenBlue cs i =>
Color RGB e -> Color (cs l) e
mkColorRGB (Color RGB e -> Color (cs 'NonLinear) e)
-> (Color (cs 'Linear) e -> Color RGB e)
-> Color (cs 'Linear) e
-> Color (cs 'NonLinear) e
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (e -> e) -> Color RGB e -> Color RGB e
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall (i :: k) e. (RedGreenBlue cs i, RealFloat e) => e -> e
forall k (cs :: Linearity -> *) (i :: k) e.
(RedGreenBlue cs i, RealFloat e) =>
e -> e
transfer @_ @cs) (Color RGB e -> Color RGB e)
-> (Color (cs 'Linear) e -> Color RGB e)
-> Color (cs 'Linear) e
-> Color RGB e
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Color (cs 'Linear) e -> Color RGB e
forall k (cs :: Linearity -> *) (i :: k) (l :: Linearity) e.
RedGreenBlue cs i =>
Color (cs l) e -> Color RGB e
unColorRGB
{-# INLINE ecctf #-}

-- | Decoding color component transfer function (inverse).  Also known as electro-optical
-- transfer function (EOTF / EOCF).
--
-- @since 0.1.0
dcctf ::
     forall cs e i. (RedGreenBlue cs i, RealFloat e)
  => Color (cs 'NonLinear) e
  -> Color (cs 'Linear) e
dcctf :: Color (cs 'NonLinear) e -> Color (cs 'Linear) e
dcctf = Color RGB e -> Color (cs 'Linear) e
forall k (cs :: Linearity -> *) (i :: k) e (l :: Linearity).
RedGreenBlue cs i =>
Color RGB e -> Color (cs l) e
mkColorRGB (Color RGB e -> Color (cs 'Linear) e)
-> (Color (cs 'NonLinear) e -> Color RGB e)
-> Color (cs 'NonLinear) e
-> Color (cs 'Linear) e
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (e -> e) -> Color RGB e -> Color RGB e
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall (i :: k) e. (RedGreenBlue cs i, RealFloat e) => e -> e
forall k (cs :: Linearity -> *) (i :: k) e.
(RedGreenBlue cs i, RealFloat e) =>
e -> e
itransfer @_ @cs) (Color RGB e -> Color RGB e)
-> (Color (cs 'NonLinear) e -> Color RGB e)
-> Color (cs 'NonLinear) e
-> Color RGB e
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Color (cs 'NonLinear) e -> Color RGB e
forall k (cs :: Linearity -> *) (i :: k) (l :: Linearity) e.
RedGreenBlue cs i =>
Color (cs l) e -> Color RGB e
unColorRGB
{-# INLINE dcctf #-}


-- | Linear transformation of a pixel in a linear RGB color space into XYZ color space
--
-- ==== __Examples__
--
-- This example depicts the fact that even in @ghci@ when @npm@ is instantiated to a
-- concrete type, despite being derived it is memoized and gets computed only once.
--
-- >>> :set -XDataKinds
-- >>> import Debug.Trace
-- >>> import Graphics.Color.Illuminant.CIE1931
-- >>> import Graphics.Color.Space.RGB.Derived.SRGB
-- >>> :{
-- srgbFromLinear :: Color (SRGB 'D65 'Linear) Float -> Color (XYZ 'D65) Float
-- srgbFromLinear = npmApply npm'
--   where npm' = trace "Evaluated only once!!!" npm :: NPM (SRGB 'D65) Float
-- :}
--
-- >>> srgbFromLinear $ ColorRGB 0.1 0.2 0.3
-- <XYZ CIE1931 'D65:(Evaluated only once!!!
--  0.16688849, 0.18595251, 0.31085595)>
-- >>> srgbFromLinear $ ColorRGB 0.1 0.2 0.3
-- <XYZ CIE1931 'D65:( 0.16688849, 0.18595251, 0.31085595)>
-- >>> rgb = ColorRGB 0.1 0.2 0.3 :: Color (SRGB 'D65 'Linear) Float
-- >>> npmApply npm rgb :: Color (XYZ 'D65) Float
-- <XYZ CIE1931 'D65:( 0.16688849, 0.18595251, 0.31085595)>
--
-- Here is a comparison with a non-liner sRGB conversion:
--
-- >>> rgb = ColorRGB 0.1 0.2 0.3 :: Color (SRGB 'D65 'NonLinear) Float
-- >>> npmApply npm (dcctf rgb) :: Color (XYZ 'D65) Float {- non-linear transformation -}
-- <XYZ CIE1931 'D65:( 0.02918611, 0.03109305, 0.07373714)>
-- >>> toColorXYZ rgb :: Color (XYZ 'D65) Float           {- non-linear transformation -}
-- <XYZ CIE1931 'D65:( 0.02918611, 0.03109305, 0.07373714)>
--
--
-- @since 0.1.0
npmApply ::
     (RedGreenBlue cs i, Elevator e)
  => NPM cs e
  -> Color (cs 'Linear) e
  -> Color (XYZ i) e
npmApply :: NPM cs e -> Color (cs 'Linear) e -> Color (XYZ i) e
npmApply (NPM M3x3 e
npm') = V3 e -> Color (XYZ i) e
coerce (V3 e -> Color (XYZ i) e)
-> (Color (cs 'Linear) e -> V3 e)
-> Color (cs 'Linear) e
-> Color (XYZ i) e
forall b c a. (b -> c) -> (a -> b) -> a -> c
. M3x3 e -> V3 e -> V3 e
forall a. Num a => M3x3 a -> V3 a -> V3 a
multM3x3byV3 M3x3 e
npm' (V3 e -> V3 e)
-> (Color (cs 'Linear) e -> V3 e) -> Color (cs 'Linear) e -> V3 e
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Color RGB e -> V3 e
coerce (Color RGB e -> V3 e)
-> (Color (cs 'Linear) e -> Color RGB e)
-> Color (cs 'Linear) e
-> V3 e
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Color (cs 'Linear) e -> Color RGB e
forall k (cs :: Linearity -> *) (i :: k) (l :: Linearity) e.
RedGreenBlue cs i =>
Color (cs l) e -> Color RGB e
unColorRGB
{-# INLINE npmApply #-}

-- | Linear transformation of a pixel in XYZ color space into a linear RGB color space
--
-- @since 0.1.0
inpmApply ::
     (RedGreenBlue cs i, Elevator e)
  => INPM cs e
  -> Color (XYZ i) e
  -> Color (cs 'Linear) e
inpmApply :: INPM cs e -> Color (XYZ i) e -> Color (cs 'Linear) e
inpmApply (INPM M3x3 e
inpm') = Color RGB e -> Color (cs 'Linear) e
forall k (cs :: Linearity -> *) (i :: k) e (l :: Linearity).
RedGreenBlue cs i =>
Color RGB e -> Color (cs l) e
mkColorRGB (Color RGB e -> Color (cs 'Linear) e)
-> (Color (XYZ i) e -> Color RGB e)
-> Color (XYZ i) e
-> Color (cs 'Linear) e
forall b c a. (b -> c) -> (a -> b) -> a -> c
. V3 e -> Color RGB e
coerce (V3 e -> Color RGB e)
-> (Color (XYZ i) e -> V3 e) -> Color (XYZ i) e -> Color RGB e
forall b c a. (b -> c) -> (a -> b) -> a -> c
. M3x3 e -> V3 e -> V3 e
forall a. Num a => M3x3 a -> V3 a -> V3 a
multM3x3byV3 M3x3 e
inpm' (V3 e -> V3 e)
-> (Color (XYZ i) e -> V3 e) -> Color (XYZ i) e -> V3 e
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Color (XYZ i) e -> V3 e
coerce
{-# INLINE inpmApply #-}

-- | Linear transformation of a color into a linear luminance, i.e. the Y component of
-- XYZ color space
rgbLinearLuminance ::
     forall cs i e. (RedGreenBlue cs i, ColorSpace (cs 'Linear) i e, RealFloat e)
  => Color (cs 'Linear) e
  -> Color (Y i) e
rgbLinearLuminance :: Color (cs 'Linear) e -> Color (Y i) e
rgbLinearLuminance Color (cs 'Linear) e
px =
  e -> Color (Y i) e
forall k e (i :: k). e -> Color (Y i) e
Y (M3x3 e -> V3 e
forall a. M3x3 a -> V3 a
m3x3row1 (NPM cs e -> M3x3 e
forall k (cs :: k) e. NPM cs e -> M3x3 e
unNPM (NPM cs e
forall k (cs :: Linearity -> *) (i :: k) e.
(RedGreenBlue cs i, ColorSpace (cs 'Linear) i e, RealFloat e) =>
NPM cs e
npm :: NPM cs e)) V3 e -> V3 e -> e
forall a. Num a => V3 a -> V3 a -> a
`dotProduct` Color RGB e -> V3 e
coerce (Color (cs 'Linear) e -> Color RGB e
forall k (cs :: Linearity -> *) (i :: k) (l :: Linearity) e.
RedGreenBlue cs i =>
Color (cs l) e -> Color RGB e
unColorRGB Color (cs 'Linear) e
px))
{-# INLINE rgbLinearLuminance #-}


rgbLuminance ::
     (RedGreenBlue cs i, ColorSpace (cs 'Linear) i e, RealFloat e)
  => Color (cs 'NonLinear) e
  -> Color (Y i) e
rgbLuminance :: Color (cs 'NonLinear) e -> Color (Y i) e
rgbLuminance = Color (cs 'Linear) e -> Color (Y i) e
forall k (cs :: Linearity -> *) (i :: k) e.
(RedGreenBlue cs i, ColorSpace (cs 'Linear) i e, RealFloat e) =>
Color (cs 'Linear) e -> Color (Y i) e
rgbLinearLuminance (Color (cs 'Linear) e -> Color (Y i) e)
-> (Color (cs 'NonLinear) e -> Color (cs 'Linear) e)
-> Color (cs 'NonLinear) e
-> Color (Y i) e
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Color (cs 'NonLinear) e -> Color (cs 'Linear) e
forall k (cs :: Linearity -> *) e (i :: k).
(RedGreenBlue cs i, RealFloat e) =>
Color (cs 'NonLinear) e -> Color (cs 'Linear) e
dcctf
{-# INLINE rgbLuminance #-}

rgb2xyz ::
     (RedGreenBlue cs i, ColorSpace (cs 'NonLinear) i e, ColorSpace (cs 'Linear) i e, RealFloat e)
  => Color (cs 'NonLinear) e
  -> Color (XYZ i) e
rgb2xyz :: Color (cs 'NonLinear) e -> Color (XYZ i) e
rgb2xyz = NPM cs e -> Color (cs 'Linear) e -> Color (XYZ i) e
forall k (cs :: Linearity -> *) (i :: k) e.
(RedGreenBlue cs i, Elevator e) =>
NPM cs e -> Color (cs 'Linear) e -> Color (XYZ i) e
npmApply NPM cs e
forall k (cs :: Linearity -> *) (i :: k) e.
(RedGreenBlue cs i, ColorSpace (cs 'Linear) i e, RealFloat e) =>
NPM cs e
npm (Color (cs 'Linear) e -> Color (XYZ i) e)
-> (Color (cs 'NonLinear) e -> Color (cs 'Linear) e)
-> Color (cs 'NonLinear) e
-> Color (XYZ i) e
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Color (cs 'NonLinear) e -> Color (cs 'Linear) e
forall k (cs :: Linearity -> *) e (i :: k).
(RedGreenBlue cs i, RealFloat e) =>
Color (cs 'NonLinear) e -> Color (cs 'Linear) e
dcctf
{-# INLINE rgb2xyz #-}

xyz2rgb ::
     (RedGreenBlue cs i, ColorSpace (cs 'NonLinear) i e, ColorSpace (cs 'Linear) i e, RealFloat e)
  => Color (XYZ i) e
  -> Color (cs 'NonLinear) e
xyz2rgb :: Color (XYZ i) e -> Color (cs 'NonLinear) e
xyz2rgb = Color (cs 'Linear) e -> Color (cs 'NonLinear) e
forall k (cs :: Linearity -> *) e (i :: k).
(RedGreenBlue cs i, RealFloat e) =>
Color (cs 'Linear) e -> Color (cs 'NonLinear) e
ecctf (Color (cs 'Linear) e -> Color (cs 'NonLinear) e)
-> (Color (XYZ i) e -> Color (cs 'Linear) e)
-> Color (XYZ i) e
-> Color (cs 'NonLinear) e
forall b c a. (b -> c) -> (a -> b) -> a -> c
. INPM cs e -> Color (XYZ i) e -> Color (cs 'Linear) e
forall k (cs :: Linearity -> *) (i :: k) e.
(RedGreenBlue cs i, Elevator e) =>
INPM cs e -> Color (XYZ i) e -> Color (cs 'Linear) e
inpmApply INPM cs e
forall k (cs :: Linearity -> *) (i :: k) e.
(RedGreenBlue cs i, ColorSpace (cs 'Linear) i e, RealFloat e) =>
INPM cs e
inpm
{-# INLINE xyz2rgb #-}


rgbLinear2xyz ::
     (RedGreenBlue cs i, ColorSpace (cs 'NonLinear) i e, ColorSpace (cs 'Linear) i e, RealFloat e)
  => Color (cs 'Linear) e
  -> Color (XYZ i) e
rgbLinear2xyz :: Color (cs 'Linear) e -> Color (XYZ i) e
rgbLinear2xyz = NPM cs e -> Color (cs 'Linear) e -> Color (XYZ i) e
forall k (cs :: Linearity -> *) (i :: k) e.
(RedGreenBlue cs i, Elevator e) =>
NPM cs e -> Color (cs 'Linear) e -> Color (XYZ i) e
npmApply NPM cs e
forall k (cs :: Linearity -> *) (i :: k) e.
(RedGreenBlue cs i, ColorSpace (cs 'Linear) i e, RealFloat e) =>
NPM cs e
npm
{-# INLINE rgbLinear2xyz #-}

xyz2rgbLinear ::
     forall cs i e.
     (RedGreenBlue cs i, ColorSpace (cs 'NonLinear) i e, ColorSpace (cs 'Linear) i e, RealFloat e)
  => Color (XYZ i) e
  -> Color (cs 'Linear) e
xyz2rgbLinear :: Color (XYZ i) e -> Color (cs 'Linear) e
xyz2rgbLinear = INPM cs e -> Color (XYZ i) e -> Color (cs 'Linear) e
forall k (cs :: Linearity -> *) (i :: k) e.
(RedGreenBlue cs i, Elevator e) =>
INPM cs e -> Color (XYZ i) e -> Color (cs 'Linear) e
inpmApply INPM cs e
forall k (cs :: Linearity -> *) (i :: k) e.
(RedGreenBlue cs i, ColorSpace (cs 'Linear) i e, RealFloat e) =>
INPM cs e
inpm
{-# INLINE xyz2rgbLinear #-}

-- | Constructor for an RGB color space.
pattern ColorRGB :: RedGreenBlue cs i => e -> e -> e -> Color (cs l) e
pattern $bColorRGB :: e -> e -> e -> Color (cs l) e
$mColorRGB :: forall r k (cs :: Linearity -> *) (i :: k) e (l :: Linearity).
RedGreenBlue cs i =>
Color (cs l) e -> (e -> e -> e -> r) -> (Void# -> r) -> r
ColorRGB r g b <- (unColorRGB -> CM.ColorRGB r g b) where
        ColorRGB e
r e
g e
b = Color RGB e -> Color (cs l) e
forall k (cs :: Linearity -> *) (i :: k) e (l :: Linearity).
RedGreenBlue cs i =>
Color RGB e -> Color (cs l) e
mkColorRGB (e -> e -> e -> Color RGB e
forall e. e -> e -> e -> Color RGB e
CM.ColorRGB e
r e
g e
b)
{-# COMPLETE ColorRGB #-}

-- | Constructor for an RGB color space with Alpha channel
pattern ColorRGBA :: RedGreenBlue cs i => e -> e -> e -> e -> Color (Alpha (cs l)) e
pattern $bColorRGBA :: e -> e -> e -> e -> Color (Alpha (cs l)) e
$mColorRGBA :: forall r k (cs :: Linearity -> *) (i :: k) e (l :: Linearity).
RedGreenBlue cs i =>
Color (Alpha (cs l)) e
-> (e -> e -> e -> e -> r) -> (Void# -> r) -> r
ColorRGBA r g b a <- Alpha (unColorRGB -> CM.ColorRGB r g b) a where
        ColorRGBA e
r e
g e
b e
a = Color (cs l) e -> e -> Color (Alpha (cs l)) e
forall cs e. Color cs e -> e -> Color (Alpha cs) e
Alpha (Color RGB e -> Color (cs l) e
forall k (cs :: Linearity -> *) (i :: k) e (l :: Linearity).
RedGreenBlue cs i =>
Color RGB e -> Color (cs l) e
mkColorRGB (e -> e -> e -> Color RGB e
forall e. e -> e -> e -> Color RGB e
CM.ColorRGB e
r e
g e
b)) e
a
{-# COMPLETE ColorRGBA #-}


-- newtype ConversionMatrix cs' cs = ConversionMatrix M3x3

-- conversionMatrix ::
--      forall cs' i' cs i. (RedGreenBlue cs' i', RedGreenBlue cs i)
--   => ConversionMatrix (cs' i') (cs i)
-- conversionMatrix =
--   ConversionMatrix $ multM3x3byM3x3 (unINPM (inpm :: INPM cs i)) (unNPM (npm :: NPM cs' i'))

-- makeConversionMatrix ::
--      forall cta cs' i' cs i. (RedGreenBlue cs' i', RedGreenBlue cs i)
--   => cta -> ConversionMatrix (cs' i') (cs i)
-- makeConversionMatrix _cta =
--   ConversionMatrix $ multM3x3byM3x3 (unINPM (inpm :: INPM cs i)) (unNPM (npm :: NPM cs' i'))


-- applyConversionMatrix ::
--      (RedGreenBlue cs1 i1, RedGreenBlue cs2 i2, Elevator e2, Elevator e1)
--   => ConversionMatrix (cs1 i1) (cs2 i2)
--   -> Color (cs1 i1) e1
--   -> Color (cs2 i2) e2
-- applyConversionMatrix (ConversionMatrix m) px =
--   mkColorRGB $ fromV3 CM.ColorRGB $ multM3x3byV3 m (toV3 r g b)
--   where
--     CM.ColorRGB r g b = unColorRGB px

-- | Normalized primary matrix (NPM), which is used to tranform linear RGB color space
-- into `Graphics.Color.Space.CIE1931.XYZ.XYZ` color space.
--
-- @since 0.1.0
newtype NPM cs e = NPM
  { NPM cs e -> M3x3 e
unNPM :: M3x3 e
  } deriving (NPM cs e -> NPM cs e -> Bool
(NPM cs e -> NPM cs e -> Bool)
-> (NPM cs e -> NPM cs e -> Bool) -> Eq (NPM cs e)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall k (cs :: k) e. Eq e => NPM cs e -> NPM cs e -> Bool
/= :: NPM cs e -> NPM cs e -> Bool
$c/= :: forall k (cs :: k) e. Eq e => NPM cs e -> NPM cs e -> Bool
== :: NPM cs e -> NPM cs e -> Bool
$c== :: forall k (cs :: k) e. Eq e => NPM cs e -> NPM cs e -> Bool
Eq, a -> NPM cs b -> NPM cs a
(a -> b) -> NPM cs a -> NPM cs b
(forall a b. (a -> b) -> NPM cs a -> NPM cs b)
-> (forall a b. a -> NPM cs b -> NPM cs a) -> Functor (NPM cs)
forall k (cs :: k) a b. a -> NPM cs b -> NPM cs a
forall k (cs :: k) a b. (a -> b) -> NPM cs a -> NPM cs b
forall a b. a -> NPM cs b -> NPM cs a
forall a b. (a -> b) -> NPM cs a -> NPM cs b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: a -> NPM cs b -> NPM cs a
$c<$ :: forall k (cs :: k) a b. a -> NPM cs b -> NPM cs a
fmap :: (a -> b) -> NPM cs a -> NPM cs b
$cfmap :: forall k (cs :: k) a b. (a -> b) -> NPM cs a -> NPM cs b
Functor, Functor (NPM cs)
a -> NPM cs a
Functor (NPM cs)
-> (forall a. a -> NPM cs a)
-> (forall a b. NPM cs (a -> b) -> NPM cs a -> NPM cs b)
-> (forall a b c.
    (a -> b -> c) -> NPM cs a -> NPM cs b -> NPM cs c)
-> (forall a b. NPM cs a -> NPM cs b -> NPM cs b)
-> (forall a b. NPM cs a -> NPM cs b -> NPM cs a)
-> Applicative (NPM cs)
NPM cs a -> NPM cs b -> NPM cs b
NPM cs a -> NPM cs b -> NPM cs a
NPM cs (a -> b) -> NPM cs a -> NPM cs b
(a -> b -> c) -> NPM cs a -> NPM cs b -> NPM cs c
forall a. a -> NPM cs a
forall k (cs :: k). Functor (NPM cs)
forall k (cs :: k) a. a -> NPM cs a
forall k (cs :: k) a b. NPM cs a -> NPM cs b -> NPM cs a
forall k (cs :: k) a b. NPM cs a -> NPM cs b -> NPM cs b
forall k (cs :: k) a b. NPM cs (a -> b) -> NPM cs a -> NPM cs b
forall k (cs :: k) a b c.
(a -> b -> c) -> NPM cs a -> NPM cs b -> NPM cs c
forall a b. NPM cs a -> NPM cs b -> NPM cs a
forall a b. NPM cs a -> NPM cs b -> NPM cs b
forall a b. NPM cs (a -> b) -> NPM cs a -> NPM cs b
forall a b c. (a -> b -> c) -> NPM cs a -> NPM cs b -> NPM cs c
forall (f :: * -> *).
Functor f
-> (forall a. a -> f a)
-> (forall a b. f (a -> b) -> f a -> f b)
-> (forall a b c. (a -> b -> c) -> f a -> f b -> f c)
-> (forall a b. f a -> f b -> f b)
-> (forall a b. f a -> f b -> f a)
-> Applicative f
<* :: NPM cs a -> NPM cs b -> NPM cs a
$c<* :: forall k (cs :: k) a b. NPM cs a -> NPM cs b -> NPM cs a
*> :: NPM cs a -> NPM cs b -> NPM cs b
$c*> :: forall k (cs :: k) a b. NPM cs a -> NPM cs b -> NPM cs b
liftA2 :: (a -> b -> c) -> NPM cs a -> NPM cs b -> NPM cs c
$cliftA2 :: forall k (cs :: k) a b c.
(a -> b -> c) -> NPM cs a -> NPM cs b -> NPM cs c
<*> :: NPM cs (a -> b) -> NPM cs a -> NPM cs b
$c<*> :: forall k (cs :: k) a b. NPM cs (a -> b) -> NPM cs a -> NPM cs b
pure :: a -> NPM cs a
$cpure :: forall k (cs :: k) a. a -> NPM cs a
$cp1Applicative :: forall k (cs :: k). Functor (NPM cs)
Applicative, a -> NPM cs a -> Bool
NPM cs m -> m
NPM cs a -> [a]
NPM cs a -> Bool
NPM cs a -> Int
NPM cs a -> a
NPM cs a -> a
NPM cs a -> a
NPM cs a -> a
(a -> m) -> NPM cs a -> m
(a -> m) -> NPM cs a -> m
(a -> b -> b) -> b -> NPM cs a -> b
(a -> b -> b) -> b -> NPM cs a -> b
(b -> a -> b) -> b -> NPM cs a -> b
(b -> a -> b) -> b -> NPM cs a -> b
(a -> a -> a) -> NPM cs a -> a
(a -> a -> a) -> NPM cs a -> a
(forall m. Monoid m => NPM cs m -> m)
-> (forall m a. Monoid m => (a -> m) -> NPM cs a -> m)
-> (forall m a. Monoid m => (a -> m) -> NPM cs a -> m)
-> (forall a b. (a -> b -> b) -> b -> NPM cs a -> b)
-> (forall a b. (a -> b -> b) -> b -> NPM cs a -> b)
-> (forall b a. (b -> a -> b) -> b -> NPM cs a -> b)
-> (forall b a. (b -> a -> b) -> b -> NPM cs a -> b)
-> (forall a. (a -> a -> a) -> NPM cs a -> a)
-> (forall a. (a -> a -> a) -> NPM cs a -> a)
-> (forall a. NPM cs a -> [a])
-> (forall a. NPM cs a -> Bool)
-> (forall a. NPM cs a -> Int)
-> (forall a. Eq a => a -> NPM cs a -> Bool)
-> (forall a. Ord a => NPM cs a -> a)
-> (forall a. Ord a => NPM cs a -> a)
-> (forall a. Num a => NPM cs a -> a)
-> (forall a. Num a => NPM cs a -> a)
-> Foldable (NPM cs)
forall a. Eq a => a -> NPM cs a -> Bool
forall a. Num a => NPM cs a -> a
forall a. Ord a => NPM cs a -> a
forall m. Monoid m => NPM cs m -> m
forall a. NPM cs a -> Bool
forall a. NPM cs a -> Int
forall a. NPM cs a -> [a]
forall a. (a -> a -> a) -> NPM cs a -> a
forall k (cs :: k) a. Eq a => a -> NPM cs a -> Bool
forall k (cs :: k) a. Num a => NPM cs a -> a
forall k (cs :: k) a. Ord a => NPM cs a -> a
forall k (cs :: k) m. Monoid m => NPM cs m -> m
forall k (cs :: k) a. NPM cs a -> Bool
forall k (cs :: k) a. NPM cs a -> Int
forall k (cs :: k) a. NPM cs a -> [a]
forall k (cs :: k) a. (a -> a -> a) -> NPM cs a -> a
forall k (cs :: k) m a. Monoid m => (a -> m) -> NPM cs a -> m
forall k (cs :: k) b a. (b -> a -> b) -> b -> NPM cs a -> b
forall k (cs :: k) a b. (a -> b -> b) -> b -> NPM cs a -> b
forall m a. Monoid m => (a -> m) -> NPM cs a -> m
forall b a. (b -> a -> b) -> b -> NPM cs a -> b
forall a b. (a -> b -> b) -> b -> NPM cs a -> b
forall (t :: * -> *).
(forall m. Monoid m => t m -> m)
-> (forall m a. Monoid m => (a -> m) -> t a -> m)
-> (forall m a. Monoid m => (a -> m) -> t a -> m)
-> (forall a b. (a -> b -> b) -> b -> t a -> b)
-> (forall a b. (a -> b -> b) -> b -> t a -> b)
-> (forall b a. (b -> a -> b) -> b -> t a -> b)
-> (forall b a. (b -> a -> b) -> b -> t a -> b)
-> (forall a. (a -> a -> a) -> t a -> a)
-> (forall a. (a -> a -> a) -> t a -> a)
-> (forall a. t a -> [a])
-> (forall a. t a -> Bool)
-> (forall a. t a -> Int)
-> (forall a. Eq a => a -> t a -> Bool)
-> (forall a. Ord a => t a -> a)
-> (forall a. Ord a => t a -> a)
-> (forall a. Num a => t a -> a)
-> (forall a. Num a => t a -> a)
-> Foldable t
product :: NPM cs a -> a
$cproduct :: forall k (cs :: k) a. Num a => NPM cs a -> a
sum :: NPM cs a -> a
$csum :: forall k (cs :: k) a. Num a => NPM cs a -> a
minimum :: NPM cs a -> a
$cminimum :: forall k (cs :: k) a. Ord a => NPM cs a -> a
maximum :: NPM cs a -> a
$cmaximum :: forall k (cs :: k) a. Ord a => NPM cs a -> a
elem :: a -> NPM cs a -> Bool
$celem :: forall k (cs :: k) a. Eq a => a -> NPM cs a -> Bool
length :: NPM cs a -> Int
$clength :: forall k (cs :: k) a. NPM cs a -> Int
null :: NPM cs a -> Bool
$cnull :: forall k (cs :: k) a. NPM cs a -> Bool
toList :: NPM cs a -> [a]
$ctoList :: forall k (cs :: k) a. NPM cs a -> [a]
foldl1 :: (a -> a -> a) -> NPM cs a -> a
$cfoldl1 :: forall k (cs :: k) a. (a -> a -> a) -> NPM cs a -> a
foldr1 :: (a -> a -> a) -> NPM cs a -> a
$cfoldr1 :: forall k (cs :: k) a. (a -> a -> a) -> NPM cs a -> a
foldl' :: (b -> a -> b) -> b -> NPM cs a -> b
$cfoldl' :: forall k (cs :: k) b a. (b -> a -> b) -> b -> NPM cs a -> b
foldl :: (b -> a -> b) -> b -> NPM cs a -> b
$cfoldl :: forall k (cs :: k) b a. (b -> a -> b) -> b -> NPM cs a -> b
foldr' :: (a -> b -> b) -> b -> NPM cs a -> b
$cfoldr' :: forall k (cs :: k) a b. (a -> b -> b) -> b -> NPM cs a -> b
foldr :: (a -> b -> b) -> b -> NPM cs a -> b
$cfoldr :: forall k (cs :: k) a b. (a -> b -> b) -> b -> NPM cs a -> b
foldMap' :: (a -> m) -> NPM cs a -> m
$cfoldMap' :: forall k (cs :: k) m a. Monoid m => (a -> m) -> NPM cs a -> m
foldMap :: (a -> m) -> NPM cs a -> m
$cfoldMap :: forall k (cs :: k) m a. Monoid m => (a -> m) -> NPM cs a -> m
fold :: NPM cs m -> m
$cfold :: forall k (cs :: k) m. Monoid m => NPM cs m -> m
Foldable, Functor (NPM cs)
Foldable (NPM cs)
Functor (NPM cs)
-> Foldable (NPM cs)
-> (forall (f :: * -> *) a b.
    Applicative f =>
    (a -> f b) -> NPM cs a -> f (NPM cs b))
-> (forall (f :: * -> *) a.
    Applicative f =>
    NPM cs (f a) -> f (NPM cs a))
-> (forall (m :: * -> *) a b.
    Monad m =>
    (a -> m b) -> NPM cs a -> m (NPM cs b))
-> (forall (m :: * -> *) a.
    Monad m =>
    NPM cs (m a) -> m (NPM cs a))
-> Traversable (NPM cs)
(a -> f b) -> NPM cs a -> f (NPM cs b)
forall k (cs :: k). Functor (NPM cs)
forall k (cs :: k). Foldable (NPM cs)
forall k (cs :: k) (m :: * -> *) a.
Monad m =>
NPM cs (m a) -> m (NPM cs a)
forall k (cs :: k) (f :: * -> *) a.
Applicative f =>
NPM cs (f a) -> f (NPM cs a)
forall k (cs :: k) (m :: * -> *) a b.
Monad m =>
(a -> m b) -> NPM cs a -> m (NPM cs b)
forall k (cs :: k) (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> NPM cs a -> f (NPM cs b)
forall (t :: * -> *).
Functor t
-> Foldable t
-> (forall (f :: * -> *) a b.
    Applicative f =>
    (a -> f b) -> t a -> f (t b))
-> (forall (f :: * -> *) a. Applicative f => t (f a) -> f (t a))
-> (forall (m :: * -> *) a b.
    Monad m =>
    (a -> m b) -> t a -> m (t b))
-> (forall (m :: * -> *) a. Monad m => t (m a) -> m (t a))
-> Traversable t
forall (m :: * -> *) a. Monad m => NPM cs (m a) -> m (NPM cs a)
forall (f :: * -> *) a.
Applicative f =>
NPM cs (f a) -> f (NPM cs a)
forall (m :: * -> *) a b.
Monad m =>
(a -> m b) -> NPM cs a -> m (NPM cs b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> NPM cs a -> f (NPM cs b)
sequence :: NPM cs (m a) -> m (NPM cs a)
$csequence :: forall k (cs :: k) (m :: * -> *) a.
Monad m =>
NPM cs (m a) -> m (NPM cs a)
mapM :: (a -> m b) -> NPM cs a -> m (NPM cs b)
$cmapM :: forall k (cs :: k) (m :: * -> *) a b.
Monad m =>
(a -> m b) -> NPM cs a -> m (NPM cs b)
sequenceA :: NPM cs (f a) -> f (NPM cs a)
$csequenceA :: forall k (cs :: k) (f :: * -> *) a.
Applicative f =>
NPM cs (f a) -> f (NPM cs a)
traverse :: (a -> f b) -> NPM cs a -> f (NPM cs b)
$ctraverse :: forall k (cs :: k) (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> NPM cs a -> f (NPM cs b)
$cp2Traversable :: forall k (cs :: k). Foldable (NPM cs)
$cp1Traversable :: forall k (cs :: k). Functor (NPM cs)
Traversable)

instance Elevator e => Show (NPM cs e) where
  show :: NPM cs e -> String
show = M3x3 e -> String
forall a. Show a => a -> String
show (M3x3 e -> String) -> (NPM cs e -> M3x3 e) -> NPM cs e -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NPM cs e -> M3x3 e
forall k (cs :: k) e. NPM cs e -> M3x3 e
unNPM

-- | Inverse normalized primary matrix (iNPM), which is used to tranform linear
-- `Graphics.Color.Space.CIE1931.XYZ.XYZ` color space into a linear RGB color space. It is
-- literally a inverse matrix of `NPM`
--
-- @since 0.1.0
newtype INPM cs e = INPM
  { INPM cs e -> M3x3 e
unINPM :: M3x3 e
  } deriving (INPM cs e -> INPM cs e -> Bool
(INPM cs e -> INPM cs e -> Bool)
-> (INPM cs e -> INPM cs e -> Bool) -> Eq (INPM cs e)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall k (cs :: k) e. Eq e => INPM cs e -> INPM cs e -> Bool
/= :: INPM cs e -> INPM cs e -> Bool
$c/= :: forall k (cs :: k) e. Eq e => INPM cs e -> INPM cs e -> Bool
== :: INPM cs e -> INPM cs e -> Bool
$c== :: forall k (cs :: k) e. Eq e => INPM cs e -> INPM cs e -> Bool
Eq, a -> INPM cs b -> INPM cs a
(a -> b) -> INPM cs a -> INPM cs b
(forall a b. (a -> b) -> INPM cs a -> INPM cs b)
-> (forall a b. a -> INPM cs b -> INPM cs a) -> Functor (INPM cs)
forall k (cs :: k) a b. a -> INPM cs b -> INPM cs a
forall k (cs :: k) a b. (a -> b) -> INPM cs a -> INPM cs b
forall a b. a -> INPM cs b -> INPM cs a
forall a b. (a -> b) -> INPM cs a -> INPM cs b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: a -> INPM cs b -> INPM cs a
$c<$ :: forall k (cs :: k) a b. a -> INPM cs b -> INPM cs a
fmap :: (a -> b) -> INPM cs a -> INPM cs b
$cfmap :: forall k (cs :: k) a b. (a -> b) -> INPM cs a -> INPM cs b
Functor, Functor (INPM cs)
a -> INPM cs a
Functor (INPM cs)
-> (forall a. a -> INPM cs a)
-> (forall a b. INPM cs (a -> b) -> INPM cs a -> INPM cs b)
-> (forall a b c.
    (a -> b -> c) -> INPM cs a -> INPM cs b -> INPM cs c)
-> (forall a b. INPM cs a -> INPM cs b -> INPM cs b)
-> (forall a b. INPM cs a -> INPM cs b -> INPM cs a)
-> Applicative (INPM cs)
INPM cs a -> INPM cs b -> INPM cs b
INPM cs a -> INPM cs b -> INPM cs a
INPM cs (a -> b) -> INPM cs a -> INPM cs b
(a -> b -> c) -> INPM cs a -> INPM cs b -> INPM cs c
forall a. a -> INPM cs a
forall k (cs :: k). Functor (INPM cs)
forall k (cs :: k) a. a -> INPM cs a
forall k (cs :: k) a b. INPM cs a -> INPM cs b -> INPM cs a
forall k (cs :: k) a b. INPM cs a -> INPM cs b -> INPM cs b
forall k (cs :: k) a b. INPM cs (a -> b) -> INPM cs a -> INPM cs b
forall k (cs :: k) a b c.
(a -> b -> c) -> INPM cs a -> INPM cs b -> INPM cs c
forall a b. INPM cs a -> INPM cs b -> INPM cs a
forall a b. INPM cs a -> INPM cs b -> INPM cs b
forall a b. INPM cs (a -> b) -> INPM cs a -> INPM cs b
forall a b c. (a -> b -> c) -> INPM cs a -> INPM cs b -> INPM cs c
forall (f :: * -> *).
Functor f
-> (forall a. a -> f a)
-> (forall a b. f (a -> b) -> f a -> f b)
-> (forall a b c. (a -> b -> c) -> f a -> f b -> f c)
-> (forall a b. f a -> f b -> f b)
-> (forall a b. f a -> f b -> f a)
-> Applicative f
<* :: INPM cs a -> INPM cs b -> INPM cs a
$c<* :: forall k (cs :: k) a b. INPM cs a -> INPM cs b -> INPM cs a
*> :: INPM cs a -> INPM cs b -> INPM cs b
$c*> :: forall k (cs :: k) a b. INPM cs a -> INPM cs b -> INPM cs b
liftA2 :: (a -> b -> c) -> INPM cs a -> INPM cs b -> INPM cs c
$cliftA2 :: forall k (cs :: k) a b c.
(a -> b -> c) -> INPM cs a -> INPM cs b -> INPM cs c
<*> :: INPM cs (a -> b) -> INPM cs a -> INPM cs b
$c<*> :: forall k (cs :: k) a b. INPM cs (a -> b) -> INPM cs a -> INPM cs b
pure :: a -> INPM cs a
$cpure :: forall k (cs :: k) a. a -> INPM cs a
$cp1Applicative :: forall k (cs :: k). Functor (INPM cs)
Applicative, a -> INPM cs a -> Bool
INPM cs m -> m
INPM cs a -> [a]
INPM cs a -> Bool
INPM cs a -> Int
INPM cs a -> a
INPM cs a -> a
INPM cs a -> a
INPM cs a -> a
(a -> m) -> INPM cs a -> m
(a -> m) -> INPM cs a -> m
(a -> b -> b) -> b -> INPM cs a -> b
(a -> b -> b) -> b -> INPM cs a -> b
(b -> a -> b) -> b -> INPM cs a -> b
(b -> a -> b) -> b -> INPM cs a -> b
(a -> a -> a) -> INPM cs a -> a
(a -> a -> a) -> INPM cs a -> a
(forall m. Monoid m => INPM cs m -> m)
-> (forall m a. Monoid m => (a -> m) -> INPM cs a -> m)
-> (forall m a. Monoid m => (a -> m) -> INPM cs a -> m)
-> (forall a b. (a -> b -> b) -> b -> INPM cs a -> b)
-> (forall a b. (a -> b -> b) -> b -> INPM cs a -> b)
-> (forall b a. (b -> a -> b) -> b -> INPM cs a -> b)
-> (forall b a. (b -> a -> b) -> b -> INPM cs a -> b)
-> (forall a. (a -> a -> a) -> INPM cs a -> a)
-> (forall a. (a -> a -> a) -> INPM cs a -> a)
-> (forall a. INPM cs a -> [a])
-> (forall a. INPM cs a -> Bool)
-> (forall a. INPM cs a -> Int)
-> (forall a. Eq a => a -> INPM cs a -> Bool)
-> (forall a. Ord a => INPM cs a -> a)
-> (forall a. Ord a => INPM cs a -> a)
-> (forall a. Num a => INPM cs a -> a)
-> (forall a. Num a => INPM cs a -> a)
-> Foldable (INPM cs)
forall a. Eq a => a -> INPM cs a -> Bool
forall a. Num a => INPM cs a -> a
forall a. Ord a => INPM cs a -> a
forall m. Monoid m => INPM cs m -> m
forall a. INPM cs a -> Bool
forall a. INPM cs a -> Int
forall a. INPM cs a -> [a]
forall a. (a -> a -> a) -> INPM cs a -> a
forall k (cs :: k) a. Eq a => a -> INPM cs a -> Bool
forall k (cs :: k) a. Num a => INPM cs a -> a
forall k (cs :: k) a. Ord a => INPM cs a -> a
forall k (cs :: k) m. Monoid m => INPM cs m -> m
forall k (cs :: k) a. INPM cs a -> Bool
forall k (cs :: k) a. INPM cs a -> Int
forall k (cs :: k) a. INPM cs a -> [a]
forall k (cs :: k) a. (a -> a -> a) -> INPM cs a -> a
forall k (cs :: k) m a. Monoid m => (a -> m) -> INPM cs a -> m
forall k (cs :: k) b a. (b -> a -> b) -> b -> INPM cs a -> b
forall k (cs :: k) a b. (a -> b -> b) -> b -> INPM cs a -> b
forall m a. Monoid m => (a -> m) -> INPM cs a -> m
forall b a. (b -> a -> b) -> b -> INPM cs a -> b
forall a b. (a -> b -> b) -> b -> INPM cs a -> b
forall (t :: * -> *).
(forall m. Monoid m => t m -> m)
-> (forall m a. Monoid m => (a -> m) -> t a -> m)
-> (forall m a. Monoid m => (a -> m) -> t a -> m)
-> (forall a b. (a -> b -> b) -> b -> t a -> b)
-> (forall a b. (a -> b -> b) -> b -> t a -> b)
-> (forall b a. (b -> a -> b) -> b -> t a -> b)
-> (forall b a. (b -> a -> b) -> b -> t a -> b)
-> (forall a. (a -> a -> a) -> t a -> a)
-> (forall a. (a -> a -> a) -> t a -> a)
-> (forall a. t a -> [a])
-> (forall a. t a -> Bool)
-> (forall a. t a -> Int)
-> (forall a. Eq a => a -> t a -> Bool)
-> (forall a. Ord a => t a -> a)
-> (forall a. Ord a => t a -> a)
-> (forall a. Num a => t a -> a)
-> (forall a. Num a => t a -> a)
-> Foldable t
product :: INPM cs a -> a
$cproduct :: forall k (cs :: k) a. Num a => INPM cs a -> a
sum :: INPM cs a -> a
$csum :: forall k (cs :: k) a. Num a => INPM cs a -> a
minimum :: INPM cs a -> a
$cminimum :: forall k (cs :: k) a. Ord a => INPM cs a -> a
maximum :: INPM cs a -> a
$cmaximum :: forall k (cs :: k) a. Ord a => INPM cs a -> a
elem :: a -> INPM cs a -> Bool
$celem :: forall k (cs :: k) a. Eq a => a -> INPM cs a -> Bool
length :: INPM cs a -> Int
$clength :: forall k (cs :: k) a. INPM cs a -> Int
null :: INPM cs a -> Bool
$cnull :: forall k (cs :: k) a. INPM cs a -> Bool
toList :: INPM cs a -> [a]
$ctoList :: forall k (cs :: k) a. INPM cs a -> [a]
foldl1 :: (a -> a -> a) -> INPM cs a -> a
$cfoldl1 :: forall k (cs :: k) a. (a -> a -> a) -> INPM cs a -> a
foldr1 :: (a -> a -> a) -> INPM cs a -> a
$cfoldr1 :: forall k (cs :: k) a. (a -> a -> a) -> INPM cs a -> a
foldl' :: (b -> a -> b) -> b -> INPM cs a -> b
$cfoldl' :: forall k (cs :: k) b a. (b -> a -> b) -> b -> INPM cs a -> b
foldl :: (b -> a -> b) -> b -> INPM cs a -> b
$cfoldl :: forall k (cs :: k) b a. (b -> a -> b) -> b -> INPM cs a -> b
foldr' :: (a -> b -> b) -> b -> INPM cs a -> b
$cfoldr' :: forall k (cs :: k) a b. (a -> b -> b) -> b -> INPM cs a -> b
foldr :: (a -> b -> b) -> b -> INPM cs a -> b
$cfoldr :: forall k (cs :: k) a b. (a -> b -> b) -> b -> INPM cs a -> b
foldMap' :: (a -> m) -> INPM cs a -> m
$cfoldMap' :: forall k (cs :: k) m a. Monoid m => (a -> m) -> INPM cs a -> m
foldMap :: (a -> m) -> INPM cs a -> m
$cfoldMap :: forall k (cs :: k) m a. Monoid m => (a -> m) -> INPM cs a -> m
fold :: INPM cs m -> m
$cfold :: forall k (cs :: k) m. Monoid m => INPM cs m -> m
Foldable, Functor (INPM cs)
Foldable (INPM cs)
Functor (INPM cs)
-> Foldable (INPM cs)
-> (forall (f :: * -> *) a b.
    Applicative f =>
    (a -> f b) -> INPM cs a -> f (INPM cs b))
-> (forall (f :: * -> *) a.
    Applicative f =>
    INPM cs (f a) -> f (INPM cs a))
-> (forall (m :: * -> *) a b.
    Monad m =>
    (a -> m b) -> INPM cs a -> m (INPM cs b))
-> (forall (m :: * -> *) a.
    Monad m =>
    INPM cs (m a) -> m (INPM cs a))
-> Traversable (INPM cs)
(a -> f b) -> INPM cs a -> f (INPM cs b)
forall k (cs :: k). Functor (INPM cs)
forall k (cs :: k). Foldable (INPM cs)
forall k (cs :: k) (m :: * -> *) a.
Monad m =>
INPM cs (m a) -> m (INPM cs a)
forall k (cs :: k) (f :: * -> *) a.
Applicative f =>
INPM cs (f a) -> f (INPM cs a)
forall k (cs :: k) (m :: * -> *) a b.
Monad m =>
(a -> m b) -> INPM cs a -> m (INPM cs b)
forall k (cs :: k) (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> INPM cs a -> f (INPM cs b)
forall (t :: * -> *).
Functor t
-> Foldable t
-> (forall (f :: * -> *) a b.
    Applicative f =>
    (a -> f b) -> t a -> f (t b))
-> (forall (f :: * -> *) a. Applicative f => t (f a) -> f (t a))
-> (forall (m :: * -> *) a b.
    Monad m =>
    (a -> m b) -> t a -> m (t b))
-> (forall (m :: * -> *) a. Monad m => t (m a) -> m (t a))
-> Traversable t
forall (m :: * -> *) a. Monad m => INPM cs (m a) -> m (INPM cs a)
forall (f :: * -> *) a.
Applicative f =>
INPM cs (f a) -> f (INPM cs a)
forall (m :: * -> *) a b.
Monad m =>
(a -> m b) -> INPM cs a -> m (INPM cs b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> INPM cs a -> f (INPM cs b)
sequence :: INPM cs (m a) -> m (INPM cs a)
$csequence :: forall k (cs :: k) (m :: * -> *) a.
Monad m =>
INPM cs (m a) -> m (INPM cs a)
mapM :: (a -> m b) -> INPM cs a -> m (INPM cs b)
$cmapM :: forall k (cs :: k) (m :: * -> *) a b.
Monad m =>
(a -> m b) -> INPM cs a -> m (INPM cs b)
sequenceA :: INPM cs (f a) -> f (INPM cs a)
$csequenceA :: forall k (cs :: k) (f :: * -> *) a.
Applicative f =>
INPM cs (f a) -> f (INPM cs a)
traverse :: (a -> f b) -> INPM cs a -> f (INPM cs b)
$ctraverse :: forall k (cs :: k) (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> INPM cs a -> f (INPM cs b)
$cp2Traversable :: forall k (cs :: k). Foldable (INPM cs)
$cp1Traversable :: forall k (cs :: k). Functor (INPM cs)
Traversable)

instance Elevator e => Show (INPM cs e) where
  show :: INPM cs e -> String
show = M3x3 e -> String
forall a. Show a => a -> String
show (M3x3 e -> String) -> (INPM cs e -> M3x3 e) -> INPM cs e -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. INPM cs e -> M3x3 e
forall k (cs :: k) e. INPM cs e -> M3x3 e
unINPM


-- | Derive a `NPM` form chromaticities and a white point
--
-- @since 0.1.0
npmDerive ::
     forall cs i e. (ColorSpace (cs 'Linear) i e, RealFloat e)
  => Gamut cs i e
  -> NPM cs e
npmDerive :: Gamut cs i e -> NPM cs e
npmDerive (Gamut Primary i e
r Primary i e
g Primary i e
b) = M3x3 e -> NPM cs e
forall k (cs :: k) e. M3x3 e -> NPM cs e
NPM (M3x3 e
primaries' M3x3 e -> M3x3 e -> M3x3 e
forall a. Num a => a -> a -> a
* V3 e -> V3 e -> V3 e -> M3x3 e
forall a. V3 a -> V3 a -> V3 a -> M3x3 a
M3x3 V3 e
coeff V3 e
coeff V3 e
coeff)
  where
    !primaries' :: M3x3 e
primaries' =
      e -> e
forall e a. (Elevator e, Elevator a, RealFloat a) => e -> a
toRealFloat (e -> e) -> M3x3 e -> M3x3 e
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>
      -- transposed matrix with xyz primaries
      V3 e -> V3 e -> V3 e -> M3x3 e
forall a. V3 a -> V3 a -> V3 a -> M3x3 a
M3x3
        (e -> e -> e -> V3 e
forall a. a -> a -> a -> V3 a
V3 (Primary i e -> e
forall k (i :: k) e. Primary i e -> e
xPrimary Primary i e
r) (Primary i e -> e
forall k (i :: k) e. Primary i e -> e
xPrimary Primary i e
g) (Primary i e -> e
forall k (i :: k) e. Primary i e -> e
xPrimary Primary i e
b))
        (e -> e -> e -> V3 e
forall a. a -> a -> a -> V3 a
V3 (Primary i e -> e
forall k (i :: k) e. Primary i e -> e
yPrimary Primary i e
r) (Primary i e -> e
forall k (i :: k) e. Primary i e -> e
yPrimary Primary i e
g) (Primary i e -> e
forall k (i :: k) e. Primary i e -> e
yPrimary Primary i e
b))
        (e -> e -> e -> V3 e
forall a. a -> a -> a -> V3 a
V3 (Primary i e -> e
forall k e (i :: k). Num e => Primary i e -> e
zPrimary Primary i e
r) (Primary i e -> e
forall k e (i :: k). Num e => Primary i e -> e
zPrimary Primary i e
g) (Primary i e -> e
forall k e (i :: k). Num e => Primary i e -> e
zPrimary Primary i e
b))
    !coeff :: V3 e
coeff = M3x3 e -> M3x3 e
forall a. Fractional a => M3x3 a -> M3x3 a
invertM3x3 M3x3 e
primaries' M3x3 e -> V3 e -> V3 e
forall a. Num a => M3x3 a -> V3 a -> V3 a
`multM3x3byV3` Color (XYZ i) e -> V3 e
coerce (Color (XYZ i) e
forall k (i :: k) e.
(Illuminant i, RealFloat e, Elevator e) =>
Color (XYZ i) e
whitePointTristimulus :: Color (XYZ i) e)
{-# INLINE npmDerive #-}

-- | Derive an `INPM` form chromaticities and a white point
--
-- @since 0.1.0
inpmDerive ::
     forall cs i e. (ColorSpace (cs 'Linear) i e, RealFloat e)
  => Gamut cs i e
  -> INPM cs e
inpmDerive :: Gamut cs i e -> INPM cs e
inpmDerive = M3x3 e -> INPM cs e
forall k (cs :: k) e. M3x3 e -> INPM cs e
INPM (M3x3 e -> INPM cs e)
-> (Gamut cs i e -> M3x3 e) -> Gamut cs i e -> INPM cs e
forall b c a. (b -> c) -> (a -> b) -> a -> c
. M3x3 e -> M3x3 e
forall a. Fractional a => M3x3 a -> M3x3 a
invertM3x3 (M3x3 e -> M3x3 e)
-> (Gamut cs i e -> M3x3 e) -> Gamut cs i e -> M3x3 e
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NPM cs e -> M3x3 e
forall k (cs :: k) e. NPM cs e -> M3x3 e
unNPM (NPM cs e -> M3x3 e)
-> (Gamut cs i e -> NPM cs e) -> Gamut cs i e -> M3x3 e
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Gamut cs i e -> NPM cs e
forall k (cs :: Linearity -> *) (i :: k) e.
(ColorSpace (cs 'Linear) i e, RealFloat e) =>
Gamut cs i e -> NPM cs e
npmDerive
{-# INLINE inpmDerive #-}



-- | Get the `Chromaticity` of a pixel in RGB color space. Color itself isn't actually
-- evaluated, its type carries enough information for this operation.
--
-- @since 0.1.0
rgbColorGamut :: (RedGreenBlue cs i, RealFloat e) => Color (cs l) a -> Gamut cs i e
rgbColorGamut :: Color (cs l) a -> Gamut cs i e
rgbColorGamut Color (cs l) a
_ = Gamut cs i e
forall k (cs :: Linearity -> *) (i :: k) e.
(RedGreenBlue cs i, RealFloat e) =>
Gamut cs i e
gamut
{-# INLINE rgbColorGamut #-}


-- | Get the white point of any RGB pixel. Color itself isn't evaluated, since its type
-- carries enough information for getting the white point.
--
-- >>> import Graphics.Color.Space.RGB
-- >>> :set -XTypeApplications
-- >>> pixelWhitePoint @Float (ColorSRGB @Word8 1 2 3)
-- WhitePoint (Chromaticity {chromaticityCIExyY = <CIExyY * D65:( 0.31270000, 0.32900000)>})
--
-- @since 0.1.0
pixelWhitePoint ::
     forall e cs a i l. (RedGreenBlue cs i, RealFloat e)
  => Color (cs l) a
  -> WhitePoint i e
pixelWhitePoint :: Color (cs l) a -> WhitePoint i e
pixelWhitePoint Color (cs l) a
_ = WhitePoint i e
forall k (i :: k) e. (Illuminant i, RealFloat e) => WhitePoint i e
whitePoint
{-# INLINE pixelWhitePoint #-}