Chris Wendt
Chris Wendt

Reputation: 310

Haskell gloss: render Picture to Bitmap

I want to access the pixel data of what is being displayed to the window, but I have not had any luck finding such a function in gloss, nor by attempting to call OpenGL readPixels in a keyboard event callback. It looks like gloss renders a Picture to the window without exposing the rendered bitmap.

If this is hard to do in gloss, is there an alternative which has realtime high-level bitmap manipulation (translation, rotation, transparency)?

Upvotes: 9

Views: 1674

Answers (3)

AleXoundOS
AleXoundOS

Reputation: 446

Recently a new package gloss-export was released with the appropriate purpose:

Export gloss pictures as PNG, Bitmap, TGA, TIFF, Gif

Upvotes: 1

Chris Wendt
Chris Wendt

Reputation: 310

It turns out readPixels can be used in this case. I found this snippet while digging through #haskell chat logs:

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

writeSnapshot :: FilePath -> Position -> Size -> IO ()
writeSnapshot f = snapshotWith (BS.writeFile f)

From https://gitorious.org/maximus/mandulia/source/58695617c322b0b37ec72f9a0bd3eed8308bf700:src/Snapshot.hs

Upvotes: 1

Yuriosity
Yuriosity

Reputation: 1918

I once had the same problem and couldn't find a good solution, so my answer probably won't be appropriate. My workaround was to use bmp package, deal with the BMP content manually (via ByteString manipulation), and then convert it to a glossy bitmap with bitmapOfBMP. For example, this was a function for blending a bitmap with a color:

recolor :: (Float, Float, Float) -> BMP -> BMP
recolor (rc, gc, bc) bmp@BMP {bmpRawImageData = raw} =
    bmp {bmpRawImageData = B.pack $ process $ B.unpack raw} where
    process (b:g:r:a:xs) = (mul b bc):(mul g gc):(mul r rc):a:process xs
    process xs = xs
    mul c cc = round $ cc * fromIntegral c

This was enough for me in that time, so I stopped finding a better solution. If you'll find something, please share.

Upvotes: 0

Related Questions