packages feed

accelerate-examples-1.2.0.0: examples/fft/src-acc/HighPass.hs

{-# LANGUAGE NoImplicitPrelude #-}

module HighPass
  where

import Data.Array.Accelerate                            as A
import Data.Array.Accelerate.IO.Codec.BMP               as A
import Data.Array.Accelerate.Data.Colour.RGBA           as A
import Data.Array.Accelerate.Math.FFT                   as A
import Data.Array.Accelerate.Math.DFT.Centre            as A
import Data.Array.Accelerate.Data.Complex               as A


highpassFFT :: Int -> Acc (Array DIM2 RGBA32) -> Acc (Array DIM2 RGBA32)
highpassFFT cutoff img = img'
  where
    (r,g,b,a)   = A.unzip4
                $ A.map (\c -> let RGBA x y z w = unlift c :: RGBA (Exp Word8)
                               in lift (x,y,z,w) :: Exp (Word8, Word8, Word8, Word8))
                $ A.map unpackRGBA8 img
    r'          = transform cutoff r
    g'          = transform cutoff g
    b'          = transform cutoff b
    --
    img'        = A.zipWith4 (\x y z w -> packRGBA8 . lift $ RGBA x y z w) r' g' b' a


transform :: Int -> Acc (Array DIM2 Word8) -> Acc (Array DIM2 Word8)
transform cutoff' arrReal = arrResult
  where
    cutoff      = the (unit (constant cutoff'))

    arrComplex :: Acc (Array DIM2 (Complex Float))
    arrComplex  = A.map (\r -> lift (A.fromIntegral r :+ constant 0)) arrReal

    -- Do the 2D transform
    arrCentered = centre2D arrComplex
    arrFreq     = fft2D Forward arrCentered

    -- Zap out the low-frequency components
    Z :. h :. w = unlift (shape arrReal)
    centreX     = w `div` 2
    centreY     = h `div` 2

    zap ix      = let (Z :. y :. x)     = unlift ix
                      inx               = x > centreX - cutoff && x A.< centreX + cutoff
                      iny               = y > centreY - cutoff && y A.< centreY + cutoff
                  in
                  inx && iny ? (constant (0 :+ 0), arrFreq A.! ix)

    arrFilt     = A.generate (A.shape arrFreq) zap

    -- Do the inverse transform to get back to image space
    arrInv      = fft2D Inverse arrFilt

    -- The magnitude of the transformed array
    arrResult   = A.map (A.truncate . magnitude) arrInv