4

我有 PNG 文件,光泽库有一个Bitmap用于Picture. 由于文件类型,我无法使用loadBMP :: FilePath -> IO Picture,所以我正在搜索如何加载 PNG 文件,将其转换为 BMP,并将其提供给 bitmapOfBMP :: BMP -> Picture,bitmapOfForeignPtr :: Int -> Int -> ForeignPtr Word8 -> Bool -> PicturebitmapOfByteString :: Int -> Int -> ByteString -> Bool -> Picture.


使用 JuicyPixels 进行测试

import Data.ByteString as B
import System.IO as A

import Codec.Picture.Png
import Graphics.Gloss.Interface.Pure.Game


main = do
    png <- B.readFile "samus.png"
    let img = decodePng png
    case img of
        Left x -> A.putStrLn x
        Right x -> do
            let bmp = encodeDynamicPng x
            case bmp of
                Left x -> A.putStrLn x
                Right x -> do
                    let pic = bitmapOfByteString 29 52 x True
                    game pic

game pic
    =  play
        (InWindow "Test" (700, 500) (10, 10))
        white
        30
        pic
        draw
        (const id)
        (const id)

draw bmp
    = bmp

一切都成功了,但图像根本不一样。

4

3 回答 3

4

这就是我制作 JuicyPixel-repa 的原因。您在图像中读取为 Repa 数组并将其转换为,就像我在gloss-osm中所做的那样Picture

repaToPicture :: Bool -> Array F.F DIM3 Word8 -> (Int, Int, Picture)
repaToPicture b arr =
let fptr = F.toForeignPtr arr
bs = BI.fromForeignPtr fptr 0 len
in (col, row, bitmapOfByteString row col bs b)
 where
  len = row * col * depth
  (Z :. row :. col :. depth) = extent arr

或者,您可以直接使用 JuicyPixels,将大小写覆盖在DynamicImage类型上并imgData从包含的Image.

于 2012-08-31T21:48:39.620 回答
3

即使我没有单独提供答案,但由于托马斯的回答,我将其发布在这里而不是问题中。

提醒一下,目标是将 BMP 文件转换为 Gloss 图片,因此我编写了一个名为bmpToPic. 我把它放在一个模块中,因为它使用了另外两个函数,并且需要很多导入。此外,repaToPicture托马斯的回答在这里略有不同。

module PngToPic
    (pngToPic)
    where

import Data.ByteString as B
import Data.Word

import Codec.Picture.Png
import Codec.Picture.Repa
import qualified Data.ByteString.Internal as BI
import Data.Array.Repa ((:.)(..), Z, Z(..), extent, DIM3, Array)
import qualified Data.Array.Repa as R
import qualified Data.Array.Repa.Repr.ForeignPtr as F
import Graphics.Gloss.Data.Picture


pngToPic :: ByteString -> Picture
pngToPic png
    = let
        Right img -- unsafe
            = decodePng png
        repa
            = imgData (convertImage img :: Img RGBA)
    in repaToPicture True repa

repaToPicture :: Bool -> Array F.F DIM3 Word8 -> Picture
repaToPicture b arr
    = bitmapOfByteString row col bs b
    where
        bs
            = BI.fromForeignPtr fptr 0 (R.size sh)
        fptr
            = F.toForeignPtr arr'
        sh@(Z :. col :. row :. depth)
            = extent arr'
        arr'
            = flipVert arr

flipVert :: Array F.F DIM3 Word8 -> Array F.F DIM3 Word8
flipVert g
    = R.computeS $ R.backpermute e flop g
    where
        e@(Z :. x :. y :. _)
            = extent g
        flop (Z :. i         :. j         :. k)
            = Z :. x - i - 1 :. j :. k

你这样使用它:

import Data.ByteString as B

import Graphics.Gloss.Interface.Pure.Game

import PngToPic

main = do
    png <- B.readFile "someImage.png"
    game $ pngToPic png

game pic
    = play
        (InWindow "Test" (700, 500) (10, 10))
        white
        30
        pic
        id
        (const id)
        (const id)

并且图像将显示在窗口中间。

于 2012-09-05T18:40:43.723 回答
0

对于任何在 2017 年偶然发现这一点的人来说,这变得容易多了!我花了一段时间才弄清楚,因为上面的示例代码似乎不再起作用。这是我将 PNG 读入图片的函数:

import Codec.Picture.Repa (readImageRGBA, toByteString, reverseColorChannel)
import Graphics.Gloss

readPng :: FilePath -> Int -> Int -> IO Picture
readPng path w h = do
  (Right img) <- readImageRGBA path
  let bs = toByteString $ reverseColorChannel img
  return $ bitmapOfByteString w h (BitmapFormat TopToBottom PxRGBA) bs True
于 2017-11-26T17:26:57.753 回答