packages feed

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

{-# LANGUAGE ScopedTypeVariables #-}

-- | Perform the 2D FFT 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				as A
import System.Environment
import Control.Monad

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

         _ -> putStr $ unlines
		[ "Usage: repa-fft2d <fileIn.bmp> <clip mag :: Int> <fileOutMag.bmp> <fileOutPhase.bmp>"
		, " "
		, "    Image dimensions must be powers of two, eg 128x512 or 64x256"
		, ""
		, "    The output magnitude has a high dynamic range. We need to clip it otherwise"
		, "    most of the pixels in the output BMP will be black. Start with a value equal"
		, "    to about the width of the image (eg 512)"
		, "" ]
			
	
mainWithArgs fileIn (clipMag :: Double) fileMag filePhase
 = do	
	-- Load in the matrix.
	arrReal		<- liftM (either (\e -> error $ show e) force)
			$  readMatrixFromGreyscaleBMP fileIn

	let arrComplex	= force $ A.map (\r -> (r, 0 :: Double)) arrReal

	-- Apply the centering transform so that the output has the zero
	--	frequency in the middle of the image.
	let arrCentered	= center2d arrComplex
		
	-- Do the 2d transform.
	let arrFreq 	= fft2d Forward arrCentered
				
	-- Write out the magnitude of the transformed array, 
	--	clipping it at the given value.
	let clip m	= if m >= clipMag then clipMag else m
	let arrMag	= force $ A.map (clip . mag) arrFreq
	writeMatrixToGreyscaleBMP fileMag arrMag

	-- Write out the phase of the transofmed array, 
	-- 	scaling it to make full use of the 8 bit greyscale.
	let scaledArg x	= (arg x + pi) * (255 / (2 * pi))
	let arrPhase	= force $ A.map scaledArg arrFreq
	writeMatrixToGreyscaleBMP filePhase arrPhase