Kei*_*man 6 arrays haskell bytestring
我正在尝试加载PNG文件,获取未压缩的RGBA字节,然后将它们发送到gzip或zlib包.
pngload包将图像数据作为(StorableArray(Int,Int)Word8)返回,压缩包采用惰性ByteStrings.因此,我试图构建一个(StorableArray(Int,Int)Word8 - > ByteString)函数.
到目前为止,我尝试过以下方法:
import qualified Codec.Image.PNG as PNG
import Control.Monad (mapM)
import Data.Array.Storable (withStorableArray)
import qualified Data.ByteString.Lazy as LB (ByteString, pack, take)
import Data.Word (Word8)
import Foreign (Ptr, peekByteOff)
main = do
-- Load PNG into "image"...
bytes <- withStorableArray
(PNG.imageData image)
(bytesFromPointer lengthOfImageData)
bytesFromPointer :: Int -> Ptr Word8 -> IO LB.ByteString
bytesFromPointer count pointer = LB.pack $
mapM (peekByteOff pointer) [0..(count-1)]
Run Code Online (Sandbox Code Playgroud)
这会导致堆栈内存不足,所以很明显我做错了.我可以用Ptr和ForeignPtr尝试更多的东西,但是那里有很多"不安全"的功能.
这里的任何帮助将不胜感激; 我很难过.
通常,打包和解包对性能来说不是一个好主意.如果你有一个Ptr和一个以字节为单位的长度,你可以用两种不同的方式生成一个严格的字节串:
像这样:
import qualified Codec.Image.PNG as PNG
import Control.Monad
import Data.Array.Storable (withStorableArray)
import Codec.Compression.GZip
import qualified Data.ByteString.Lazy as L
import qualified Data.ByteString.Unsafe as S
import Data.Word
import Foreign
-- Pack a Ptr Word8 as a strict bytestring, then box it to a lazy one, very
-- efficiently
bytesFromPointer :: Int -> Ptr Word8 -> IO L.ByteString
bytesFromPointer n ptr = do
s <- S.unsafePackCStringLen (castPtr ptr, n)
return $! L.fromChunks [s]
-- Dummies, since they were not provided
image = undefined
lengthOfImageData = 10^3
-- Load a PNG, and compress it, writing it back to disk
main = do
bytes <- withStorableArray
(PNG.imageData image)
(bytesFromPointer lengthOfImageData)
L.writeFile "foo" . compress $ bytes
Run Code Online (Sandbox Code Playgroud)
我正在使用O(1)版本,只是从StorableArray重新打包Ptr.您可能希望首先通过"packCStringLen"复制它.