#ifndef ENABLE_INTERNAL_DOCUMENTATION
#endif
module OpenCV.Internal.Core.Types.Mat.HMat
( HMat(..)
, HElems(..)
, hElemsDepth
, hElemsLength
, ToHElems(toHElems)
, matToHMat
, hMatToMat
) where
import "base" Data.Foldable
import "base" Data.Int
import "base" Data.Word
import "base" Foreign.C.Types
import "base" Foreign.Ptr ( Ptr )
import "base" Foreign.Storable ( Storable(..), peekElemOff, pokeElemOff )
import "base" System.IO.Unsafe ( unsafePerformIO )
import qualified "bytestring" Data.ByteString as B
import "linear" Linear.Vector ( zero )
import "linear" Linear.V4 ( V4(..) )
import "this" OpenCV.Core.Types
import "this" OpenCV.Internal.Core.Types.Mat
import "this" OpenCV.TypeLevel
import qualified "vector" Data.Vector as V
import qualified "vector" Data.Vector.Generic as VG
import qualified "vector" Data.Vector.Unboxed as VU
import qualified "vector" Data.Vector.Unboxed.Mutable as VUM
data HMat
= HMat
{ hmShape :: ![Int32]
, hmChannels :: !Int32
, hmElems :: !HElems
} deriving (Show, Eq)
data HElems
= HElems_8U !(VU.Vector Word8)
| HElems_8S !(VU.Vector Int8)
| HElems_16U !(VU.Vector Word16)
| HElems_16S !(VU.Vector Int16)
| HElems_32S !(VU.Vector Int32)
| HElems_32F !(VU.Vector Float)
| HElems_64F !(VU.Vector Double)
| HElems_USRTYPE1 !(V.Vector B.ByteString)
deriving (Show, Eq)
hElemsDepth :: HElems -> Depth
hElemsDepth = \case
HElems_8U _v -> Depth_8U
HElems_8S _v -> Depth_8S
HElems_16U _v -> Depth_16U
HElems_16S _v -> Depth_16S
HElems_32S _v -> Depth_32S
HElems_32F _v -> Depth_32F
HElems_64F _v -> Depth_64F
HElems_USRTYPE1 _v -> Depth_USRTYPE1
hElemsLength :: HElems -> Int
hElemsLength = \case
HElems_8U v -> VG.length v
HElems_8S v -> VG.length v
HElems_16U v -> VG.length v
HElems_16S v -> VG.length v
HElems_32S v -> VG.length v
HElems_32F v -> VG.length v
HElems_64F v -> VG.length v
HElems_USRTYPE1 v -> VG.length v
class ToHElems a where
toHElems :: VU.Vector a -> HElems
instance ToHElems Word8 where toHElems = HElems_8U
instance ToHElems Int8 where toHElems = HElems_8S
instance ToHElems Word16 where toHElems = HElems_16U
instance ToHElems Int16 where toHElems = HElems_16S
instance ToHElems Int32 where toHElems = HElems_32S
instance ToHElems Float where toHElems = HElems_32F
instance ToHElems Double where toHElems = HElems_64F
matToHMat :: Mat shape channels depth -> HMat
matToHMat mat = unsafePerformIO $ withMatData mat $ \step dataPtr -> do
elems <- copyElems info (map fromIntegral step) dataPtr
pure HMat
{ hmShape = miShape info
, hmChannels = miChannels info
, hmElems = elems
}
where
info = matInfo mat
copyElems
:: MatInfo
-> [Int]
-> Ptr Word8
-> IO HElems
copyElems (MatInfo shape depth channels) step dataPtr =
case depth of
Depth_8U -> HElems_8U <$> copyToVec
Depth_8S -> HElems_8S <$> copyToVec
Depth_16U -> HElems_16U <$> copyToVec
Depth_16S -> HElems_16S <$> copyToVec
Depth_32S -> HElems_32S <$> copyToVec
Depth_32F -> HElems_32F <$> copyToVec
Depth_64F -> HElems_64F <$> copyToVec
Depth_USRTYPE1 -> HElems_USRTYPE1 <$> error "todo"
where
copyToVec :: (Storable a, VU.Unbox a) => IO (VU.Vector a)
copyToVec = do
v <- VUM.unsafeNew $ product0 (map fromIntegral shape) * (fromIntegral channels)
forM_ (zip [0,channels..] $ dimPositions $ map fromIntegral shape) $ \(posIx, pos) -> do
let elemPtr = matElemAddress dataPtr step pos
forM_ [0 .. channels 1] $ \channelIx -> do
e <- peekElemOff elemPtr $ fromIntegral channelIx
VUM.unsafeWrite v (fromIntegral $ posIx + channelIx) e
VU.unsafeFreeze v
hMatToMat :: HMat -> Mat 'D 'D 'D
hMatToMat (HMat shape channels elems) = unsafePerformIO $ do
mat <- exceptErrorIO $ newMat sizes channels depth scalar
withMatData mat copyElems
pure mat
where
sizes = V.fromList shape
depth = hElemsDepth elems
scalar :: Scalar
scalar = toScalar (zero :: V4 CDouble)
copyElems :: [CSize] -> Ptr Word8 -> IO ()
copyElems step dataPtr = case elems of
HElems_8U v -> copyFromVec v
HElems_8S v -> copyFromVec v
HElems_16U v -> copyFromVec v
HElems_16S v -> copyFromVec v
HElems_32S v -> copyFromVec v
HElems_32F v -> copyFromVec v
HElems_64F v -> copyFromVec v
HElems_USRTYPE1 _v -> error "todo"
where
copyFromVec :: (Storable a, VU.Unbox a) => VU.Vector a -> IO ()
copyFromVec v =
forM_ (zip [0, fromIntegral channels ..] $ dimPositions (fromIntegral <$> shape)) $ \(posIx, pos) -> do
let elemPtr = matElemAddress dataPtr (fromIntegral <$> step) pos
forM_ [0 .. channels 1] $ \channelIx ->
pokeElemOff elemPtr (fromIntegral channelIx) $ VU.unsafeIndex v (fromIntegral $ posIx + channelIx)
product0 :: (Num a) => [a] -> a
product0 [] = 0
product0 xs = product xs