patch-image-0.3.4: src/Knead/Color.hs
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE Rank2Types #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE EmptyDataDecls #-}
module Knead.Color where
import qualified Data.Array.Knead.Expression as Expr
import Data.Array.Knead.Expression (Exp)
import qualified LLVM.Extra.Nice.Value.Storable as Storable
import qualified LLVM.Extra.Nice.Vector as NiceVector
import qualified LLVM.Extra.Nice.Value as NiceValue
import qualified LLVM.Extra.Vector as Vector
import qualified LLVM.Extra.Tuple as Tuple
import qualified LLVM.Core as LLVM
import qualified Type.Data.Num.Decimal as TypeNum
import qualified Foreign.Storable.Traversable as StoreTrav
import Foreign.Storable (Storable, sizeOf, alignment, poke, peek)
import Foreign.Ptr (Ptr)
import Control.Monad ((<=<))
import Control.Applicative (Applicative, liftA3, pure, (<*>))
import Data.Traversable (Traversable, traverse)
import Data.Foldable (Foldable, foldMap)
import Data.Monoid ((<>))
data C3 space a = C3 a a a
type YUV = C3 SpaceYUV; data SpaceYUV
type RGB = C3 SpaceRGB; data SpaceRGB
instance Functor (C3 space) where
fmap f (C3 y u v) = C3 (f y) (f u) (f v)
instance Foldable (C3 space) where
foldMap f (C3 y u v) = f y <> f u <> f v
instance Traversable (C3 space) where
traverse f (C3 y u v) = liftA3 C3 (f y) (f u) (f v)
instance Applicative (C3 space) where
pure a = C3 a a a
C3 fy fu fv <*> C3 y u v = C3 (fy y) (fu u) (fv v)
instance (Storable a) => Storable (C3 space a) where
sizeOf = StoreTrav.sizeOf . lazyElements
alignment = StoreTrav.alignment
peek = StoreTrav.peekApplicative
poke = StoreTrav.poke
lazyElements :: C3 space a -> C3 space a
lazyElements ~(C3 y u v) = C3 y u v
instance
(Storable.Vector a, LLVM.IsPrimitive a, LLVM.IsConst a,
NiceVector.C a,
NiceVector.Repr TypeNum.D3 a ~ LLVM.Value (LLVM.Vector TypeNum.D3 a)) =>
Storable.C (C3 space a) where
load = fmap NiceValue.cast . Storable.load <=< castVectorPtr
store x = Storable.store (NiceValue.cast x) <=< castVectorPtr
castVectorPtr ::
LLVM.Value (Ptr (C3 space a)) ->
LLVM.CodeGenFunction r (LLVM.Value (Ptr (LLVM.Vector TypeNum.D3 a)))
castVectorPtr = LLVM.bitcast
instance
(LLVM.IsPrimitive a, LLVM.IsConst a) =>
Tuple.Value (C3 space a) where
type ValueOf (C3 space a) = LLVM.Value (LLVM.Vector TypeNum.D3 a)
valueOf (C3 a0 a1 a2) = LLVM.valueOf $ LLVM.consVector a0 a1 a2
instance
(LLVM.IsPrimitive a, LLVM.IsConst a) =>
NiceValue.C (C3 space a) where
type Repr (C3 space a) = LLVM.Value (LLVM.Vector TypeNum.D3 a)
cons (C3 a0 a1 a2) =
NiceValue.Cons $ LLVM.valueOf $ LLVM.consVector a0 a1 a2
undef = NiceValue.undefTuple
zero = NiceValue.zeroTuple
phi = NiceValue.phiTuple
addPhi = NiceValue.addPhiTuple
cons ::
(LLVM.IsPrimitive a, NiceValue.Repr a ~ LLVM.Value a) =>
Exp a -> Exp a -> Exp a -> Exp (C3 space a)
cons =
Expr.liftReprM3
(\y u v -> do
arr0 <- LLVM.insertelement Tuple.undef y (LLVM.valueOf 0)
arr1 <- LLVM.insertelement arr0 u (LLVM.valueOf 1)
LLVM.insertelement arr1 v (LLVM.valueOf 2))
yuv ::
(LLVM.IsPrimitive a, NiceValue.Repr a ~ LLVM.Value a) =>
Exp a -> Exp a -> Exp a -> Exp (YUV a)
yuv = cons
rgb ::
(LLVM.IsPrimitive a, NiceValue.Repr a ~ LLVM.Value a) =>
Exp a -> Exp a -> Exp a -> Exp (RGB a)
rgb = cons
class Space space where
brightness ::
(NiceValue.Field a, NiceValue.RationalConstant a, NiceValue.Real a,
LLVM.IsPrimitive a, NiceValue.Repr a ~ LLVM.Value a) =>
Exp (C3 space a) -> Exp a
luma ::
(LLVM.IsPrimitive a, NiceValue.Repr a ~ LLVM.Value a) =>
Exp (YUV a) -> Exp a
luma = Expr.liftReprM (flip LLVM.extractelement (LLVM.valueOf 0))
instance Space SpaceYUV where
brightness = luma
red, green, blue ::
(LLVM.IsPrimitive a, NiceValue.Repr a ~ LLVM.Value a) =>
Exp (RGB a) -> Exp a
red = Expr.liftReprM (flip LLVM.extractelement (LLVM.valueOf 0))
green = Expr.liftReprM (flip LLVM.extractelement (LLVM.valueOf 1))
blue = Expr.liftReprM (flip LLVM.extractelement (LLVM.valueOf 2))
instance Space SpaceRGB where
brightness c = 0.299 * red c + 0.587 * green c + 0.114 * blue c
mapPlain ::
(LLVM.IsPrimitive a, LLVM.IsPrimitive b) =>
(forall r. LLVM.Value a -> LLVM.CodeGenFunction r (LLVM.Value b)) ->
Exp (C3 space a) -> Exp (C3 space b)
mapPlain f = Expr.liftReprM (Vector.map f)
exprUnliftM1 ::
(NiceValue.Repr a ~ al, NiceValue.Repr b ~ bl) =>
(Exp a -> Exp b) -> al -> LLVM.CodeGenFunction r bl
exprUnliftM1 f a =
fmap (\(NiceValue.Cons b) -> b) $ Expr.unliftM1 f $ NiceValue.Cons a
map ::
(LLVM.IsPrimitive a, NiceValue.Repr a ~ LLVM.Value a,
LLVM.IsPrimitive b, NiceValue.Repr b ~ LLVM.Value b) =>
(Exp a -> Exp b) -> Exp (C3 space a) -> Exp (C3 space b)
map f = mapPlain (exprUnliftM1 f)