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 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)