module Graphics.Image.Processing.Convolution (
convolve, convolveRows, convolveCols,
) where
import Prelude hiding (map)
import qualified Prelude as P (map)
import Graphics.Image.Interface
import Graphics.Image.Processing.Geometric
convolve'' :: ManifestArray arr cs e =>
Border (Pixel cs e) -> Image arr cs e -> Image arr cs e -> Image arr cs e
convolve'' !border !kernel !img =
img `deepSeqImage` kernel `deepSeqImage` traverse2 kernel img (const . const sz) stencil
where
!(krnM, krnN) = dims kernel
!krnM2 = krnM `div` 2
!krnN2 = krnN `div` 2
!sz = dims img
getPxB !getPx !ix = borderIndex border sz getPx ix
stencil !getKrnPx !getImgPx !(i, j) = integrate 0 0 0 where
!ikrnM = i krnM2
!jkrnN = j krnN2
integrate !ki !kj !acc
| kj == krnN = integrate (ki+1) 0 acc
| kj == 0 && ki == krnM = acc
| otherwise = let !krnPx = getKrnPx (ki, kj)
!imgPx = getPxB getImgPx (ki + ikrnM, kj + jkrnN)
in integrate ki (kj + 1) (acc + krnPx * imgPx)
convolve :: ManifestArray arr cs e =>
Border (Pixel cs e)
-> Image arr cs e
-> Image arr cs e
-> Image arr cs e
convolve !out = convolve'' out . rotate180
convolveRows :: ManifestArray arr cs e =>
Border (Pixel cs e) -> [Pixel cs e] -> Image arr cs e -> Image arr cs e
convolveRows !out = convolve out . fromLists . (:[]) . reverse
convolveCols :: ManifestArray arr cs e =>
Border (Pixel cs e) -> [Pixel cs e] -> Image arr cs e -> Image arr cs e
convolveCols !out = convolve out . fromLists . P.map (:[]) . reverse