packages feed

colour-space 0.1.0.0 → 0.1.1.0

raw patch · 2 files changed

+138/−9 lines, 2 filesdep +constrained-categoriesdep +lineardep +linearmap-categorydep ~basedep ~manifoldsPVP ok

version bump matches the API change (PVP)

Dependencies added: constrained-categories, linear, linearmap-category

Dependency ranges changed: base, manifolds

API changes (from Hackage documentation)

+ Data.Colour.Manifold: instance Data.Manifold.Riemannian.Geodesic Data.Colour.Manifold.ColourNeedle
+ Data.Colour.Manifold: instance GHC.Show.Show Data.Colour.Manifold.ColourNeedle
+ Data.Colour.Manifold: instance Math.LinearMap.Category.Class.LinearSpace Data.Colour.Manifold.ColourNeedle
+ Data.Colour.Manifold: instance Math.LinearMap.Category.Class.TensorSpace Data.Colour.Manifold.ColourNeedle
+ Data.Colour.Manifold: instance Math.VectorSpace.Docile.FiniteDimensional Data.Colour.Manifold.ColourNeedle
+ Data.Colour.Manifold: instance Math.VectorSpace.Docile.SemiInner Data.Colour.Manifold.ColourNeedle

Files

colour-space.cabal view
@@ -2,7 +2,7 @@ -- documentation, see http://haskell.org/cabal/users-guide/  name:                colour-space-version:             0.1.0.0+version:             0.1.1.0 synopsis:            Instances of the manifold-classes for colour types -- description:          homepage:            https://github.com/leftaroundabout/colour-space@@ -20,8 +20,11 @@   exposed-modules:     Data.Colour.Manifold   -- other-modules:          -- other-extensions:    -  build-depends:       base >=4.7 && <4.9-                     , manifolds >=0.1.5 && <0.4+  build-depends:       base >=4.7 && <5+                     , manifolds >=0.3 && <0.3.1+                     , constrained-categories+                     , linearmap-category+                     , linear                      , vector-space                      , semigroups                      , colour > 2 && < 3
src/Data/Colour/Manifold.hs view
@@ -1,10 +1,13 @@ {-# LANGUAGE TypeFamilies      #-} {-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FlexibleContexts  #-}+{-# LANGUAGE TypeOperators     #-}  module Data.Colour.Manifold (Colour, QuantisedColour(..)) where -import Control.Applicative-import Control.Arrow+import Control.Applicative (empty)+import Control.Applicative.Constrained+import Control.Arrow.Constrained import Data.Semigroup  import Data.Manifold.PseudoAffine@@ -17,10 +20,31 @@ import Data.Colour.SRGB.Linear import Data.Colour +import Math.LinearMap.Category+import Linear.V3++import qualified Prelude as Hask+import Control.Category.Constrained.Prelude+ import Codec.Picture.Types -newtype ColourNeedle = ColourNeedle { getRGBNeedle :: RGB ℝ }+import Data.Coerce+import Data.Type.Coercion +newtype ColourNeedle = ColourNeedle { getRGBNeedle :: RGB ℝ } deriving (Show)++asV3Needle :: ColourNeedle -+> V3 ℝ+asV3Needle = LinearFunction $ \(ColourNeedle (RGB r g b)) -> V3 r g b++fromV3Needle :: V3 ℝ -+> ColourNeedle+fromV3Needle = LinearFunction $ \(V3 r g b) -> ColourNeedle $ RGB r g b++asV3Tensor :: (ColourNeedle⊗w) -+> (V3 ℝ⊗w)+asV3Tensor = LinearFunction $ \(Tensor (RGB r g b)) -> Tensor $ V3 r g b++fromV3Tensor :: (V3 ℝ⊗w) -+> (ColourNeedle⊗w)+fromV3Tensor = LinearFunction $ \(Tensor (V3 r g b)) -> Tensor $ RGB r g b+ withRGBNeedle :: (RGB Double -> RGB Double) -> ColourNeedle -> ColourNeedle withRGBNeedle f (ColourNeedle q) = ColourNeedle $ f q @@ -32,6 +56,96 @@   type Scalar ColourNeedle = ℝ   (*^)μ = withRGBNeedle $ fmap (μ*) +instance TensorSpace ColourNeedle where+  type TensorProduct ColourNeedle w = RGB w+  zeroTensor = Tensor (RGB zeroV zeroV zeroV)+  toFlatTensor = LinearFunction $ \(ColourNeedle (RGB r g b)) -> Tensor (RGB r g b)+  fromFlatTensor = LinearFunction $ \(Tensor (RGB r g b)) -> ColourNeedle (RGB r g b)+  addTensors (Tensor (RGB r g b)) (Tensor (RGB r' g' b'))+                = Tensor $ RGB (r^+^r') (g^+^g') (b^+^b')+  negateTensor = LinearFunction $ \(Tensor (RGB r g b))+                       -> Tensor (RGB (negateV r) (negateV g) (negateV b))+  scaleTensor = bilinearFunction $ \μ (Tensor (RGB r g b))+                       -> Tensor (RGB (μ*^r) (μ*^g) (μ*^b))+  tensorProduct = bilinearFunction $ \(ColourNeedle (RGB r g b)) w+                       -> Tensor (RGB (r*^w) (g*^w) (b*^w))+  transposeTensor = (fmapTensor $ fromV3Needle) . transposeTensor . asV3Tensor+  fmapTensor = bilinearFunction $ \f (Tensor (RGB r g b))+                   -> Tensor $ RGB (f $ r) (f $ g) (f $ b)+  fzipTensorWith = bilinearFunction $ \f (Tensor (RGB r g b), Tensor (RGB r' g' b'))+                   -> Tensor $ RGB (f $ (r,r')) (f $ (g,g')) (f $ (b,b'))+  coerceFmapTensorProduct _ Coercion = Coercion++instance LinearSpace ColourNeedle where+  type DualVector ColourNeedle = ColourNeedle+  linearId = LinearMap $ RGB (ColourNeedle $ RGB 1 0 0)+                             (ColourNeedle $ RGB 0 1 0)+                             (ColourNeedle $ RGB 0 0 1)+  coerceDoubleDual = Coercion+  blockVectSpan = LinearFunction $ \w -> Tensor $ RGB (LinearMap $ RGB w o o)+                                                      (LinearMap $ RGB o w o)+                                                      (LinearMap $ RGB o o w)+   where o = zeroV+  contractTensorMap = LinearFunction $ \(LinearMap (RGB (Tensor (RGB r _ _))+                                                        (Tensor (RGB _ g _))+                                                        (Tensor (RGB _ _ b))))+                        -> r ^+^ g ^+^ b+  contractMapTensor = LinearFunction $ \(Tensor (RGB (LinearMap (RGB r _ _))+                                                     (LinearMap (RGB _ g _))+                                                     (LinearMap (RGB _ _ b))))+                        -> r ^+^ g ^+^ b+  contractLinearMapAgainst = bilinearFunction $ \(LinearMap (RGB r g b)) f+                        -> channelRed (getRGBNeedle $ f $ r)+                         + channelGreen (getRGBNeedle $ f $ g)+                         + channelBlue (getRGBNeedle $ f $ b)+  applyDualVector = bilinearFunction $+         \(ColourNeedle (RGB r' g' b')) (ColourNeedle (RGB r g b))+            -> r'*r + g'*g + b'*b+  applyLinear = bilinearFunction $ \(LinearMap (RGB r' g' b')) (ColourNeedle (RGB r g b))+            -> r'^*r ^+^ g'^*g ^+^ b'^*b+  composeLinear = bilinearFunction $ \f (LinearMap (RGB r' g' b'))+            -> LinearMap $ RGB (f $ r') (f $ g') (f $ b')++instance SemiInner ColourNeedle where+  dualBasisCandidates = cartesianDualBasisCandidates+           [ColourNeedle (RGB 1 0 0), ColourNeedle (RGB 0 1 0), ColourNeedle (RGB 0 0 1)]+           (\(ColourNeedle (RGB r g b)) -> abs <$> [r,g,b])++instance FiniteDimensional ColourNeedle where+  data SubBasis ColourNeedle = ColourNeedleBasis+  entireBasis = ColourNeedleBasis+  enumerateSubBasis ColourNeedleBasis+          = ColourNeedle <$> [RGB 1 0 0, RGB 0 1 0, RGB 0 0 1]+  decomposeLinMap (LinearMap (RGB r g b)) = (ColourNeedleBasis, ([r,g,b]++))+  decomposeLinMapWithin ColourNeedleBasis (LinearMap (RGB r g b)) = pure ([r,g,b]++)+  recomposeSB ColourNeedleBasis [] = (ColourNeedle $ RGB 0 0 0, [])+  recomposeSB ColourNeedleBasis [r] = (ColourNeedle $ RGB r 0 0, [])+  recomposeSB ColourNeedleBasis [r,g] = (ColourNeedle $ RGB r g 0, [])+  recomposeSB ColourNeedleBasis (r:g:b:l) = (ColourNeedle $ RGB r g b, l)+  recomposeSBTensor ColourNeedleBasis sbw l+          = let (r,l') = recomposeSB sbw l+                (g,l'') = recomposeSB sbw l'+                (b,l''') = recomposeSB sbw l''+            in (Tensor $ RGB r g b, l''')+  recomposeLinMap ColourNeedleBasis [] = (LinearMap $ RGB zeroV zeroV zeroV, [])+  recomposeLinMap ColourNeedleBasis [r] = (LinearMap $ RGB r zeroV zeroV, [])+  recomposeLinMap ColourNeedleBasis [r,g] = (LinearMap $ RGB r g zeroV, [])+  recomposeLinMap ColourNeedleBasis (r:g:b:l) = (LinearMap $ RGB r g b, l)+  recomposeContraLinMap f l = LinearMap $ RGB (f $ fmap (channelRed . getRGBNeedle) l)+                                              (f $ fmap (channelGreen . getRGBNeedle) l)+                                              (f $ fmap (channelBlue . getRGBNeedle) l)+  recomposeContraLinMapTensor fw mv = LinearMap $+       (\c -> fromLinearMap $ recomposeContraLinMap fw+                $ fmap (\(Tensor q) -> c q) mv)+                       <$> RGB channelRed channelGreen channelBlue+  uncanonicallyFromDual = id+  uncanonicallyToDual = id++fromLinearMap :: (LSpace u, Scalar u ~ s) => LinearMap s (DualVector u) w -> Tensor s u w+fromLinearMap = coerce++  + instance Semimanifold ColourNeedle where   type Needle ColourNeedle = ColourNeedle   fromInterior = id; toInterior = pure@@ -50,13 +164,19 @@ type LtdCol = RGB (CD¹ ℝ⁰)  bijectToLtd :: ℝ -> CD¹ ℝ⁰-bijectToLtd y = CD¹ ( ( y - 1 + sqrt(1+y^2) ) / (2*y) ) Origin+bijectToLtd 0 = CD¹ 0.5 Origin+bijectToLtd y+  | ψ > 0.5    = CD¹ 1 Origin+  | ψ > -0.5   = CD¹ ( 0.5 - ψ ) Origin+  | otherwise  = CD¹ 0 Origin+ where ψ = (1 - sqrt(1+y^2)) / (2*y) -- y = (x - 1/2) / (x*(1 - x)) -- y * x * (1 - x) = x - 1/2 -- y * x² - (1 - y) * x - 1/2 = 0 -- y * x² + (y - 1) * x - 1/2 = 0 -- x = (1 - y ± sqrt( (1-y)² + 2*y ) ) / (-2*y)---   = (y - 1 +! sqrt( 1 + y² ) ) / (2*y)+--   = (y - 1 +! sqrt( 1 + y² ) ) / (2*y)  -- unstable for y ≈ 0+--   = 1/2 - (1 - sqrt( 1 + y² ) ) / (2*y)  bijectFromLtd :: CD¹ ℝ⁰ -> Option ℝ bijectFromLtd (CD¹ x Origin)@@ -75,8 +195,14 @@   c .-~. ζ = (^-^ζ) <$> toInterior c  instance Geodesic (Colour ℝ) where-  geodesicBetween a b = pure $ \(D¹ q) -> blend ((q+1)/2) b a+  geodesicBetween a b = return $ \(D¹ q) -> blend ((q+1)/2) b a +instance Geodesic ColourNeedle where+  geodesicBetween (ColourNeedle (RGB r g b)) (ColourNeedle (RGB r' g' b'))+                 = return $ \(D¹ q) -> let η' = (q+1)/2 in ColourNeedle+                                        $ RGB (lerp r r' η')+                                              (lerp g g' η')+                                              (lerp b b' η')  class QuantisedColour c where   quantiseColour :: Colour ℝ -> c