如何使用 Haskell 图像处理生成图像

How to generate an image using Haskell Image Processing

我刚开始学习 Haskell,所以我可能遗漏了一些非常微不足道的东西。我正在尝试使用 Haskell 图像处理生成图像。我正在改编来自文档示例片段的代码。我的代码如下。

{-# LANGUAGE NoImplicitPrelude #-}
module Main where

import Prelude as P
import Graphics.Image as I

getPixel :: (Int, Int) -> Pixel RGB Word8
getPixel (i, j) = PixelRGB (fromIntegral i) (fromIntegral j) (fromIntegral (i + j))

getImage :: (Int, Int) -> Image VS RGB Word8
getImage (w, h) = makeImageR VS (w, h) getPixel

main :: IO ()
main = writeImage "image.png" image
    where image = getImage (1024, 1024)

当我尝试构建它时,我得到以下信息

• No instance for (Writable (Image VS RGB Word8) OutputFormat)
    arising from a use of ‘writeImage’
• In the expression: writeImage "image.png" image
  In an equation for ‘main’:
      main
        = writeImage "image.png" image
        where
            image = getImage (1024, 1024)

似乎无法弄清楚我做错了什么。

HIP 包广泛使用类型系统来处理多种外部图像格式和内部图像布局。特别是,writeImage 函数具有签名:

writeImage
  :: (Array VS cs e, Array arr cs e, Writable (Image VS cs e) OutputFormat)  
  => FilePath   
  -> Image arr cs e 
  -> IO ()

这里的关键是,如果你想用这个函数写一个 Image arr cs e,那个类型必须服从约束(即有一个类型 class 的实例):

Writable (Image VS cs e) OutputFormat

要查看该库提供了哪些实例,您可以查看 Writable 的文档,其中包含大量可用实例。但是,y 等于 OutputFormat(这意味着 "a general format unknown at compile time")的唯一 Writable x y 实例是:

instance AllWritable arr cs => Writable (Image arr cs Double) OutputFormat   

这意味着只有 e 等于 DoubleImage arr cs ewriteImage 函数兼容。这背后的原因可能是,因为 writeImage 函数只在运行时识别要写入的文件类型(通过检查提供的文件路径的文件扩展名),它只想接受通道数据为的图像已经是 high-precision 类型(例如 Double),以防它确定最终格式可以处理 high-precision 通道数据;您可能会争辩说此限制并没有多大意义,但事实就是如此。

因此,正如@DanielWagner 指出的那样,您需要提供 writeImage 具有 Double 通道数据的图像。或者,您可以使用 writeImageExact,它在编译时指定格式,并允许使用任何 Writable 实例来获得适当的格式。因此,例如,将 writeImage 调用替换为:

writeImageExact PNG [] "image.png" image

会工作得很好,因为有一个合适的实例:

instance Writable (Image VS RGB Word8) PNG