 {-#OPTIONS_GHC -fwarn-unused-imports#-}
 
 -- | This module is a collection of various image filters
-module CV.Filters(gaussian,gaussianOp
+module CV.Filters(
+               gaussian,gaussianOp
               ,blurOp,blur,blurNS
+              ,bilateral
               ,HasMedianFiltering,median
               ,susan,getCentralMoment,getAbsCentralMoment
               ,getMoment,secondMomentBinarize,secondMomentBinarizeOp

                                (\i-> {#call smab#} i w h t)
secondMomentAdaptiveBinarize w h t i = unsafeOperate (secondMomentAdaptiveBinarizeOp w h t) i

data SmoothType = BlurNoScale | Blur 
                | Gaussian | Median 
                | Bilateral
                deriving(Enum)

{#fun cvSmooth as smooth' 
    {withGenImage* `Image GrayScale D32'

    ,`Int',`Int',`Int',`Float',`Float'}
    -> `()'#}


-- | Image operation which applies gaussian or unifarm smoothing with a given window size to the image.
gaussianOp,blurOp,blurNSOp :: (Int, Int) -> ImageOperation GrayScale D32
gaussianOp m =  withMask m $ \(w,h) img -> smooth' img img (fromEnum Gaussian) w h 0 0
blurOp m = withMask m $ \(w,h) img -> smooth' img img (fromEnum Blur) w h 0 0
blurNSOp m = withMask m $ \(w,h) img -> smooth' img img (fromEnum BlurNoScale) w h 0 0

-- | Create a new image by applying gaussian, or uniform smoothing.
gaussian,blur,blurNS :: (Int, Int) -> Image GrayScale D32 -> Image GrayScale D32
gaussian = unsafeOperate . gaussianOp
blur     = unsafeOperate . blurOp
blurNS   = unsafeOperate . blurNSOp

withMask (w,h) op 
    | maskIsOk (w,h) = ImgOp $ op (w,h)
    | otherwise = error "One of aperture dimensions is incorrect (should be >=1 and odd))"



-- | Apply bilateral filtering 
bilateral :: (Int,Int) -> (Int,Int) -> Image a D8 -> Image a D8
bilateral (w,h) (s1,s2) img = unsafePerformIO $ 
            withClone img $ \clone ->
             withGenImage img $ \cimg ->
              withGenImage clone $ \ccln -> do
                   {#call cvSmooth#} cimg ccln  (fromIntegral $ fromEnum Bilateral)
                        (fromIntegral w) (fromIntegral h) 
                        (realToFrac s1) (realToFrac s2) 


class HasMedianFiltering a where
    median :: (Int,Int) -> a -> a
