module CV.ImageOp where import System.IO.Unsafe (unsafePerformIO) import CV.Image import Control.Monad ((>=>)) import Data.Monoid import Control.Category import Prelude hiding ((.),id) -- |ImageOperation is a name for unary operators that mutate images inplace. newtype ImageOperation c d = ImgOp (Image c d-> IO ()) -- |Compose two image operations (#>) :: ImageOperation c d-> ImageOperation c d -> ImageOperation c d (#>) (ImgOp a) (ImgOp b) = ImgOp (\img -> (a img >> b img)) -- |An unit operation for compose nonOp = ImgOp (\i -> return ()) -- |Apply image operation to a Copy of an image img <# op = unsafeOperate op img blitOp img pos = ImgOp $ \i -> blit img i pos setPixelOp pos v = ImgOp $ \i -> setPixel pos v i -- motivating example: -- >>> hop i = stretchHistogram $ i #- gaussian (5,5) -- allocates two extra images -- >>> hop = (gaussian (5,5) &#& id) #> subtract #> stretchHistogram -- could be implemented in a way that allocates just one extra fromImageOp (ImgOp f) = IOP $ \i -> (f i >> return i) newtype IOP a b = IOP (a -> IO b) instance Category IOP where id = IOP return (IOP f) . (IOP g) = IOP $ g >=> (f >>= return) (&#&) :: IOP (Image c d) e -> IOP (Image c d) f -> IOP (Image c d) (Image c d,Image c d) (IOP f) &#& (IOP g) = IOP $ op where op i = withCloneValue i $ \cl -> (f i >> g cl >> return (i,cl)) unsafeOperate op img = unsafePerformIO $ operate op img runIOP (IOP f) img = withCloneValue img $ \clone -> f clone -- |Apply list of image operations to a Copy of an image. (Makes a single copy and is -- faster than folding over (<#) img <## [] = img img <## op = unsafeOperate (foldl1 (#>) op) img operate ::ImageOperation c d -> Image c d -> IO (Image c d) operate (ImgOp op) img = withCloneValue img $ \clone -> op clone >> return clone operateOn = flip operate -- |Iterate an operation N times times n op = foldl (#>) nonOp (replicate n op) directOp i (ImgOp op) = op i operateInPlace (ImgOp op) img = op img unsafeOperateOn img op = unsafePerformIO $ operate op img operateWithROI pos size (ImgOp op) img = withClone img $ \clone -> withIOROI pos size clone (op clone)