Haskell中的PNG到BMP(用于光泽)
我有PNG文件,并且有一个Haskell中的PNG到BMP(用于光泽),haskell,png,bmp,gloss,Haskell,Png,Bmp,Gloss,我有PNG文件,并且有一个位图构造函数,用于图片。由于文件类型的原因,我无法使用loadBMP::FilePath->IO Picture,因此我正在搜索如何加载PNG文件,将其转换为BMP,并将其馈送到bitmapOfBMP::BMP->Picture,bitmapOfForeignPtr::Int->Int->ForeignPtr Word8->Bool->Picture或bitmapOfByteString::Int->Int->ByteString->Bool->Picture 使用J
位图
构造函数,用于图片
。由于文件类型的原因,我无法使用loadBMP::FilePath->IO Picture
,因此我正在搜索如何加载PNG文件,将其转换为BMP,并将其馈送到bitmapOfBMP::BMP->Picture
,bitmapOfForeignPtr::Int->Int->ForeignPtr Word8->Bool->Picture
或bitmapOfByteString::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
将Data.ByteString作为B导入
将System.IO作为
导入Codec.Picture.Png
导入Graphics.Gloss.Interface.Pure.Game
main=do
png A.putStrLn x
右x->do
设bmp=encodeDynamicPng x
bmp案例
左x->A.putStrLn x
右x->do
设pic=bitmapOfByteString 29 52 x True
游戏图片
游戏图片
=玩
(窗口“测试”(700500)(10,10))
白色
30
照片
画
(const id)
(const id)
绘制bmp
=bmp
一切都成功了,但图像一点都不一样。这就是我制作JuicyPixel repa的原因。您以Repa数组的形式读入图像,并将其转换为
图片
:
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,尽管我没有单独给出答案,但多亏了Thomas的答案,我将把它贴在这里,而不是在问题内部
作为提醒,我们的目标是将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)
将Data.ByteString作为B导入
导入Graphics.Gloss.Interface.Pure.Game
进口气视
main=do
png对于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
导入Codec.Picture.Repa(readImageRGBA、toByteString、reverseColorChannel)
导入图形。光泽
readPng::FilePath->Int->Int->IO图片
readPng路径w h=do
(右img)谢谢,我尝试了第二种解决方案。我没有使用imgData
,因为我不知道如何使用它,而是通过testring
转换为BMP,它不显示我的图像,而是扩展了蓝色和粉色像素。我在问题中添加了代码。我成功地使用了您的重新主题图片
。我把密码放在问题里了。Bool
参数用于什么?为什么它返回(Int,Int,Picture)
而不是Picture
?生成的Picture
是“错误的”,所以我这样做了:let(w,h,pic)=repatpicture-True-repa;位图u u.bmp u=位图中的pic w h bmp True
。现在,图像显示了,但它逆时针旋转了180度。对不起,我一直很忙,但如果你到那时还需要的话,我会尽力在这个周末帮你。布尔值确定OpenGL系统是否缓存图片。至于轮换,请使用repa。谢谢您的帮助!该教程非常有用:它对我破解代码并使其正常工作进行了充分的解释,并提供了一个随时可用的函数。我在表示方面遇到了一些麻烦,但是计算
成功了。另外,我说图像旋转了180度,但事实上它是垂直翻转的,所以我只是将y-j-1
改为j
,效果很好。另外,作为一个风格点,请注意\\\\\->id
与const id
相同。值得一提的是,我已经为此编写了。很好,它看起来更完整;我试试你的包裹!对于大多数严肃的光泽项目来说,这绝对是必须的。感谢您的帮助和赞扬。我想制作一个更通用的函数,比如fileFormatToGlossPicture,因为它很简单,涵盖了所有的情况,并将其制作成一个包。这是否适用于Graphics.Gloss.Interface.Pure.Game中的Play?我在这里尝试过,但得到的结果是“无法将预期类型Picture'与实际类型Int->Int->IO Picture'匹配”。也许我做错了什么。。。有没有办法将IO图片转换成图片?@alitalvez这是一种IO
类型,因为它需要从文件系统读取。在haskell中,您不能仅在纯函数中将IO图片
转换为图片
,因为它与文件系统交互。因此,我为您提供的选项是在初始化游戏之前运行此代码(如图片)