我正在使用repa-devil
来读取和写入图像。现在我需要以编程方式创建图像。但是,Image
中的RGB
构造函数(例如Data.Array.Repa.IO.DevIL
)都需要外部内存缓冲区数组。我是否必须去学习如何使用那些外来指针(听起来很可怕)?或者我可以将未装箱的阵列转换为我需要的类型吗?
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
答案 0 :(得分:1)
最简单的方法是使用更通用的fromList
函数。
这样,你可以做到
...
let arr = fromList (Z :. w :. h :. (3 :: Int)) ps :: Array F DIM3 Word8
return $ RGB arr
可以在fromList
Data.Array.Repa.Eval
功能
fromList :: (Shape sh, Target r e) => sh -> [e] -> Array r sh eSource
通常,您可以确保在展示时产生所需的表示
使用computeP
函数的数组。所以,你可以做类似的事情
以下(如果您不介意额外复制)
let arr = fromListUnboxed (Z :. w :. h :. (3::Int)) ps :: Array U DIM3 Word8
arr2 <- computeP arr
return $ RGB arr2
类型注释是不必要的,因为编译器知道它需要什么类型
能够使用RGB
构造函数。
答案 1 :(得分:1)
我想你真的需要写一些与随机图像不同的东西。如果你可以构造纯索引函数,那么通过D
elayed array将数组加载到内存中的方法有很多:
let delayed = fromFunction (Z :. w :. h :. (3::Int))
(\(Z :. x :. y :. comp) -> myComp)
foreignArr <- computeP delayed
使用yarr
库和yarr-image-io
包 - 端口repa-devil
,它看起来像:
let delayed =
fromFunction (h, w)
(\(y, x) -> return $ VecList [myRed, myGreen, myBlue])
foreignArr <- dComputeP delayed
但是,如果你确实想要一个随机图像,yarr
允许以相对较快的速度加载有状态计算的数组:
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')