module Vision.Image.Type (
Manifest (..)
, Delayed (..)
, DelayedMask (..)
, delay, compute, delayed, manifest
) where
#if __GLASGOW_HASKELL__ < 710
import Control.Applicative ((<$>))
#endif
import Control.DeepSeq (NFData (..))
import Data.Convertible (Convertible (..), convert)
import Data.Vector.Storable (Vector, create, enumFromN, forM_, generate)
import Data.Vector.Storable.Mutable (new, write)
import Foreign.Storable (Storable)
import Prelude hiding (map, read)
import qualified Data.Vector.Storable as V
import Vision.Image.Class (
MaskedImage (..), Image (..), FromFunction (..), FunctorImage (..), (!)
)
import Vision.Primitive (Z (..), (:.) (..), Point, Size, ix2)
data Manifest p = Manifest {
manifestSize :: !Size
, manifestVector :: !(Vector p)
} deriving (Eq, Ord, Show)
instance NFData (Manifest p) where
rnf !_ = ()
instance Storable p => MaskedImage (Manifest p) where
type ImagePixel (Manifest p) = p
shape = manifestSize
Manifest _ vec `maskedLinearIndex` ix = Just $! vec V.! ix
values = manifestVector
instance Storable p => Image (Manifest p) where
Manifest _ vec `linearIndex` ix = vec V.! ix
vector = manifestVector
instance Storable p => FromFunction (Manifest p) where
type FromFunctionPixel (Manifest p) = p
fromFunction !size@(Z :. h :. w) f =
Manifest size $ create $ do
arr <- new (h * w)
forM_ (enumFromN 0 h) $ \y -> do
let !lineOffset = y * w
forM_ (enumFromN 0 w) $ \x -> do
let !offset = lineOffset + x
!val = f (ix2 y x)
write arr offset val
return arr
fromFunctionLine !size@(Z :. h :. w) line f =
Manifest size $ create $ do
arr <- new (h * w)
forM_ (enumFromN 0 h) $ \y -> do
let !lineVal = line y
!lineOffset = y * w
forM_ (enumFromN 0 w) $ \x -> do
let !offset = lineOffset + x
!val = f lineVal (ix2 y x)
write arr offset val
return arr
fromFunctionCol !size@(Z :. h :. w) col f =
Manifest size $ create $ do
arr <- new (h * w)
forM_ (enumFromN 0 h) $ \y -> do
let !lineOffset = y * w
forM_ (enumFromN 0 w) $ \x -> do
let !offset = lineOffset + x
!val = f (cols V.! x) (ix2 y x)
write arr offset val
return arr
where
!cols = generate w col
fromFunctionCached !size@(Z :. h :. w) line col f =
Manifest size $ create $ do
arr <- new (h * w)
forM_ (enumFromN 0 h) $ \y -> do
let !lineVal = line y
!lineOffset = y * w
forM_ (enumFromN 0 w) $ \x -> do
let !offset = lineOffset + x
!val = f lineVal (cols V.! x) (ix2 y x)
write arr offset val
return arr
where
!cols = generate w col
instance (Image src, Storable p) => FunctorImage src (Manifest p) where
map f img = fromFunction (shape img) (f . (img !))
data Delayed p = Delayed {
delayedSize :: !Size
, delayedFun :: !(Point -> p)
}
instance Storable p => MaskedImage (Delayed p) where
type ImagePixel (Delayed p) = p
shape = delayedSize
maskedIndex img = Just . delayedFun img
instance Storable p => Image (Delayed p) where
index = delayedFun
instance FromFunction (Delayed p) where
type FromFunctionPixel (Delayed p) = p
fromFunction = Delayed
instance (Image src, Storable p) => FunctorImage src (Delayed p) where
map f img = fromFunction (shape img) (f . (img !))
data DelayedMask p = DelayedMask {
delayedMaskSize :: !Size
, delayedMaskFun :: !(Point -> Maybe p)
}
instance Storable p => MaskedImage (DelayedMask p) where
type ImagePixel (DelayedMask p) = p
shape = delayedMaskSize
maskedIndex = delayedMaskFun
instance Storable p => FromFunction (DelayedMask p) where
type FromFunctionPixel (DelayedMask p) = Maybe p
fromFunction = DelayedMask
instance (MaskedImage src, Storable p) => FunctorImage src (DelayedMask p) where
map f img = fromFunction (shape img) (\pt -> f <$> (img `maskedIndex` pt))
delay :: Image i => i -> Delayed (ImagePixel i)
delay = map id
compute :: (Image i, Storable (ImagePixel i)) => i -> Manifest (ImagePixel i)
compute = map id
instance (Storable p1, Storable p2, Convertible p1 p2)
=> Convertible (Manifest p1) (Manifest p2) where
safeConvert = Right . map convert
instance (Storable p1, Storable p2, Convertible p1 p2)
=> Convertible (Delayed p1) (Delayed p2) where
safeConvert = Right . map convert
instance (Storable p1, Storable p2, Convertible p1 p2)
=> Convertible (Delayed p1) (Manifest p2) where
safeConvert = Right . map convert
instance (Storable p1, Storable p2, Convertible p1 p2)
=> Convertible (Manifest p1) (Delayed p2) where
safeConvert = Right . map convert
delayed :: Delayed p -> Delayed p
delayed = id
manifest :: Manifest p -> Manifest p
manifest = id