{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Graphics.Image.Processing.Convolution (
convolve, convolveRows, convolveCols,
correlate
) where
import Graphics.Image.ColorSpace (Pixel (..), X)
import Graphics.Image.Interface as I
import Graphics.Image.Processing.Geometric
import Graphics.Image.Utils (loop)
import Prelude as P
correlate :: (Array arr X e, Array arr cs e)
=> Border (Pixel cs e) -> Image arr X e -> Image arr cs e -> Image arr cs e
correlate !border !kernel !img =
makeImageWindowed
sz
(kM2, kN2)
(m - kM2 * 2, n - kN2 * 2)
(getStencil (I.unsafeIndex imgM))
(getStencil (borderIndex border imgM))
where
!imgM = toManifest img
!sz@(m, n) = dims img
!kernelM = toManifest kernel
!(kM, kN) = dims kernel
!(kM2, kN2) = (kM `div` 2, kN `div` 2)
getStencil getImgPx !(i, j) =
loop 0 (< kM) (+ 1) 0 $ \ !iK !acc0 ->
let !iD = i + iK - kM2 in
loop 0 (< kN) (+ 1) acc0 $ \ !jK !acc1 ->
let !jD = j + jK - kN2 in
acc1 + liftPx (* getX (unsafeIndex kernelM (iK, jK))) (getImgPx (iD, jD))
{-# INLINE getStencil #-}
{-# INLINE correlate #-}
convolve :: (Array arr X e, Array arr cs e) =>
Border (Pixel cs e)
-> Image arr X e
-> Image arr cs e
-> Image arr cs e
convolve !out = correlate out . rotate180
{-# INLINE convolve #-}
convolveRows :: (Array arr X e, Array arr cs e) =>
Border (Pixel cs e) -> [Pixel X e] -> Image arr cs e -> Image arr cs e
convolveRows !out = convolve out . fromLists . (:[]) . reverse
{-# INLINE convolveRows #-}
convolveCols :: (Array arr X e, Array arr cs e) =>
Border (Pixel cs e) -> [Pixel X e] -> Image arr cs e -> Image arr cs e
convolveCols !out = convolve out . fromLists . P.map (:[]) . reverse
{-# INLINE convolveCols #-}