哪个Haskell库可以让我将2D数组/向量保存为png/jpg/gif...文件?

15

我正在尝试使用Haskell编写简单的绘图程序。我需要一个库,能让我将2D数组/向量保存为图片文件。我不想手动编写颜色列表,而是希望使用专门用于数组/向量计算的容器,可以自动(几乎)并行化。

编辑 必须具备存储彩色图片的能力。


请参考 https://dev59.com/HG025IYBdhLWcg3wblg3#6007139。 - Don Stewart
4个回答

8
我将从PGM库开始翻译。它是一种非常简单的未压缩灰度图格式,几乎没有其他的依赖项。你可以使用ImageMagick或其他工具将PGM转换为其他格式。

PGM支持通用的IArray接口,并应该可以与大多数标准的Haskell数组一起使用。你可以很容易地使用Control.Parallel.Strategies并行化数组计算。

以下是PGM的使用示例:

ghci> :m + Data.Array Graphics.Pgm 
ghci> let a = accumArray (+) 0 ((0::Int,0::Int),(127,127)) [ ((i,i), 1.0::Double) | i <- [0..127] ]
ghci> arrayToFile "t.pgm" (fmap round a)

以下是图片:

t.pgm

否则,您可以使用Codec-Image-DevIL,它可以将非装箱数组保存为许多图像格式。 您还需要DevIL库。 您需要将所有数组转换为那种特定类型的数组(UArray(Int,Int,Int)Word8)。

最后,如果您想要尝试最新技术,可以考虑使用repa 并对应使用 repa-io 库,可以将它们写成BMP图像。不幸的是,今天repa仍无法在新的GHC 7.0.2上构建,并且在旧的GHC 6.12上也没有性能优势。


谢谢你。我需要彩色图像,所以我会考虑使用魔鬼函数。 - rpg
1
@rpg Codec.Image.PPM 支持彩色。但 NetPBM 格式的一个伟大之处在于,你不需要库来编写它们;它们足够简单,可以在任何地方进行开放式编码。 - ephemient

6
一个新的组合是:
  • repa:用于n维数组,加上
  • repa-devil:用于以数十种格式加载图像。

Repa是唯一自动并行化的广泛使用的数组库。

以下是一个示例,来自repa教程,使用readImagewriteImage读取一张图片,旋转它并将其以任何格式写回:

import System.Environment
import Data.Word
import Data.Array.Repa hiding ((++))
import Data.Array.Repa.IO.DevIL

main = do
    [f] <- getArgs
    runIL $ do
        v   <- readImage f
        writeImage ("flip-"++f) (rot180 v)

rot180 :: Array DIM3 Word8 -> Array DIM3 Word8
rot180 g = backpermute e flop g
    where
        e@(Z :. x :. y :. _)   = extent g

        flop (Z :. i         :. j         :. k) =
             (Z :. x - i - 1 :. y - j - 1 :. k)

repa与整个生态系统的互操作性非常好。现在只需添加SIMD,它将成为自面包切片以来最伟大的事物。 - rpg

2

最近更新的JuicyPixels库可以让你轻松地将图像保存为Jpg/Png/Tiff格式,你可以与Repa结合使用,并且还可以使用JuicyPixels-repa库。


1

你可能还想查看Diagrams

龙形分形的示例代码:

{- Heighway dragon.  See http://en.wikipedia.org/wiki/Dragon_curve. -}
module Main where

import Graphics.Rendering.Diagrams
import Control.Monad.State
import Data.Maybe

dragonStr :: Int -> String
dragonStr 0 = "FX"
dragonStr n = concatMap rules $ dragonStr (n-1)
  where rules 'X' = "X+YF+"
        rules 'Y' = "-FX-Y"
        rules c = [c]

strToPath :: String -> Path
strToPath s = pathFromVectors . catMaybes $ evalState c (0,-1)
  where c        = mapM exec s
        exec 'F' = Just `fmap` get
        exec '-' = modify left >> return Nothing
        exec '+' = modify right >> return Nothing
        exec _   = return Nothing
        left (x,y)  = (-y,x)
        right (x,y) = (y,-x)

dragon :: Int -> Diagram
dragon = lc red . curved 0.8 . strToPath . dragonStr

main = renderAs PNG "dragon.png" (Width 300) (dragon 12)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接