packages feed

repa-examples-2.0.0.1: examples/FFT/HighPass2d/src-repa/Main.hs

{-# LANGUAGE PatternGuards #-}

-- | Perform high pass filtering on a BMP image.
import Data.Array.Repa.Algorithms.FFT
import Data.Array.Repa.Algorithms.DFT.Center
import Data.Array.Repa.Algorithms.Complex
import Data.Array.Repa.IO.BMP
import Data.Array.Repa.IO.Timing
import Data.Array.Repa				as A
import System.Environment
import Control.Monad


main :: IO ()
main 
 = do	args	<- getArgs
	case args of
	 [cutoff, fileIn, fileOut]
	   -> mainWithArgs (read cutoff) fileIn fileOut

         _ -> putStr $ unlines
		[ "Usage: repa-fft-highpass <cutoff::Int> <fileIn.bmp> <fileOut.bmp>"
		, ""
		, "    Image dimensions must be powers of two, eg 128x512 or 64x256"
		, "" ]
			
	
mainWithArgs cutoff fileIn fileOut
 = do	
	-- Load in the matrix.
	(arrRed, arrGreen, arrBlue)
		<- liftM (either (\e -> error $ show e) id)
		$  readComponentsFromBMP fileIn
	
	-- The deepSeqs are to make sure we're just measuring the transform time.
	arrRed 
	 `deepSeqArray` arrGreen
	 `deepSeqArray` arrBlue
	 `deepSeqArray` return ()
		
	-- Do the transform on each component individually
	((arrRed', arrGreen', arrBlue'), t)
		<- time
		$ let	arrRed'		= transform cutoff arrRed
			arrGreen'	= transform cutoff arrGreen
			arrBlue'	= transform cutoff arrBlue
		  in	arrRed' 
		         `deepSeqArray` arrGreen'
			 `deepSeqArray` arrBlue'
			 `deepSeqArray` return (arrRed', arrGreen', arrBlue')
	
	putStr (prettyTime t)
	
	-- Write it back to file.
	writeComponentsToBMP fileOut
		arrRed' arrGreen' arrBlue' 
		

transform cutoff arrReal
 = let	arrComplex	= force $ A.map (\r -> (fromIntegral r, 0)) arrReal
			
	-- Do the 2d transform.
	arrCentered	= center2d arrComplex
	arrFreq		= fft2d Forward arrCentered

	-- Zap out the low frequency components.
	_ :. height :. width = extent arrFreq
	centerX		= width  `div` 2
	centerY		= height `div` 2
	
	{-# INLINE highpass #-}
	highpass get ix@(_ :. y :. x)
		|   x > centerX + cutoff
		 || x < centerX - cutoff
		 || y > centerY + cutoff
		 || y < centerY - cutoff
		= get ix
		
		| otherwise
		= 0
		
	arrFilt	= traverse arrFreq id highpass

	-- Do the inverse transform to get back to image space.
	arrInv	= fft2d Inverse arrFilt
		
	-- Get the magnitude of the transformed array, 
	arrMag	= A.map (truncate . mag) arrInv

   in	arrMag