如何使用 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
等于 Double
的 Image arr cs e
与 writeImage
函数兼容。这背后的原因可能是,因为 writeImage
函数只在运行时识别要写入的文件类型(通过检查提供的文件路径的文件扩展名),它只想接受通道数据为的图像已经是 high-precision 类型(例如 Double
),以防它确定最终格式可以处理 high-precision 通道数据;您可能会争辩说此限制并没有多大意义,但事实就是如此。
因此,正如@DanielWagner 指出的那样,您需要提供 writeImage
具有 Double
通道数据的图像。或者,您可以使用 writeImageExact
,它在编译时指定格式,并允许使用任何 Writable
实例来获得适当的格式。因此,例如,将 writeImage
调用替换为:
writeImageExact PNG [] "image.png" image
会工作得很好,因为有一个合适的实例:
instance Writable (Image VS RGB Word8) PNG
我刚开始学习 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
等于 Double
的 Image arr cs e
与 writeImage
函数兼容。这背后的原因可能是,因为 writeImage
函数只在运行时识别要写入的文件类型(通过检查提供的文件路径的文件扩展名),它只想接受通道数据为的图像已经是 high-precision 类型(例如 Double
),以防它确定最终格式可以处理 high-precision 通道数据;您可能会争辩说此限制并没有多大意义,但事实就是如此。
因此,正如@DanielWagner 指出的那样,您需要提供 writeImage
具有 Double
通道数据的图像。或者,您可以使用 writeImageExact
,它在编译时指定格式,并允许使用任何 Writable
实例来获得适当的格式。因此,例如,将 writeImage
调用替换为:
writeImageExact PNG [] "image.png" image
会工作得很好,因为有一个合适的实例:
instance Writable (Image VS RGB Word8) PNG