Haskell中的PNG到BMP(用于光泽)

时间:2012-08-31 21:33:27

标签: haskell png bmp

我有PNG文件,而the Gloss libraryBitmap的{​​{1}}构造函数。由于文件类型,我无法使用Picture,因此我正在搜索如何加载PNG文件,将其转换为BMP,并将其提供给loadBMP :: FilePath -> IO PicturebitmapOfBMP :: BMP -> Picture或{ {1}}。


使用JuicyPixels进行测试

bitmapOfForeignPtr :: Int -> Int -> ForeignPtr Word8 -> Bool -> Picture

一切都成功,但图像完全不同。

3 个答案:

答案 0 :(得分:3)

这就是我制作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

DynamicImage

或者,您可以直接使用JuicyPixels,大约使用imgData类型,并从包含的Image获取基础{{1}}。

答案 1 :(得分:1)

即使我没有单独回答,但多亏了托马斯的回答,我会在这里发帖而不是问题。

提醒一下,目标是将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)

,图像将显示在窗口中间。

答案 2 :(得分: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