#endif
+#ifdef HAVE_IPP
+#define IPP_WARPAFFINE_PARALLEL 1
+
+#ifdef HAVE_IPP_IW
+
+class ipp_warpAffineParallel: public ParallelLoopBody
+{
+public:
+ ipp_warpAffineParallel(::ipp::IwiImage &src, ::ipp::IwiImage &dst, IppiInterpolationType _inter, double (&_coeffs)[2][3], ::ipp::IwiBorderType _borderType, IwTransDirection _iwTransDirection, bool *_ok):m_src(src), m_dst(dst)
+ {
+ pOk = _ok;
+
+ inter = _inter;
+ borderType = _borderType;
+ iwTransDirection = _iwTransDirection;
+
+ for( int i = 0; i < 2; i++ )
+ for( int j = 0; j < 3; j++ )
+ coeffs[i][j] = _coeffs[i][j];
+
+ *pOk = true;
+ }
+ ~ipp_warpAffineParallel() {}
+
+ virtual void operator() (const Range& range) const CV_OVERRIDE
+ {
+ CV_INSTRUMENT_REGION_IPP();
+
+ if(*pOk == false)
+ return;
+
+ try
+ {
+ ::ipp::IwiTile tile = ::ipp::IwiRoi(0, range.start, m_dst.m_size.width, range.end - range.start);
+ CV_INSTRUMENT_FUN_IPP(::ipp::iwiWarpAffine, m_src, m_dst, coeffs, iwTransDirection, inter, ::ipp::IwiWarpAffineParams(), borderType, tile);
+ }
+ catch(const ::ipp::IwException &)
+ {
+ *pOk = false;
+ return;
+ }
+ }
+private:
+ ::ipp::IwiImage &m_src;
+ ::ipp::IwiImage &m_dst;
+
+ IppiInterpolationType inter;
+ double coeffs[2][3];
+ ::ipp::IwiBorderType borderType;
+ IwTransDirection iwTransDirection;
+
+ bool *pOk;
+ const ipp_warpAffineParallel& operator= (const ipp_warpAffineParallel&);
+};
+
+#endif
+
+static bool ipp_warpAffine( InputArray _src, OutputArray _dst, int interpolation, int borderType, InputArray _M, int flags )
+{
+#ifdef HAVE_IPP_IW
+ CV_INSTRUMENT_REGION_IPP();
+
+ if (!cv::ipp::useIPP_NotExact())
+ return false;
+
+ IppiInterpolationType ippInter = ippiGetInterpolation(interpolation);
+ if((int)ippInter < 0)
+ return false;
+
+ // Acquire data and begin processing
+ try
+ {
+ Mat src = _src.getMat();
+ Mat dst = _dst.getMat();
+ ::ipp::IwiImage iwSrc = ippiGetImage(src);
+ ::ipp::IwiImage iwDst = ippiGetImage(dst);
+ ::ipp::IwiBorderType ippBorder(ippiGetBorderType(borderType));
+ IwTransDirection iwTransDirection;
+ if(!ippBorder)
+ return false;
+
+ if( !(flags & WARP_INVERSE_MAP) )
+ iwTransDirection = iwTransForward;
+ else
+ iwTransDirection = iwTransInverse;
+
+ Mat M = _M.getMat();
+ double coeffs[2][3];
+ for( int i = 0; i < 2; i++ )
+ for( int j = 0; j < 3; j++ )
+ coeffs[i][j] = M.at<double>(i, j);
+
+ const int threads = ippiSuggestThreadsNum(iwDst, 2);
+
+ if(IPP_WARPAFFINE_PARALLEL && threads > 1)
+ {
+ bool ok = true;
+ Range range(0, (int)iwDst.m_size.height);
+ ipp_warpAffineParallel invoker(iwSrc, iwDst, ippInter, coeffs, ippBorder, iwTransDirection, &ok);
+ if(!ok)
+ return false;
+
+ parallel_for_(range, invoker, threads*4);
+
+ if(!ok)
+ return false;
+ } else {
+ CV_INSTRUMENT_FUN_IPP(::ipp::iwiWarpAffine, iwSrc, iwDst, coeffs, iwTransDirection, ippInter, ::ipp::IwiWarpAffineParams(), ippBorder);
+ }
+
+ }
+ catch (const ::ipp::IwException &)
+ {
+ return false;
+ }
+
+ return true;
+#endif
+}
+#endif
+
namespace hal {
void warpAffine(int src_type,
CV_Assert( (M0.type() == CV_32F || M0.type() == CV_64F) && M0.rows == 2 && M0.cols == 3 );
M0.convertTo(matM, matM.type());
+ CV_IPP_RUN_FAST(ipp_warpAffine(src, dst, interpolation, borderType, matM, flags));
+
if( !(flags & WARP_INVERSE_MAP) )
{
double D = M[0]*M[4] - M[1]*M[3];