#include #include #include namespace icl{ namespace{ #define TRUE_VAL 255 // general implementation for transforming a single value // implemented as class to provide part-specialization template 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 struct Apply{ \ 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 Img *apply_inplace_arithmetical_op_all(Img *src, bool roiOnly, icl64f val, InplaceLogicalOp::optype t){ switch(t){ #define CASE(X) \ case InplaceLogicalOp::X##Op: \ src->forEach(Apply(clipped_cast(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 Img *apply_inplace_arithmetical_op_float(Img *src, bool roiOnly, icl64f val, InplaceLogicalOp::optype t){ switch(t){ #define CASE(X) \ case InplaceLogicalOp::X##Op: \ src->forEach(Apply(clipped_cast(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(), \ 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(), \ getROIOnly(), \ getValue(), \ getOpType()); \ break; ICL_INSTANTIATE_ALL_FLOAT_DEPTHS; #undef ICL_INSTANTIATE_DEPTH } if (!getROIOnly() && !srcIn->hasFullROI()){ delete src; } return srcIn; } }