#include <ICLFilter/InplaceLogicalOp.h> #include <ICLCore/Img.h> #include <cmath> namespace icl{ namespace{ #define TRUE_VAL 255 // general implementation for transforming a single value // implemented as class to provide part-specialization template<class T,InplaceLogicalOp::optype O> struct Apply{ Apply(T val):val(val){} inline void operator()(T &t){} T val; }; // define how to specialize a single optype O##Op with given func F #define SPECIALIZE(O,F) \ template<class T> struct Apply<T,InplaceLogicalOp::O##Op>{ \ Apply(icl64f val):val(val){} \ inline void operator()(T &t){ \ t = (F); \ } \ T val; \ }; // define specializations for all optypes SPECIALIZE(and,(t&&val)*TRUE_VAL); SPECIALIZE(or,(t||val)*TRUE_VAL); SPECIALIZE(xor,(!!val xor !!t)*TRUE_VAL); // using !! to convert v into boolean SPECIALIZE(not,(!t)*TRUE_VAL); SPECIALIZE(binAnd,t&val); SPECIALIZE(binOr,t|val); SPECIALIZE(binXor,t^val); SPECIALIZE(binNot,~t); #undef SPECIALIZE // expand the optype from runtime parameter to template parameter // by this means, switching over optype is done at compile type template<class T> Img<T> *apply_inplace_arithmetical_op_all(Img<T> *src, bool roiOnly, icl64f val, InplaceLogicalOp::optype t){ switch(t){ #define CASE(X) \ case InplaceLogicalOp::X##Op: \ src->forEach(Apply<T,InplaceLogicalOp::X##Op>(clipped_cast<icl64f,T>(val))); \ break CASE(and); CASE(or); CASE(xor); CASE(not); CASE(binAnd); CASE(binOr); CASE(binXor); CASE(binNot); #undef CASE default: break; } return src; } // expand the optype from runtime parameter to template parameter // by this means, switching over optype is done at compile type template<class T> Img<T> *apply_inplace_arithmetical_op_float(Img<T> *src, bool roiOnly, icl64f val, InplaceLogicalOp::optype t){ switch(t){ #define CASE(X) \ case InplaceLogicalOp::X##Op: \ src->forEach(Apply<T,InplaceLogicalOp::X##Op>(clipped_cast<icl64f,T>(val))); \ break CASE(and); CASE(or); CASE(xor); CASE(not); #undef CASE default: break; } return src; } } // underlying apply function: switches over the src images depth // binary operations are only instantiated for int depths pure // logical operations are instantiated for all depths ImgBase *InplaceLogicalOp::apply(ImgBase *srcIn){ ICLASSERT_RETURN_VAL(srcIn,0); ICLASSERT_RETURN_VAL(srcIn->getChannels(),srcIn); ImgBase *src = 0; if(!getROIOnly() && !srcIn->hasFullROI()){ src = srcIn->shallowCopy(srcIn->getImageRect()); }else{ src = srcIn; } depth d = src->getDepth(); if(d==depth32f || d ==depth64f){ if(m_eOpType > 3){ ERROR_LOG("Bitwise operations are not implemented for floating point types"); return src; } } switch(d){ #define ICL_INSTANTIATE_DEPTH(D) \ case depth##D: \ return apply_inplace_arithmetical_op_all(src->asImg<icl##D>(), \ getROIOnly(), \ getValue(), \ getOpType()); \ break; ICL_INSTANTIATE_ALL_INT_DEPTHS; #undef ICL_INSTANTIATE_DEPTH #define ICL_INSTANTIATE_DEPTH(D) \ case depth##D: \ return apply_inplace_arithmetical_op_float(src->asImg<icl##D>(), \ getROIOnly(), \ getValue(), \ getOpType()); \ break; ICL_INSTANTIATE_ALL_FLOAT_DEPTHS; #undef ICL_INSTANTIATE_DEPTH } if (!getROIOnly() && !srcIn->hasFullROI()){ delete src; } return srcIn; } }