moduleCV.ImageOpwhereimportSystem.IO.Unsafe(unsafePerformIO)importCV.ImageimportControl.Monad((>=>))importData.MonoidimportControl.CategoryimportPreludehiding((.),id)-- |ImageOperation is a name for unary operators that mutate images inplace.newtypeImageOperationcd=ImgOp(Imagecd->IO())-- |Compose two image operations(#>)::ImageOperationcd->ImageOperationcd->ImageOperationcd(#>)(ImgOpa)(ImgOpb)=ImgOp(\img->(aimg>>bimg))-- |An unit operation for composenonOp=ImgOp(\i->return())-- |Apply image operation to a Copy of an imageimg<#op=unsafeOperateopimg-- 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 extrafromImageOp(ImgOpf)=IOP$\i->(fi>>returni)newtypeIOPab=IOP(a->IOb)instanceCategoryIOPwhereid=IOPreturn(IOPf).(IOPg)=IOP$g>=>(f>>=return)(&#&)::IOP(Imagecd)e->IOP(Imagecd)f->IOP(Imagecd)(Imagecd,Imagecd)(IOPf)&#&(IOPg)=IOP$opwhereopi=withCloneValuei$\cl->(fi>>gcl>>return(i,cl))unsafeOperateopimg=unsafePerformIO$operateopimgrunIOP(IOPf)img=withCloneValueimg$\clone->fclone-- |Apply list of image operations to a Copy of an image. (Makes a single copy and is-- faster than folding over (<#)img<##[]=imgimg<##op=unsafeOperate(foldl1(#>)op)imgoperate::ImageOperationcd->Imagecd->IO(Imagecd)operate(ImgOpop)img=withCloneValueimg$\clone->opclone>>returncloneoperateOn=flipoperate-- |Iterate an operation N timestimesnop=foldl(#>)nonOp(replicatenop)directOpi(ImgOpop)=opioperateInPlace(ImgOpop)img=opimgunsafeOperateOnimgop=unsafePerformIO$operateopimgoperateWithROIpossize(ImgOpop)img=withCloneimg$\clone->withIOROIpossizeclone(opclone)