#if __GLASGOW_HASKELL__ >= 800
#endif
module Graphics.Image.Interface.Repa.Generic where
import Prelude as P
import Data.Array.Repa.Index
import qualified Data.Array.Repa as R
import qualified Data.Array.Repa.Eval as R
import qualified Data.Vector.Generic as VG
import Graphics.Image.ColorSpace.Binary (Bit(..))
import Graphics.Image.Interface as I
import qualified Graphics.Image.Interface.Vector.Unboxed as IVU
import Graphics.Image.Interface.Repa.Helpers
type family Repr arr :: *
data RP r = RP r
data RS r = RS r
instance Show r => Show (RP r) where
show (RP r) = "RepaParallel " ++ show r
instance Show r => Show (RS r) where
show (RS r) = "RepaSequential " ++ show r
instance SuperClass (RS r) cs e => BaseArray (RS r) cs e where
type SuperClass (RS r) cs e =
(Show r, ColorSpace cs e, R.Elt (Pixel cs e), R.Elt e,
R.Target (Repr r) (Pixel cs e), R.Source (Repr r) (Pixel cs e),
BaseArray r cs e)
data Image (RS r) cs e = SScalar !(Pixel cs e)
| STImage !(R.Array (Repr r) R.DIM2 (Pixel cs e))
| SDImage !(R.Array R.D R.DIM2 (Pixel cs e))
dims (SScalar _ ) = (1, 1)
dims (STImage (R.extent -> (Z :. m :. n))) = (m, n)
dims (SDImage (R.extent -> (Z :. m :. n))) = (m, n)
instance (VG.Vector (Vector r) (Pixel cs e),
MArray (Manifest r) cs e, BaseArray (RS r) cs e) => Array (RS r) cs e where
type Manifest (RS r) = Manifest r
type Vector (RS r) = Vector r
makeImage !(checkDims "RS.makeImage" -> (m, n)) f =
SDImage $ R.fromFunction (Z :. m :. n) (f . sh2ix)
makeImageWindowed !(checkDims "RS.makeImage" -> (m, n)) !window getWindowPx getBorderPx =
SDImage $ R.delay $ makeWindowed (Z :. m :. n) window
(R.fromFunction (Z :. m :. n) (getWindowPx . sh2ix))
(R.fromFunction (Z :. m :. n) (getBorderPx . sh2ix))
scalar = SScalar
index00 (SScalar px) = px
index00 (STImage arr) = R.index arr (Z :. 0 :. 0)
index00 (SDImage arr) = R.index arr (Z :. 0 :. 0)
map f (SScalar px) = SScalar (f px)
map f (STImage arr) = SDImage (R.map f arr)
map f (SDImage arr) = SDImage (R.map f arr)
imap f (SScalar px) = SScalar (f (0, 0) px)
imap f (STImage arr) = SDImage (imapR f arr)
imap f (SDImage arr) = SDImage (imapR f arr)
zipWith f (SScalar px1) (SScalar px2) = SScalar (f px1 px2)
zipWith f (SScalar px1) !img2 = I.map (f px1) img2
zipWith f !img1 (SScalar px2) = I.map (`f` px2) img1
zipWith f !img1 !img2 =
SDImage (R.zipWith f (getDelayedS img1) (getDelayedS img2))
izipWith f (SScalar px1) (SScalar px2) = SScalar (f (0, 0) px1 px2)
izipWith f (SScalar px1) !img2 = imap (`f` px1) img2
izipWith f !img1 (SScalar px2) = imap (\ !ix !px -> f ix px px2) img1
izipWith f !img1 !img2 =
SDImage (izipWithR f (getDelayedS img1) (getDelayedS img2))
traverse !img getNewDims getNewPx =
SDImage (traverseR (getDelayedS img) getNewDims getNewPx)
traverse2 !img1 !img2 getNewDims getNewPx =
SDImage (traverse2R (getDelayedS img1) (getDelayedS img2) getNewDims getNewPx)
transpose (SDImage arr) = SDImage (R.transpose arr)
transpose (STImage arr) = SDImage (R.transpose arr)
transpose !img = img
backpermute !newDims g !img = SDImage (backpermuteR (getDelayedS img) newDims g)
fromLists = STImage . fromListsRepa
fold f !px0 (SDImage arr) = R.foldAllS f px0 arr
fold f !px0 (STImage arr) = R.foldAllS f px0 arr
fold f !px0 (SScalar px) = f px px0
foldIx f !px0 (SDImage arr) = foldIxS f px0 arr
foldIx f !px0 (STImage arr) = foldIxS f px0 arr
foldIx f !px0 (SScalar px) = f px0 (0, 0) px
eq (SScalar px1) (SScalar px2) = px1 == px2
eq !img1 !img2 = R.equalsS (getDelayedS img1) (getDelayedS img2)
compute !img@(SScalar _) = img
compute !img@(STImage _) = img
compute (SDImage arr) = STImage (R.computeS arr)
(|*|) img1@(STImage arr1) img2@(STImage arr2) =
SDImage (multR (show img1 ++ " X " ++ show img2) arr1 arr2)
(|*|) img1@(SDImage _) !img2 = compute img1 |*| img2
(|*|) !img1 img2@(SDImage _) = img1 |*| compute img2
(|*|) (SScalar px1) !img2 = STImage (scalarR px1) |*| img2
(|*|) !img1 (SScalar px2) = img1 |*| STImage (scalarR px2)
toManifest _ = error $ "RS.toManifest: Cannot convert generic Repa " ++
"representation to a generic Vector representation."
toVector _ = error $ "RS.toVector: Cannot convert generic Repa " ++
"representation to a generic Vector."
fromVector _ = error $ "RS.fromVector: Cannot convert to generic Repa " ++
"from a generic Vector."
instance SuperClass (RP r) cs e => BaseArray (RP r) cs e where
type SuperClass (RP r) cs e = (
Show r, ColorSpace cs e,
R.Target (Repr r) (Pixel cs e), R.Source (Repr r) (Pixel cs e),
BaseArray r cs e,
R.Elt e, R.Elt (Pixel cs e))
data Image (RP r) cs e = PScalar !(Pixel cs e)
| PTImage !(R.Array (Repr r) R.DIM2 (Pixel cs e))
| PDImage !(R.Array R.D R.DIM2 (Pixel cs e))
dims (PScalar _ ) = (1, 1)
dims (PTImage (R.extent -> (Z :. m :. n))) = (m, n)
dims (PDImage (R.extent -> (Z :. m :. n))) = (m, n)
instance (VG.Vector (Vector r) (Pixel cs e),
MArray (Manifest r) cs e, BaseArray (RP r) cs e) => Array (RP r) cs e where
type Manifest (RP r) = Manifest r
type Vector (RP r) = Vector r
makeImage !(checkDims "RP.makeImage" -> (m, n)) f =
PDImage $ R.fromFunction (Z :. m :. n) (f . sh2ix)
makeImageWindowed !(checkDims "RP.makeImage" -> (m, n)) !window getWindowPx getBorderPx =
PDImage $ R.delay $ makeWindowed (Z :. m :. n) window
(R.fromFunction (Z :. m :. n) (getWindowPx . sh2ix))
(R.fromFunction (Z :. m :. n) (getBorderPx . sh2ix))
scalar = PScalar
index00 (PScalar px) = px
index00 (PTImage arr) = R.index arr (Z :. 0 :. 0)
index00 (PDImage arr) = R.index arr (Z :. 0 :. 0)
map f (PScalar px) = PScalar (f px)
map f (PTImage arr) = PDImage (R.map f arr)
map f (PDImage arr) = PDImage (R.map f arr)
imap f (PScalar px) = PScalar (f (0, 0) px)
imap f (PTImage arr) = PDImage (imapR f arr)
imap f (PDImage arr) = PDImage (imapR f arr)
zipWith f (PScalar px1) (PScalar px2) = PScalar (f px1 px2)
zipWith f (PScalar px1) !img2 = I.map (f px1) img2
zipWith f !img1 (PScalar px2) = I.map (`f` px2) img1
zipWith f !img1 !img2 =
PDImage (R.zipWith f (getDelayedP img1) (getDelayedP img2))
izipWith f (PScalar px1) (PScalar px2) = PScalar (f (0, 0) px1 px2)
izipWith f (PScalar px1) !img2 = imap (`f` px1) img2
izipWith f !img1 (PScalar px2) = imap (\ !ix !px -> f ix px px2) img1
izipWith f !img1 !img2 =
PDImage (izipWithR f (getDelayedP img1) (getDelayedP img2))
traverse !img getNewDims getNewPx =
PDImage (traverseR (getDelayedP img) getNewDims getNewPx)
traverse2 !img1 !img2 getNewDims getNewPx =
PDImage (traverse2R (getDelayedP img1) (getDelayedP img2) getNewDims getNewPx)
transpose (PDImage arr) = PDImage (R.transpose arr)
transpose (PTImage arr) = PDImage (R.transpose arr)
transpose !img = img
backpermute !newDims g !img = PDImage (backpermuteR (getDelayedP img) newDims g)
fromLists = PTImage . fromListsRepa
fold f !px0 (PScalar px) = f px0 px
fold f !px0 img =
case R.foldAllP f px0 (getDelayedP img) of
Just e -> e
Nothing -> error $ "RP.fold: impossible happened."
foldIx f !px0 (PScalar px) = f px0 (0, 0) px
foldIx f !px0 img =
case foldIxPUnboxed f px0 (getDelayedP img) of
Just e -> e
Nothing -> error $ "RP.foldIx: impossible happened."
eq (PScalar px1) (PScalar px2) = px1 == px2
eq !img1 !img2 =
case R.equalsP (getDelayedP img1) (getDelayedP img2) of
Just e -> e
Nothing -> error $ "RP.eq: impossible happened."
compute !img@(PScalar _) = img
compute !img@(PTImage _) = img
compute (PDImage arr) = arrManifest `R.deepSeqArray` PTImage arrManifest
where arrManifest = R.suspendedComputeP arr
(|*|) img1@(PTImage arr1) img2@(PTImage arr2) =
PDImage (multR (show img1 ++ " X " ++ show img2) arr1 arr2)
(|*|) img1@(PDImage _) !img2 = compute img1 |*| img2
(|*|) !img1 img2@(PDImage _) = img1 |*| compute img2
(|*|) (PScalar px1) !img2 = PTImage (scalarR px1) |*| img2
(|*|) !img1 (PScalar px2) = img1 |*| PTImage (scalarR px2)
toManifest _ = error $ "RP.toManifest: Cannot convert generic Repa " ++
"representation to a generic Vector."
toVector _ = error $ "RP.toVector: Cannot convert generic Repa " ++
"representation to a generic Vector."
fromVector _ = error $ "RP.fromVector: Cannot convert to generic Repa " ++
"from a generic Vector."
sh2ix :: DIM2 -> (Int, Int)
sh2ix (Z :. i :. j) = (i, j)
ix2sh :: (Int, Int) -> DIM2
ix2sh !(i, j) = Z :. i :. j
toRS :: Image (RP r) cs e -> Image (RS r) cs e
toRS (PScalar px) = SScalar px
toRS (PDImage img) = SDImage img
toRS (PTImage img) = STImage img
toRP :: Image (RS r) cs e -> Image (RP r) cs e
toRP (SScalar px) = PScalar px
toRP (SDImage img) = PDImage img
toRP (STImage img) = PTImage img
imapR
:: R.Source r2 b =>
((Int, Int) -> b -> c) -> R.Array r2 DIM2 b -> R.Array R.D DIM2 c
imapR f !arr = R.zipWith f (R.fromFunction (R.extent arr) sh2ix) arr
izipWithR
:: (R.Source r2 t1, R.Source r1 t)
=> ((Int, Int) -> t -> t1 -> c)
-> R.Array r1 DIM2 t
-> R.Array r2 DIM2 t1
-> R.Array R.D DIM2 c
izipWithR f !arr1 !arr2 =
(R.traverse2 arr1 arr2 getNewDims getNewPx) where
getNewPx !getPx1 !getPx2 !sh = f (sh2ix sh) (getPx1 sh) (getPx2 sh)
getNewDims (Z :. m1 :. n1) (Z :. m2 :. n2) = Z :. min m1 m2 :. min n1 n2
traverseR
:: R.Source r c
=> R.Array r DIM2 c
-> ((Int, Int) -> (Int, Int))
-> (((Int, Int) -> c) -> (Int, Int) -> b)
-> R.Array R.D DIM2 b
traverseR !arr getNewDims getNewPx =
R.traverse arr (ix2sh . checkDims "traverseR" . getNewDims . sh2ix) getNewE
where
getNewE getPx = getNewPx (getPx . ix2sh) . sh2ix
traverse2R
:: (R.Source r2 c1, R.Source r1 c)
=> R.Array r1 DIM2 c
-> R.Array r2 DIM2 c1
-> ((Int, Int) -> (Int, Int) -> (Int, Int))
-> (((Int, Int) -> c) -> ((Int, Int) -> c1) -> (Int, Int) -> c2)
-> R.Array R.D DIM2 c2
traverse2R !arr1 !arr2 getNewDims getNewPx =
R.traverse2 arr1 arr2 getNewSh getNewE
where getNewE getPx1 getPx2 = getNewPx (getPx1 . ix2sh) (getPx2 . ix2sh) . sh2ix
getNewSh !sh1 !sh2 =
ix2sh . checkDims "traverse2R" $ getNewDims (sh2ix sh1) (sh2ix sh2)
backpermuteR
:: R.Source r e
=> R.Array r DIM2 e
-> (Int, Int)
-> ((Int, Int) -> (Int, Int))
-> R.Array R.D DIM2 e
backpermuteR !arr newDims g =
R.backpermute
(ix2sh (checkDims "backpermuteR" newDims))
(ix2sh . g . sh2ix)
arr
fromListsRepa :: (R.Target r e) => [[e]] -> R.Array r DIM2 e
fromListsRepa ls =
if all (== n) (P.map length ls)
then R.fromList (Z :. m :. n) . concat $ ls
else error "fromListsRepa: Inner lists do not all have an equal length."
where
!(m, n) = checkDims "fromListsRepa" (length ls, length $ head ls)
multR
:: (ColorSpace cs e, Num (Pixel cs e), R.Elt (Pixel cs e),
R.Target r (Pixel cs e), R.Source r (Pixel cs e))
=> String -> R.Array r DIM2 (Pixel cs e) -> R.Array r DIM2 (Pixel cs e) -> R.Array R.D DIM2 (Pixel cs e)
multR errMsg !arr1 !arr2 =
if n1 /= m2
then error $
"Inner dimensions of multiplied images must be the same, but received: " ++ errMsg
else R.fromFunction (Z :. m1 :. n2) $ getPx
where
(Z :. m1 :. n1) = R.extent arr1
(Z :. m2 :. n2) = R.extent arr2
getPx (Z :. i :. j) =
R.sumAllS
(R.slice arr1 (R.Any :. (i :: Int) :. R.All) R.*^
R.slice arr2 (R.Any :. (j :: Int)))
scalarR :: (IVU.Unbox a, R.Target r a) => a -> R.Array r DIM2 a
scalarR !px = R.computeS $ R.fromFunction (Z :. 1 :. 1) $ const px
getDelayedS :: Array (RS r) cs e => Image (RS r) cs e -> R.Array R.D DIM2 (Pixel cs e)
getDelayedS (STImage arr) = R.delay arr
getDelayedS (SDImage arr) = arr
getDelayedS (SScalar px) = R.fromFunction (Z :. 1 :. 1) (const px)
getDelayedP :: Array (RP r) cs e => Image (RP r) cs e -> R.Array R.D DIM2 (Pixel cs e)
getDelayedP (PTImage arr) = R.delay arr
getDelayedP (PDImage arr) = arr
getDelayedP (PScalar px) = R.fromFunction (Z :. 1 :. 1) (const px)
instance R.Elt Bit where
touch (Bit w) = R.touch w
zero = 0
one = 1
instance (ColorSpace cs e, R.Elt e, Num (Pixel cs e)) => R.Elt (Pixel cs e) where
touch !px = P.mapM_ (R.touch . getPxC px) (enumFrom (toEnum 0))
zero = 0
one = 1
addIxArr
:: R.Source r2 b =>
R.Array r2 DIM2 b -> R.Array R.D DIM2 ((Int, Int), b)
addIxArr !arr = R.zipWith (,) arrIx arr
where
!arrIx = R.fromFunction (R.extent arr) sh2ix
foldIxS
:: (R.Elt b, IVU.Unbox b, R.Source r2 b) =>
(b -> (Int, Int) -> b -> b) -> b -> R.Array r2 DIM2 b -> b
foldIxS f !acc !arr = snd $ R.foldAllS g ((1, 0), acc) arr'
where
!arr' = addIxArr arr
g (accIx@(1, _), acc') !(ix, px) = (accIx, f acc' ix px)
g !(ix, px) (accIx@(1, _), acc') = (accIx, f acc' ix px)
g (acc1Ix, _) (acc2Ix, _) =
error $ "foldIxS: Impossible happened. Received: " ++ show acc1Ix ++ " " ++ show acc2Ix
foldIxPUnboxed
:: (R.Source r2 b, IVU.Unbox b, R.Elt b, Functor m, Monad m)
=> (b -> (Int, Int) -> b -> b) -> b -> R.Array r2 DIM2 b -> m b
foldIxPUnboxed f !acc !arr = snd <$> R.foldAllP g ((1, 0), acc) arr'
where
!arr' = addIxArr arr
g (accIx@(1, _), acc') !(ix, px) = (accIx, f acc' ix px)
g !(ix, px) (accIx@(1, _), acc') = (accIx, f acc' ix px)
g (acc1Ix, _) (acc2Ix, _) =
error $ "foldIxPUnboxed: Impossible happened. Received: " ++ show acc1Ix ++ " " ++ show acc2Ix