gruff-0.2: src/Snapshot.hs
module Snapshot (hSnapshot, writeSnapshot, snapshotWith) where
import Control.Monad(forM_)
import System.IO(Handle())
import Graphics.Rendering.OpenGL(
readPixels,
Position,
Size(Size),
PixelData(PixelData),
PixelFormat(RGB),
DataType(UnsignedByte))
import Foreign.Marshal.Alloc(allocaBytes)
import Foreign.Ptr(plusPtr)
import qualified Data.ByteString.Internal as BSI
import qualified Data.ByteString as BS
-- save a screenshot to a handle as binary PPM
snapshotWith :: (BS.ByteString -> IO b) -> Position -> Size -> IO b
snapshotWith f p0 vp@(Size vw vh) = do
let fi q = fromIntegral q
p6 = "P6\n" ++ show vw ++ " " ++ show vh ++ " 255\n"
allocaBytes (fi (vw*vh*3)) $ \ptr -> do
readPixels p0 vp $ PixelData RGB UnsignedByte ptr
px <- BSI.create (fi $ vw * vh * 3) $ \d -> forM_ [0..vh-1] $ \y ->
BSI.memcpy
(d`plusPtr`fi(y*vw*3))
(ptr`plusPtr`fi ((vh-1-y)*vw*3))
(fi(vw*3))
f $ BS.pack (map (toEnum . fromEnum) p6) `BS.append` px
hSnapshot :: Handle -> Position -> Size -> IO ()
hSnapshot h = snapshotWith (BS.hPutStr h)
writeSnapshot :: FilePath -> Position -> Size -> IO ()
writeSnapshot f = snapshotWith (BS.writeFile f)