diff --git a/modules/core/include/opencv2/core/cv_cpu_dispatch.h b/modules/core/include/opencv2/core/cv_cpu_dispatch.h index 08909f8b28..7f6d6b0fb9 100644 --- a/modules/core/include/opencv2/core/cv_cpu_dispatch.h +++ b/modules/core/include/opencv2/core/cv_cpu_dispatch.h @@ -124,6 +124,10 @@ #if defined CV_CPU_COMPILE_AVX && !defined CV_CPU_BASELINE_COMPILE_AVX struct VZeroUpperGuard { +#ifdef __GNUC__ + __attribute__((always_inline)) +#endif + inline VZeroUpperGuard() { _mm256_zeroupper(); } #ifdef __GNUC__ __attribute__((always_inline)) #endif diff --git a/modules/core/include/opencv2/core/private.hpp b/modules/core/include/opencv2/core/private.hpp index 1ea8c28643..c3f5b87267 100644 --- a/modules/core/include/opencv2/core/private.hpp +++ b/modules/core/include/opencv2/core/private.hpp @@ -796,9 +796,9 @@ CV_EXPORTS InstrNode* getCurrentNode(); #endif #ifdef __CV_AVX_GUARD -#define CV_INSTRUMENT_REGION(); __CV_AVX_GUARD CV_INSTRUMENT_REGION_(); +#define CV_INSTRUMENT_REGION() __CV_AVX_GUARD CV_INSTRUMENT_REGION_(); #else -#define CV_INSTRUMENT_REGION(); CV_INSTRUMENT_REGION_(); +#define CV_INSTRUMENT_REGION() CV_INSTRUMENT_REGION_(); #endif namespace cv { diff --git a/modules/imgproc/CMakeLists.txt b/modules/imgproc/CMakeLists.txt index 1caadbbbad..6232aa5fab 100644 --- a/modules/imgproc/CMakeLists.txt +++ b/modules/imgproc/CMakeLists.txt @@ -1,3 +1,6 @@ set(the_description "Image Processing") ocv_add_dispatched_file(accum SSE4_1 AVX AVX2) +ocv_add_dispatched_file(color_hsv SSE2 SSE4_1 AVX2) +ocv_add_dispatched_file(color_rgb SSE2 SSE4_1 AVX2) +ocv_add_dispatched_file(color_yuv SSE2 SSE4_1 AVX2) ocv_define_module(imgproc opencv_core WRAP java python js) diff --git a/modules/imgproc/src/color.cpp b/modules/imgproc/src/color.cpp index 38d35c014d..8f268e07e0 100644 --- a/modules/imgproc/src/color.cpp +++ b/modules/imgproc/src/color.cpp @@ -3,6 +3,7 @@ // of this distribution and at http://opencv.org/license.html #include "precomp.hpp" +#include "opencl_kernels_imgproc.hpp" #include "color.hpp" namespace cv diff --git a/modules/imgproc/src/color.hpp b/modules/imgproc/src/color.hpp index 70e7844277..8c1f19fa8a 100644 --- a/modules/imgproc/src/color.hpp +++ b/modules/imgproc/src/color.hpp @@ -3,59 +3,17 @@ // of this distribution and at http://opencv.org/license.html #include "opencv2/imgproc.hpp" -#include "opencv2/core/utility.hpp" -#include -#include "opencl_kernels_imgproc.hpp" #include "hal_replacement.hpp" -#include "opencv2/core/hal/intrin.hpp" -#include "opencv2/core/softfloat.hpp" -#define CV_DESCALE(x,n) (((x) + (1 << ((n)-1))) >> (n)) - -namespace cv -{ - -//constants for conversion from/to RGB and Gray, YUV, YCrCb according to BT.601 -const float B2YF = 0.114f; -const float G2YF = 0.587f; -const float R2YF = 0.299f; - -enum -{ - yuv_shift = 14, - xyz_shift = 12, - R2Y = 4899, // == R2YF*16384 - G2Y = 9617, // == G2YF*16384 - B2Y = 1868, // == B2YF*16384 - BLOCK_SIZE = 256 -}; - -template struct ColorChannel -{ - typedef float worktype_f; - static _Tp max() { return std::numeric_limits<_Tp>::max(); } - static _Tp half() { return (_Tp)(max()/2 + 1); } -}; - -template<> struct ColorChannel -{ - typedef float worktype_f; - static float max() { return 1.f; } - static float half() { return 0.5f; } -}; - -/*template<> struct ColorChannel -{ - typedef double worktype_f; - static double max() { return 1.; } - static double half() { return 0.5; } -};*/ +namespace cv { // // Helper functions // -namespace { +namespace impl { + +#include "color.simd_helpers.hpp" inline bool isHSV(int code) { @@ -209,40 +167,9 @@ inline int uIndex(int code) } } // namespace:: +using namespace impl; -template -struct Set -{ - static bool contains(int i) - { - return (i == i0 || i == i1 || i == i2); - } -}; - -template -struct Set -{ - static bool contains(int i) - { - return (i == i0 || i == i1); - } -}; - -template -struct Set -{ - static bool contains(int i) - { - return (i == i0); - } -}; - -enum SizePolicy -{ - TO_YUV, FROM_YUV, NONE -}; - -template< typename VScn, typename VDcn, typename VDepth, SizePolicy sizePolicy = NONE > +/*template< typename VScn, typename VDcn, typename VDepth, SizePolicy sizePolicy = NONE > struct CvtHelper { CvtHelper(InputArray _src, OutputArray _dst, int dcn) @@ -282,7 +209,7 @@ struct CvtHelper Mat src, dst; int depth, scn; Size dstSz; -}; +};*/ #ifdef HAVE_OPENCL @@ -380,49 +307,7 @@ struct OclHelper #endif -///////////////////////////// Top-level template function //////////////////////////////// -template -class CvtColorLoop_Invoker : public ParallelLoopBody -{ - typedef typename Cvt::channel_type _Tp; -public: - - CvtColorLoop_Invoker(const uchar * src_data_, size_t src_step_, uchar * dst_data_, size_t dst_step_, int width_, const Cvt& _cvt) : - ParallelLoopBody(), src_data(src_data_), src_step(src_step_), dst_data(dst_data_), dst_step(dst_step_), - width(width_), cvt(_cvt) - { - } - - virtual void operator()(const Range& range) const CV_OVERRIDE - { - CV_TRACE_FUNCTION(); - - const uchar* yS = src_data + static_cast(range.start) * src_step; - uchar* yD = dst_data + static_cast(range.start) * dst_step; - - for( int i = range.start; i < range.end; ++i, yS += src_step, yD += dst_step ) - cvt(reinterpret_cast(yS), reinterpret_cast<_Tp*>(yD), width); - } - -private: - const uchar * src_data; - const size_t src_step; - uchar * dst_data; - const size_t dst_step; - const int width; - const Cvt& cvt; - - const CvtColorLoop_Invoker& operator= (const CvtColorLoop_Invoker&); -}; - -template -void CvtColorLoop(const uchar * src_data, size_t src_step, uchar * dst_data, size_t dst_step, int width, int height, const Cvt& cvt) -{ - parallel_for_(Range(0, height), - CvtColorLoop_Invoker(src_data, src_step, dst_data, dst_step, width, cvt), - (width * height) / static_cast(1<<16)); -} #if defined (HAVE_IPP) && (IPP_VERSION_X100 >= 700) # define NEED_IPP 1 diff --git a/modules/imgproc/src/color.simd_helpers.hpp b/modules/imgproc/src/color.simd_helpers.hpp new file mode 100644 index 0000000000..343491f2c6 --- /dev/null +++ b/modules/imgproc/src/color.simd_helpers.hpp @@ -0,0 +1,167 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html + +#define CV_DESCALE(x,n) (((x) + (1 << ((n)-1))) >> (n)) + +namespace { + +//constants for conversion from/to RGB and Gray, YUV, YCrCb according to BT.601 +static const float B2YF = 0.114f; +static const float G2YF = 0.587f; +static const float R2YF = 0.299f; + +enum +{ + yuv_shift = 14, + xyz_shift = 12, + R2Y = 4899, // == R2YF*16384 + G2Y = 9617, // == G2YF*16384 + B2Y = 1868, // == B2YF*16384 + BLOCK_SIZE = 256 +}; + +template struct ColorChannel +{ + typedef float worktype_f; + static inline _Tp max() { return std::numeric_limits<_Tp>::max(); } + static inline _Tp half() { return (_Tp)(max()/2 + 1); } +}; + +template<> struct ColorChannel +{ + typedef float worktype_f; + static inline float max() { return 1.f; } + static inline float half() { return 0.5f; } +}; + +/*template<> struct ColorChannel +{ + typedef double worktype_f; + static double max() { return 1.; } + static double half() { return 0.5; } +};*/ + + +template +struct Set +{ + static inline bool contains(int i) + { + return (i == i0 || i == i1 || i == i2); + } +}; + +template +struct Set +{ + static inline bool contains(int i) + { + return (i == i0 || i == i1); + } +}; + +template +struct Set +{ + static inline bool contains(int i) + { + return (i == i0); + } +}; + +enum SizePolicy +{ + TO_YUV, FROM_YUV, NONE +}; + +template< typename VScn, typename VDcn, typename VDepth, SizePolicy sizePolicy = NONE > +struct CvtHelper +{ + CvtHelper(InputArray _src, OutputArray _dst, int dcn) + { + CV_Assert(!_src.empty()); + + int stype = _src.type(); + scn = CV_MAT_CN(stype), depth = CV_MAT_DEPTH(stype); + + CV_Check(scn, VScn::contains(scn), "Invalid number of channels in input image"); + CV_Check(dcn, VDcn::contains(dcn), "Invalid number of channels in output image"); + CV_CheckDepth(depth, VDepth::contains(depth), "Unsupported depth of input image"); + + if (_src.getObj() == _dst.getObj()) // inplace processing (#6653) + _src.copyTo(src); + else + src = _src.getMat(); + Size sz = src.size(); + switch (sizePolicy) + { + case TO_YUV: + CV_Assert( sz.width % 2 == 0 && sz.height % 2 == 0); + dstSz = Size(sz.width, sz.height / 2 * 3); + break; + case FROM_YUV: + CV_Assert( sz.width % 2 == 0 && sz.height % 3 == 0); + dstSz = Size(sz.width, sz.height * 2 / 3); + break; + case NONE: + default: + dstSz = sz; + break; + } + _dst.create(dstSz, CV_MAKETYPE(depth, dcn)); + dst = _dst.getMat(); + } + Mat src, dst; + int depth, scn; + Size dstSz; +}; + + +///////////////////////////// Top-level template function //////////////////////////////// + +template +class CvtColorLoop_Invoker : public ParallelLoopBody +{ + typedef typename Cvt::channel_type _Tp; +public: + + CvtColorLoop_Invoker(const uchar * src_data_, size_t src_step_, uchar * dst_data_, size_t dst_step_, int width_, const Cvt& _cvt) : + ParallelLoopBody(), src_data(src_data_), src_step(src_step_), dst_data(dst_data_), dst_step(dst_step_), + width(width_), cvt(_cvt) + { + } + + virtual void operator()(const Range& range) const CV_OVERRIDE + { + CV_TRACE_FUNCTION(); + + const uchar* yS = src_data + static_cast(range.start) * src_step; + uchar* yD = dst_data + static_cast(range.start) * dst_step; + + for( int i = range.start; i < range.end; ++i, yS += src_step, yD += dst_step ) + cvt(reinterpret_cast(yS), reinterpret_cast<_Tp*>(yD), width); + } + +private: + const uchar * src_data; + const size_t src_step; + uchar * dst_data; + const size_t dst_step; + const int width; + const Cvt& cvt; + + CvtColorLoop_Invoker(const CvtColorLoop_Invoker&); // = delete; + const CvtColorLoop_Invoker& operator= (const CvtColorLoop_Invoker&); // = delete; +}; + +template static inline +void CvtColorLoop(const uchar * src_data, size_t src_step, uchar * dst_data, size_t dst_step, int width, int height, const Cvt& cvt) +{ + CV_AVX_GUARD + parallel_for_(Range(0, height), + CvtColorLoop_Invoker(src_data, src_step, dst_data, dst_step, width, cvt), + (width * height) / static_cast(1<<16)); +} + +} //namespace diff --git a/modules/imgproc/src/color_hsv.dispatch.cpp b/modules/imgproc/src/color_hsv.dispatch.cpp new file mode 100644 index 0000000000..f1678f5deb --- /dev/null +++ b/modules/imgproc/src/color_hsv.dispatch.cpp @@ -0,0 +1,358 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html + +#include "precomp.hpp" + +#include "opencl_kernels_imgproc.hpp" + +#include "color.hpp" + +#include "color_hsv.simd.hpp" +#include "color_hsv.simd_declarations.hpp" // defines CV_CPU_DISPATCH_MODES_ALL=AVX2,...,BASELINE based on CMakeLists.txt content + +namespace cv { + +// +// IPP functions +// + +#if NEED_IPP + +#if !IPP_DISABLE_RGB_HSV +static ippiGeneralFunc ippiRGB2HSVTab[] = +{ + (ippiGeneralFunc)ippiRGBToHSV_8u_C3R, 0, (ippiGeneralFunc)ippiRGBToHSV_16u_C3R, 0, + 0, 0, 0, 0 +}; +#endif + +static ippiGeneralFunc ippiHSV2RGBTab[] = +{ + (ippiGeneralFunc)ippiHSVToRGB_8u_C3R, 0, (ippiGeneralFunc)ippiHSVToRGB_16u_C3R, 0, + 0, 0, 0, 0 +}; + +static ippiGeneralFunc ippiRGB2HLSTab[] = +{ + (ippiGeneralFunc)ippiRGBToHLS_8u_C3R, 0, (ippiGeneralFunc)ippiRGBToHLS_16u_C3R, 0, + 0, (ippiGeneralFunc)ippiRGBToHLS_32f_C3R, 0, 0 +}; + +static ippiGeneralFunc ippiHLS2RGBTab[] = +{ + (ippiGeneralFunc)ippiHLSToRGB_8u_C3R, 0, (ippiGeneralFunc)ippiHLSToRGB_16u_C3R, 0, + 0, (ippiGeneralFunc)ippiHLSToRGB_32f_C3R, 0, 0 +}; + +#endif + +// +// HAL functions +// + +namespace hal +{ + +// 8u, 32f +void cvtBGRtoHSV(const uchar * src_data, size_t src_step, + uchar * dst_data, size_t dst_step, + int width, int height, + int depth, int scn, bool swapBlue, bool isFullRange, bool isHSV) +{ + CV_INSTRUMENT_REGION(); + + CALL_HAL(cvtBGRtoHSV, cv_hal_cvtBGRtoHSV, src_data, src_step, dst_data, dst_step, width, height, depth, scn, swapBlue, isFullRange, isHSV); + +#if defined(HAVE_IPP) && IPP_VERSION_X100 >= 700 + CV_IPP_CHECK() + { + if(depth == CV_8U && isFullRange) + { + if (isHSV) + { +#if !IPP_DISABLE_RGB_HSV // breaks OCL accuracy tests + if(scn == 3 && !swapBlue) + { + if( CvtColorIPPLoopCopy(src_data, src_step, CV_MAKE_TYPE(depth, scn), dst_data, dst_step, width, height, + IPPReorderGeneralFunctor(ippiSwapChannelsC3RTab[depth], ippiRGB2HSVTab[depth], 2, 1, 0, depth)) ) + return; + } + else if(scn == 4 && !swapBlue) + { + if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], ippiRGB2HSVTab[depth], 2, 1, 0, depth)) ) + return; + } + else if(scn == 4 && swapBlue) + { + if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], ippiRGB2HSVTab[depth], 0, 1, 2, depth)) ) + return; + } +#endif + } + else + { + if(scn == 3 && !swapBlue) + { + if( CvtColorIPPLoopCopy(src_data, src_step, CV_MAKE_TYPE(depth, scn), dst_data, dst_step, width, height, + IPPReorderGeneralFunctor(ippiSwapChannelsC3RTab[depth], ippiRGB2HLSTab[depth], 2, 1, 0, depth)) ) + return; + } + else if(scn == 4 && !swapBlue) + { + if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], ippiRGB2HLSTab[depth], 2, 1, 0, depth)) ) + return; + } + else if(scn == 3 && swapBlue) + { + if( CvtColorIPPLoopCopy(src_data, src_step, CV_MAKE_TYPE(depth, scn), dst_data, dst_step, width, height, + IPPGeneralFunctor(ippiRGB2HLSTab[depth])) ) + return; + } + else if(scn == 4 && swapBlue) + { + if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], ippiRGB2HLSTab[depth], 0, 1, 2, depth)) ) + return; + } + } + } + } +#endif + + CV_CPU_DISPATCH(cvtBGRtoHSV, (src_data, src_step, dst_data, dst_step, width, height, depth, scn, swapBlue, isFullRange, isHSV), + CV_CPU_DISPATCH_MODES_ALL); +} + +// 8u, 32f +void cvtHSVtoBGR(const uchar * src_data, size_t src_step, + uchar * dst_data, size_t dst_step, + int width, int height, + int depth, int dcn, bool swapBlue, bool isFullRange, bool isHSV) +{ + CV_INSTRUMENT_REGION(); + + CALL_HAL(cvtHSVtoBGR, cv_hal_cvtHSVtoBGR, src_data, src_step, dst_data, dst_step, width, height, depth, dcn, swapBlue, isFullRange, isHSV); + +#if defined(HAVE_IPP) && IPP_VERSION_X100 >= 700 + CV_IPP_CHECK() + { + if (depth == CV_8U && isFullRange) + { + if (isHSV) + { + if(dcn == 3 && !swapBlue) + { + if( CvtColorIPPLoopCopy(src_data, src_step, CV_MAKETYPE(depth, 3), dst_data, dst_step, width, height, + IPPGeneralReorderFunctor(ippiHSV2RGBTab[depth], ippiSwapChannelsC3RTab[depth], 2, 1, 0, depth)) ) + return; + } + else if(dcn == 4 && !swapBlue) + { + if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPGeneralReorderFunctor(ippiHSV2RGBTab[depth], ippiSwapChannelsC3C4RTab[depth], 2, 1, 0, depth)) ) + return; + } + else if(dcn == 3 && swapBlue) + { + if( CvtColorIPPLoopCopy(src_data, src_step, CV_MAKETYPE(depth, 3), dst_data, dst_step, width, height, + IPPGeneralFunctor(ippiHSV2RGBTab[depth])) ) + return; + } + else if(dcn == 4 && swapBlue) + { + if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPGeneralReorderFunctor(ippiHSV2RGBTab[depth], ippiSwapChannelsC3C4RTab[depth], 0, 1, 2, depth)) ) + return; + } + } + else + { + if(dcn == 3 && !swapBlue) + { + if( CvtColorIPPLoopCopy(src_data, src_step, CV_MAKETYPE(depth, 3), dst_data, dst_step, width, height, + IPPGeneralReorderFunctor(ippiHLS2RGBTab[depth], ippiSwapChannelsC3RTab[depth], 2, 1, 0, depth)) ) + return; + } + else if(dcn == 4 && !swapBlue) + { + if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPGeneralReorderFunctor(ippiHLS2RGBTab[depth], ippiSwapChannelsC3C4RTab[depth], 2, 1, 0, depth)) ) + return; + } + else if(dcn == 3 && swapBlue) + { + if( CvtColorIPPLoopCopy(src_data, src_step, CV_MAKETYPE(depth, 3), dst_data, dst_step, width, height, + IPPGeneralFunctor(ippiHLS2RGBTab[depth])) ) + return; + } + else if(dcn == 4 && swapBlue) + { + if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPGeneralReorderFunctor(ippiHLS2RGBTab[depth], ippiSwapChannelsC3C4RTab[depth], 0, 1, 2, depth)) ) + return; + } + } + } + } +#endif + + CV_CPU_DISPATCH(cvtHSVtoBGR, (src_data, src_step, dst_data, dst_step, width, height, depth, dcn, swapBlue, isFullRange, isHSV), + CV_CPU_DISPATCH_MODES_ALL); +} + +} // namespace hal + +// +// OCL calls +// + +#ifdef HAVE_OPENCL + +bool oclCvtColorHSV2BGR( InputArray _src, OutputArray _dst, int dcn, int bidx, bool full ) +{ + OclHelper< Set<3>, Set<3, 4>, Set > h(_src, _dst, dcn); + + int hrange = _src.depth() == CV_32F ? 360 : (!full ? 180 : 255); + + if(!h.createKernel("HSV2RGB", ocl::imgproc::color_hsv_oclsrc, + format("-D dcn=%d -D bidx=%d -D hrange=%d -D hscale=%ff", dcn, bidx, hrange, 6.f/hrange))) + { + return false; + } + + return h.run(); +} + +bool oclCvtColorHLS2BGR( InputArray _src, OutputArray _dst, int dcn, int bidx, bool full ) +{ + OclHelper< Set<3>, Set<3, 4>, Set > h(_src, _dst, dcn); + + int hrange = _src.depth() == CV_32F ? 360 : (!full ? 180 : 255); + + if(!h.createKernel("HLS2RGB", ocl::imgproc::color_hsv_oclsrc, + format("-D dcn=%d -D bidx=%d -D hrange=%d -D hscale=%ff", dcn, bidx, hrange, 6.f/hrange))) + { + return false; + } + + return h.run(); +} + +bool oclCvtColorBGR2HLS( InputArray _src, OutputArray _dst, int bidx, bool full ) +{ + OclHelper< Set<3, 4>, Set<3>, Set > h(_src, _dst, 3); + + float hscale = (_src.depth() == CV_32F ? 360.f : (!full ? 180.f : 256.f))/360.f; + + if(!h.createKernel("RGB2HLS", ocl::imgproc::color_hsv_oclsrc, + format("-D hscale=%ff -D bidx=%d -D dcn=3", hscale, bidx))) + { + return false; + } + + return h.run(); +} + +bool oclCvtColorBGR2HSV( InputArray _src, OutputArray _dst, int bidx, bool full ) +{ + OclHelper< Set<3, 4>, Set<3>, Set > h(_src, _dst, 3); + + int hrange = _src.depth() == CV_32F ? 360 : (!full ? 180 : 256); + + cv::String options = (_src.depth() == CV_8U ? + format("-D hrange=%d -D bidx=%d -D dcn=3", hrange, bidx) : + format("-D hscale=%ff -D bidx=%d -D dcn=3", hrange*(1.f/360.f), bidx)); + + if(!h.createKernel("RGB2HSV", ocl::imgproc::color_hsv_oclsrc, options)) + { + return false; + } + + if(_src.depth() == CV_8U) + { + static UMat sdiv_data; + static UMat hdiv_data180; + static UMat hdiv_data256; + static int sdiv_table[256]; + static int hdiv_table180[256]; + static int hdiv_table256[256]; + static volatile bool initialized180 = false, initialized256 = false; + volatile bool & initialized = hrange == 180 ? initialized180 : initialized256; + + if (!initialized) + { + int * const hdiv_table = hrange == 180 ? hdiv_table180 : hdiv_table256, hsv_shift = 12; + UMat & hdiv_data = hrange == 180 ? hdiv_data180 : hdiv_data256; + + sdiv_table[0] = hdiv_table180[0] = hdiv_table256[0] = 0; + + int v = 255 << hsv_shift; + if (!initialized180 && !initialized256) + { + for(int i = 1; i < 256; i++ ) + sdiv_table[i] = saturate_cast(v/(1.*i)); + Mat(1, 256, CV_32SC1, sdiv_table).copyTo(sdiv_data); + } + + v = hrange << hsv_shift; + for (int i = 1; i < 256; i++ ) + hdiv_table[i] = saturate_cast(v/(6.*i)); + + Mat(1, 256, CV_32SC1, hdiv_table).copyTo(hdiv_data); + initialized = true; + } + + h.setArg(ocl::KernelArg::PtrReadOnly(sdiv_data)); + h.setArg(hrange == 256 ? ocl::KernelArg::PtrReadOnly(hdiv_data256) : + ocl::KernelArg::PtrReadOnly(hdiv_data180)); + } + + return h.run(); +} + +#endif + +// +// HAL calls +// + +void cvtColorBGR2HLS( InputArray _src, OutputArray _dst, bool swapb, bool fullRange ) +{ + CvtHelper< Set<3, 4>, Set<3>, Set > h(_src, _dst, 3); + + hal::cvtBGRtoHSV(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows, + h.depth, h.scn, swapb, fullRange, false); +} + +void cvtColorBGR2HSV( InputArray _src, OutputArray _dst, bool swapb, bool fullRange ) +{ + CvtHelper< Set<3, 4>, Set<3>, Set > h(_src, _dst, 3); + + hal::cvtBGRtoHSV(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows, + h.depth, h.scn, swapb, fullRange, true); +} + +void cvtColorHLS2BGR( InputArray _src, OutputArray _dst, int dcn, bool swapb, bool fullRange) +{ + if(dcn <= 0) dcn = 3; + CvtHelper< Set<3>, Set<3, 4>, Set > h(_src, _dst, dcn); + + hal::cvtHSVtoBGR(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows, + h.depth, dcn, swapb, fullRange, false); +} + +void cvtColorHSV2BGR( InputArray _src, OutputArray _dst, int dcn, bool swapb, bool fullRange) +{ + if(dcn <= 0) dcn = 3; + CvtHelper< Set<3>, Set<3, 4>, Set > h(_src, _dst, dcn); + + hal::cvtHSVtoBGR(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows, + h.depth, dcn, swapb, fullRange, true); +} + + +} // namespace cv diff --git a/modules/imgproc/src/color_hsv.cpp b/modules/imgproc/src/color_hsv.simd.hpp similarity index 78% rename from modules/imgproc/src/color_hsv.cpp rename to modules/imgproc/src/color_hsv.simd.hpp index f0a4c87558..30ae7064bc 100644 --- a/modules/imgproc/src/color_hsv.cpp +++ b/modules/imgproc/src/color_hsv.simd.hpp @@ -3,11 +3,31 @@ // of this distribution and at http://opencv.org/license.html #include "precomp.hpp" -#include "color.hpp" +#include "opencv2/core/hal/intrin.hpp" -namespace cv -{ +namespace cv { +namespace hal { +CV_CPU_OPTIMIZATION_NAMESPACE_BEGIN +// forward declarations +void cvtBGRtoHSV(const uchar * src_data, size_t src_step, + uchar * dst_data, size_t dst_step, + int width, int height, + int depth, int scn, bool swapBlue, bool isFullRange, bool isHSV); +void cvtHSVtoBGR(const uchar * src_data, size_t src_step, + uchar * dst_data, size_t dst_step, + int width, int height, + int depth, int dcn, bool swapBlue, bool isFullRange, bool isHSV); + +#ifndef CV_CPU_OPTIMIZATION_DECLARATIONS_ONLY + +#if defined(CV_CPU_BASELINE_MODE) +// included in color.hpp +#else +#include "color.simd_helpers.hpp" +#endif + +namespace { ////////////////////////////////////// RGB <-> HSV /////////////////////////////////////// @@ -1192,46 +1212,7 @@ struct HLS2RGB_b #endif }; -// -// IPP functions -// - -#if NEED_IPP - -#if !IPP_DISABLE_RGB_HSV -static ippiGeneralFunc ippiRGB2HSVTab[] = -{ - (ippiGeneralFunc)ippiRGBToHSV_8u_C3R, 0, (ippiGeneralFunc)ippiRGBToHSV_16u_C3R, 0, - 0, 0, 0, 0 -}; -#endif - -static ippiGeneralFunc ippiHSV2RGBTab[] = -{ - (ippiGeneralFunc)ippiHSVToRGB_8u_C3R, 0, (ippiGeneralFunc)ippiHSVToRGB_16u_C3R, 0, - 0, 0, 0, 0 -}; - -static ippiGeneralFunc ippiRGB2HLSTab[] = -{ - (ippiGeneralFunc)ippiRGBToHLS_8u_C3R, 0, (ippiGeneralFunc)ippiRGBToHLS_16u_C3R, 0, - 0, (ippiGeneralFunc)ippiRGBToHLS_32f_C3R, 0, 0 -}; - -static ippiGeneralFunc ippiHLS2RGBTab[] = -{ - (ippiGeneralFunc)ippiHLSToRGB_8u_C3R, 0, (ippiGeneralFunc)ippiHLSToRGB_16u_C3R, 0, - 0, (ippiGeneralFunc)ippiHLSToRGB_32f_C3R, 0, 0 -}; - -#endif - -// -// HAL functions -// - -namespace hal -{ +} // namespace anon // 8u, 32f void cvtBGRtoHSV(const uchar * src_data, size_t src_step, @@ -1241,67 +1222,6 @@ void cvtBGRtoHSV(const uchar * src_data, size_t src_step, { CV_INSTRUMENT_REGION(); - CALL_HAL(cvtBGRtoHSV, cv_hal_cvtBGRtoHSV, src_data, src_step, dst_data, dst_step, width, height, depth, scn, swapBlue, isFullRange, isHSV); - -#if defined(HAVE_IPP) && IPP_VERSION_X100 >= 700 - CV_IPP_CHECK() - { - if(depth == CV_8U && isFullRange) - { - if (isHSV) - { -#if !IPP_DISABLE_RGB_HSV // breaks OCL accuracy tests - if(scn == 3 && !swapBlue) - { - if( CvtColorIPPLoopCopy(src_data, src_step, CV_MAKE_TYPE(depth, scn), dst_data, dst_step, width, height, - IPPReorderGeneralFunctor(ippiSwapChannelsC3RTab[depth], ippiRGB2HSVTab[depth], 2, 1, 0, depth)) ) - return; - } - else if(scn == 4 && !swapBlue) - { - if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, - IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], ippiRGB2HSVTab[depth], 2, 1, 0, depth)) ) - return; - } - else if(scn == 4 && swapBlue) - { - if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, - IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], ippiRGB2HSVTab[depth], 0, 1, 2, depth)) ) - return; - } -#endif - } - else - { - if(scn == 3 && !swapBlue) - { - if( CvtColorIPPLoopCopy(src_data, src_step, CV_MAKE_TYPE(depth, scn), dst_data, dst_step, width, height, - IPPReorderGeneralFunctor(ippiSwapChannelsC3RTab[depth], ippiRGB2HLSTab[depth], 2, 1, 0, depth)) ) - return; - } - else if(scn == 4 && !swapBlue) - { - if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, - IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], ippiRGB2HLSTab[depth], 2, 1, 0, depth)) ) - return; - } - else if(scn == 3 && swapBlue) - { - if( CvtColorIPPLoopCopy(src_data, src_step, CV_MAKE_TYPE(depth, scn), dst_data, dst_step, width, height, - IPPGeneralFunctor(ippiRGB2HLSTab[depth])) ) - return; - } - else if(scn == 4 && swapBlue) - { - if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, - IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], ippiRGB2HLSTab[depth], 0, 1, 2, depth)) ) - return; - } - } - } - } -#endif - int hrange = depth == CV_32F ? 360 : isFullRange ? 256 : 180; int blueIdx = swapBlue ? 2 : 0; if(isHSV) @@ -1322,77 +1242,12 @@ void cvtBGRtoHSV(const uchar * src_data, size_t src_step, // 8u, 32f void cvtHSVtoBGR(const uchar * src_data, size_t src_step, - uchar * dst_data, size_t dst_step, - int width, int height, - int depth, int dcn, bool swapBlue, bool isFullRange, bool isHSV) + uchar * dst_data, size_t dst_step, + int width, int height, + int depth, int dcn, bool swapBlue, bool isFullRange, bool isHSV) { CV_INSTRUMENT_REGION(); - CALL_HAL(cvtHSVtoBGR, cv_hal_cvtHSVtoBGR, src_data, src_step, dst_data, dst_step, width, height, depth, dcn, swapBlue, isFullRange, isHSV); - -#if defined(HAVE_IPP) && IPP_VERSION_X100 >= 700 - CV_IPP_CHECK() - { - if (depth == CV_8U && isFullRange) - { - if (isHSV) - { - if(dcn == 3 && !swapBlue) - { - if( CvtColorIPPLoopCopy(src_data, src_step, CV_MAKETYPE(depth, 3), dst_data, dst_step, width, height, - IPPGeneralReorderFunctor(ippiHSV2RGBTab[depth], ippiSwapChannelsC3RTab[depth], 2, 1, 0, depth)) ) - return; - } - else if(dcn == 4 && !swapBlue) - { - if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, - IPPGeneralReorderFunctor(ippiHSV2RGBTab[depth], ippiSwapChannelsC3C4RTab[depth], 2, 1, 0, depth)) ) - return; - } - else if(dcn == 3 && swapBlue) - { - if( CvtColorIPPLoopCopy(src_data, src_step, CV_MAKETYPE(depth, 3), dst_data, dst_step, width, height, - IPPGeneralFunctor(ippiHSV2RGBTab[depth])) ) - return; - } - else if(dcn == 4 && swapBlue) - { - if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, - IPPGeneralReorderFunctor(ippiHSV2RGBTab[depth], ippiSwapChannelsC3C4RTab[depth], 0, 1, 2, depth)) ) - return; - } - } - else - { - if(dcn == 3 && !swapBlue) - { - if( CvtColorIPPLoopCopy(src_data, src_step, CV_MAKETYPE(depth, 3), dst_data, dst_step, width, height, - IPPGeneralReorderFunctor(ippiHLS2RGBTab[depth], ippiSwapChannelsC3RTab[depth], 2, 1, 0, depth)) ) - return; - } - else if(dcn == 4 && !swapBlue) - { - if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, - IPPGeneralReorderFunctor(ippiHLS2RGBTab[depth], ippiSwapChannelsC3C4RTab[depth], 2, 1, 0, depth)) ) - return; - } - else if(dcn == 3 && swapBlue) - { - if( CvtColorIPPLoopCopy(src_data, src_step, CV_MAKETYPE(depth, 3), dst_data, dst_step, width, height, - IPPGeneralFunctor(ippiHLS2RGBTab[depth])) ) - return; - } - else if(dcn == 4 && swapBlue) - { - if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, - IPPGeneralReorderFunctor(ippiHLS2RGBTab[depth], ippiSwapChannelsC3C4RTab[depth], 0, 1, 2, depth)) ) - return; - } - } - } - } -#endif - int hrange = depth == CV_32F ? 360 : isFullRange ? 255 : 180; int blueIdx = swapBlue ? 2 : 0; if(isHSV) @@ -1411,155 +1266,6 @@ void cvtHSVtoBGR(const uchar * src_data, size_t src_step, } } -} // namespace hal - -// -// OCL calls -// - -#ifdef HAVE_OPENCL - -bool oclCvtColorHSV2BGR( InputArray _src, OutputArray _dst, int dcn, int bidx, bool full ) -{ - OclHelper< Set<3>, Set<3, 4>, Set > h(_src, _dst, dcn); - - int hrange = _src.depth() == CV_32F ? 360 : (!full ? 180 : 255); - - if(!h.createKernel("HSV2RGB", ocl::imgproc::color_hsv_oclsrc, - format("-D dcn=%d -D bidx=%d -D hrange=%d -D hscale=%ff", dcn, bidx, hrange, 6.f/hrange))) - { - return false; - } - - return h.run(); -} - -bool oclCvtColorHLS2BGR( InputArray _src, OutputArray _dst, int dcn, int bidx, bool full ) -{ - OclHelper< Set<3>, Set<3, 4>, Set > h(_src, _dst, dcn); - - int hrange = _src.depth() == CV_32F ? 360 : (!full ? 180 : 255); - - if(!h.createKernel("HLS2RGB", ocl::imgproc::color_hsv_oclsrc, - format("-D dcn=%d -D bidx=%d -D hrange=%d -D hscale=%ff", dcn, bidx, hrange, 6.f/hrange))) - { - return false; - } - - return h.run(); -} - -bool oclCvtColorBGR2HLS( InputArray _src, OutputArray _dst, int bidx, bool full ) -{ - OclHelper< Set<3, 4>, Set<3>, Set > h(_src, _dst, 3); - - float hscale = (_src.depth() == CV_32F ? 360.f : (!full ? 180.f : 256.f))/360.f; - - if(!h.createKernel("RGB2HLS", ocl::imgproc::color_hsv_oclsrc, - format("-D hscale=%ff -D bidx=%d -D dcn=3", hscale, bidx))) - { - return false; - } - - return h.run(); -} - -bool oclCvtColorBGR2HSV( InputArray _src, OutputArray _dst, int bidx, bool full ) -{ - OclHelper< Set<3, 4>, Set<3>, Set > h(_src, _dst, 3); - - int hrange = _src.depth() == CV_32F ? 360 : (!full ? 180 : 256); - - cv::String options = (_src.depth() == CV_8U ? - format("-D hrange=%d -D bidx=%d -D dcn=3", hrange, bidx) : - format("-D hscale=%ff -D bidx=%d -D dcn=3", hrange*(1.f/360.f), bidx)); - - if(!h.createKernel("RGB2HSV", ocl::imgproc::color_hsv_oclsrc, options)) - { - return false; - } - - if(_src.depth() == CV_8U) - { - static UMat sdiv_data; - static UMat hdiv_data180; - static UMat hdiv_data256; - static int sdiv_table[256]; - static int hdiv_table180[256]; - static int hdiv_table256[256]; - static volatile bool initialized180 = false, initialized256 = false; - volatile bool & initialized = hrange == 180 ? initialized180 : initialized256; - - if (!initialized) - { - int * const hdiv_table = hrange == 180 ? hdiv_table180 : hdiv_table256, hsv_shift = 12; - UMat & hdiv_data = hrange == 180 ? hdiv_data180 : hdiv_data256; - - sdiv_table[0] = hdiv_table180[0] = hdiv_table256[0] = 0; - - int v = 255 << hsv_shift; - if (!initialized180 && !initialized256) - { - for(int i = 1; i < 256; i++ ) - sdiv_table[i] = saturate_cast(v/(1.*i)); - Mat(1, 256, CV_32SC1, sdiv_table).copyTo(sdiv_data); - } - - v = hrange << hsv_shift; - for (int i = 1; i < 256; i++ ) - hdiv_table[i] = saturate_cast(v/(6.*i)); - - Mat(1, 256, CV_32SC1, hdiv_table).copyTo(hdiv_data); - initialized = true; - } - - h.setArg(ocl::KernelArg::PtrReadOnly(sdiv_data)); - h.setArg(hrange == 256 ? ocl::KernelArg::PtrReadOnly(hdiv_data256) : - ocl::KernelArg::PtrReadOnly(hdiv_data180)); - } - - return h.run(); -} - #endif - -// -// HAL calls -// - -void cvtColorBGR2HLS( InputArray _src, OutputArray _dst, bool swapb, bool fullRange ) -{ - CvtHelper< Set<3, 4>, Set<3>, Set > h(_src, _dst, 3); - - hal::cvtBGRtoHSV(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows, - h.depth, h.scn, swapb, fullRange, false); -} - -void cvtColorBGR2HSV( InputArray _src, OutputArray _dst, bool swapb, bool fullRange ) -{ - CvtHelper< Set<3, 4>, Set<3>, Set > h(_src, _dst, 3); - - hal::cvtBGRtoHSV(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows, - h.depth, h.scn, swapb, fullRange, true); -} - -void cvtColorHLS2BGR( InputArray _src, OutputArray _dst, int dcn, bool swapb, bool fullRange) -{ - if(dcn <= 0) dcn = 3; - CvtHelper< Set<3>, Set<3, 4>, Set > h(_src, _dst, dcn); - - hal::cvtHSVtoBGR(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows, - h.depth, dcn, swapb, fullRange, false); -} - -void cvtColorHSV2BGR( InputArray _src, OutputArray _dst, int dcn, bool swapb, bool fullRange) -{ - if(dcn <= 0) dcn = 3; - CvtHelper< Set<3>, Set<3, 4>, Set > h(_src, _dst, dcn); - - hal::cvtHSVtoBGR(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows, - h.depth, dcn, swapb, fullRange, true); -} - - -} // namespace cv +CV_CPU_OPTIMIZATION_NAMESPACE_END +}} // namespace diff --git a/modules/imgproc/src/color_lab.cpp b/modules/imgproc/src/color_lab.cpp index 0fff89358c..cb5c0fdf53 100644 --- a/modules/imgproc/src/color_lab.cpp +++ b/modules/imgproc/src/color_lab.cpp @@ -9,6 +9,10 @@ \**********************************************************************************/ #include "precomp.hpp" +#include "opencl_kernels_imgproc.hpp" +#include "opencv2/core/hal/intrin.hpp" +#include "opencv2/core/softfloat.hpp" + #include "color.hpp" using cv::softfloat; diff --git a/modules/imgproc/src/color_rgb.dispatch.cpp b/modules/imgproc/src/color_rgb.dispatch.cpp new file mode 100644 index 0000000000..ed2961f0fb --- /dev/null +++ b/modules/imgproc/src/color_rgb.dispatch.cpp @@ -0,0 +1,619 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html + +#include "precomp.hpp" +#include "opencl_kernels_imgproc.hpp" + +#include "color.hpp" + +#include "color_rgb.simd.hpp" +#include "color_rgb.simd_declarations.hpp" // defines CV_CPU_DISPATCH_MODES_ALL=AVX2,...,BASELINE based on CMakeLists.txt content + +#define IPP_DISABLE_CVTCOLOR_GRAY2BGR_8UC3 1 + +namespace cv { + +// +// IPP functions +// + +#if NEED_IPP + +static const ippiColor2GrayFunc ippiColor2GrayC3Tab[] = +{ + (ippiColor2GrayFunc)ippiColorToGray_8u_C3C1R, 0, (ippiColor2GrayFunc)ippiColorToGray_16u_C3C1R, 0, + 0, (ippiColor2GrayFunc)ippiColorToGray_32f_C3C1R, 0, 0 +}; + +static const ippiColor2GrayFunc ippiColor2GrayC4Tab[] = +{ + (ippiColor2GrayFunc)ippiColorToGray_8u_AC4C1R, 0, (ippiColor2GrayFunc)ippiColorToGray_16u_AC4C1R, 0, + 0, (ippiColor2GrayFunc)ippiColorToGray_32f_AC4C1R, 0, 0 +}; + +static const ippiGeneralFunc ippiRGB2GrayC3Tab[] = +{ + (ippiGeneralFunc)ippiRGBToGray_8u_C3C1R, 0, (ippiGeneralFunc)ippiRGBToGray_16u_C3C1R, 0, + 0, (ippiGeneralFunc)ippiRGBToGray_32f_C3C1R, 0, 0 +}; + +static const ippiGeneralFunc ippiRGB2GrayC4Tab[] = +{ + (ippiGeneralFunc)ippiRGBToGray_8u_AC4C1R, 0, (ippiGeneralFunc)ippiRGBToGray_16u_AC4C1R, 0, + 0, (ippiGeneralFunc)ippiRGBToGray_32f_AC4C1R, 0, 0 +}; + + +#if !IPP_DISABLE_CVTCOLOR_GRAY2BGR_8UC3 +static IppStatus ippiGrayToRGB_C1C3R(const Ipp8u* pSrc, int srcStep, Ipp8u* pDst, int dstStep, IppiSize roiSize) +{ + return CV_INSTRUMENT_FUN_IPP(ippiGrayToRGB_8u_C1C3R, pSrc, srcStep, pDst, dstStep, roiSize); +} +#endif +static IppStatus ippiGrayToRGB_C1C3R(const Ipp16u* pSrc, int srcStep, Ipp16u* pDst, int dstStep, IppiSize roiSize) +{ + return CV_INSTRUMENT_FUN_IPP(ippiGrayToRGB_16u_C1C3R, pSrc, srcStep, pDst, dstStep, roiSize); +} +static IppStatus ippiGrayToRGB_C1C3R(const Ipp32f* pSrc, int srcStep, Ipp32f* pDst, int dstStep, IppiSize roiSize) +{ + return CV_INSTRUMENT_FUN_IPP(ippiGrayToRGB_32f_C1C3R, pSrc, srcStep, pDst, dstStep, roiSize); +} + +static IppStatus ippiGrayToRGB_C1C4R(const Ipp8u* pSrc, int srcStep, Ipp8u* pDst, int dstStep, IppiSize roiSize, Ipp8u aval) +{ + return CV_INSTRUMENT_FUN_IPP(ippiGrayToRGB_8u_C1C4R, pSrc, srcStep, pDst, dstStep, roiSize, aval); +} +static IppStatus ippiGrayToRGB_C1C4R(const Ipp16u* pSrc, int srcStep, Ipp16u* pDst, int dstStep, IppiSize roiSize, Ipp16u aval) +{ + return CV_INSTRUMENT_FUN_IPP(ippiGrayToRGB_16u_C1C4R, pSrc, srcStep, pDst, dstStep, roiSize, aval); +} +static IppStatus ippiGrayToRGB_C1C4R(const Ipp32f* pSrc, int srcStep, Ipp32f* pDst, int dstStep, IppiSize roiSize, Ipp32f aval) +{ + return CV_INSTRUMENT_FUN_IPP(ippiGrayToRGB_32f_C1C4R, pSrc, srcStep, pDst, dstStep, roiSize, aval); +} + +struct IPPColor2GrayFunctor +{ + IPPColor2GrayFunctor(ippiColor2GrayFunc _func) : + ippiColorToGray(_func) + { + coeffs[0] = B2YF; + coeffs[1] = G2YF; + coeffs[2] = R2YF; + } + bool operator()(const void *src, int srcStep, void *dst, int dstStep, int cols, int rows) const + { + return ippiColorToGray ? CV_INSTRUMENT_FUN_IPP(ippiColorToGray, src, srcStep, dst, dstStep, ippiSize(cols, rows), coeffs) >= 0 : false; + } +private: + ippiColor2GrayFunc ippiColorToGray; + Ipp32f coeffs[3]; +}; + +template +struct IPPGray2BGRFunctor +{ + IPPGray2BGRFunctor(){} + + bool operator()(const void *src, int srcStep, void *dst, int dstStep, int cols, int rows) const + { + return ippiGrayToRGB_C1C3R((T*)src, srcStep, (T*)dst, dstStep, ippiSize(cols, rows)) >= 0; + } +}; + +template +struct IPPGray2BGRAFunctor +{ + IPPGray2BGRAFunctor() + { + alpha = ColorChannel::max(); + } + + bool operator()(const void *src, int srcStep, void *dst, int dstStep, int cols, int rows) const + { + return ippiGrayToRGB_C1C4R((T*)src, srcStep, (T*)dst, dstStep, ippiSize(cols, rows), alpha) >= 0; + } + + T alpha; +}; + +static IppStatus CV_STDCALL ippiSwapChannels_8u_C3C4Rf(const Ipp8u* pSrc, int srcStep, Ipp8u* pDst, int dstStep, + IppiSize roiSize, const int *dstOrder) +{ + return CV_INSTRUMENT_FUN_IPP(ippiSwapChannels_8u_C3C4R, pSrc, srcStep, pDst, dstStep, roiSize, dstOrder, MAX_IPP8u); +} + +static IppStatus CV_STDCALL ippiSwapChannels_16u_C3C4Rf(const Ipp16u* pSrc, int srcStep, Ipp16u* pDst, int dstStep, + IppiSize roiSize, const int *dstOrder) +{ + return CV_INSTRUMENT_FUN_IPP(ippiSwapChannels_16u_C3C4R, pSrc, srcStep, pDst, dstStep, roiSize, dstOrder, MAX_IPP16u); +} + +static IppStatus CV_STDCALL ippiSwapChannels_32f_C3C4Rf(const Ipp32f* pSrc, int srcStep, Ipp32f* pDst, int dstStep, + IppiSize roiSize, const int *dstOrder) +{ + return CV_INSTRUMENT_FUN_IPP(ippiSwapChannels_32f_C3C4R, pSrc, srcStep, pDst, dstStep, roiSize, dstOrder, MAX_IPP32f); +} + +// shared +ippiReorderFunc ippiSwapChannelsC3C4RTab[] = +{ + (ippiReorderFunc)ippiSwapChannels_8u_C3C4Rf, 0, (ippiReorderFunc)ippiSwapChannels_16u_C3C4Rf, 0, + 0, (ippiReorderFunc)ippiSwapChannels_32f_C3C4Rf, 0, 0 +}; + +static ippiGeneralFunc ippiCopyAC4C3RTab[] = +{ + (ippiGeneralFunc)ippiCopy_8u_AC4C3R, 0, (ippiGeneralFunc)ippiCopy_16u_AC4C3R, 0, + 0, (ippiGeneralFunc)ippiCopy_32f_AC4C3R, 0, 0 +}; + +// shared +ippiReorderFunc ippiSwapChannelsC4C3RTab[] = +{ + (ippiReorderFunc)ippiSwapChannels_8u_C4C3R, 0, (ippiReorderFunc)ippiSwapChannels_16u_C4C3R, 0, + 0, (ippiReorderFunc)ippiSwapChannels_32f_C4C3R, 0, 0 +}; + +// shared +ippiReorderFunc ippiSwapChannelsC3RTab[] = +{ + (ippiReorderFunc)ippiSwapChannels_8u_C3R, 0, (ippiReorderFunc)ippiSwapChannels_16u_C3R, 0, + 0, (ippiReorderFunc)ippiSwapChannels_32f_C3R, 0, 0 +}; + +#if IPP_VERSION_X100 >= 810 +static ippiReorderFunc ippiSwapChannelsC4RTab[] = +{ + (ippiReorderFunc)ippiSwapChannels_8u_C4R, 0, (ippiReorderFunc)ippiSwapChannels_16u_C4R, 0, + 0, (ippiReorderFunc)ippiSwapChannels_32f_C4R, 0, 0 +}; +#endif + +#endif + +// +// HAL functions +// + +namespace hal { + +// 8u, 16u, 32f +void cvtBGRtoBGR(const uchar * src_data, size_t src_step, + uchar * dst_data, size_t dst_step, + int width, int height, + int depth, int scn, int dcn, bool swapBlue) +{ + CV_INSTRUMENT_REGION(); + + CALL_HAL(cvtBGRtoBGR, cv_hal_cvtBGRtoBGR, src_data, src_step, dst_data, dst_step, width, height, depth, scn, dcn, swapBlue); + +#if defined(HAVE_IPP) && IPP_VERSION_X100 >= 700 + CV_IPP_CHECK() + { + if(scn == 3 && dcn == 4 && !swapBlue) + { + if ( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPReorderFunctor(ippiSwapChannelsC3C4RTab[depth], 0, 1, 2)) ) + return; + } + else if(scn == 4 && dcn == 3 && !swapBlue) + { + if ( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPGeneralFunctor(ippiCopyAC4C3RTab[depth])) ) + return; + } + else if(scn == 3 && dcn == 4 && swapBlue) + { + if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPReorderFunctor(ippiSwapChannelsC3C4RTab[depth], 2, 1, 0)) ) + return; + } + else if(scn == 4 && dcn == 3 && swapBlue) + { + if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPReorderFunctor(ippiSwapChannelsC4C3RTab[depth], 2, 1, 0)) ) + return; + } + else if(scn == 3 && dcn == 3 && swapBlue) + { + if( CvtColorIPPLoopCopy(src_data, src_step, CV_MAKETYPE(depth, scn), dst_data, dst_step, width, height, + IPPReorderFunctor(ippiSwapChannelsC3RTab[depth], 2, 1, 0)) ) + return; + } +#if IPP_VERSION_X100 >= 810 + else if(scn == 4 && dcn == 4 && swapBlue) + { + if( CvtColorIPPLoopCopy(src_data, src_step, CV_MAKETYPE(depth, scn), dst_data, dst_step, width, height, + IPPReorderFunctor(ippiSwapChannelsC4RTab[depth], 2, 1, 0)) ) + return; + } + } +#endif +#endif + + CV_CPU_DISPATCH(cvtBGRtoBGR, (src_data, src_step, dst_data, dst_step, width, height, depth, scn, dcn, swapBlue), + CV_CPU_DISPATCH_MODES_ALL); +} + +// only 8u +void cvtBGRtoBGR5x5(const uchar * src_data, size_t src_step, + uchar * dst_data, size_t dst_step, + int width, int height, + int scn, bool swapBlue, int greenBits) +{ + CV_INSTRUMENT_REGION(); + + CALL_HAL(cvtBGRtoBGR5x5, cv_hal_cvtBGRtoBGR5x5, src_data, src_step, dst_data, dst_step, width, height, scn, swapBlue, greenBits); + + CV_CPU_DISPATCH(cvtBGRtoBGR5x5, (src_data, src_step, dst_data, dst_step, width, height, scn, swapBlue, greenBits), + CV_CPU_DISPATCH_MODES_ALL); +} + +// only 8u +void cvtBGR5x5toBGR(const uchar * src_data, size_t src_step, + uchar * dst_data, size_t dst_step, + int width, int height, + int dcn, bool swapBlue, int greenBits) +{ + CV_INSTRUMENT_REGION(); + + CALL_HAL(cvtBGR5x5toBGR, cv_hal_cvtBGR5x5toBGR, src_data, src_step, dst_data, dst_step, width, height, dcn, swapBlue, greenBits); + + CV_CPU_DISPATCH(cvtBGR5x5toBGR, (src_data, src_step, dst_data, dst_step, width, height, dcn, swapBlue, greenBits), + CV_CPU_DISPATCH_MODES_ALL); +} + +// 8u, 16u, 32f +void cvtBGRtoGray(const uchar * src_data, size_t src_step, + uchar * dst_data, size_t dst_step, + int width, int height, + int depth, int scn, bool swapBlue) +{ + CV_INSTRUMENT_REGION(); + + CALL_HAL(cvtBGRtoGray, cv_hal_cvtBGRtoGray, src_data, src_step, dst_data, dst_step, width, height, depth, scn, swapBlue); + +#if defined(HAVE_IPP) && IPP_VERSION_X100 >= 700 + CV_IPP_CHECK() + { + if(depth == CV_32F && scn == 3 && !swapBlue) + { + if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPColor2GrayFunctor(ippiColor2GrayC3Tab[depth])) ) + return; + } + else if(depth == CV_32F && scn == 3 && swapBlue) + { + if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPGeneralFunctor(ippiRGB2GrayC3Tab[depth])) ) + return; + } + else if(depth == CV_32F && scn == 4 && !swapBlue) + { + if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPColor2GrayFunctor(ippiColor2GrayC4Tab[depth])) ) + return; + } + else if(depth == CV_32F && scn == 4 && swapBlue) + { + if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPGeneralFunctor(ippiRGB2GrayC4Tab[depth])) ) + return; + } + } +#endif + + CV_CPU_DISPATCH(cvtBGRtoGray, (src_data, src_step, dst_data, dst_step, width, height, depth, scn, swapBlue), + CV_CPU_DISPATCH_MODES_ALL); +} + +// 8u, 16u, 32f +void cvtGraytoBGR(const uchar * src_data, size_t src_step, + uchar * dst_data, size_t dst_step, + int width, int height, + int depth, int dcn) +{ + CV_INSTRUMENT_REGION(); + + CALL_HAL(cvtGraytoBGR, cv_hal_cvtGraytoBGR, src_data, src_step, dst_data, dst_step, width, height, depth, dcn); + +#if defined(HAVE_IPP) && IPP_VERSION_X100 >= 700 + CV_IPP_CHECK() + { + bool ippres = false; + if(dcn == 3) + { + if( depth == CV_8U ) + { +#if !IPP_DISABLE_CVTCOLOR_GRAY2BGR_8UC3 + ippres = CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, IPPGray2BGRFunctor()); +#endif + } + else if( depth == CV_16U ) + ippres = CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, IPPGray2BGRFunctor()); + else + ippres = CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, IPPGray2BGRFunctor()); + } + else if(dcn == 4) + { + if( depth == CV_8U ) + ippres = CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, IPPGray2BGRAFunctor()); + else if( depth == CV_16U ) + ippres = CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, IPPGray2BGRAFunctor()); + else + ippres = CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, IPPGray2BGRAFunctor()); + } + if(ippres) + return; + } +#endif + + CV_CPU_DISPATCH(cvtGraytoBGR, (src_data, src_step, dst_data, dst_step, width, height, depth, dcn), + CV_CPU_DISPATCH_MODES_ALL); +} + +// only 8u +void cvtBGR5x5toGray(const uchar * src_data, size_t src_step, + uchar * dst_data, size_t dst_step, + int width, int height, + int greenBits) +{ + CV_INSTRUMENT_REGION(); + + CALL_HAL(cvtBGR5x5toGray, cv_hal_cvtBGR5x5toGray, src_data, src_step, dst_data, dst_step, width, height, greenBits); + + CV_CPU_DISPATCH(cvtBGR5x5toGray, (src_data, src_step, dst_data, dst_step, width, height, greenBits), + CV_CPU_DISPATCH_MODES_ALL); +} + +// only 8u +void cvtGraytoBGR5x5(const uchar * src_data, size_t src_step, + uchar * dst_data, size_t dst_step, + int width, int height, + int greenBits) +{ + CV_INSTRUMENT_REGION(); + + CALL_HAL(cvtGraytoBGR5x5, cv_hal_cvtGraytoBGR5x5, src_data, src_step, dst_data, dst_step, width, height, greenBits); + + CV_CPU_DISPATCH(cvtGraytoBGR5x5, (src_data, src_step, dst_data, dst_step, width, height, greenBits), + CV_CPU_DISPATCH_MODES_ALL); +} + +void cvtRGBAtoMultipliedRGBA(const uchar * src_data, size_t src_step, + uchar * dst_data, size_t dst_step, + int width, int height) +{ + CV_INSTRUMENT_REGION(); + + CALL_HAL(cvtRGBAtoMultipliedRGBA, cv_hal_cvtRGBAtoMultipliedRGBA, src_data, src_step, dst_data, dst_step, width, height); + +#ifdef HAVE_IPP + CV_IPP_CHECK() + { + if (CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPGeneralFunctor((ippiGeneralFunc)ippiAlphaPremul_8u_AC4R))) + return; + } +#endif + + CV_CPU_DISPATCH(cvtRGBAtoMultipliedRGBA, (src_data, src_step, dst_data, dst_step, width, height), + CV_CPU_DISPATCH_MODES_ALL); +} + +void cvtMultipliedRGBAtoRGBA(const uchar * src_data, size_t src_step, + uchar * dst_data, size_t dst_step, + int width, int height) +{ + CV_INSTRUMENT_REGION(); + + CALL_HAL(cvtMultipliedRGBAtoRGBA, cv_hal_cvtMultipliedRGBAtoRGBA, src_data, src_step, dst_data, dst_step, width, height); + + CV_CPU_DISPATCH(cvtMultipliedRGBAtoRGBA, (src_data, src_step, dst_data, dst_step, width, height), + CV_CPU_DISPATCH_MODES_ALL); +} + +} // namespace hal + +// +// OCL calls +// + +#ifdef HAVE_OPENCL + +bool oclCvtColorBGR2BGR( InputArray _src, OutputArray _dst, int dcn, bool reverse ) +{ + OclHelper< Set<3, 4>, Set<3, 4>, Set > h(_src, _dst, dcn); + + if(!h.createKernel("RGB", ocl::imgproc::color_rgb_oclsrc, + format("-D dcn=%d -D bidx=0 -D %s", dcn, reverse ? "REVERSE" : "ORDER"))) + { + return false; + } + + return h.run(); +} + +bool oclCvtColorBGR25x5( InputArray _src, OutputArray _dst, int bidx, int gbits ) +{ + OclHelper< Set<3, 4>, Set<2>, Set > h(_src, _dst, 2); + + if(!h.createKernel("RGB2RGB5x5", ocl::imgproc::color_rgb_oclsrc, + format("-D dcn=2 -D bidx=%d -D greenbits=%d", bidx, gbits))) + { + return false; + } + + return h.run(); +} + +bool oclCvtColor5x52BGR( InputArray _src, OutputArray _dst, int dcn, int bidx, int gbits) +{ + OclHelper< Set<2>, Set<3, 4>, Set > h(_src, _dst, dcn); + + if(!h.createKernel("RGB5x52RGB", ocl::imgproc::color_rgb_oclsrc, + format("-D dcn=%d -D bidx=%d -D greenbits=%d", dcn, bidx, gbits))) + { + return false; + } + + return h.run(); +} + +bool oclCvtColor5x52Gray( InputArray _src, OutputArray _dst, int gbits) +{ + OclHelper< Set<2>, Set<1>, Set > h(_src, _dst, 1); + + if(!h.createKernel("BGR5x52Gray", ocl::imgproc::color_rgb_oclsrc, + format("-D dcn=1 -D bidx=0 -D greenbits=%d", gbits))) + { + return false; + } + + return h.run(); +} + +bool oclCvtColorGray25x5( InputArray _src, OutputArray _dst, int gbits) +{ + OclHelper< Set<1>, Set<2>, Set > h(_src, _dst, 2); + + if(!h.createKernel("Gray2BGR5x5", ocl::imgproc::color_rgb_oclsrc, + format("-D dcn=2 -D bidx=0 -D greenbits=%d", gbits))) + { + return false; + } + + return h.run(); +} + +bool oclCvtColorBGR2Gray( InputArray _src, OutputArray _dst, int bidx) +{ + OclHelper< Set<3, 4>, Set<1>, Set > h(_src, _dst, 1); + + int stripeSize = 1; + if(!h.createKernel("RGB2Gray", ocl::imgproc::color_rgb_oclsrc, + format("-D dcn=1 -D bidx=%d -D STRIPE_SIZE=%d", bidx, stripeSize))) + { + return false; + } + + h.globalSize[0] = (h.src.cols + stripeSize - 1)/stripeSize; + return h.run(); +} + +bool oclCvtColorGray2BGR( InputArray _src, OutputArray _dst, int dcn) +{ + OclHelper< Set<1>, Set<3, 4>, Set > h(_src, _dst, dcn); + if(!h.createKernel("Gray2RGB", ocl::imgproc::color_rgb_oclsrc, + format("-D bidx=0 -D dcn=%d", dcn))) + { + return false; + } + + return h.run(); +} + +bool oclCvtColorRGBA2mRGBA( InputArray _src, OutputArray _dst) +{ + OclHelper< Set<4>, Set<4>, Set > h(_src, _dst, 4); + + if(!h.createKernel("RGBA2mRGBA", ocl::imgproc::color_rgb_oclsrc, + "-D dcn=4 -D bidx=3")) + { + return false; + } + + return h.run(); +} + +bool oclCvtColormRGBA2RGBA( InputArray _src, OutputArray _dst) +{ + OclHelper< Set<4>, Set<4>, Set > h(_src, _dst, 4); + + if(!h.createKernel("mRGBA2RGBA", ocl::imgproc::color_rgb_oclsrc, + "-D dcn=4 -D bidx=3")) + { + return false; + } + + return h.run(); +} + +#endif + +// +// HAL calls +// + +void cvtColorBGR2BGR( InputArray _src, OutputArray _dst, int dcn, bool swapb) +{ + CvtHelper< Set<3, 4>, Set<3, 4>, Set > h(_src, _dst, dcn); + + hal::cvtBGRtoBGR(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows, + h.depth, h.scn, dcn, swapb); +} + +void cvtColorBGR25x5( InputArray _src, OutputArray _dst, bool swapb, int gbits) +{ + CvtHelper< Set<3, 4>, Set<2>, Set > h(_src, _dst, 2); + + hal::cvtBGRtoBGR5x5(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows, + h.scn, swapb, gbits); +} + +void cvtColor5x52BGR( InputArray _src, OutputArray _dst, int dcn, bool swapb, int gbits) +{ + if(dcn <= 0) dcn = 3; + CvtHelper< Set<2>, Set<3, 4>, Set > h(_src, _dst, dcn); + + hal::cvtBGR5x5toBGR(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows, + dcn, swapb, gbits); +} + +void cvtColorBGR2Gray( InputArray _src, OutputArray _dst, bool swapb) +{ + CvtHelper< Set<3, 4>, Set<1>, Set > h(_src, _dst, 1); + + hal::cvtBGRtoGray(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows, + h.depth, h.scn, swapb); +} + +void cvtColorGray2BGR( InputArray _src, OutputArray _dst, int dcn) +{ + if(dcn <= 0) dcn = 3; + CvtHelper< Set<1>, Set<3, 4>, Set > h(_src, _dst, dcn); + + hal::cvtGraytoBGR(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows, h.depth, dcn); +} + +void cvtColor5x52Gray( InputArray _src, OutputArray _dst, int gbits) +{ + CvtHelper< Set<2>, Set<1>, Set > h(_src, _dst, 1); + + hal::cvtBGR5x5toGray(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows, gbits); +} + +void cvtColorGray25x5( InputArray _src, OutputArray _dst, int gbits) +{ + CvtHelper< Set<1>, Set<2>, Set > h(_src, _dst, 2); + + hal::cvtGraytoBGR5x5(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows, gbits); +} + +void cvtColorRGBA2mRGBA( InputArray _src, OutputArray _dst) +{ + CvtHelper< Set<4>, Set<4>, Set > h(_src, _dst, 4); + + hal::cvtRGBAtoMultipliedRGBA(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows); +} + +void cvtColormRGBA2RGBA( InputArray _src, OutputArray _dst) +{ + CvtHelper< Set<4>, Set<4>, Set > h(_src, _dst, 4); + + hal::cvtMultipliedRGBAtoRGBA(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows); +} + +} // namespace cv diff --git a/modules/imgproc/src/color_rgb.cpp b/modules/imgproc/src/color_rgb.simd.hpp similarity index 65% rename from modules/imgproc/src/color_rgb.cpp rename to modules/imgproc/src/color_rgb.simd.hpp index 9245f26d05..76dc4e5e1e 100644 --- a/modules/imgproc/src/color_rgb.cpp +++ b/modules/imgproc/src/color_rgb.simd.hpp @@ -3,13 +3,58 @@ // of this distribution and at http://opencv.org/license.html #include "precomp.hpp" -#include "color.hpp" +#include "opencv2/core/hal/intrin.hpp" -#define IPP_DISABLE_CVTCOLOR_GRAY2BGR_8UC3 1 +namespace cv { +namespace hal { +CV_CPU_OPTIMIZATION_NAMESPACE_BEGIN +// forward declarations -namespace cv -{ +void cvtBGRtoBGR(const uchar * src_data, size_t src_step, + uchar * dst_data, size_t dst_step, + int width, int height, + int depth, int scn, int dcn, bool swapBlue); +void cvtBGRtoBGR5x5(const uchar * src_data, size_t src_step, + uchar * dst_data, size_t dst_step, + int width, int height, + int scn, bool swapBlue, int greenBits); +void cvtBGR5x5toBGR(const uchar * src_data, size_t src_step, + uchar * dst_data, size_t dst_step, + int width, int height, + int dcn, bool swapBlue, int greenBits); +void cvtBGRtoGray(const uchar * src_data, size_t src_step, + uchar * dst_data, size_t dst_step, + int width, int height, + int depth, int scn, bool swapBlue); +void cvtGraytoBGR(const uchar * src_data, size_t src_step, + uchar * dst_data, size_t dst_step, + int width, int height, + int depth, int dcn); +void cvtBGR5x5toGray(const uchar * src_data, size_t src_step, + uchar * dst_data, size_t dst_step, + int width, int height, + int greenBits); +void cvtGraytoBGR5x5(const uchar * src_data, size_t src_step, + uchar * dst_data, size_t dst_step, + int width, int height, + int greenBits); +void cvtRGBAtoMultipliedRGBA(const uchar * src_data, size_t src_step, + uchar * dst_data, size_t dst_step, + int width, int height); +void cvtMultipliedRGBAtoRGBA(const uchar * src_data, size_t src_step, + uchar * dst_data, size_t dst_step, + int width, int height); + +#ifndef CV_CPU_OPTIMIZATION_DECLARATIONS_ONLY + +#if defined(CV_CPU_BASELINE_MODE) +// included in color.hpp +#else +#include "color.simd_helpers.hpp" +#endif + +namespace { ////////////////// Various 3/4-channel to 3/4-channel RGB transformations ///////////////// template struct v_type; @@ -1044,172 +1089,7 @@ struct mRGBA2RGBA } } }; - -// -// IPP functions -// - -#if NEED_IPP - -static ippiColor2GrayFunc ippiColor2GrayC3Tab[] = -{ - (ippiColor2GrayFunc)ippiColorToGray_8u_C3C1R, 0, (ippiColor2GrayFunc)ippiColorToGray_16u_C3C1R, 0, - 0, (ippiColor2GrayFunc)ippiColorToGray_32f_C3C1R, 0, 0 -}; - -static ippiColor2GrayFunc ippiColor2GrayC4Tab[] = -{ - (ippiColor2GrayFunc)ippiColorToGray_8u_AC4C1R, 0, (ippiColor2GrayFunc)ippiColorToGray_16u_AC4C1R, 0, - 0, (ippiColor2GrayFunc)ippiColorToGray_32f_AC4C1R, 0, 0 -}; - -static ippiGeneralFunc ippiRGB2GrayC3Tab[] = -{ - (ippiGeneralFunc)ippiRGBToGray_8u_C3C1R, 0, (ippiGeneralFunc)ippiRGBToGray_16u_C3C1R, 0, - 0, (ippiGeneralFunc)ippiRGBToGray_32f_C3C1R, 0, 0 -}; - -static ippiGeneralFunc ippiRGB2GrayC4Tab[] = -{ - (ippiGeneralFunc)ippiRGBToGray_8u_AC4C1R, 0, (ippiGeneralFunc)ippiRGBToGray_16u_AC4C1R, 0, - 0, (ippiGeneralFunc)ippiRGBToGray_32f_AC4C1R, 0, 0 -}; - - -#if !IPP_DISABLE_CVTCOLOR_GRAY2BGR_8UC3 -static IppStatus ippiGrayToRGB_C1C3R(const Ipp8u* pSrc, int srcStep, Ipp8u* pDst, int dstStep, IppiSize roiSize) -{ - return CV_INSTRUMENT_FUN_IPP(ippiGrayToRGB_8u_C1C3R, pSrc, srcStep, pDst, dstStep, roiSize); -} -#endif -static IppStatus ippiGrayToRGB_C1C3R(const Ipp16u* pSrc, int srcStep, Ipp16u* pDst, int dstStep, IppiSize roiSize) -{ - return CV_INSTRUMENT_FUN_IPP(ippiGrayToRGB_16u_C1C3R, pSrc, srcStep, pDst, dstStep, roiSize); -} -static IppStatus ippiGrayToRGB_C1C3R(const Ipp32f* pSrc, int srcStep, Ipp32f* pDst, int dstStep, IppiSize roiSize) -{ - return CV_INSTRUMENT_FUN_IPP(ippiGrayToRGB_32f_C1C3R, pSrc, srcStep, pDst, dstStep, roiSize); -} - -static IppStatus ippiGrayToRGB_C1C4R(const Ipp8u* pSrc, int srcStep, Ipp8u* pDst, int dstStep, IppiSize roiSize, Ipp8u aval) -{ - return CV_INSTRUMENT_FUN_IPP(ippiGrayToRGB_8u_C1C4R, pSrc, srcStep, pDst, dstStep, roiSize, aval); -} -static IppStatus ippiGrayToRGB_C1C4R(const Ipp16u* pSrc, int srcStep, Ipp16u* pDst, int dstStep, IppiSize roiSize, Ipp16u aval) -{ - return CV_INSTRUMENT_FUN_IPP(ippiGrayToRGB_16u_C1C4R, pSrc, srcStep, pDst, dstStep, roiSize, aval); -} -static IppStatus ippiGrayToRGB_C1C4R(const Ipp32f* pSrc, int srcStep, Ipp32f* pDst, int dstStep, IppiSize roiSize, Ipp32f aval) -{ - return CV_INSTRUMENT_FUN_IPP(ippiGrayToRGB_32f_C1C4R, pSrc, srcStep, pDst, dstStep, roiSize, aval); -} - -struct IPPColor2GrayFunctor -{ - IPPColor2GrayFunctor(ippiColor2GrayFunc _func) : - ippiColorToGray(_func) - { - coeffs[0] = B2YF; - coeffs[1] = G2YF; - coeffs[2] = R2YF; - } - bool operator()(const void *src, int srcStep, void *dst, int dstStep, int cols, int rows) const - { - return ippiColorToGray ? CV_INSTRUMENT_FUN_IPP(ippiColorToGray, src, srcStep, dst, dstStep, ippiSize(cols, rows), coeffs) >= 0 : false; - } -private: - ippiColor2GrayFunc ippiColorToGray; - Ipp32f coeffs[3]; -}; - -template -struct IPPGray2BGRFunctor -{ - IPPGray2BGRFunctor(){} - - bool operator()(const void *src, int srcStep, void *dst, int dstStep, int cols, int rows) const - { - return ippiGrayToRGB_C1C3R((T*)src, srcStep, (T*)dst, dstStep, ippiSize(cols, rows)) >= 0; - } -}; - -template -struct IPPGray2BGRAFunctor -{ - IPPGray2BGRAFunctor() - { - alpha = ColorChannel::max(); - } - - bool operator()(const void *src, int srcStep, void *dst, int dstStep, int cols, int rows) const - { - return ippiGrayToRGB_C1C4R((T*)src, srcStep, (T*)dst, dstStep, ippiSize(cols, rows), alpha) >= 0; - } - - T alpha; -}; - -static IppStatus CV_STDCALL ippiSwapChannels_8u_C3C4Rf(const Ipp8u* pSrc, int srcStep, Ipp8u* pDst, int dstStep, - IppiSize roiSize, const int *dstOrder) -{ - return CV_INSTRUMENT_FUN_IPP(ippiSwapChannels_8u_C3C4R, pSrc, srcStep, pDst, dstStep, roiSize, dstOrder, MAX_IPP8u); -} - -static IppStatus CV_STDCALL ippiSwapChannels_16u_C3C4Rf(const Ipp16u* pSrc, int srcStep, Ipp16u* pDst, int dstStep, - IppiSize roiSize, const int *dstOrder) -{ - return CV_INSTRUMENT_FUN_IPP(ippiSwapChannels_16u_C3C4R, pSrc, srcStep, pDst, dstStep, roiSize, dstOrder, MAX_IPP16u); -} - -static IppStatus CV_STDCALL ippiSwapChannels_32f_C3C4Rf(const Ipp32f* pSrc, int srcStep, Ipp32f* pDst, int dstStep, - IppiSize roiSize, const int *dstOrder) -{ - return CV_INSTRUMENT_FUN_IPP(ippiSwapChannels_32f_C3C4R, pSrc, srcStep, pDst, dstStep, roiSize, dstOrder, MAX_IPP32f); -} - -// shared -ippiReorderFunc ippiSwapChannelsC3C4RTab[] = -{ - (ippiReorderFunc)ippiSwapChannels_8u_C3C4Rf, 0, (ippiReorderFunc)ippiSwapChannels_16u_C3C4Rf, 0, - 0, (ippiReorderFunc)ippiSwapChannels_32f_C3C4Rf, 0, 0 -}; - -static ippiGeneralFunc ippiCopyAC4C3RTab[] = -{ - (ippiGeneralFunc)ippiCopy_8u_AC4C3R, 0, (ippiGeneralFunc)ippiCopy_16u_AC4C3R, 0, - 0, (ippiGeneralFunc)ippiCopy_32f_AC4C3R, 0, 0 -}; - -// shared -ippiReorderFunc ippiSwapChannelsC4C3RTab[] = -{ - (ippiReorderFunc)ippiSwapChannels_8u_C4C3R, 0, (ippiReorderFunc)ippiSwapChannels_16u_C4C3R, 0, - 0, (ippiReorderFunc)ippiSwapChannels_32f_C4C3R, 0, 0 -}; - -// shared -ippiReorderFunc ippiSwapChannelsC3RTab[] = -{ - (ippiReorderFunc)ippiSwapChannels_8u_C3R, 0, (ippiReorderFunc)ippiSwapChannels_16u_C3R, 0, - 0, (ippiReorderFunc)ippiSwapChannels_32f_C3R, 0, 0 -}; - -#if IPP_VERSION_X100 >= 810 -static ippiReorderFunc ippiSwapChannelsC4RTab[] = -{ - (ippiReorderFunc)ippiSwapChannels_8u_C4R, 0, (ippiReorderFunc)ippiSwapChannels_16u_C4R, 0, - 0, (ippiReorderFunc)ippiSwapChannels_32f_C4R, 0, 0 -}; -#endif - -#endif - -// -// HAL functions -// - -namespace hal -{ +} // namespace anon // 8u, 16u, 32f void cvtBGRtoBGR(const uchar * src_data, size_t src_step, @@ -1219,52 +1099,6 @@ void cvtBGRtoBGR(const uchar * src_data, size_t src_step, { CV_INSTRUMENT_REGION(); - CALL_HAL(cvtBGRtoBGR, cv_hal_cvtBGRtoBGR, src_data, src_step, dst_data, dst_step, width, height, depth, scn, dcn, swapBlue); - -#if defined(HAVE_IPP) && IPP_VERSION_X100 >= 700 - CV_IPP_CHECK() - { - if(scn == 3 && dcn == 4 && !swapBlue) - { - if ( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, - IPPReorderFunctor(ippiSwapChannelsC3C4RTab[depth], 0, 1, 2)) ) - return; - } - else if(scn == 4 && dcn == 3 && !swapBlue) - { - if ( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, - IPPGeneralFunctor(ippiCopyAC4C3RTab[depth])) ) - return; - } - else if(scn == 3 && dcn == 4 && swapBlue) - { - if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, - IPPReorderFunctor(ippiSwapChannelsC3C4RTab[depth], 2, 1, 0)) ) - return; - } - else if(scn == 4 && dcn == 3 && swapBlue) - { - if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, - IPPReorderFunctor(ippiSwapChannelsC4C3RTab[depth], 2, 1, 0)) ) - return; - } - else if(scn == 3 && dcn == 3 && swapBlue) - { - if( CvtColorIPPLoopCopy(src_data, src_step, CV_MAKETYPE(depth, scn), dst_data, dst_step, width, height, - IPPReorderFunctor(ippiSwapChannelsC3RTab[depth], 2, 1, 0)) ) - return; - } -#if IPP_VERSION_X100 >= 810 - else if(scn == 4 && dcn == 4 && swapBlue) - { - if( CvtColorIPPLoopCopy(src_data, src_step, CV_MAKETYPE(depth, scn), dst_data, dst_step, width, height, - IPPReorderFunctor(ippiSwapChannelsC4RTab[depth], 2, 1, 0)) ) - return; - } - } -#endif -#endif - int blueIdx = swapBlue ? 2 : 0; if( depth == CV_8U ) CvtColorLoop(src_data, src_step, dst_data, dst_step, width, height, RGB2RGB(scn, dcn, blueIdx)); @@ -1282,8 +1116,6 @@ void cvtBGRtoBGR5x5(const uchar * src_data, size_t src_step, { CV_INSTRUMENT_REGION(); - CALL_HAL(cvtBGRtoBGR5x5, cv_hal_cvtBGRtoBGR5x5, src_data, src_step, dst_data, dst_step, width, height, scn, swapBlue, greenBits); - CvtColorLoop(src_data, src_step, dst_data, dst_step, width, height, RGB2RGB5x5(scn, swapBlue ? 2 : 0, greenBits)); } @@ -1295,8 +1127,6 @@ void cvtBGR5x5toBGR(const uchar * src_data, size_t src_step, { CV_INSTRUMENT_REGION(); - CALL_HAL(cvtBGR5x5toBGR, cv_hal_cvtBGR5x5toBGR, src_data, src_step, dst_data, dst_step, width, height, dcn, swapBlue, greenBits); - CvtColorLoop(src_data, src_step, dst_data, dst_step, width, height, RGB5x52RGB(dcn, swapBlue ? 2 : 0, greenBits)); } @@ -1308,38 +1138,6 @@ void cvtBGRtoGray(const uchar * src_data, size_t src_step, { CV_INSTRUMENT_REGION(); - CALL_HAL(cvtBGRtoGray, cv_hal_cvtBGRtoGray, src_data, src_step, dst_data, dst_step, width, height, depth, scn, swapBlue); - -#if defined(HAVE_IPP) && IPP_VERSION_X100 >= 700 - CV_IPP_CHECK() - { - if(depth == CV_32F && scn == 3 && !swapBlue) - { - if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, - IPPColor2GrayFunctor(ippiColor2GrayC3Tab[depth])) ) - return; - } - else if(depth == CV_32F && scn == 3 && swapBlue) - { - if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, - IPPGeneralFunctor(ippiRGB2GrayC3Tab[depth])) ) - return; - } - else if(depth == CV_32F && scn == 4 && !swapBlue) - { - if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, - IPPColor2GrayFunctor(ippiColor2GrayC4Tab[depth])) ) - return; - } - else if(depth == CV_32F && scn == 4 && swapBlue) - { - if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, - IPPGeneralFunctor(ippiRGB2GrayC4Tab[depth])) ) - return; - } - } -#endif - int blueIdx = swapBlue ? 2 : 0; if( depth == CV_8U ) CvtColorLoop(src_data, src_step, dst_data, dst_step, width, height, RGB2Gray(scn, blueIdx, 0)); @@ -1357,39 +1155,6 @@ void cvtGraytoBGR(const uchar * src_data, size_t src_step, { CV_INSTRUMENT_REGION(); - CALL_HAL(cvtGraytoBGR, cv_hal_cvtGraytoBGR, src_data, src_step, dst_data, dst_step, width, height, depth, dcn); - -#if defined(HAVE_IPP) && IPP_VERSION_X100 >= 700 - CV_IPP_CHECK() - { - bool ippres = false; - if(dcn == 3) - { - if( depth == CV_8U ) - { -#if !IPP_DISABLE_CVTCOLOR_GRAY2BGR_8UC3 - ippres = CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, IPPGray2BGRFunctor()); -#endif - } - else if( depth == CV_16U ) - ippres = CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, IPPGray2BGRFunctor()); - else - ippres = CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, IPPGray2BGRFunctor()); - } - else if(dcn == 4) - { - if( depth == CV_8U ) - ippres = CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, IPPGray2BGRAFunctor()); - else if( depth == CV_16U ) - ippres = CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, IPPGray2BGRAFunctor()); - else - ippres = CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, IPPGray2BGRAFunctor()); - } - if(ippres) - return; - } -#endif - if( depth == CV_8U ) CvtColorLoop(src_data, src_step, dst_data, dst_step, width, height, Gray2RGB(dcn)); else if( depth == CV_16U ) @@ -1406,7 +1171,6 @@ void cvtBGR5x5toGray(const uchar * src_data, size_t src_step, { CV_INSTRUMENT_REGION(); - CALL_HAL(cvtBGR5x5toGray, cv_hal_cvtBGR5x5toGray, src_data, src_step, dst_data, dst_step, width, height, greenBits); CvtColorLoop(src_data, src_step, dst_data, dst_step, width, height, RGB5x52Gray(greenBits)); } @@ -1418,7 +1182,6 @@ void cvtGraytoBGR5x5(const uchar * src_data, size_t src_step, { CV_INSTRUMENT_REGION(); - CALL_HAL(cvtGraytoBGR5x5, cv_hal_cvtGraytoBGR5x5, src_data, src_step, dst_data, dst_step, width, height, greenBits); CvtColorLoop(src_data, src_step, dst_data, dst_step, width, height, Gray2RGB5x5(greenBits)); } @@ -1428,17 +1191,6 @@ void cvtRGBAtoMultipliedRGBA(const uchar * src_data, size_t src_step, { CV_INSTRUMENT_REGION(); - CALL_HAL(cvtRGBAtoMultipliedRGBA, cv_hal_cvtRGBAtoMultipliedRGBA, src_data, src_step, dst_data, dst_step, width, height); - -#ifdef HAVE_IPP - CV_IPP_CHECK() - { - if (CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, - IPPGeneralFunctor((ippiGeneralFunc)ippiAlphaPremul_8u_AC4R))) - return; - } -#endif - CvtColorLoop(src_data, src_step, dst_data, dst_step, width, height, RGBA2mRGBA()); } @@ -1448,209 +1200,9 @@ void cvtMultipliedRGBAtoRGBA(const uchar * src_data, size_t src_step, { CV_INSTRUMENT_REGION(); - CALL_HAL(cvtMultipliedRGBAtoRGBA, cv_hal_cvtMultipliedRGBAtoRGBA, src_data, src_step, dst_data, dst_step, width, height); CvtColorLoop(src_data, src_step, dst_data, dst_step, width, height, mRGBA2RGBA()); } -} // namespace hal - -// -// OCL calls -// - -#ifdef HAVE_OPENCL - -bool oclCvtColorBGR2BGR( InputArray _src, OutputArray _dst, int dcn, bool reverse ) -{ - OclHelper< Set<3, 4>, Set<3, 4>, Set > h(_src, _dst, dcn); - - if(!h.createKernel("RGB", ocl::imgproc::color_rgb_oclsrc, - format("-D dcn=%d -D bidx=0 -D %s", dcn, reverse ? "REVERSE" : "ORDER"))) - { - return false; - } - - return h.run(); -} - -bool oclCvtColorBGR25x5( InputArray _src, OutputArray _dst, int bidx, int gbits ) -{ - OclHelper< Set<3, 4>, Set<2>, Set > h(_src, _dst, 2); - - if(!h.createKernel("RGB2RGB5x5", ocl::imgproc::color_rgb_oclsrc, - format("-D dcn=2 -D bidx=%d -D greenbits=%d", bidx, gbits))) - { - return false; - } - - return h.run(); -} - -bool oclCvtColor5x52BGR( InputArray _src, OutputArray _dst, int dcn, int bidx, int gbits) -{ - OclHelper< Set<2>, Set<3, 4>, Set > h(_src, _dst, dcn); - - if(!h.createKernel("RGB5x52RGB", ocl::imgproc::color_rgb_oclsrc, - format("-D dcn=%d -D bidx=%d -D greenbits=%d", dcn, bidx, gbits))) - { - return false; - } - - return h.run(); -} - -bool oclCvtColor5x52Gray( InputArray _src, OutputArray _dst, int gbits) -{ - OclHelper< Set<2>, Set<1>, Set > h(_src, _dst, 1); - - if(!h.createKernel("BGR5x52Gray", ocl::imgproc::color_rgb_oclsrc, - format("-D dcn=1 -D bidx=0 -D greenbits=%d", gbits))) - { - return false; - } - - return h.run(); -} - -bool oclCvtColorGray25x5( InputArray _src, OutputArray _dst, int gbits) -{ - OclHelper< Set<1>, Set<2>, Set > h(_src, _dst, 2); - - if(!h.createKernel("Gray2BGR5x5", ocl::imgproc::color_rgb_oclsrc, - format("-D dcn=2 -D bidx=0 -D greenbits=%d", gbits))) - { - return false; - } - - return h.run(); -} - -bool oclCvtColorBGR2Gray( InputArray _src, OutputArray _dst, int bidx) -{ - OclHelper< Set<3, 4>, Set<1>, Set > h(_src, _dst, 1); - - int stripeSize = 1; - if(!h.createKernel("RGB2Gray", ocl::imgproc::color_rgb_oclsrc, - format("-D dcn=1 -D bidx=%d -D STRIPE_SIZE=%d", bidx, stripeSize))) - { - return false; - } - - h.globalSize[0] = (h.src.cols + stripeSize - 1)/stripeSize; - return h.run(); -} - -bool oclCvtColorGray2BGR( InputArray _src, OutputArray _dst, int dcn) -{ - OclHelper< Set<1>, Set<3, 4>, Set > h(_src, _dst, dcn); - if(!h.createKernel("Gray2RGB", ocl::imgproc::color_rgb_oclsrc, - format("-D bidx=0 -D dcn=%d", dcn))) - { - return false; - } - - return h.run(); -} - -bool oclCvtColorRGBA2mRGBA( InputArray _src, OutputArray _dst) -{ - OclHelper< Set<4>, Set<4>, Set > h(_src, _dst, 4); - - if(!h.createKernel("RGBA2mRGBA", ocl::imgproc::color_rgb_oclsrc, - "-D dcn=4 -D bidx=3")) - { - return false; - } - - return h.run(); -} - -bool oclCvtColormRGBA2RGBA( InputArray _src, OutputArray _dst) -{ - OclHelper< Set<4>, Set<4>, Set > h(_src, _dst, 4); - - if(!h.createKernel("mRGBA2RGBA", ocl::imgproc::color_rgb_oclsrc, - "-D dcn=4 -D bidx=3")) - { - return false; - } - - return h.run(); -} - #endif - -// -// HAL calls -// - -void cvtColorBGR2BGR( InputArray _src, OutputArray _dst, int dcn, bool swapb) -{ - CvtHelper< Set<3, 4>, Set<3, 4>, Set > h(_src, _dst, dcn); - - hal::cvtBGRtoBGR(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows, - h.depth, h.scn, dcn, swapb); -} - -void cvtColorBGR25x5( InputArray _src, OutputArray _dst, bool swapb, int gbits) -{ - CvtHelper< Set<3, 4>, Set<2>, Set > h(_src, _dst, 2); - - hal::cvtBGRtoBGR5x5(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows, - h.scn, swapb, gbits); -} - -void cvtColor5x52BGR( InputArray _src, OutputArray _dst, int dcn, bool swapb, int gbits) -{ - if(dcn <= 0) dcn = 3; - CvtHelper< Set<2>, Set<3, 4>, Set > h(_src, _dst, dcn); - - hal::cvtBGR5x5toBGR(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows, - dcn, swapb, gbits); -} - -void cvtColorBGR2Gray( InputArray _src, OutputArray _dst, bool swapb) -{ - CvtHelper< Set<3, 4>, Set<1>, Set > h(_src, _dst, 1); - - hal::cvtBGRtoGray(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows, - h.depth, h.scn, swapb); -} - -void cvtColorGray2BGR( InputArray _src, OutputArray _dst, int dcn) -{ - if(dcn <= 0) dcn = 3; - CvtHelper< Set<1>, Set<3, 4>, Set > h(_src, _dst, dcn); - - hal::cvtGraytoBGR(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows, h.depth, dcn); -} - -void cvtColor5x52Gray( InputArray _src, OutputArray _dst, int gbits) -{ - CvtHelper< Set<2>, Set<1>, Set > h(_src, _dst, 1); - - hal::cvtBGR5x5toGray(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows, gbits); -} - -void cvtColorGray25x5( InputArray _src, OutputArray _dst, int gbits) -{ - CvtHelper< Set<1>, Set<2>, Set > h(_src, _dst, 2); - - hal::cvtGraytoBGR5x5(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows, gbits); -} - -void cvtColorRGBA2mRGBA( InputArray _src, OutputArray _dst) -{ - CvtHelper< Set<4>, Set<4>, Set > h(_src, _dst, 4); - - hal::cvtRGBAtoMultipliedRGBA(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows); -} - -void cvtColormRGBA2RGBA( InputArray _src, OutputArray _dst) -{ - CvtHelper< Set<4>, Set<4>, Set > h(_src, _dst, 4); - - hal::cvtMultipliedRGBAtoRGBA(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows); -} - -} // namespace cv +CV_CPU_OPTIMIZATION_NAMESPACE_END +}} // namespace diff --git a/modules/imgproc/src/color_yuv.dispatch.cpp b/modules/imgproc/src/color_yuv.dispatch.cpp new file mode 100644 index 0000000000..6cb508f980 --- /dev/null +++ b/modules/imgproc/src/color_yuv.dispatch.cpp @@ -0,0 +1,417 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html + +#include "precomp.hpp" +#include "opencl_kernels_imgproc.hpp" + +#include "color.hpp" + +#include "color_yuv.simd.hpp" +#include "color_yuv.simd_declarations.hpp" // defines CV_CPU_DISPATCH_MODES_ALL=AVX2,...,BASELINE based on CMakeLists.txt content + +namespace cv { + +// +// HAL functions +// +namespace hal { + +// 8u, 16u, 32f +void cvtBGRtoYUV(const uchar * src_data, size_t src_step, + uchar * dst_data, size_t dst_step, + int width, int height, + int depth, int scn, bool swapBlue, bool isCbCr) +{ + CV_INSTRUMENT_REGION(); + + CALL_HAL(cvtBGRtoYUV, cv_hal_cvtBGRtoYUV, src_data, src_step, dst_data, dst_step, width, height, depth, scn, swapBlue, isCbCr); + +#if defined(HAVE_IPP) +#if !IPP_DISABLE_RGB_YUV + CV_IPP_CHECK() + { + if (scn == 3 && depth == CV_8U && swapBlue && !isCbCr) + { + if (CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPGeneralFunctor((ippiGeneralFunc)ippiRGBToYUV_8u_C3R))) + return; + } + else if (scn == 3 && depth == CV_8U && !swapBlue && !isCbCr) + { + if (CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPReorderGeneralFunctor(ippiSwapChannelsC3RTab[depth], + (ippiGeneralFunc)ippiRGBToYUV_8u_C3R, 2, 1, 0, depth))) + return; + } + else if (scn == 4 && depth == CV_8U && swapBlue && !isCbCr) + { + if (CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], + (ippiGeneralFunc)ippiRGBToYUV_8u_C3R, 0, 1, 2, depth))) + return; + } + else if (scn == 4 && depth == CV_8U && !swapBlue && !isCbCr) + { + if (CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], + (ippiGeneralFunc)ippiRGBToYUV_8u_C3R, 2, 1, 0, depth))) + return; + } + } +#endif +#endif + + CV_CPU_DISPATCH(cvtBGRtoYUV, (src_data, src_step, dst_data, dst_step, width, height, depth, scn, swapBlue, isCbCr), + CV_CPU_DISPATCH_MODES_ALL); +} + +void cvtYUVtoBGR(const uchar * src_data, size_t src_step, + uchar * dst_data, size_t dst_step, + int width, int height, + int depth, int dcn, bool swapBlue, bool isCbCr) +{ + CV_INSTRUMENT_REGION(); + + CALL_HAL(cvtYUVtoBGR, cv_hal_cvtYUVtoBGR, src_data, src_step, dst_data, dst_step, width, height, depth, dcn, swapBlue, isCbCr); + + +#if defined(HAVE_IPP) +#if !IPP_DISABLE_YUV_RGB + CV_IPP_CHECK() + { + if (dcn == 3 && depth == CV_8U && swapBlue && !isCbCr) + { + if (CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPGeneralFunctor((ippiGeneralFunc)ippiYUVToRGB_8u_C3R))) + return; + } + else if (dcn == 3 && depth == CV_8U && !swapBlue && !isCbCr) + { + if (CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPGeneralReorderFunctor((ippiGeneralFunc)ippiYUVToRGB_8u_C3R, + ippiSwapChannelsC3RTab[depth], 2, 1, 0, depth))) + return; + } + else if (dcn == 4 && depth == CV_8U && swapBlue && !isCbCr) + { + if (CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPGeneralReorderFunctor((ippiGeneralFunc)ippiYUVToRGB_8u_C3R, + ippiSwapChannelsC3C4RTab[depth], 0, 1, 2, depth))) + return; + } + else if (dcn == 4 && depth == CV_8U && !swapBlue && !isCbCr) + { + if (CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPGeneralReorderFunctor((ippiGeneralFunc)ippiYUVToRGB_8u_C3R, + ippiSwapChannelsC3C4RTab[depth], 2, 1, 0, depth))) + return; + } + } +#endif +#endif + + CV_CPU_DISPATCH(cvtYUVtoBGR, (src_data, src_step, dst_data, dst_step, width, height, depth, dcn, swapBlue, isCbCr), + CV_CPU_DISPATCH_MODES_ALL); +} + +void cvtTwoPlaneYUVtoBGR(const uchar * src_data, size_t src_step, + uchar * dst_data, size_t dst_step, + int dst_width, int dst_height, + int dcn, bool swapBlue, int uIdx) +{ + CV_INSTRUMENT_REGION(); + + CALL_HAL(cvtTwoPlaneYUVtoBGR, cv_hal_cvtTwoPlaneYUVtoBGR, src_data, src_step, dst_data, dst_step, dst_width, dst_height, dcn, swapBlue, uIdx); + + CV_CPU_DISPATCH(cvtTwoPlaneYUVtoBGR, (src_data, src_step, dst_data, dst_step, dst_width, dst_height, dcn, swapBlue, uIdx), + CV_CPU_DISPATCH_MODES_ALL); +} + +void cvtTwoPlaneYUVtoBGR(const uchar * y_data, const uchar * uv_data, size_t src_step, + uchar * dst_data, size_t dst_step, + int dst_width, int dst_height, + int dcn, bool swapBlue, int uIdx) +{ + CV_INSTRUMENT_REGION(); + + CV_CPU_DISPATCH(cvtTwoPlaneYUVtoBGR, (y_data, uv_data, src_step, dst_data, dst_step, dst_width, dst_height, dcn, swapBlue, uIdx), + CV_CPU_DISPATCH_MODES_ALL); +} + +void cvtThreePlaneYUVtoBGR(const uchar * src_data, size_t src_step, + uchar * dst_data, size_t dst_step, + int dst_width, int dst_height, + int dcn, bool swapBlue, int uIdx) +{ + CV_INSTRUMENT_REGION(); + + CALL_HAL(cvtThreePlaneYUVtoBGR, cv_hal_cvtThreePlaneYUVtoBGR, src_data, src_step, dst_data, dst_step, dst_width, dst_height, dcn, swapBlue, uIdx); + + CV_CPU_DISPATCH(cvtThreePlaneYUVtoBGR, (src_data, src_step, dst_data, dst_step, dst_width, dst_height, dcn, swapBlue, uIdx), + CV_CPU_DISPATCH_MODES_ALL); +} + +void cvtBGRtoThreePlaneYUV(const uchar * src_data, size_t src_step, + uchar * dst_data, size_t dst_step, + int width, int height, + int scn, bool swapBlue, int uIdx) +{ + CV_INSTRUMENT_REGION(); + + CALL_HAL(cvtBGRtoThreePlaneYUV, cv_hal_cvtBGRtoThreePlaneYUV, src_data, src_step, dst_data, dst_step, width, height, scn, swapBlue, uIdx); + + CV_CPU_DISPATCH(cvtBGRtoThreePlaneYUV, (src_data, src_step, dst_data, dst_step, width, height, scn, swapBlue, uIdx), + CV_CPU_DISPATCH_MODES_ALL); +} + +void cvtBGRtoTwoPlaneYUV(const uchar * src_data, size_t src_step, + uchar * y_data, uchar * uv_data, size_t dst_step, + int width, int height, + int scn, bool swapBlue, int uIdx) +{ + CV_INSTRUMENT_REGION(); + + // TODO: add hal replacement method + + CV_CPU_DISPATCH(cvtBGRtoTwoPlaneYUV, (src_data, src_step, y_data, uv_data, dst_step, width, height, scn, swapBlue, uIdx), + CV_CPU_DISPATCH_MODES_ALL); +} + +void cvtOnePlaneYUVtoBGR(const uchar * src_data, size_t src_step, + uchar * dst_data, size_t dst_step, + int width, int height, + int dcn, bool swapBlue, int uIdx, int ycn) +{ + CV_INSTRUMENT_REGION(); + + CALL_HAL(cvtOnePlaneYUVtoBGR, cv_hal_cvtOnePlaneYUVtoBGR, src_data, src_step, dst_data, dst_step, width, height, dcn, swapBlue, uIdx, ycn); + + CV_CPU_DISPATCH(cvtOnePlaneYUVtoBGR, (src_data, src_step, dst_data, dst_step, width, height, dcn, swapBlue, uIdx, ycn), + CV_CPU_DISPATCH_MODES_ALL); +} + +} // namespace hal + +// +// OCL calls +// + +#ifdef HAVE_OPENCL + +bool oclCvtColorYUV2BGR( InputArray _src, OutputArray _dst, int dcn, int bidx ) +{ + OclHelper< Set<3>, Set<3, 4>, Set > h(_src, _dst, dcn); + + if(!h.createKernel("YUV2RGB", ocl::imgproc::color_yuv_oclsrc, + format("-D dcn=%d -D bidx=%d", dcn, bidx))) + { + return false; + } + + return h.run(); +} + +bool oclCvtColorBGR2YUV( InputArray _src, OutputArray _dst, int bidx ) +{ + OclHelper< Set<3, 4>, Set<3>, Set > h(_src, _dst, 3); + + if(!h.createKernel("RGB2YUV", ocl::imgproc::color_yuv_oclsrc, + format("-D dcn=3 -D bidx=%d", bidx))) + { + return false; + } + + return h.run(); +} + +bool oclCvtcolorYCrCb2BGR( InputArray _src, OutputArray _dst, int dcn, int bidx) +{ + OclHelper< Set<3>, Set<3, 4>, Set > h(_src, _dst, dcn); + + if(!h.createKernel("YCrCb2RGB", ocl::imgproc::color_yuv_oclsrc, + format("-D dcn=%d -D bidx=%d", dcn, bidx))) + { + return false; + } + + return h.run(); +} + +bool oclCvtColorBGR2YCrCb( InputArray _src, OutputArray _dst, int bidx) +{ + OclHelper< Set<3, 4>, Set<3>, Set > h(_src, _dst, 3); + + if(!h.createKernel("RGB2YCrCb", ocl::imgproc::color_yuv_oclsrc, + format("-D dcn=3 -D bidx=%d", bidx))) + { + return false; + } + + return h.run(); +} + +bool oclCvtColorOnePlaneYUV2BGR( InputArray _src, OutputArray _dst, int dcn, int bidx, int uidx, int yidx ) +{ + OclHelper< Set<2>, Set<3, 4>, Set > h(_src, _dst, dcn); + + bool optimized = _src.offset() % 4 == 0 && _src.step() % 4 == 0; + if(!h.createKernel("YUV2RGB_422", ocl::imgproc::color_yuv_oclsrc, + format("-D dcn=%d -D bidx=%d -D uidx=%d -D yidx=%d%s", dcn, bidx, uidx, yidx, + optimized ? " -D USE_OPTIMIZED_LOAD" : ""))) + { + return false; + } + + return h.run(); +} + +bool oclCvtColorYUV2Gray_420( InputArray _src, OutputArray _dst ) +{ + OclHelper< Set<1>, Set<1>, Set, FROM_YUV> h(_src, _dst, 1); + + h.src.rowRange(0, _dst.rows()).copyTo(_dst); + return true; +} + +bool oclCvtColorTwoPlaneYUV2BGR( InputArray _src, OutputArray _dst, int dcn, int bidx, int uidx ) +{ + OclHelper< Set<1>, Set<3, 4>, Set, FROM_YUV > h(_src, _dst, dcn); + + if(!h.createKernel("YUV2RGB_NVx", ocl::imgproc::color_yuv_oclsrc, + format("-D dcn=%d -D bidx=%d -D uidx=%d", dcn, bidx, uidx))) + { + return false; + } + + return h.run(); +} + +bool oclCvtColorThreePlaneYUV2BGR( InputArray _src, OutputArray _dst, int dcn, int bidx, int uidx ) +{ + OclHelper< Set<1>, Set<3, 4>, Set, FROM_YUV > h(_src, _dst, dcn); + + if(!h.createKernel("YUV2RGB_YV12_IYUV", ocl::imgproc::color_yuv_oclsrc, + format("-D dcn=%d -D bidx=%d -D uidx=%d%s", dcn, bidx, uidx, + _src.isContinuous() ? " -D SRC_CONT" : ""))) + { + return false; + } + + return h.run(); +} + +bool oclCvtColorBGR2ThreePlaneYUV( InputArray _src, OutputArray _dst, int bidx, int uidx ) +{ + OclHelper< Set<3, 4>, Set<1>, Set, TO_YUV > h(_src, _dst, 1); + + if(!h.createKernel("RGB2YUV_YV12_IYUV", ocl::imgproc::color_yuv_oclsrc, + format("-D dcn=1 -D bidx=%d -D uidx=%d", bidx, uidx))) + { + return false; + } + + return h.run(); +} + +#endif + +// +// HAL calls +// + +void cvtColorBGR2YUV(InputArray _src, OutputArray _dst, bool swapb, bool crcb) +{ + CvtHelper< Set<3, 4>, Set<3>, Set > h(_src, _dst, 3); + + hal::cvtBGRtoYUV(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows, + h.depth, h.scn, swapb, crcb); +} + +void cvtColorYUV2BGR(InputArray _src, OutputArray _dst, int dcn, bool swapb, bool crcb) +{ + if(dcn <= 0) dcn = 3; + CvtHelper< Set<3>, Set<3, 4>, Set > h(_src, _dst, dcn); + + hal::cvtYUVtoBGR(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows, + h.depth, dcn, swapb, crcb); +} + +void cvtColorOnePlaneYUV2BGR( InputArray _src, OutputArray _dst, int dcn, bool swapb, int uidx, int ycn) +{ + CvtHelper< Set<2>, Set<3, 4>, Set > h(_src, _dst, dcn); + + hal::cvtOnePlaneYUVtoBGR(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows, + dcn, swapb, uidx, ycn); +} + +void cvtColorYUV2Gray_ch( InputArray _src, OutputArray _dst, int coi ) +{ + CV_Assert( _src.channels() == 2 && _src.depth() == CV_8U ); + + extractChannel(_src, _dst, coi); +} + +void cvtColorBGR2ThreePlaneYUV( InputArray _src, OutputArray _dst, bool swapb, int uidx) +{ + CvtHelper< Set<3, 4>, Set<1>, Set, TO_YUV > h(_src, _dst, 1); + + hal::cvtBGRtoThreePlaneYUV(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows, + h.scn, swapb, uidx); +} + +void cvtColorYUV2Gray_420( InputArray _src, OutputArray _dst ) +{ + CvtHelper< Set<1>, Set<1>, Set, FROM_YUV > h(_src, _dst, 1); + +#ifdef HAVE_IPP +#if IPP_VERSION_X100 >= 201700 + if (CV_INSTRUMENT_FUN_IPP(ippiCopy_8u_C1R_L, h.src.data, (IppSizeL)h.src.step, h.dst.data, (IppSizeL)h.dst.step, + ippiSizeL(h.dstSz.width, h.dstSz.height)) >= 0) + return; +#endif +#endif + h.src(Range(0, h.dstSz.height), Range::all()).copyTo(h.dst); +} + +void cvtColorThreePlaneYUV2BGR( InputArray _src, OutputArray _dst, int dcn, bool swapb, int uidx) +{ + if(dcn <= 0) dcn = 3; + CvtHelper< Set<1>, Set<3, 4>, Set, FROM_YUV> h(_src, _dst, dcn); + + hal::cvtThreePlaneYUVtoBGR(h.src.data, h.src.step, h.dst.data, h.dst.step, h.dst.cols, h.dst.rows, + dcn, swapb, uidx); +} + +// http://www.fourcc.org/yuv.php#NV21 == yuv420sp -> a plane of 8 bit Y samples followed by an interleaved V/U plane containing 8 bit 2x2 subsampled chroma samples +// http://www.fourcc.org/yuv.php#NV12 -> a plane of 8 bit Y samples followed by an interleaved U/V plane containing 8 bit 2x2 subsampled colour difference samples + +void cvtColorTwoPlaneYUV2BGR( InputArray _src, OutputArray _dst, int dcn, bool swapb, int uidx ) +{ + if(dcn <= 0) dcn = 3; + CvtHelper< Set<1>, Set<3, 4>, Set, FROM_YUV> h(_src, _dst, dcn); + + hal::cvtTwoPlaneYUVtoBGR(h.src.data, h.src.step, h.dst.data, h.dst.step, h.dst.cols, h.dst.rows, + dcn, swapb, uidx); +} + +void cvtColorTwoPlaneYUV2BGRpair( InputArray _ysrc, InputArray _uvsrc, OutputArray _dst, int dcn, bool swapb, int uidx ) +{ + int stype = _ysrc.type(); + int depth = CV_MAT_DEPTH(stype); + Size ysz = _ysrc.size(), uvs = _uvsrc.size(); + CV_Assert( dcn == 3 || dcn == 4 ); + CV_Assert( depth == CV_8U ); + CV_Assert( ysz.width == uvs.width * 2 && ysz.height == uvs.height * 2 ); + + Mat ysrc = _ysrc.getMat(), uvsrc = _uvsrc.getMat(); + + _dst.create( ysz, CV_MAKETYPE(depth, dcn)); + Mat dst = _dst.getMat(); + + hal::cvtTwoPlaneYUVtoBGR(ysrc.data, uvsrc.data, ysrc.step, + dst.data, dst.step, dst.cols, dst.rows, + dcn, swapb, uidx); +} + +} // namespace cv diff --git a/modules/imgproc/src/color_yuv.cpp b/modules/imgproc/src/color_yuv.simd.hpp similarity index 85% rename from modules/imgproc/src/color_yuv.cpp rename to modules/imgproc/src/color_yuv.simd.hpp index 7d731378e2..8bbd78b244 100644 --- a/modules/imgproc/src/color_yuv.cpp +++ b/modules/imgproc/src/color_yuv.simd.hpp @@ -3,11 +3,54 @@ // of this distribution and at http://opencv.org/license.html #include "precomp.hpp" -#include "color.hpp" +#include "opencv2/core/hal/intrin.hpp" -namespace cv -{ +namespace cv { +namespace hal { +CV_CPU_OPTIMIZATION_NAMESPACE_BEGIN +// forward declarations +void cvtBGRtoYUV(const uchar * src_data, size_t src_step, + uchar * dst_data, size_t dst_step, + int width, int height, + int depth, int scn, bool swapBlue, bool isCbCr); +void cvtYUVtoBGR(const uchar * src_data, size_t src_step, + uchar * dst_data, size_t dst_step, + int width, int height, + int depth, int dcn, bool swapBlue, bool isCbCr); +void cvtTwoPlaneYUVtoBGR(const uchar * src_data, size_t src_step, + uchar * dst_data, size_t dst_step, + int dst_width, int dst_height, + int dcn, bool swapBlue, int uIdx); +void cvtTwoPlaneYUVtoBGR(const uchar * y_data, const uchar * uv_data, size_t src_step, + uchar * dst_data, size_t dst_step, + int dst_width, int dst_height, + int dcn, bool swapBlue, int uIdx); +void cvtThreePlaneYUVtoBGR(const uchar * src_data, size_t src_step, + uchar * dst_data, size_t dst_step, + int dst_width, int dst_height, + int dcn, bool swapBlue, int uIdx); +void cvtBGRtoThreePlaneYUV(const uchar * src_data, size_t src_step, + uchar * dst_data, size_t dst_step, + int width, int height, + int scn, bool swapBlue, int uIdx); +void cvtBGRtoTwoPlaneYUV(const uchar * src_data, size_t src_step, + uchar * y_data, uchar * uv_data, size_t dst_step, + int width, int height, + int scn, bool swapBlue, int uIdx); +void cvtOnePlaneYUVtoBGR(const uchar * src_data, size_t src_step, + uchar * dst_data, size_t dst_step, + int width, int height, + int dcn, bool swapBlue, int uIdx, int ycn); +#ifndef CV_CPU_OPTIMIZATION_DECLARATIONS_ONLY + +#if defined(CV_CPU_BASELINE_MODE) +// included in color.hpp +#else +#include "color.simd_helpers.hpp" +#endif + +namespace { //constants for conversion from/to RGB and YUV, YCrCb according to BT.601 //to YCbCr @@ -1738,12 +1781,8 @@ inline void cvtYUV422toRGB(uchar * dst_data, size_t dst_step, const uchar * src_ converter(Range(0, height)); } -// -// HAL functions -// +} // namespace anon -namespace hal -{ // 8u, 16u, 32f void cvtBGRtoYUV(const uchar * src_data, size_t src_step, @@ -1753,43 +1792,6 @@ void cvtBGRtoYUV(const uchar * src_data, size_t src_step, { CV_INSTRUMENT_REGION(); - CALL_HAL(cvtBGRtoYUV, cv_hal_cvtBGRtoYUV, src_data, src_step, dst_data, dst_step, width, height, depth, scn, swapBlue, isCbCr); - -#if defined(HAVE_IPP) -#if !IPP_DISABLE_RGB_YUV - CV_IPP_CHECK() - { - if (scn == 3 && depth == CV_8U && swapBlue && !isCbCr) - { - if (CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, - IPPGeneralFunctor((ippiGeneralFunc)ippiRGBToYUV_8u_C3R))) - return; - } - else if (scn == 3 && depth == CV_8U && !swapBlue && !isCbCr) - { - if (CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, - IPPReorderGeneralFunctor(ippiSwapChannelsC3RTab[depth], - (ippiGeneralFunc)ippiRGBToYUV_8u_C3R, 2, 1, 0, depth))) - return; - } - else if (scn == 4 && depth == CV_8U && swapBlue && !isCbCr) - { - if (CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, - IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], - (ippiGeneralFunc)ippiRGBToYUV_8u_C3R, 0, 1, 2, depth))) - return; - } - else if (scn == 4 && depth == CV_8U && !swapBlue && !isCbCr) - { - if (CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, - IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], - (ippiGeneralFunc)ippiRGBToYUV_8u_C3R, 2, 1, 0, depth))) - return; - } - } -#endif -#endif - int blueIdx = swapBlue ? 2 : 0; if( depth == CV_8U ) CvtColorLoop(src_data, src_step, dst_data, dst_step, width, height, RGB2YCrCb_i(scn, blueIdx, isCbCr)); @@ -1806,44 +1808,6 @@ void cvtYUVtoBGR(const uchar * src_data, size_t src_step, { CV_INSTRUMENT_REGION(); - CALL_HAL(cvtYUVtoBGR, cv_hal_cvtYUVtoBGR, src_data, src_step, dst_data, dst_step, width, height, depth, dcn, swapBlue, isCbCr); - - -#if defined(HAVE_IPP) -#if !IPP_DISABLE_YUV_RGB - CV_IPP_CHECK() - { - if (dcn == 3 && depth == CV_8U && swapBlue && !isCbCr) - { - if (CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, - IPPGeneralFunctor((ippiGeneralFunc)ippiYUVToRGB_8u_C3R))) - return; - } - else if (dcn == 3 && depth == CV_8U && !swapBlue && !isCbCr) - { - if (CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, - IPPGeneralReorderFunctor((ippiGeneralFunc)ippiYUVToRGB_8u_C3R, - ippiSwapChannelsC3RTab[depth], 2, 1, 0, depth))) - return; - } - else if (dcn == 4 && depth == CV_8U && swapBlue && !isCbCr) - { - if (CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, - IPPGeneralReorderFunctor((ippiGeneralFunc)ippiYUVToRGB_8u_C3R, - ippiSwapChannelsC3C4RTab[depth], 0, 1, 2, depth))) - return; - } - else if (dcn == 4 && depth == CV_8U && !swapBlue && !isCbCr) - { - if (CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, - IPPGeneralReorderFunctor((ippiGeneralFunc)ippiYUVToRGB_8u_C3R, - ippiSwapChannelsC3C4RTab[depth], 2, 1, 0, depth))) - return; - } - } -#endif -#endif - int blueIdx = swapBlue ? 2 : 0; if( depth == CV_8U ) CvtColorLoop(src_data, src_step, dst_data, dst_step, width, height, YCrCb2RGB_i(dcn, blueIdx, isCbCr)); @@ -1860,7 +1824,6 @@ void cvtTwoPlaneYUVtoBGR(const uchar * src_data, size_t src_step, { CV_INSTRUMENT_REGION(); - CALL_HAL(cvtTwoPlaneYUVtoBGR, cv_hal_cvtTwoPlaneYUVtoBGR, src_data, src_step, dst_data, dst_step, dst_width, dst_height, dcn, swapBlue, uIdx); const uchar* uv = src_data + src_step * static_cast(dst_height); cvtTwoPlaneYUVtoBGR(src_data, uv, src_step, dst_data, dst_step, dst_width, dst_height, dcn, swapBlue, uIdx); } @@ -1880,8 +1843,6 @@ void cvtTwoPlaneYUVtoBGR(const uchar * y_data, const uchar * uv_data, size_t src { CV_INSTRUMENT_REGION(); - // TODO: add hal replacement method - int blueIdx = swapBlue ? 2 : 0; cvt_2plane_yuv_ptr_t cvtPtr; @@ -1919,7 +1880,6 @@ void cvtThreePlaneYUVtoBGR(const uchar * src_data, size_t src_step, { CV_INSTRUMENT_REGION(); - CALL_HAL(cvtThreePlaneYUVtoBGR, cv_hal_cvtThreePlaneYUVtoBGR, src_data, src_step, dst_data, dst_step, dst_width, dst_height, dcn, swapBlue, uIdx); const uchar* u = src_data + src_step * static_cast(dst_height); const uchar* v = src_data + src_step * static_cast(dst_height + dst_height/4) + (dst_width/2) * ((dst_height % 4)/2); @@ -1949,7 +1909,6 @@ void cvtBGRtoThreePlaneYUV(const uchar * src_data, size_t src_step, { CV_INSTRUMENT_REGION(); - CALL_HAL(cvtBGRtoThreePlaneYUV, cv_hal_cvtBGRtoThreePlaneYUV, src_data, src_step, dst_data, dst_step, width, height, scn, swapBlue, uIdx); uchar * uv_data = dst_data + dst_step * height; RGB8toYUV420pInvoker cvt(src_data, src_step, dst_data, uv_data, dst_step, width, height, @@ -1968,8 +1927,6 @@ void cvtBGRtoTwoPlaneYUV(const uchar * src_data, size_t src_step, { CV_INSTRUMENT_REGION(); - // TODO: add hal replacement method - RGB8toYUV420pInvoker cvt(src_data, src_step, y_data, uv_data, dst_step, width, height, scn, swapBlue, uIdx == 2, true); @@ -1993,8 +1950,6 @@ void cvtOnePlaneYUVtoBGR(const uchar * src_data, size_t src_step, { CV_INSTRUMENT_REGION(); - CALL_HAL(cvtOnePlaneYUVtoBGR, cv_hal_cvtOnePlaneYUVtoBGR, src_data, src_step, dst_data, dst_step, width, height, dcn, swapBlue, uIdx, ycn); - cvt_1plane_yuv_ptr_t cvtPtr; int blueIdx = swapBlue ? 2 : 0; switch(dcn*1000 + blueIdx*100 + uIdx*10 + ycn) @@ -2017,227 +1972,6 @@ void cvtOnePlaneYUVtoBGR(const uchar * src_data, size_t src_step, cvtPtr(dst_data, dst_step, src_data, src_step, width, height); } -} // namespace hal - -// -// OCL calls -// - -#ifdef HAVE_OPENCL - -bool oclCvtColorYUV2BGR( InputArray _src, OutputArray _dst, int dcn, int bidx ) -{ - OclHelper< Set<3>, Set<3, 4>, Set > h(_src, _dst, dcn); - - if(!h.createKernel("YUV2RGB", ocl::imgproc::color_yuv_oclsrc, - format("-D dcn=%d -D bidx=%d", dcn, bidx))) - { - return false; - } - - return h.run(); -} - -bool oclCvtColorBGR2YUV( InputArray _src, OutputArray _dst, int bidx ) -{ - OclHelper< Set<3, 4>, Set<3>, Set > h(_src, _dst, 3); - - if(!h.createKernel("RGB2YUV", ocl::imgproc::color_yuv_oclsrc, - format("-D dcn=3 -D bidx=%d", bidx))) - { - return false; - } - - return h.run(); -} - -bool oclCvtcolorYCrCb2BGR( InputArray _src, OutputArray _dst, int dcn, int bidx) -{ - OclHelper< Set<3>, Set<3, 4>, Set > h(_src, _dst, dcn); - - if(!h.createKernel("YCrCb2RGB", ocl::imgproc::color_yuv_oclsrc, - format("-D dcn=%d -D bidx=%d", dcn, bidx))) - { - return false; - } - - return h.run(); -} - -bool oclCvtColorBGR2YCrCb( InputArray _src, OutputArray _dst, int bidx) -{ - OclHelper< Set<3, 4>, Set<3>, Set > h(_src, _dst, 3); - - if(!h.createKernel("RGB2YCrCb", ocl::imgproc::color_yuv_oclsrc, - format("-D dcn=3 -D bidx=%d", bidx))) - { - return false; - } - - return h.run(); -} - -bool oclCvtColorOnePlaneYUV2BGR( InputArray _src, OutputArray _dst, int dcn, int bidx, int uidx, int yidx ) -{ - OclHelper< Set<2>, Set<3, 4>, Set > h(_src, _dst, dcn); - - bool optimized = _src.offset() % 4 == 0 && _src.step() % 4 == 0; - if(!h.createKernel("YUV2RGB_422", ocl::imgproc::color_yuv_oclsrc, - format("-D dcn=%d -D bidx=%d -D uidx=%d -D yidx=%d%s", dcn, bidx, uidx, yidx, - optimized ? " -D USE_OPTIMIZED_LOAD" : ""))) - { - return false; - } - - return h.run(); -} - -bool oclCvtColorYUV2Gray_420( InputArray _src, OutputArray _dst ) -{ - OclHelper< Set<1>, Set<1>, Set, FROM_YUV> h(_src, _dst, 1); - - h.src.rowRange(0, _dst.rows()).copyTo(_dst); - return true; -} - -bool oclCvtColorTwoPlaneYUV2BGR( InputArray _src, OutputArray _dst, int dcn, int bidx, int uidx ) -{ - OclHelper< Set<1>, Set<3, 4>, Set, FROM_YUV > h(_src, _dst, dcn); - - if(!h.createKernel("YUV2RGB_NVx", ocl::imgproc::color_yuv_oclsrc, - format("-D dcn=%d -D bidx=%d -D uidx=%d", dcn, bidx, uidx))) - { - return false; - } - - return h.run(); -} - -bool oclCvtColorThreePlaneYUV2BGR( InputArray _src, OutputArray _dst, int dcn, int bidx, int uidx ) -{ - OclHelper< Set<1>, Set<3, 4>, Set, FROM_YUV > h(_src, _dst, dcn); - - if(!h.createKernel("YUV2RGB_YV12_IYUV", ocl::imgproc::color_yuv_oclsrc, - format("-D dcn=%d -D bidx=%d -D uidx=%d%s", dcn, bidx, uidx, - _src.isContinuous() ? " -D SRC_CONT" : ""))) - { - return false; - } - - return h.run(); -} - -bool oclCvtColorBGR2ThreePlaneYUV( InputArray _src, OutputArray _dst, int bidx, int uidx ) -{ - OclHelper< Set<3, 4>, Set<1>, Set, TO_YUV > h(_src, _dst, 1); - - if(!h.createKernel("RGB2YUV_YV12_IYUV", ocl::imgproc::color_yuv_oclsrc, - format("-D dcn=1 -D bidx=%d -D uidx=%d", bidx, uidx))) - { - return false; - } - - return h.run(); -} - #endif - -// -// HAL calls -// - -void cvtColorBGR2YUV(InputArray _src, OutputArray _dst, bool swapb, bool crcb) -{ - CvtHelper< Set<3, 4>, Set<3>, Set > h(_src, _dst, 3); - - hal::cvtBGRtoYUV(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows, - h.depth, h.scn, swapb, crcb); -} - -void cvtColorYUV2BGR(InputArray _src, OutputArray _dst, int dcn, bool swapb, bool crcb) -{ - if(dcn <= 0) dcn = 3; - CvtHelper< Set<3>, Set<3, 4>, Set > h(_src, _dst, dcn); - - hal::cvtYUVtoBGR(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows, - h.depth, dcn, swapb, crcb); -} - -void cvtColorOnePlaneYUV2BGR( InputArray _src, OutputArray _dst, int dcn, bool swapb, int uidx, int ycn) -{ - CvtHelper< Set<2>, Set<3, 4>, Set > h(_src, _dst, dcn); - - hal::cvtOnePlaneYUVtoBGR(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows, - dcn, swapb, uidx, ycn); -} - -void cvtColorYUV2Gray_ch( InputArray _src, OutputArray _dst, int coi ) -{ - CV_Assert( _src.channels() == 2 && _src.depth() == CV_8U ); - - extractChannel(_src, _dst, coi); -} - -void cvtColorBGR2ThreePlaneYUV( InputArray _src, OutputArray _dst, bool swapb, int uidx) -{ - CvtHelper< Set<3, 4>, Set<1>, Set, TO_YUV > h(_src, _dst, 1); - - hal::cvtBGRtoThreePlaneYUV(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows, - h.scn, swapb, uidx); -} - -void cvtColorYUV2Gray_420( InputArray _src, OutputArray _dst ) -{ - CvtHelper< Set<1>, Set<1>, Set, FROM_YUV > h(_src, _dst, 1); - -#ifdef HAVE_IPP -#if IPP_VERSION_X100 >= 201700 - if (CV_INSTRUMENT_FUN_IPP(ippiCopy_8u_C1R_L, h.src.data, (IppSizeL)h.src.step, h.dst.data, (IppSizeL)h.dst.step, - ippiSizeL(h.dstSz.width, h.dstSz.height)) >= 0) - return; -#endif -#endif - h.src(Range(0, h.dstSz.height), Range::all()).copyTo(h.dst); -} - -void cvtColorThreePlaneYUV2BGR( InputArray _src, OutputArray _dst, int dcn, bool swapb, int uidx) -{ - if(dcn <= 0) dcn = 3; - CvtHelper< Set<1>, Set<3, 4>, Set, FROM_YUV> h(_src, _dst, dcn); - - hal::cvtThreePlaneYUVtoBGR(h.src.data, h.src.step, h.dst.data, h.dst.step, h.dst.cols, h.dst.rows, - dcn, swapb, uidx); -} - -// http://www.fourcc.org/yuv.php#NV21 == yuv420sp -> a plane of 8 bit Y samples followed by an interleaved V/U plane containing 8 bit 2x2 subsampled chroma samples -// http://www.fourcc.org/yuv.php#NV12 -> a plane of 8 bit Y samples followed by an interleaved U/V plane containing 8 bit 2x2 subsampled colour difference samples - -void cvtColorTwoPlaneYUV2BGR( InputArray _src, OutputArray _dst, int dcn, bool swapb, int uidx ) -{ - if(dcn <= 0) dcn = 3; - CvtHelper< Set<1>, Set<3, 4>, Set, FROM_YUV> h(_src, _dst, dcn); - - hal::cvtTwoPlaneYUVtoBGR(h.src.data, h.src.step, h.dst.data, h.dst.step, h.dst.cols, h.dst.rows, - dcn, swapb, uidx); -} - -void cvtColorTwoPlaneYUV2BGRpair( InputArray _ysrc, InputArray _uvsrc, OutputArray _dst, int dcn, bool swapb, int uidx ) -{ - int stype = _ysrc.type(); - int depth = CV_MAT_DEPTH(stype); - Size ysz = _ysrc.size(), uvs = _uvsrc.size(); - CV_Assert( dcn == 3 || dcn == 4 ); - CV_Assert( depth == CV_8U ); - CV_Assert( ysz.width == uvs.width * 2 && ysz.height == uvs.height * 2 ); - - Mat ysrc = _ysrc.getMat(), uvsrc = _uvsrc.getMat(); - - _dst.create( ysz, CV_MAKETYPE(depth, dcn)); - Mat dst = _dst.getMat(); - - hal::cvtTwoPlaneYUVtoBGR(ysrc.data, uvsrc.data, ysrc.step, - dst.data, dst.step, dst.cols, dst.rows, - dcn, swapb, uidx); -} - -} // namespace cv +CV_CPU_OPTIMIZATION_NAMESPACE_END +}} // namespace