在本文中,我发现了一些将MutableImage
与readPixel
和writePixel
函数一起使用的示例,但我认为这太复杂了,我的意思是,没有ST Monad
我能做到吗?
假设我有这个
eDynamicImage <- readImage
eImage <- convertRGBA8 <$> eDynamicImage
所以我可以像negative <$> eImage
一样将基于pixelMap
的滤波器应用于图像,但我如何处理像素及其坐标呢?有人能解释一下什么是Mutable Image
吗?我如何从DynamicImage
或Image
得到这个?
有没有干净的代码可以使用这个函数旋转图像?
UPD2.0:我已经使用内置的JuicyPixelsgenerateImage
功能实现了完全工作的旋转功能:
rotate :: Double -> Image PixelRGBA8 -> Image PixelRGBA8
rotate n img@Image {..} = generateImage rotater newW newH
where rotater x y = if srcX x y < imageWidth && srcX x y >= 0 && srcY x y < imageHeight && srcY x y >= 0
then pixelAt img (srcX x y) (srcY x y)
else PixelRGBA8 255 255 255 255
srcX x y = getX center + rounding (fromIntegral (x - getX newCenter) * cos' + fromIntegral (y - getY newCenter) * sin')
srcY x y = getY center + rounding (fromIntegral (y - getY newCenter) * cos' - fromIntegral (x - getX newCenter) * sin')
center = (imageWidth `div` 2, imageHeight `div` 2)
newCenter = (newW `div` 2, newH `div` 2)
newW = rounding $ abs (fromIntegral imageHeight * sin') + abs (fromIntegral imageWidth * cos')
newH = rounding $ abs (fromIntegral imageHeight * cos') + abs (fromIntegral imageWidth * sin')
sin' = sin $ toRad n
cos' = cos $ toRad n
其中
rounding a = floor (a + 0.5)
getX = fst
getY = snd
toRad deg = deg * (pi/180)
如果有人需要的话就这样。谢谢@Carsten的建议!
MutableImage
是一个可以变异(就地更改(的Image
,默认情况下是不可变的。不过,您需要某种允许这样做的monad(请参阅文档——有一些包括ST
和IO
(。
要获得MutableImage
,可以使用thawImage
,然后使用readPixel
和writePixel
处理(获取/设置(像素,然后再次使用freezeImage
以获得不可变的Image
如果你想知道如何旋转图像,你可以查看rotateLeft
:的source code
rotateLeft90 :: Pixel a => Image a -> Image a
rotateLeft90 img@Image {..} =
generateImage gen imageHeight imageWidth
where
gen x y = pixelAt img (imageWidth - 1 - y) x
正如您所看到的,它不使用可变图像,而是从旧像素生成一个新图像(使用pixelAt
而不是readPixel
(
以防万一-这是使用记录通配符扩展从Image a
-参数中提取所有字段(这就是Image {..}
的作用-imageHeight
,imageWidth
从中提取(