Question

I am using repa-devil to read and write images. Now I need to programmatically create images. However, the Image constructors (such as RGB) in Data.Array.Repa.IO.DevIL all require foreign memory buffer arrays. Do I have to go off and learn how to work with that foreign pointer stuff (which sounds scary)? Or can I convert an unboxed array to the type I need?

emptyImage :: RandomGen r => (Int, Int) -> Rand r Image
emptyImage (w,h) = do
  xs <- getRandomRs (0, 255)
  let ps = take (w*h*3) xs :: [Word8]
  let arr = fromListUnboxed (Z :. w :. h :. (3::Int)) ps :: Array U DIM3 Word8
  let arr2 = ???how can I convert arr??? :: Array F DIM3 Word8
  return $ RGB arr2
Was it helpful?

Solution

The easiest way would be to use the more general fromList function. That way, you can just do

...
let arr = fromList (Z :. w :. h :. (3 :: Int)) ps :: Array F DIM3 Word8
return $ RGB arr

The fromList function can be found in Data.Array.Repa.Eval

fromList :: (Shape sh, Target r e) => sh -> [e] -> Array r sh eSource

In general, you can ensure you produce the desired representation when you manifest your arrays using the computeP function. So, you could have done something like the following (if you don't mind the extra copying)

let arr = fromListUnboxed (Z :. w :. h :. (3::Int)) ps :: Array U DIM3 Word8
arr2 <- computeP arr
return $ RGB arr2

The type annotation is unnecessary as the compiler knows what type it needs to be able to use the RGB constructor.

OTHER TIPS

I suppose really you need to write something different from random image. If you can construct pure indexing function, there is MUCH more efficient way to load array into memory, by means of Delayed array:

let delayed = fromFunction (Z :. w :. h :. (3::Int))
                           (\(Z :. x :. y :. comp) -> myComp)
foreignArr <- computeP delayed

With yarr library and yarr-image-io package - port of repa-devil it looks like:

let delayed =
        fromFunction (h, w)
                     (\(y, x) -> return $ VecList [myRed, myGreen, myBlue])
foreignArr <- dComputeP delayed

However, if you indeed want a random image, yarr allows to load array with stateful computation relatively fast:

import Data.Yarr
import Data.Yarr.Shape as S
import qualified Data.Yarr.Utils.FixedVector as V
import Data.Yarr.IO.Image

emptyImage :: StdGen -> Dim2 -> IO (Image, StdGen)
emptyImage gen sh@(h, w) = do
    arr <- new sh
    let writeRandColor gen i _ = do
            let (rgb, gen') = runRand (V.replicateM random) gen
            linearWrite arr i rgb
            return gen'
    gen' <- S.foldl writeRandColor (return gen) (const ()) 0 (size sh)
    touchArray arr
    return (RGB arr, gen')
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top