diff --git a/hal/ipp/CMakeLists.txt b/hal/ipp/CMakeLists.txt index 345a7534b1..0ea93ffb67 100644 --- a/hal/ipp/CMakeLists.txt +++ b/hal/ipp/CMakeLists.txt @@ -13,6 +13,7 @@ add_library(ipphal STATIC "${CMAKE_CURRENT_SOURCE_DIR}/src/minmax_ipp.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/src/norm_ipp.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/src/cart_polar_ipp.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/src/color_ipp.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/src/transforms_ipp.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/src/warp_ipp.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/src/sum_ipp.cpp" diff --git a/hal/ipp/include/ipp_hal_imgproc.hpp b/hal/ipp/include/ipp_hal_imgproc.hpp index 1e37326881..1357c758b6 100644 --- a/hal/ipp/include/ipp_hal_imgproc.hpp +++ b/hal/ipp/include/ipp_hal_imgproc.hpp @@ -39,4 +39,88 @@ int ipp_hal_remap32f(int src_type, const uchar *src_data, size_t src_step, int s #endif //IPP_VERSION_X100 >= 810 +#if IPP_VERSION_X100 >= 700 + +#define IPP_DISABLE_YUV_RGB 1 // accuracy difference +#define IPP_DISABLE_RGB_YUV 1 // breaks OCL accuracy tests +#define IPP_DISABLE_RGB_HSV 1 // breaks OCL accuracy tests +#define IPP_DISABLE_RGB_LAB 1 // breaks OCL accuracy tests +#define IPP_DISABLE_LAB_RGB 1 // breaks OCL accuracy tests +#define IPP_DISABLE_RGB_XYZ 1 // big accuracy difference +#define IPP_DISABLE_XYZ_RGB 1 // big accuracy difference + +int ipp_hal_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); +#undef cv_hal_cvtBGRtoGray +#define cv_hal_cvtBGRtoGray ipp_hal_cvtBGRtoGray + +int ipp_hal_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); +#undef cv_hal_cvtBGRtoBGR +#define cv_hal_cvtBGRtoBGR ipp_hal_cvtBGRtoBGR + +int ipp_hal_cvtGraytoBGR(const uchar * src_data, size_t src_step, uchar * dst_data, size_t dst_step, + int width, int height, int depth, int dcn); +#undef cv_hal_cvtGraytoBGR +#define cv_hal_cvtGraytoBGR ipp_hal_cvtGraytoBGR + +int ipp_hal_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); +#undef cv_hal_cvtBGRtoHSV +#define cv_hal_cvtBGRtoHSV ipp_hal_cvtBGRtoHSV + +int ipp_hal_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); +#undef cv_hal_cvtHSVtoBGR +#define cv_hal_cvtHSVtoBGR ipp_hal_cvtHSVtoBGR + +int ipp_hal_cvtRGBAtoMultipliedRGBA(const uchar * src_data, size_t src_step, uchar * dst_data, size_t dst_step, + int width, int height); +#undef cv_hal_cvtRGBAtoMultipliedRGBA +#define cv_hal_cvtRGBAtoMultipliedRGBA ipp_hal_cvtRGBAtoMultipliedRGBA + +#if !IPP_DISABLE_RGB_YUV +int ipp_hal_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); +#undef cv_hal_cvtBGRtoYUV +#define cv_hal_cvtBGRtoYUV ipp_hal_cvtBGRtoYUV +#endif // !IPP_DISABLE_RGB_YUV + +#if !IPP_DISABLE_YUV_RGB +int ipp_hal_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); +#undef cv_hal_cvtYUVtoBGR +#define cv_hal_cvtYUVtoBGR ipp_hal_cvtYUVtoBGR +#endif // !IPP_DISABLE_YUV_RGB + +#if !IPP_DISABLE_RGB_XYZ +int ipp_hal_cvtBGRtoXYZ(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); +#undef cv_hal_cvtBGRtoXYZ +#define cv_hal_cvtBGRtoXYZ ipp_hal_cvtBGRtoXYZ +#endif // !IPP_DISABLE_RGB_XYZ + +#if !IPP_DISABLE_XYZ_RGB +int ipp_hal_cvtXYZtoBGR(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); +#undef cv_hal_cvtXYZtoBGR +#define cv_hal_cvtXYZtoBGR ipp_hal_cvtXYZtoBGR +#endif // !IPP_DISABLE_XYZ_RGB + +#if !IPP_DISABLE_RGB_LAB +int ipp_hal_cvtBGRtoLab(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 isLab, bool srgb); +#undef cv_hal_cvtBGRtoLab +#define cv_hal_cvtBGRtoLab ipp_hal_cvtBGRtoLab +#endif // !IPP_DISABLE_RGB_LAB + +#if !IPP_DISABLE_LAB_RGB +int ipp_hal_cvtLabtoBGR(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 isLab, bool srgb); +#undef cv_hal_cvtLabtoBGR +#define cv_hal_cvtLabtoBGR ipp_hal_cvtLabtoBGR +#endif // !IPP_DISABLE_LAB_RGB + +#endif //IPP_VERSION_X100 >= 700 + #endif //__IPP_HAL_IMGPROC_HPP__ diff --git a/hal/ipp/src/color_ipp.cpp b/hal/ipp/src/color_ipp.cpp new file mode 100644 index 0000000000..4d9c1b3986 --- /dev/null +++ b/hal/ipp/src/color_ipp.cpp @@ -0,0 +1,942 @@ +// 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 "ipp_hal_imgproc.hpp" +#include +#include "precomp_ipp.hpp" + +#include + +#if IPP_VERSION_X100 >= 700 + +#define MAX_IPP8u 255 +#define MAX_IPP16u 65535 +#define MAX_IPP32f 1.0 + +#define IPP_DISABLE_CVTCOLOR_GRAY2BGR_8UC3 1 + +namespace { + +typedef IppStatus (CV_STDCALL* ippiGeneralFunc)(const void *, int, void *, int, IppiSize); +typedef IppStatus (CV_STDCALL* ippiColor2GrayFunc)(const void *, int, void *, int, IppiSize, const Ipp32f *); +typedef IppStatus (CV_STDCALL* ippiReorderFunc)(const void *, int, void *, int, IppiSize, const int *); + +// BT.601 BGR->Y weights +static const float B2YF = 0.114f; +static const float G2YF = 0.587f; +static const float R2YF = 0.299f; + +template struct ColorChannel +{ + static inline _Tp max() { return std::numeric_limits<_Tp>::max(); } +}; +template<> struct ColorChannel +{ + static inline float max() { return 1.f; } +}; + +template +class CvtColorIPPLoop_Invoker : public cv::ParallelLoopBody +{ +public: + CvtColorIPPLoop_Invoker(const uchar * src_data_, size_t src_step_, uchar * dst_data_, size_t dst_step_, + int width_, const Cvt& _cvt, bool *_ok) : + ParallelLoopBody(), src_data(src_data_), src_step(src_step_), dst_data(dst_data_), dst_step(dst_step_), + width(width_), cvt(_cvt), ok(_ok) + { + *ok = true; + } + + virtual void operator()(const cv::Range& range) const CV_OVERRIDE + { + const void *yS = src_data + src_step * range.start; + void *yD = dst_data + dst_step * range.start; + if( !cvt(yS, static_cast(src_step), yD, static_cast(dst_step), width, range.end - range.start) ) + *ok = false; + else + { + CV_IMPL_ADD(CV_IMPL_IPP|CV_IMPL_MT); + } + } + +private: + const uchar * src_data; + const size_t src_step; + uchar * dst_data; + const size_t dst_step; + const int width; + const Cvt& cvt; + bool *ok; + + const CvtColorIPPLoop_Invoker& operator= (const CvtColorIPPLoop_Invoker&); +}; + +template +bool CvtColorIPPLoop(const uchar * src_data, size_t src_step, uchar * dst_data, size_t dst_step, + int width, int height, const Cvt& cvt) +{ + bool ok; + cv::parallel_for_(cv::Range(0, height), + CvtColorIPPLoop_Invoker(src_data, src_step, dst_data, dst_step, width, cvt, &ok), + (width * height)/(double)(1<<16) ); + return ok; +} + +template +bool CvtColorIPPLoopCopy(const uchar * src_data, size_t src_step, int src_type, uchar * dst_data, size_t dst_step, + int width, int height, const Cvt& cvt) +{ + cv::Mat temp; + cv::Mat src(cv::Size(width, height), src_type, const_cast(src_data), src_step); + cv::Mat source = src; + if( src_data == dst_data ) + { + src.copyTo(temp); + source = temp; + } + bool ok; + cv::parallel_for_(cv::Range(0, source.rows), + CvtColorIPPLoop_Invoker(source.data, source.step, dst_data, dst_step, + source.cols, cvt, &ok), + source.total()/(double)(1<<16) ); + return ok; +} + +struct IPPGeneralFunctor +{ + IPPGeneralFunctor(ippiGeneralFunc _func) : ippiColorConvertGeneral(_func){} + bool operator()(const void *src, int srcStep, void *dst, int dstStep, int cols, int rows) const + { + return ippiColorConvertGeneral ? CV_INSTRUMENT_FUN_IPP(ippiColorConvertGeneral, src, srcStep, dst, dstStep, ippiSize(cols, rows)) >= 0 : false; + } +private: + ippiGeneralFunc ippiColorConvertGeneral; +}; + +struct IPPReorderFunctor +{ + IPPReorderFunctor(ippiReorderFunc _func, int _order0, int _order1, int _order2) : ippiColorConvertReorder(_func) + { + order[0] = _order0; + order[1] = _order1; + order[2] = _order2; + order[3] = 3; + } + bool operator()(const void *src, int srcStep, void *dst, int dstStep, int cols, int rows) const + { + return ippiColorConvertReorder ? CV_INSTRUMENT_FUN_IPP(ippiColorConvertReorder, src, srcStep, dst, dstStep, ippiSize(cols, rows), order) >= 0 : false; + } +private: + ippiReorderFunc ippiColorConvertReorder; + int order[4]; +}; + +struct IPPReorderGeneralFunctor +{ + IPPReorderGeneralFunctor(ippiReorderFunc _func1, ippiGeneralFunc _func2, int _order0, int _order1, int _order2, int _depth) : + ippiColorConvertReorder(_func1), ippiColorConvertGeneral(_func2), depth(_depth) + { + order[0] = _order0; + order[1] = _order1; + order[2] = _order2; + order[3] = 3; + } + bool operator()(const void *src, int srcStep, void *dst, int dstStep, int cols, int rows) const + { + if (ippiColorConvertReorder == 0 || ippiColorConvertGeneral == 0) + return false; + + cv::Mat temp; + temp.create(rows, cols, CV_MAKETYPE(depth, 3)); + if(CV_INSTRUMENT_FUN_IPP(ippiColorConvertReorder, src, srcStep, temp.ptr(), (int)temp.step[0], ippiSize(cols, rows), order) < 0) + return false; + return CV_INSTRUMENT_FUN_IPP(ippiColorConvertGeneral, temp.ptr(), (int)temp.step[0], dst, dstStep, ippiSize(cols, rows)) >= 0; + } +private: + ippiReorderFunc ippiColorConvertReorder; + ippiGeneralFunc ippiColorConvertGeneral; + int order[4]; + int depth; +}; + +struct IPPGeneralReorderFunctor +{ + IPPGeneralReorderFunctor(ippiGeneralFunc _func1, ippiReorderFunc _func2, int _order0, int _order1, int _order2, int _depth) : + ippiColorConvertGeneral(_func1), ippiColorConvertReorder(_func2), depth(_depth) + { + order[0] = _order0; + order[1] = _order1; + order[2] = _order2; + order[3] = 3; + } + bool operator()(const void *src, int srcStep, void *dst, int dstStep, int cols, int rows) const + { + if (ippiColorConvertGeneral == 0 || ippiColorConvertReorder == 0) + return false; + + cv::Mat temp; + temp.create(rows, cols, CV_MAKETYPE(depth, 3)); + if(CV_INSTRUMENT_FUN_IPP(ippiColorConvertGeneral, src, srcStep, temp.ptr(), (int)temp.step[0], ippiSize(cols, rows)) < 0) + return false; + return CV_INSTRUMENT_FUN_IPP(ippiColorConvertReorder, temp.ptr(), (int)temp.step[0], dst, dstStep, ippiSize(cols, rows), order) >= 0; + } +private: + ippiGeneralFunc ippiColorConvertGeneral; + ippiReorderFunc ippiColorConvertReorder; + int order[4]; + int depth; +}; + +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]; +}; + +#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); +} + +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); +} + +static const ippiColor2GrayFunc ippiColor2GrayC3Tab[CV_DEPTH_MAX] = +{ + (ippiColor2GrayFunc)ippiColorToGray_8u_C3C1R, 0, (ippiColor2GrayFunc)ippiColorToGray_16u_C3C1R, 0, + 0, (ippiColor2GrayFunc)ippiColorToGray_32f_C3C1R, 0, 0 +}; + +static const ippiColor2GrayFunc ippiColor2GrayC4Tab[CV_DEPTH_MAX] = +{ + (ippiColor2GrayFunc)ippiColorToGray_8u_AC4C1R, 0, (ippiColor2GrayFunc)ippiColorToGray_16u_AC4C1R, 0, + 0, (ippiColor2GrayFunc)ippiColorToGray_32f_AC4C1R, 0, 0 +}; + +static const ippiGeneralFunc ippiRGB2GrayC3Tab[CV_DEPTH_MAX] = +{ + (ippiGeneralFunc)ippiRGBToGray_8u_C3C1R, 0, (ippiGeneralFunc)ippiRGBToGray_16u_C3C1R, 0, + 0, (ippiGeneralFunc)ippiRGBToGray_32f_C3C1R, 0, 0 +}; + +static const ippiGeneralFunc ippiRGB2GrayC4Tab[CV_DEPTH_MAX] = +{ + (ippiGeneralFunc)ippiRGBToGray_8u_AC4C1R, 0, (ippiGeneralFunc)ippiRGBToGray_16u_AC4C1R, 0, + 0, (ippiGeneralFunc)ippiRGBToGray_32f_AC4C1R, 0, 0 +}; + +static const ippiReorderFunc ippiSwapChannelsC3C4RTab[CV_DEPTH_MAX] = +{ + (ippiReorderFunc)ippiSwapChannels_8u_C3C4Rf, 0, (ippiReorderFunc)ippiSwapChannels_16u_C3C4Rf, 0, + 0, (ippiReorderFunc)ippiSwapChannels_32f_C3C4Rf, 0, 0 +}; + +static const ippiGeneralFunc ippiCopyAC4C3RTab[CV_DEPTH_MAX] = +{ + (ippiGeneralFunc)ippiCopy_8u_AC4C3R, 0, (ippiGeneralFunc)ippiCopy_16u_AC4C3R, 0, + 0, (ippiGeneralFunc)ippiCopy_32f_AC4C3R, 0, 0 +}; + +static const ippiReorderFunc ippiSwapChannelsC4C3RTab[CV_DEPTH_MAX] = +{ + (ippiReorderFunc)ippiSwapChannels_8u_C4C3R, 0, (ippiReorderFunc)ippiSwapChannels_16u_C4C3R, 0, + 0, (ippiReorderFunc)ippiSwapChannels_32f_C4C3R, 0, 0 +}; + +static const ippiReorderFunc ippiSwapChannelsC3RTab[CV_DEPTH_MAX] = +{ + (ippiReorderFunc)ippiSwapChannels_8u_C3R, 0, (ippiReorderFunc)ippiSwapChannels_16u_C3R, 0, + 0, (ippiReorderFunc)ippiSwapChannels_32f_C3R, 0, 0 +}; + +#if IPP_VERSION_X100 >= 810 +static const ippiReorderFunc ippiSwapChannelsC4RTab[CV_DEPTH_MAX] = +{ + (ippiReorderFunc)ippiSwapChannels_8u_C4R, 0, (ippiReorderFunc)ippiSwapChannels_16u_C4R, 0, + 0, (ippiReorderFunc)ippiSwapChannels_32f_C4R, 0, 0 +}; +#endif + +#if !IPP_DISABLE_RGB_HSV +static const ippiGeneralFunc ippiRGB2HSVTab[CV_DEPTH_MAX] = +{ + (ippiGeneralFunc)ippiRGBToHSV_8u_C3R, 0, (ippiGeneralFunc)ippiRGBToHSV_16u_C3R, 0, + 0, 0, 0, 0 +}; +#endif + +static const ippiGeneralFunc ippiHSV2RGBTab[CV_DEPTH_MAX] = +{ + (ippiGeneralFunc)ippiHSVToRGB_8u_C3R, 0, (ippiGeneralFunc)ippiHSVToRGB_16u_C3R, 0, + 0, 0, 0, 0 +}; + +static const ippiGeneralFunc ippiRGB2HLSTab[CV_DEPTH_MAX] = +{ + (ippiGeneralFunc)ippiRGBToHLS_8u_C3R, 0, (ippiGeneralFunc)ippiRGBToHLS_16u_C3R, 0, + 0, (ippiGeneralFunc)ippiRGBToHLS_32f_C3R, 0, 0 +}; + +static const ippiGeneralFunc ippiHLS2RGBTab[CV_DEPTH_MAX] = +{ + (ippiGeneralFunc)ippiHLSToRGB_8u_C3R, 0, (ippiGeneralFunc)ippiHLSToRGB_16u_C3R, 0, + 0, (ippiGeneralFunc)ippiHLSToRGB_32f_C3R, 0, 0 +}; + +#if !IPP_DISABLE_RGB_XYZ +static const ippiGeneralFunc ippiRGB2XYZTab[CV_DEPTH_MAX] = +{ + (ippiGeneralFunc)ippiRGBToXYZ_8u_C3R, 0, (ippiGeneralFunc)ippiRGBToXYZ_16u_C3R, 0, + 0, (ippiGeneralFunc)ippiRGBToXYZ_32f_C3R, 0, 0 +}; +#endif + +#if !IPP_DISABLE_XYZ_RGB +static const ippiGeneralFunc ippiXYZ2RGBTab[CV_DEPTH_MAX] = +{ + (ippiGeneralFunc)ippiXYZToRGB_8u_C3R, 0, (ippiGeneralFunc)ippiXYZToRGB_16u_C3R, 0, + 0, (ippiGeneralFunc)ippiXYZToRGB_32f_C3R, 0, 0 +}; +#endif + +#if !IPP_DISABLE_RGB_LAB +static const ippiGeneralFunc ippiRGBToLUVTab[CV_DEPTH_MAX] = +{ + (ippiGeneralFunc)ippiRGBToLUV_8u_C3R, 0, (ippiGeneralFunc)ippiRGBToLUV_16u_C3R, 0, + 0, (ippiGeneralFunc)ippiRGBToLUV_32f_C3R, 0, 0 +}; +#endif + +#if !IPP_DISABLE_LAB_RGB +static const ippiGeneralFunc ippiLUVToRGBTab[CV_DEPTH_MAX] = +{ + (ippiGeneralFunc)ippiLUVToRGB_8u_C3R, 0, (ippiGeneralFunc)ippiLUVToRGB_16u_C3R, 0, + 0, (ippiGeneralFunc)ippiLUVToRGB_32f_C3R, 0, 0 +}; +#endif + +} // namespace + +int ipp_hal_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_HAL_CHECK_USE_IPP(); + + 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 CV_HAL_ERROR_OK; + } + else if(scn == 4 && dcn == 3 && !swapBlue) + { + if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPGeneralFunctor(ippiCopyAC4C3RTab[depth])) ) + return CV_HAL_ERROR_OK; + } + 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 CV_HAL_ERROR_OK; + } + 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 CV_HAL_ERROR_OK; + } + 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 CV_HAL_ERROR_OK; + } +#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 CV_HAL_ERROR_OK; + } +#endif + + return CV_HAL_ERROR_NOT_IMPLEMENTED; +} + +int ipp_hal_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_HAL_CHECK_USE_IPP(); + + 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()); + } + + return ippres ? CV_HAL_ERROR_OK : CV_HAL_ERROR_NOT_IMPLEMENTED; +} + +int ipp_hal_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_HAL_CHECK_USE_IPP(); + + // preserves original cvtBGRtoGray routing: only 32f was sent to IPP, other depths use the dispatch path + if (depth != CV_32F) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + + if(scn == 3 && !swapBlue) + { + if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPColor2GrayFunctor(ippiColor2GrayC3Tab[depth])) ) + return CV_HAL_ERROR_OK; + } + else if(scn == 3 && swapBlue) + { + if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPGeneralFunctor(ippiRGB2GrayC3Tab[depth])) ) + return CV_HAL_ERROR_OK; + } + else if(scn == 4 && !swapBlue) + { + if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPColor2GrayFunctor(ippiColor2GrayC4Tab[depth])) ) + return CV_HAL_ERROR_OK; + } + else if(scn == 4 && swapBlue) + { + if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPGeneralFunctor(ippiRGB2GrayC4Tab[depth])) ) + return CV_HAL_ERROR_OK; + } + + return CV_HAL_ERROR_NOT_IMPLEMENTED; +} + +int ipp_hal_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_HAL_CHECK_USE_IPP(); + + 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 CV_HAL_ERROR_OK; + } + 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 CV_HAL_ERROR_OK; + } + 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 CV_HAL_ERROR_OK; + } +#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 CV_HAL_ERROR_OK; + } + 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 CV_HAL_ERROR_OK; + } + 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 CV_HAL_ERROR_OK; + } + 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 CV_HAL_ERROR_OK; + } + } + } + + return CV_HAL_ERROR_NOT_IMPLEMENTED; +} + +int ipp_hal_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_HAL_CHECK_USE_IPP(); + + 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 CV_HAL_ERROR_OK; + } + 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 CV_HAL_ERROR_OK; + } + 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 CV_HAL_ERROR_OK; + } + 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 CV_HAL_ERROR_OK; + } + } + 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 CV_HAL_ERROR_OK; + } + 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 CV_HAL_ERROR_OK; + } + 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 CV_HAL_ERROR_OK; + } + 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 CV_HAL_ERROR_OK; + } + } + } + + return CV_HAL_ERROR_NOT_IMPLEMENTED; +} + +int ipp_hal_cvtRGBAtoMultipliedRGBA(const uchar * src_data, size_t src_step, uchar * dst_data, size_t dst_step, + int width, int height) +{ + CV_HAL_CHECK_USE_IPP(); + + if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPGeneralFunctor((ippiGeneralFunc)ippiAlphaPremul_8u_AC4R)) ) + return CV_HAL_ERROR_OK; + + return CV_HAL_ERROR_NOT_IMPLEMENTED; +} + +#if !IPP_DISABLE_RGB_YUV +int ipp_hal_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_HAL_CHECK_USE_IPP(); + + 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 CV_HAL_ERROR_OK; + } + 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 CV_HAL_ERROR_OK; + } + 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 CV_HAL_ERROR_OK; + } + 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 CV_HAL_ERROR_OK; + } + + return CV_HAL_ERROR_NOT_IMPLEMENTED; +} +#endif // !IPP_DISABLE_RGB_YUV + +#if !IPP_DISABLE_YUV_RGB +int ipp_hal_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_HAL_CHECK_USE_IPP(); + + 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 CV_HAL_ERROR_OK; + } + 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 CV_HAL_ERROR_OK; + } + 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 CV_HAL_ERROR_OK; + } + 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 CV_HAL_ERROR_OK; + } + + return CV_HAL_ERROR_NOT_IMPLEMENTED; +} +#endif // !IPP_DISABLE_YUV_RGB + +#if !IPP_DISABLE_RGB_XYZ +int ipp_hal_cvtBGRtoXYZ(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_HAL_CHECK_USE_IPP(); + + if(scn == 3 && depth != CV_32F && !swapBlue) + { + if( CvtColorIPPLoopCopy(src_data, src_step, CV_MAKETYPE(depth, scn), dst_data, dst_step, width, height, + IPPReorderGeneralFunctor(ippiSwapChannelsC3RTab[depth], ippiRGB2XYZTab[depth], 2, 1, 0, depth)) ) + return CV_HAL_ERROR_OK; + } + else if(scn == 4 && depth != CV_32F && !swapBlue) + { + if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], ippiRGB2XYZTab[depth], 2, 1, 0, depth)) ) + return CV_HAL_ERROR_OK; + } + else if(scn == 3 && depth != CV_32F && swapBlue) + { + if( CvtColorIPPLoopCopy(src_data, src_step, CV_MAKETYPE(depth, scn), dst_data, dst_step, width, height, + IPPGeneralFunctor(ippiRGB2XYZTab[depth])) ) + return CV_HAL_ERROR_OK; + } + else if(scn == 4 && depth != CV_32F && swapBlue) + { + if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], ippiRGB2XYZTab[depth], 0, 1, 2, depth)) ) + return CV_HAL_ERROR_OK; + } + + return CV_HAL_ERROR_NOT_IMPLEMENTED; +} +#endif // !IPP_DISABLE_RGB_XYZ + +#if !IPP_DISABLE_XYZ_RGB +int ipp_hal_cvtXYZtoBGR(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) +{ + CV_HAL_CHECK_USE_IPP(); + + if(dcn == 3 && depth != CV_32F && !swapBlue) + { + if( CvtColorIPPLoopCopy(src_data, src_step, CV_MAKETYPE(depth, 3), dst_data, dst_step, width, height, + IPPGeneralReorderFunctor(ippiXYZ2RGBTab[depth], ippiSwapChannelsC3RTab[depth], 2, 1, 0, depth)) ) + return CV_HAL_ERROR_OK; + } + else if(dcn == 4 && depth != CV_32F && !swapBlue) + { + if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPGeneralReorderFunctor(ippiXYZ2RGBTab[depth], ippiSwapChannelsC3C4RTab[depth], 2, 1, 0, depth)) ) + return CV_HAL_ERROR_OK; + } + if(dcn == 3 && depth != CV_32F && swapBlue) + { + if( CvtColorIPPLoopCopy(src_data, src_step, CV_MAKETYPE(depth, 3), dst_data, dst_step, width, height, + IPPGeneralFunctor(ippiXYZ2RGBTab[depth])) ) + return CV_HAL_ERROR_OK; + } + else if(dcn == 4 && depth != CV_32F && swapBlue) + { + if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPGeneralReorderFunctor(ippiXYZ2RGBTab[depth], ippiSwapChannelsC3C4RTab[depth], 0, 1, 2, depth)) ) + return CV_HAL_ERROR_OK; + } + + return CV_HAL_ERROR_NOT_IMPLEMENTED; +} +#endif // !IPP_DISABLE_XYZ_RGB + +#if !IPP_DISABLE_RGB_LAB +int ipp_hal_cvtBGRtoLab(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 isLab, bool srgb) +{ + CV_HAL_CHECK_USE_IPP(); + + if (!srgb) + { + if (isLab) + { + if (scn == 3 && depth == CV_8U && !swapBlue) + { + if (CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPGeneralFunctor((ippiGeneralFunc)ippiBGRToLab_8u_C3R))) + return CV_HAL_ERROR_OK; + } + else if (scn == 4 && depth == CV_8U && !swapBlue) + { + if (CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], + (ippiGeneralFunc)ippiBGRToLab_8u_C3R, 0, 1, 2, depth))) + return CV_HAL_ERROR_OK; + } + else if (scn == 3 && depth == CV_8U && swapBlue) // slower than OpenCV + { + if (CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPReorderGeneralFunctor(ippiSwapChannelsC3RTab[depth], + (ippiGeneralFunc)ippiBGRToLab_8u_C3R, 2, 1, 0, depth))) + return CV_HAL_ERROR_OK; + } + else if (scn == 4 && depth == CV_8U && swapBlue) // slower than OpenCV + { + if (CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], + (ippiGeneralFunc)ippiBGRToLab_8u_C3R, 2, 1, 0, depth))) + return CV_HAL_ERROR_OK; + } + } + else + { + if (scn == 3 && swapBlue) + { + if (CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPGeneralFunctor(ippiRGBToLUVTab[depth]))) + return CV_HAL_ERROR_OK; + } + else if (scn == 4 && swapBlue) + { + if (CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], + ippiRGBToLUVTab[depth], 0, 1, 2, depth))) + return CV_HAL_ERROR_OK; + } + else if (scn == 3 && !swapBlue) + { + if (CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPReorderGeneralFunctor(ippiSwapChannelsC3RTab[depth], + ippiRGBToLUVTab[depth], 2, 1, 0, depth))) + return CV_HAL_ERROR_OK; + } + else if (scn == 4 && !swapBlue) + { + if (CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], + ippiRGBToLUVTab[depth], 2, 1, 0, depth))) + return CV_HAL_ERROR_OK; + } + } + } + + return CV_HAL_ERROR_NOT_IMPLEMENTED; +} +#endif // !IPP_DISABLE_RGB_LAB + +#if !IPP_DISABLE_LAB_RGB +int ipp_hal_cvtLabtoBGR(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 isLab, bool srgb) +{ + CV_HAL_CHECK_USE_IPP(); + + if (!srgb) + { + if (isLab) + { + if( dcn == 3 && depth == CV_8U && !swapBlue) + { + if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPGeneralFunctor((ippiGeneralFunc)ippiLabToBGR_8u_C3R)) ) + return CV_HAL_ERROR_OK; + } + else if( dcn == 4 && depth == CV_8U && !swapBlue) + { + if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPGeneralReorderFunctor((ippiGeneralFunc)ippiLabToBGR_8u_C3R, + ippiSwapChannelsC3C4RTab[depth], 0, 1, 2, depth)) ) + return CV_HAL_ERROR_OK; + } + if( dcn == 3 && depth == CV_8U && swapBlue) + { + if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPGeneralReorderFunctor((ippiGeneralFunc)ippiLabToBGR_8u_C3R, + ippiSwapChannelsC3RTab[depth], 2, 1, 0, depth)) ) + return CV_HAL_ERROR_OK; + } + else if( dcn == 4 && depth == CV_8U && swapBlue) + { + if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPGeneralReorderFunctor((ippiGeneralFunc)ippiLabToBGR_8u_C3R, + ippiSwapChannelsC3C4RTab[depth], 2, 1, 0, depth)) ) + return CV_HAL_ERROR_OK; + } + } + else + { + if( dcn == 3 && swapBlue) + { + if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPGeneralFunctor(ippiLUVToRGBTab[depth])) ) + return CV_HAL_ERROR_OK; + } + else if( dcn == 4 && swapBlue) + { + if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPGeneralReorderFunctor(ippiLUVToRGBTab[depth], + ippiSwapChannelsC3C4RTab[depth], 0, 1, 2, depth)) ) + return CV_HAL_ERROR_OK; + } + if( dcn == 3 && !swapBlue) + { + if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPGeneralReorderFunctor(ippiLUVToRGBTab[depth], + ippiSwapChannelsC3RTab[depth], 2, 1, 0, depth)) ) + return CV_HAL_ERROR_OK; + } + else if( dcn == 4 && !swapBlue) + { + if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPGeneralReorderFunctor(ippiLUVToRGBTab[depth], + ippiSwapChannelsC3C4RTab[depth], 2, 1, 0, depth)) ) + return CV_HAL_ERROR_OK; + } + } + } + + return CV_HAL_ERROR_NOT_IMPLEMENTED; +} +#endif // !IPP_DISABLE_LAB_RGB + +#endif // IPP_VERSION_X100 >= 700 diff --git a/hal/ipp/src/precomp_ipp.hpp b/hal/ipp/src/precomp_ipp.hpp index 8136c2869d..0d68a5a40e 100644 --- a/hal/ipp/src/precomp_ipp.hpp +++ b/hal/ipp/src/precomp_ipp.hpp @@ -23,6 +23,20 @@ static inline IppiSize ippiSize(const cv::Size & _size) return size; } +#if IPP_VERSION_X100 >= 201700 +static inline IppiSizeL ippiSizeL(size_t width, size_t height) +{ + IppiSizeL size = { (IppSizeL)width, (IppSizeL)height }; + return size; +} + +static inline IppiSizeL ippiSizeL(const cv::Size & _size) +{ + IppiSizeL size = { _size.width, _size.height }; + return size; +} +#endif + static inline IppDataType ippiGetDataType(int depth) { depth = CV_MAT_DEPTH(depth); diff --git a/modules/core/include/opencv2/core/private.hpp b/modules/core/include/opencv2/core/private.hpp index 5cb624a62e..492cafaeca 100644 --- a/modules/core/include/opencv2/core/private.hpp +++ b/modules/core/include/opencv2/core/private.hpp @@ -191,13 +191,6 @@ T* allocSingletonNew() { return new(allocSingletonNewBuffer(sizeof(T))) T(); } #define IPP_DISABLE_PYRAMIDS_DOWN 1 // Different results #define IPP_DISABLE_PYRAMIDS_BUILD 1 // Different results #define IPP_DISABLE_REMAP 1 // Different results -#define IPP_DISABLE_YUV_RGB 1 // accuracy difference -#define IPP_DISABLE_RGB_YUV 1 // breaks OCL accuracy tests -#define IPP_DISABLE_RGB_HSV 1 // breaks OCL accuracy tests -#define IPP_DISABLE_RGB_LAB 1 // breaks OCL accuracy tests -#define IPP_DISABLE_LAB_RGB 1 // breaks OCL accuracy tests -#define IPP_DISABLE_RGB_XYZ 1 // big accuracy difference -#define IPP_DISABLE_XYZ_RGB 1 // big accuracy difference #define IPP_DISABLE_HOUGH 1 // improper integration/results #define IPP_DISABLE_FILTER2D_BIG_MASK 1 // different results on masks > 7x7 diff --git a/modules/imgproc/src/color.hpp b/modules/imgproc/src/color.hpp index e6130b6887..d0822f1080 100644 --- a/modules/imgproc/src/color.hpp +++ b/modules/imgproc/src/color.hpp @@ -333,184 +333,6 @@ struct OclHelper #endif - - -#if defined (HAVE_IPP) && (IPP_VERSION_X100 >= 700) -# define NEED_IPP 1 -#else -# define NEED_IPP 0 -#endif - -#if NEED_IPP - -#define MAX_IPP8u 255 -#define MAX_IPP16u 65535 -#define MAX_IPP32f 1.0 - -typedef IppStatus (CV_STDCALL* ippiReorderFunc)(const void *, int, void *, int, IppiSize, const int *); -typedef IppStatus (CV_STDCALL* ippiGeneralFunc)(const void *, int, void *, int, IppiSize); -typedef IppStatus (CV_STDCALL* ippiColor2GrayFunc)(const void *, int, void *, int, IppiSize, const Ipp32f *); - -template -class CvtColorIPPLoop_Invoker : - public ParallelLoopBody -{ -public: - - CvtColorIPPLoop_Invoker(const uchar * src_data_, size_t src_step_, uchar * dst_data_, size_t dst_step_, int width_, const Cvt& _cvt, bool *_ok) : - ParallelLoopBody(), src_data(src_data_), src_step(src_step_), dst_data(dst_data_), dst_step(dst_step_), width(width_), cvt(_cvt), ok(_ok) - { - *ok = true; - } - - virtual void operator()(const Range& range) const CV_OVERRIDE - { - const void *yS = src_data + src_step * range.start; - void *yD = dst_data + dst_step * range.start; - if( !cvt(yS, static_cast(src_step), yD, static_cast(dst_step), width, range.end - range.start) ) - *ok = false; - else - { - CV_IMPL_ADD(CV_IMPL_IPP|CV_IMPL_MT); - } - } - -private: - const uchar * src_data; - const size_t src_step; - uchar * dst_data; - const size_t dst_step; - const int width; - const Cvt& cvt; - bool *ok; - - const CvtColorIPPLoop_Invoker& operator= (const CvtColorIPPLoop_Invoker&); -}; - - -template -bool CvtColorIPPLoop(const uchar * src_data, size_t src_step, uchar * dst_data, size_t dst_step, int width, int height, const Cvt& cvt) -{ - bool ok; - parallel_for_(Range(0, height), CvtColorIPPLoop_Invoker(src_data, src_step, dst_data, dst_step, width, cvt, &ok), (width * height)/(double)(1<<16) ); - return ok; -} - - -template -bool CvtColorIPPLoopCopy(const uchar * src_data, size_t src_step, int src_type, uchar * dst_data, size_t dst_step, int width, int height, const Cvt& cvt) -{ - Mat temp; - Mat src(Size(width, height), src_type, const_cast(src_data), src_step); - Mat source = src; - if( src_data == dst_data ) - { - src.copyTo(temp); - source = temp; - } - bool ok; - parallel_for_(Range(0, source.rows), - CvtColorIPPLoop_Invoker(source.data, source.step, dst_data, dst_step, - source.cols, cvt, &ok), - source.total()/(double)(1<<16) ); - return ok; -} - - -struct IPPGeneralFunctor -{ - IPPGeneralFunctor(ippiGeneralFunc _func) : ippiColorConvertGeneral(_func){} - bool operator()(const void *src, int srcStep, void *dst, int dstStep, int cols, int rows) const - { - return ippiColorConvertGeneral ? CV_INSTRUMENT_FUN_IPP(ippiColorConvertGeneral, src, srcStep, dst, dstStep, ippiSize(cols, rows)) >= 0 : false; - } -private: - ippiGeneralFunc ippiColorConvertGeneral; -}; - - -struct IPPReorderFunctor -{ - IPPReorderFunctor(ippiReorderFunc _func, int _order0, int _order1, int _order2) : ippiColorConvertReorder(_func) - { - order[0] = _order0; - order[1] = _order1; - order[2] = _order2; - order[3] = 3; - } - bool operator()(const void *src, int srcStep, void *dst, int dstStep, int cols, int rows) const - { - return ippiColorConvertReorder ? CV_INSTRUMENT_FUN_IPP(ippiColorConvertReorder, src, srcStep, dst, dstStep, ippiSize(cols, rows), order) >= 0 : false; - } -private: - ippiReorderFunc ippiColorConvertReorder; - int order[4]; -}; - - -struct IPPReorderGeneralFunctor -{ - IPPReorderGeneralFunctor(ippiReorderFunc _func1, ippiGeneralFunc _func2, int _order0, int _order1, int _order2, int _depth) : - ippiColorConvertReorder(_func1), ippiColorConvertGeneral(_func2), depth(_depth) - { - order[0] = _order0; - order[1] = _order1; - order[2] = _order2; - order[3] = 3; - } - bool operator()(const void *src, int srcStep, void *dst, int dstStep, int cols, int rows) const - { - if (ippiColorConvertReorder == 0 || ippiColorConvertGeneral == 0) - return false; - - Mat temp; - temp.create(rows, cols, CV_MAKETYPE(depth, 3)); - if(CV_INSTRUMENT_FUN_IPP(ippiColorConvertReorder, src, srcStep, temp.ptr(), (int)temp.step[0], ippiSize(cols, rows), order) < 0) - return false; - return CV_INSTRUMENT_FUN_IPP(ippiColorConvertGeneral, temp.ptr(), (int)temp.step[0], dst, dstStep, ippiSize(cols, rows)) >= 0; - } -private: - ippiReorderFunc ippiColorConvertReorder; - ippiGeneralFunc ippiColorConvertGeneral; - int order[4]; - int depth; -}; - - -struct IPPGeneralReorderFunctor -{ - IPPGeneralReorderFunctor(ippiGeneralFunc _func1, ippiReorderFunc _func2, int _order0, int _order1, int _order2, int _depth) : - ippiColorConvertGeneral(_func1), ippiColorConvertReorder(_func2), depth(_depth) - { - order[0] = _order0; - order[1] = _order1; - order[2] = _order2; - order[3] = 3; - } - bool operator()(const void *src, int srcStep, void *dst, int dstStep, int cols, int rows) const - { - if (ippiColorConvertGeneral == 0 || ippiColorConvertReorder == 0) - return false; - - Mat temp; - temp.create(rows, cols, CV_MAKETYPE(depth, 3)); - if(CV_INSTRUMENT_FUN_IPP(ippiColorConvertGeneral, src, srcStep, temp.ptr(), (int)temp.step[0], ippiSize(cols, rows)) < 0) - return false; - return CV_INSTRUMENT_FUN_IPP(ippiColorConvertReorder, temp.ptr(), (int)temp.step[0], dst, dstStep, ippiSize(cols, rows), order) >= 0; - } -private: - ippiGeneralFunc ippiColorConvertGeneral; - ippiReorderFunc ippiColorConvertReorder; - int order[4]; - int depth; -}; - -extern ippiReorderFunc ippiSwapChannelsC3C4RTab[CV_DEPTH_MAX]; -extern ippiReorderFunc ippiSwapChannelsC4C3RTab[CV_DEPTH_MAX]; -extern ippiReorderFunc ippiSwapChannelsC3RTab[CV_DEPTH_MAX]; - -#endif - #ifdef HAVE_OPENCL bool oclCvtColorBGR2Luv( InputArray _src, OutputArray _dst, int bidx, bool srgb ); diff --git a/modules/imgproc/src/color.simd_helpers.hpp b/modules/imgproc/src/color.simd_helpers.hpp index ef675d129a..a3f5e9c1fd 100644 --- a/modules/imgproc/src/color.simd_helpers.hpp +++ b/modules/imgproc/src/color.simd_helpers.hpp @@ -39,6 +39,12 @@ template<> struct ColorChannel static inline float half() { return 0.5f; } }; +// in-place swap; works for sizeless scalable vector types, where std::swap may not compile +template static inline void v_swap(_Tp& a, _Tp& b) +{ + _Tp t = a; a = b; b = t; +} + /*template<> struct ColorChannel { typedef double worktype_f; @@ -173,4 +179,17 @@ void CvtColorLoop(const uchar * src_data, size_t src_step, uchar * dst_data, siz (width * height) / static_cast(1<<16)); } +// run CvtColorLoop for CV_8U/CV_16U/CV_32F, building the per-depth functor via make() +template static inline +void CvtColorLoopDepth(const uchar * src_data, size_t src_step, uchar * dst_data, size_t dst_step, + int width, int height, int depth, const MakeCvt& make) +{ + if( depth == CV_8U ) + CvtColorLoop(src_data, src_step, dst_data, dst_step, width, height, make(uchar(0))); + else if( depth == CV_16U ) + CvtColorLoop(src_data, src_step, dst_data, dst_step, width, height, make(ushort(0))); + else + CvtColorLoop(src_data, src_step, dst_data, dst_step, width, height, make(float(0))); +} + } //namespace diff --git a/modules/imgproc/src/color_hsv.dispatch.cpp b/modules/imgproc/src/color_hsv.dispatch.cpp index db7aa6fe84..9c1f5f1eda 100644 --- a/modules/imgproc/src/color_hsv.dispatch.cpp +++ b/modules/imgproc/src/color_hsv.dispatch.cpp @@ -13,40 +13,6 @@ namespace cv { -// -// IPP functions -// - -#if NEED_IPP - -#if !IPP_DISABLE_RGB_HSV -static ippiGeneralFunc ippiRGB2HSVTab[CV_DEPTH_MAX] = -{ - (ippiGeneralFunc)ippiRGBToHSV_8u_C3R, 0, (ippiGeneralFunc)ippiRGBToHSV_16u_C3R, 0, - 0, 0, 0, 0 -}; -#endif - -static ippiGeneralFunc ippiHSV2RGBTab[CV_DEPTH_MAX] = -{ - (ippiGeneralFunc)ippiHSVToRGB_8u_C3R, 0, (ippiGeneralFunc)ippiHSVToRGB_16u_C3R, 0, - 0, 0, 0, 0 -}; - -static ippiGeneralFunc ippiRGB2HLSTab[CV_DEPTH_MAX] = -{ - (ippiGeneralFunc)ippiRGBToHLS_8u_C3R, 0, (ippiGeneralFunc)ippiRGBToHLS_16u_C3R, 0, - 0, (ippiGeneralFunc)ippiRGBToHLS_32f_C3R, 0, 0 -}; - -static ippiGeneralFunc ippiHLS2RGBTab[CV_DEPTH_MAX] = -{ - (ippiGeneralFunc)ippiHLSToRGB_8u_C3R, 0, (ippiGeneralFunc)ippiHLSToRGB_16u_C3R, 0, - 0, (ippiGeneralFunc)ippiHLSToRGB_32f_C3R, 0, 0 -}; - -#endif - // // HAL functions // @@ -64,65 +30,6 @@ void cvtBGRtoHSV(const uchar * src_data, size_t src_step, 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); } @@ -137,69 +44,6 @@ void cvtHSVtoBGR(const uchar * src_data, size_t src_step, 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); } diff --git a/modules/imgproc/src/color_hsv.simd.hpp b/modules/imgproc/src/color_hsv.simd.hpp index 8ae663dff4..f3d952a7b8 100644 --- a/modules/imgproc/src/color_hsv.simd.hpp +++ b/modules/imgproc/src/color_hsv.simd.hpp @@ -5,19 +5,6 @@ #include "precomp.hpp" #include "opencv2/core/hal/intrin.hpp" -#if CV_SIMD_SCALABLE -/* FIX IT: -// std::swap(a, b) is not available for RVV vector types, -// and CV_SWAP needs another "t" as input, -// For compatibility, we swap RVV vector manually by using this macro. - -// If others scalable types (e.g. type in ARM SVE) can use std::swap, -// then replace CV_SIMD_SCALABLE with CV_RVV. -// If std::swap is available for RVV vector types in future, remove this macro. -*/ -#define swap(a, b) {auto t = a; a = b; b = t;} -#endif - namespace cv { namespace hal { CV_CPU_OPTIMIZATION_NAMESPACE_BEGIN @@ -115,7 +102,7 @@ struct RGB2HSV_b } if(bidx) - swap(b, r); + v_swap(b, r); v_uint8 h, s, v; v_uint8 vmin; @@ -323,7 +310,7 @@ struct RGB2HSV_f } if(bidx) - swap(b, r); + v_swap(b, r); v_float32 h, s, v; process(b, g, r, h, s, v, hscale); @@ -484,7 +471,7 @@ struct HSV2RGB_f HSV2RGB_simd(h, s, v, b, g, r, hs); if(bidx) - swap(b, r); + v_swap(b, r); if(dcn == 4) { @@ -738,7 +725,7 @@ struct RGB2HLS_f } if(bidx) - swap(r, b); + v_swap(r, b); process(r, g, b, vhscale, h, l, s); @@ -1026,7 +1013,7 @@ struct HLS2RGB_f process(h, l, s, b, g, r); if(bidx) - swap(b, r); + v_swap(b, r); if(dcn == 3) { diff --git a/modules/imgproc/src/color_lab.cpp b/modules/imgproc/src/color_lab.cpp index 00b42f9deb..9dbfc83ba3 100644 --- a/modules/imgproc/src/color_lab.cpp +++ b/modules/imgproc/src/color_lab.cpp @@ -95,6 +95,20 @@ template static inline cv::v_float32 splineInterpolate(const cv::v namespace cv { +// swap R<->B in a row-major 3x3 coeff matrix when blueIdx==0 +template static inline void swapBlueCoeffsCols(CT* coeffs) +{ + std::swap(coeffs[0], coeffs[2]); + std::swap(coeffs[3], coeffs[5]); + std::swap(coeffs[6], coeffs[8]); +} +template static inline void swapBlueCoeffsRows(CT* coeffs) +{ + std::swap(coeffs[0], coeffs[6]); + std::swap(coeffs[1], coeffs[7]); + std::swap(coeffs[2], coeffs[8]); +} + ////////////////////////////////////// RGB <-> XYZ /////////////////////////////////////// // 0.412453, 0.357580, 0.180423, @@ -152,11 +166,7 @@ template struct RGB2XYZ_f for(int i = 0; i < 9; i++) coeffs[i] = _coeffs ? _coeffs[i] : (float)sRGB2XYZ_D65[i]; if(blueIdx == 0) - { - std::swap(coeffs[0], coeffs[2]); - std::swap(coeffs[3], coeffs[5]); - std::swap(coeffs[6], coeffs[8]); - } + swapBlueCoeffsCols(coeffs); } void operator()(const _Tp* src, _Tp* dst, int n) const { @@ -189,11 +199,7 @@ struct RGB2XYZ_f for(int i = 0; i < 9; i++) coeffs[i] = _coeffs ? _coeffs[i] : (float)sRGB2XYZ_D65[i]; if(blueIdx == 0) - { - std::swap(coeffs[0], coeffs[2]); - std::swap(coeffs[3], coeffs[5]); - std::swap(coeffs[6], coeffs[8]); - } + swapBlueCoeffsCols(coeffs); } void operator()(const float* src, float* dst, int n) const @@ -257,11 +263,7 @@ template struct RGB2XYZ_i for( int i = 0; i < 9; i++ ) coeffs[i] = _coeffs ? cvRound(_coeffs[i]*(1 << xyz_shift)) : sRGB2XYZ_D65_i[i]; if(blueIdx == 0) - { - std::swap(coeffs[0], coeffs[2]); - std::swap(coeffs[3], coeffs[5]); - std::swap(coeffs[6], coeffs[8]); - } + swapBlueCoeffsCols(coeffs); } void operator()(const _Tp* src, _Tp* dst, int n) const { @@ -296,11 +298,7 @@ struct RGB2XYZ_i for( int i = 0; i < 9; i++ ) coeffs[i] = _coeffs ? cvRound(_coeffs[i]*(1 << shift)) : sRGB2XYZ_D65_i[i]; if(blueIdx == 0) - { - std::swap(coeffs[0], coeffs[2]); - std::swap(coeffs[3], coeffs[5]); - std::swap(coeffs[6], coeffs[8]); - } + swapBlueCoeffsCols(coeffs); } void operator()(const uchar * src, uchar * dst, int n) const { @@ -416,11 +414,7 @@ struct RGB2XYZ_i for( int i = 0; i < 9; i++ ) coeffs[i] = _coeffs ? cvRound(_coeffs[i]*(1 << shift)) : sRGB2XYZ_D65_i[i]; if(blueIdx == 0) - { - std::swap(coeffs[0], coeffs[2]); - std::swap(coeffs[3], coeffs[5]); - std::swap(coeffs[6], coeffs[8]); - } + swapBlueCoeffsCols(coeffs); } void operator()(const ushort * src, ushort * dst, int n) const @@ -542,11 +536,7 @@ template struct XYZ2RGB_f for(int i = 0; i < 9; i++) coeffs[i] = _coeffs ? _coeffs[i] : (float)XYZ2sRGB_D65[i]; if(blueIdx == 0) - { - std::swap(coeffs[0], coeffs[6]); - std::swap(coeffs[1], coeffs[7]); - std::swap(coeffs[2], coeffs[8]); - } + swapBlueCoeffsRows(coeffs); } void operator()(const _Tp* src, _Tp* dst, int n) const @@ -583,11 +573,7 @@ struct XYZ2RGB_f for(int i = 0; i < 9; i++) coeffs[i] = _coeffs ? _coeffs[i] : (float)XYZ2sRGB_D65[i]; if(blueIdx == 0) - { - std::swap(coeffs[0], coeffs[6]); - std::swap(coeffs[1], coeffs[7]); - std::swap(coeffs[2], coeffs[8]); - } + swapBlueCoeffsRows(coeffs); } void operator()(const float* src, float* dst, int n) const @@ -655,11 +641,7 @@ template struct XYZ2RGB_i coeffs[i] = _coeffs ? cvRound(_coeffs[i]*(1 << xyz_shift)) : XYZ2sRGB_D65_i[i]; if(blueIdx == 0) - { - std::swap(coeffs[0], coeffs[6]); - std::swap(coeffs[1], coeffs[7]); - std::swap(coeffs[2], coeffs[8]); - } + swapBlueCoeffsRows(coeffs); } void operator()(const _Tp* src, _Tp* dst, int n) const { @@ -698,11 +680,7 @@ struct XYZ2RGB_i coeffs[i] = _coeffs ? cvRound(_coeffs[i]*(1 << shift)) : XYZ2sRGB_D65_i[i]; if(blueIdx == 0) - { - std::swap(coeffs[0], coeffs[6]); - std::swap(coeffs[1], coeffs[7]); - std::swap(coeffs[2], coeffs[8]); - } + swapBlueCoeffsRows(coeffs); } void operator()(const uchar* src, uchar* dst, int n) const @@ -821,11 +799,7 @@ struct XYZ2RGB_i coeffs[i] = _coeffs ? cvRound(_coeffs[i]*(1 << shift)) : XYZ2sRGB_D65_i[i]; if(blueIdx == 0) - { - std::swap(coeffs[0], coeffs[6]); - std::swap(coeffs[1], coeffs[7]); - std::swap(coeffs[2], coeffs[8]); - } + swapBlueCoeffsRows(coeffs); } void operator()(const ushort* src, ushort* dst, int n) const @@ -4076,47 +4050,6 @@ struct Luv2RGB_b bool useBitExactness; }; -// -// IPP functions -// - -#if NEED_IPP - -#if !IPP_DISABLE_RGB_XYZ -static ippiGeneralFunc ippiRGB2XYZTab[CV_DEPTH_MAX] = -{ - (ippiGeneralFunc)ippiRGBToXYZ_8u_C3R, 0, (ippiGeneralFunc)ippiRGBToXYZ_16u_C3R, 0, - 0, (ippiGeneralFunc)ippiRGBToXYZ_32f_C3R, 0, 0 -}; -#endif - -#if !IPP_DISABLE_XYZ_RGB -static ippiGeneralFunc ippiXYZ2RGBTab[CV_DEPTH_MAX] = -{ - (ippiGeneralFunc)ippiXYZToRGB_8u_C3R, 0, (ippiGeneralFunc)ippiXYZToRGB_16u_C3R, 0, - 0, (ippiGeneralFunc)ippiXYZToRGB_32f_C3R, 0, 0 -}; -#endif - -#if !IPP_DISABLE_RGB_LAB -static ippiGeneralFunc ippiRGBToLUVTab[CV_DEPTH_MAX] = -{ - (ippiGeneralFunc)ippiRGBToLUV_8u_C3R, 0, (ippiGeneralFunc)ippiRGBToLUV_16u_C3R, 0, - 0, (ippiGeneralFunc)ippiRGBToLUV_32f_C3R, 0, 0 -}; -#endif - -#if !IPP_DISABLE_LAB_RGB -static ippiGeneralFunc ippiLUVToRGBTab[CV_DEPTH_MAX] = -{ - (ippiGeneralFunc)ippiLUVToRGB_8u_C3R, 0, (ippiGeneralFunc)ippiLUVToRGB_16u_C3R, 0, - 0, (ippiGeneralFunc)ippiLUVToRGB_32f_C3R, 0, 0 -}; -#endif - -#endif - - // // HAL functions // @@ -4133,38 +4066,6 @@ void cvtBGRtoXYZ(const uchar * src_data, size_t src_step, CALL_HAL(cvtBGRtoXYZ, cv_hal_cvtBGRtoXYZ, src_data, src_step, dst_data, dst_step, width, height, depth, scn, swapBlue); -#if defined(HAVE_IPP) && IPP_VERSION_X100 >= 700 -#if !IPP_DISABLE_RGB_XYZ - CV_IPP_CHECK() - { - if(scn == 3 && depth != CV_32F && !swapBlue) - { - if( CvtColorIPPLoopCopy(src_data, src_step, CV_MAKETYPE(depth, scn), dst_data, dst_step, width, height, - IPPReorderGeneralFunctor(ippiSwapChannelsC3RTab[depth], ippiRGB2XYZTab[depth], 2, 1, 0, depth)) ) - return; - } - else if(scn == 4 && depth != CV_32F && !swapBlue) - { - if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, - IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], ippiRGB2XYZTab[depth], 2, 1, 0, depth)) ) - return; - } - else if(scn == 3 && depth != CV_32F && swapBlue) - { - if( CvtColorIPPLoopCopy(src_data, src_step, CV_MAKETYPE(depth, scn), dst_data, dst_step, width, height, - IPPGeneralFunctor(ippiRGB2XYZTab[depth])) ) - return; - } - else if(scn == 4 && depth != CV_32F && swapBlue) - { - if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, - IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], ippiRGB2XYZTab[depth], 0, 1, 2, depth)) ) - return; - } - } -#endif -#endif - int blueIdx = swapBlue ? 2 : 0; if( depth == CV_8U ) CvtColorLoop(src_data, src_step, dst_data, dst_step, width, height, RGB2XYZ_i(scn, blueIdx, 0)); @@ -4184,38 +4085,6 @@ void cvtXYZtoBGR(const uchar * src_data, size_t src_step, CALL_HAL(cvtXYZtoBGR, cv_hal_cvtXYZtoBGR, src_data, src_step, dst_data, dst_step, width, height, depth, dcn, swapBlue); -#if defined(HAVE_IPP) && IPP_VERSION_X100 >= 700 -#if !IPP_DISABLE_XYZ_RGB - CV_IPP_CHECK() - { - if(dcn == 3 && depth != CV_32F && !swapBlue) - { - if( CvtColorIPPLoopCopy(src_data, src_step, CV_MAKETYPE(depth, 3), dst_data, dst_step, width, height, - IPPGeneralReorderFunctor(ippiXYZ2RGBTab[depth], ippiSwapChannelsC3RTab[depth], 2, 1, 0, depth)) ) - return; - } - else if(dcn == 4 && depth != CV_32F && !swapBlue) - { - if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, - IPPGeneralReorderFunctor(ippiXYZ2RGBTab[depth], ippiSwapChannelsC3C4RTab[depth], 2, 1, 0, depth)) ) - return; - } - if(dcn == 3 && depth != CV_32F && swapBlue) - { - if( CvtColorIPPLoopCopy(src_data, src_step, CV_MAKETYPE(depth, 3), dst_data, dst_step, width, height, - IPPGeneralFunctor(ippiXYZ2RGBTab[depth])) ) - return; - } - else if(dcn == 4 && depth != CV_32F && swapBlue) - { - if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, - IPPGeneralReorderFunctor(ippiXYZ2RGBTab[depth], ippiSwapChannelsC3C4RTab[depth], 0, 1, 2, depth)) ) - return; - } - } -#endif -#endif - int blueIdx = swapBlue ? 2 : 0; if( depth == CV_8U ) CvtColorLoop(src_data, src_step, dst_data, dst_step, width, height, XYZ2RGB_i(dcn, blueIdx, 0)); @@ -4236,75 +4105,6 @@ void cvtBGRtoLab(const uchar * src_data, size_t src_step, CALL_HAL(cvtBGRtoLab, cv_hal_cvtBGRtoLab, src_data, src_step, dst_data, dst_step, width, height, depth, scn, swapBlue, isLab, srgb); -#if defined(HAVE_IPP) && !IPP_DISABLE_RGB_LAB - CV_IPP_CHECK() - { - if (!srgb) - { - if (isLab) - { - if (scn == 3 && depth == CV_8U && !swapBlue) - { - if (CvtColorIPPLoop(src_data, src_step, dst_data,dst_step, width, height, - IPPGeneralFunctor((ippiGeneralFunc)ippiBGRToLab_8u_C3R))) - return; - } - else if (scn == 4 && depth == CV_8U && !swapBlue) - { - if (CvtColorIPPLoop(src_data, src_step, dst_data,dst_step, width, height, - IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], - (ippiGeneralFunc)ippiBGRToLab_8u_C3R, 0, 1, 2, depth))) - return; - } - else if (scn == 3 && depth == CV_8U && swapBlue) // slower than OpenCV - { - if (CvtColorIPPLoop(src_data, src_step, dst_data,dst_step, width, height, - IPPReorderGeneralFunctor(ippiSwapChannelsC3RTab[depth], - (ippiGeneralFunc)ippiBGRToLab_8u_C3R, 2, 1, 0, depth))) - return; - } - else if (scn == 4 && depth == CV_8U && swapBlue) // slower than OpenCV - { - if (CvtColorIPPLoop(src_data, src_step, dst_data,dst_step, width, height, - IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], - (ippiGeneralFunc)ippiBGRToLab_8u_C3R, 2, 1, 0, depth))) - return; - } - } - else - { - if (scn == 3 && swapBlue) - { - if (CvtColorIPPLoop(src_data, src_step, dst_data,dst_step, width, height, - IPPGeneralFunctor(ippiRGBToLUVTab[depth]))) - return; - } - else if (scn == 4 && swapBlue) - { - if (CvtColorIPPLoop(src_data, src_step, dst_data,dst_step, width, height, - IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], - ippiRGBToLUVTab[depth], 0, 1, 2, depth))) - return; - } - else if (scn == 3 && !swapBlue) - { - if (CvtColorIPPLoop(src_data, src_step, dst_data,dst_step, width, height, - IPPReorderGeneralFunctor(ippiSwapChannelsC3RTab[depth], - ippiRGBToLUVTab[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], - ippiRGBToLUVTab[depth], 2, 1, 0, depth))) - return; - } - } - } - } -#endif - int blueIdx = swapBlue ? 2 : 0; if(isLab) { @@ -4333,75 +4133,6 @@ void cvtLabtoBGR(const uchar * src_data, size_t src_step, CALL_HAL(cvtLabtoBGR, cv_hal_cvtLabtoBGR, src_data, src_step, dst_data, dst_step, width, height, depth, dcn, swapBlue, isLab, srgb); -#if defined(HAVE_IPP) && !IPP_DISABLE_LAB_RGB - CV_IPP_CHECK() - { - if (!srgb) - { - if (isLab) - { - if( dcn == 3 && depth == CV_8U && !swapBlue) - { - if( CvtColorIPPLoop(src_data, src_step, dst_data,dst_step, width, height, - IPPGeneralFunctor((ippiGeneralFunc)ippiLabToBGR_8u_C3R)) ) - return; - } - else if( dcn == 4 && depth == CV_8U && !swapBlue) - { - if( CvtColorIPPLoop(src_data, src_step, dst_data,dst_step, width, height, - IPPGeneralReorderFunctor((ippiGeneralFunc)ippiLabToBGR_8u_C3R, - ippiSwapChannelsC3C4RTab[depth], 0, 1, 2, depth)) ) - return; - } - if( dcn == 3 && depth == CV_8U && swapBlue) - { - if( CvtColorIPPLoop(src_data, src_step, dst_data,dst_step, width, height, - IPPGeneralReorderFunctor((ippiGeneralFunc)ippiLabToBGR_8u_C3R, - ippiSwapChannelsC3RTab[depth], 2, 1, 0, depth)) ) - return; - } - else if( dcn == 4 && depth == CV_8U && swapBlue) - { - if( CvtColorIPPLoop(src_data, src_step, dst_data,dst_step, width, height, - IPPGeneralReorderFunctor((ippiGeneralFunc)ippiLabToBGR_8u_C3R, - ippiSwapChannelsC3C4RTab[depth], 2, 1, 0, depth)) ) - return; - } - } - else - { - if( dcn == 3 && swapBlue) - { - if( CvtColorIPPLoop(src_data, src_step, dst_data,dst_step, width, height, - IPPGeneralFunctor(ippiLUVToRGBTab[depth])) ) - return; - } - else if( dcn == 4 && swapBlue) - { - if( CvtColorIPPLoop(src_data, src_step, dst_data,dst_step, width, height, - IPPGeneralReorderFunctor(ippiLUVToRGBTab[depth], - ippiSwapChannelsC3C4RTab[depth], 0, 1, 2, depth)) ) - return; - } - if( dcn == 3 && !swapBlue) - { - if( CvtColorIPPLoop(src_data, src_step, dst_data,dst_step, width, height, - IPPGeneralReorderFunctor(ippiLUVToRGBTab[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(ippiLUVToRGBTab[depth], - ippiSwapChannelsC3C4RTab[depth], 2, 1, 0, depth)) ) - return; - } - } - } - } -#endif - int blueIdx = swapBlue ? 2 : 0; if(isLab) { @@ -4714,11 +4445,7 @@ bool oclCvtColorBGR2XYZ( InputArray _src, OutputArray _dst, int bidx ) for(int i = 0; i < 9; i++) coeffs[i] = (float)sRGB2XYZ_D65[i]; if (bidx == 0) - { - std::swap(coeffs[0], coeffs[2]); - std::swap(coeffs[3], coeffs[5]); - std::swap(coeffs[6], coeffs[8]); - } + swapBlueCoeffsCols(coeffs); Mat(1, 9, CV_32FC1, &coeffs[0]).copyTo(c); } else @@ -4727,11 +4454,7 @@ bool oclCvtColorBGR2XYZ( InputArray _src, OutputArray _dst, int bidx ) for(int i = 0; i < 9; i++) coeffs[i] = sRGB2XYZ_D65_i[i]; if (bidx == 0) - { - std::swap(coeffs[0], coeffs[2]); - std::swap(coeffs[3], coeffs[5]); - std::swap(coeffs[6], coeffs[8]); - } + swapBlueCoeffsCols(coeffs); Mat(1, 9, CV_32SC1, &coeffs[0]).copyTo(c); } @@ -4762,11 +4485,7 @@ bool oclCvtColorXYZ2BGR( InputArray _src, OutputArray _dst, int dcn, int bidx ) for(int i = 0; i < 9; i++) coeffs[i] = (float)XYZ2sRGB_D65[i]; if (bidx == 0) - { - std::swap(coeffs[0], coeffs[6]); - std::swap(coeffs[1], coeffs[7]); - std::swap(coeffs[2], coeffs[8]); - } + swapBlueCoeffsRows(coeffs); Mat(1, 9, CV_32FC1, &coeffs[0]).copyTo(c); } else @@ -4775,11 +4494,7 @@ bool oclCvtColorXYZ2BGR( InputArray _src, OutputArray _dst, int dcn, int bidx ) for(int i = 0; i < 9; i++) coeffs[i] = XYZ2sRGB_D65_i[i]; if (bidx == 0) - { - std::swap(coeffs[0], coeffs[6]); - std::swap(coeffs[1], coeffs[7]); - std::swap(coeffs[2], coeffs[8]); - } + swapBlueCoeffsRows(coeffs); Mat(1, 9, CV_32SC1, &coeffs[0]).copyTo(c); } diff --git a/modules/imgproc/src/color_rgb.dispatch.cpp b/modules/imgproc/src/color_rgb.dispatch.cpp index 746480b962..6a724def86 100644 --- a/modules/imgproc/src/color_rgb.dispatch.cpp +++ b/modules/imgproc/src/color_rgb.dispatch.cpp @@ -10,169 +10,8 @@ #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[CV_DEPTH_MAX] = -{ - (ippiColor2GrayFunc)ippiColorToGray_8u_C3C1R, 0, (ippiColor2GrayFunc)ippiColorToGray_16u_C3C1R, 0, - 0, (ippiColor2GrayFunc)ippiColorToGray_32f_C3C1R, 0, 0 -}; - -static const ippiColor2GrayFunc ippiColor2GrayC4Tab[CV_DEPTH_MAX] = -{ - (ippiColor2GrayFunc)ippiColorToGray_8u_AC4C1R, 0, (ippiColor2GrayFunc)ippiColorToGray_16u_AC4C1R, 0, - 0, (ippiColor2GrayFunc)ippiColorToGray_32f_AC4C1R, 0, 0 -}; - -static const ippiGeneralFunc ippiRGB2GrayC3Tab[CV_DEPTH_MAX] = -{ - (ippiGeneralFunc)ippiRGBToGray_8u_C3C1R, 0, (ippiGeneralFunc)ippiRGBToGray_16u_C3C1R, 0, - 0, (ippiGeneralFunc)ippiRGBToGray_32f_C3C1R, 0, 0 -}; - -static const ippiGeneralFunc ippiRGB2GrayC4Tab[CV_DEPTH_MAX] = -{ - (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[CV_DEPTH_MAX] = -{ - (ippiReorderFunc)ippiSwapChannels_8u_C3C4Rf, 0, (ippiReorderFunc)ippiSwapChannels_16u_C3C4Rf, 0, - 0, (ippiReorderFunc)ippiSwapChannels_32f_C3C4Rf, 0, 0 -}; - -static ippiGeneralFunc ippiCopyAC4C3RTab[CV_DEPTH_MAX] = -{ - (ippiGeneralFunc)ippiCopy_8u_AC4C3R, 0, (ippiGeneralFunc)ippiCopy_16u_AC4C3R, 0, - 0, (ippiGeneralFunc)ippiCopy_32f_AC4C3R, 0, 0 -}; - -// shared -ippiReorderFunc ippiSwapChannelsC4C3RTab[CV_DEPTH_MAX] = -{ - (ippiReorderFunc)ippiSwapChannels_8u_C4C3R, 0, (ippiReorderFunc)ippiSwapChannels_16u_C4C3R, 0, - 0, (ippiReorderFunc)ippiSwapChannels_32f_C4C3R, 0, 0 -}; - -// shared -ippiReorderFunc ippiSwapChannelsC3RTab[CV_DEPTH_MAX] = -{ - (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[CV_DEPTH_MAX] = -{ - (ippiReorderFunc)ippiSwapChannels_8u_C4R, 0, (ippiReorderFunc)ippiSwapChannels_16u_C4R, 0, - 0, (ippiReorderFunc)ippiSwapChannels_32f_C4R, 0, 0 -}; -#endif - -#endif - // // HAL functions // @@ -189,50 +28,6 @@ void cvtBGRtoBGR(const uchar * src_data, size_t src_step, 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); } @@ -275,36 +70,6 @@ void cvtBGRtoGray(const uchar * src_data, size_t src_step, 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); } @@ -319,37 +84,6 @@ void cvtGraytoBGR(const uchar * src_data, size_t src_step, 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); } @@ -390,15 +124,6 @@ void cvtRGBAtoMultipliedRGBA(const uchar * src_data, size_t src_step, 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); } diff --git a/modules/imgproc/src/color_rgb.simd.hpp b/modules/imgproc/src/color_rgb.simd.hpp index 40e3854460..d0c8c6a51a 100644 --- a/modules/imgproc/src/color_rgb.simd.hpp +++ b/modules/imgproc/src/color_rgb.simd.hpp @@ -139,11 +139,7 @@ struct RGB2RGB d = v_set<_Tp>::set(alphav); } if(bi == 2) { - #if CV_SIMD_SCALABLE - auto t = a; a = c; c = t; // swap(a, c); - #else - swap(a, c); - #endif + v_swap(a, c); } if(dcn == 4) @@ -235,11 +231,7 @@ struct RGB5x52RGB r = v_pack(r0, r1); if(bidx == 2) { - #if CV_SIMD_SCALABLE - auto t = r; r = b; b = t; // swap(b, r); - #else - swap(b, r); - #endif + v_swap(b, r); } if(dcn == 4) { @@ -318,11 +310,7 @@ struct RGB2RGB5x5 v_load_deinterleave(src, b, g, r, a); } if(bidx == 2){ - #if CV_SIMD_SCALABLE - auto t = r; r = b; b = t; // swap(b, r); - #else - swap(b, r); - #endif + v_swap(b, r); } r = v_and(r, v7); @@ -1106,12 +1094,8 @@ void cvtBGRtoBGR(const uchar * src_data, size_t src_step, CV_INSTRUMENT_REGION(); int blueIdx = swapBlue ? 2 : 0; - if( depth == CV_8U ) - CvtColorLoop(src_data, src_step, dst_data, dst_step, width, height, RGB2RGB(scn, dcn, blueIdx)); - else if( depth == CV_16U ) - CvtColorLoop(src_data, src_step, dst_data, dst_step, width, height, RGB2RGB(scn, dcn, blueIdx)); - else - CvtColorLoop(src_data, src_step, dst_data, dst_step, width, height, RGB2RGB(scn, dcn, blueIdx)); + CvtColorLoopDepth(src_data, src_step, dst_data, dst_step, width, height, depth, + [&](auto t){ using T = decltype(t); return RGB2RGB(scn, dcn, blueIdx); }); } // only 8u @@ -1145,12 +1129,8 @@ void cvtBGRtoGray(const uchar * src_data, size_t src_step, CV_INSTRUMENT_REGION(); int blueIdx = swapBlue ? 2 : 0; - if( depth == CV_8U ) - CvtColorLoop(src_data, src_step, dst_data, dst_step, width, height, RGB2Gray(scn, blueIdx, 0)); - else if( depth == CV_16U ) - CvtColorLoop(src_data, src_step, dst_data, dst_step, width, height, RGB2Gray(scn, blueIdx, 0)); - else - CvtColorLoop(src_data, src_step, dst_data, dst_step, width, height, RGB2Gray(scn, blueIdx, 0)); + CvtColorLoopDepth(src_data, src_step, dst_data, dst_step, width, height, depth, + [&](auto t){ using T = decltype(t); return RGB2Gray(scn, blueIdx, 0); }); } // 8u, 16u, 32f @@ -1161,12 +1141,8 @@ void cvtGraytoBGR(const uchar * src_data, size_t src_step, { CV_INSTRUMENT_REGION(); - if( depth == CV_8U ) - CvtColorLoop(src_data, src_step, dst_data, dst_step, width, height, Gray2RGB(dcn)); - else if( depth == CV_16U ) - CvtColorLoop(src_data, src_step, dst_data, dst_step, width, height, Gray2RGB(dcn)); - else - CvtColorLoop(src_data, src_step, dst_data, dst_step, width, height, Gray2RGB(dcn)); + CvtColorLoopDepth(src_data, src_step, dst_data, dst_step, width, height, depth, + [&](auto t){ using T = decltype(t); return Gray2RGB(dcn); }); } // only 8u diff --git a/modules/imgproc/src/color_yuv.dispatch.cpp b/modules/imgproc/src/color_yuv.dispatch.cpp index 2a869d5b4a..361eca16e0 100644 --- a/modules/imgproc/src/color_yuv.dispatch.cpp +++ b/modules/imgproc/src/color_yuv.dispatch.cpp @@ -32,41 +32,6 @@ void cvtBGRtoYUV(const uchar * src_data, size_t src_step, 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); } @@ -85,42 +50,6 @@ void cvtYUVtoBGR(const uchar * src_data, size_t src_step, 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); } @@ -488,13 +417,6 @@ 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); } diff --git a/modules/imgproc/src/color_yuv.simd.hpp b/modules/imgproc/src/color_yuv.simd.hpp index 44f38a3418..63f24262a9 100644 --- a/modules/imgproc/src/color_yuv.simd.hpp +++ b/modules/imgproc/src/color_yuv.simd.hpp @@ -53,15 +53,6 @@ void cvtOnePlaneBGRtoYUV(const uchar * src_data, size_t src_step, namespace { //constants for conversion from/to RGB and YUV, YCrCb according to BT.601 -#if CV_SIMD_SCALABLE -template -static void swap(T&a, T&b) { - T t = a; - a = b; - b = t; -} -#endif - //to YCbCr static const float YCBF = 0.564f; // == 1/2/(1-B2YF) static const float YCRF = 0.713f; // == 1/2/(1-R2YF) @@ -91,6 +82,14 @@ static const int CB2GI = -5636; static const int CR2GI = -11698; static const int CR2RI = 22987; +// select YCrCb (crcb) or YUV (yuv) coefficients into coeffs; size N deduced +template +static inline void selectYuvCoeffs(CT (&coeffs)[N], bool isCrCb, const CT (&crcb)[N], const CT (&yuv)[N]) +{ + for(int i = 0; i < N; i++) + coeffs[i] = isCrCb ? crcb[i] : yuv[i]; +} + ///////////////////////////////////// RGB <-> YCrCb ////////////////////////////////////// template struct RGB2YCrCb_f @@ -102,10 +101,7 @@ template struct RGB2YCrCb_f { static const float coeffs_crb[] = { R2YF, G2YF, B2YF, YCRF, YCBF }; static const float coeffs_yuv[] = { R2YF, G2YF, B2YF, R2VF, B2UF }; - for(int i = 0; i < 5; i++) - { - coeffs[i] = isCrCb ? coeffs_crb[i] : coeffs_yuv[i]; - } + selectYuvCoeffs(coeffs, isCrCb, coeffs_crb, coeffs_yuv); if(blueIdx == 0) std::swap(coeffs[0], coeffs[2]); } @@ -140,10 +136,7 @@ struct RGB2YCrCb_f { static const float coeffs_crb[] = { R2YF, G2YF, B2YF, YCRF, YCBF }; static const float coeffs_yuv[] = { R2YF, G2YF, B2YF, R2VF, B2UF }; - for(int i = 0; i < 5; i++) - { - coeffs[i] = isCrCb ? coeffs_crb[i] : coeffs_yuv[i]; - } + selectYuvCoeffs(coeffs, isCrCb, coeffs_crb, coeffs_yuv); if(blueIdx == 0) std::swap(coeffs[0], coeffs[2]); } @@ -178,7 +171,7 @@ struct RGB2YCrCb_f y = v_fma(b, vc0, v_fma(g, vc1, v_mul(r, vc2))); if(bidx) - swap(r, b); + v_swap(r, b); cr = v_fma(v_sub(r, y), vc3, vdelta); cb = v_fma(v_sub(b, y), vc4, vdelta); @@ -222,10 +215,7 @@ template struct RGB2YCrCb_i static const int coeffs_crb[] = { R2Y, G2Y, B2Y, YCRI, YCBI }; static const int coeffs_yuv[] = { R2Y, G2Y, B2Y, R2VI, B2UI }; - for(int i = 0; i < 5; i++) - { - coeffs[i] = isCrCb ? coeffs_crb[i] : coeffs_yuv[i]; - } + selectYuvCoeffs(coeffs, isCrCb, coeffs_crb, coeffs_yuv); if(blueIdx==0) std::swap(coeffs[0], coeffs[2]); } void operator()(const _Tp* src, _Tp* dst, int n) const @@ -264,10 +254,7 @@ struct RGB2YCrCb_i static const int coeffs_crb[] = { R2Y, G2Y, B2Y, YCRI, YCBI }; static const int coeffs_yuv[] = { R2Y, G2Y, B2Y, R2VI, B2UI }; - for(int i = 0; i < 5; i++) - { - coeffs[i] = isCrCb ? coeffs_crb[i] : coeffs_yuv[i]; - } + selectYuvCoeffs(coeffs, isCrCb, coeffs_crb, coeffs_yuv); if(blueIdx==0) std::swap(coeffs[0], coeffs[2]); } @@ -336,7 +323,7 @@ struct RGB2YCrCb_i y = v_reinterpret_as_u16(v_add_wrap(v_pack(ssy0, ssy1), fixmul)); if(bidx) - swap(r, b); + v_swap(r, b); // (r-Y) and (b-Y) don't fit into int16 or uint16 range v_uint32 r0, r1, b0, b1; @@ -405,10 +392,7 @@ struct RGB2YCrCb_i { static const int coeffs_crb[] = { R2Y, G2Y, B2Y, YCRI, YCBI }; static const int coeffs_yuv[] = { R2Y, G2Y, B2Y, R2VI, B2UI }; - for(int i = 0; i < 5; i++) - { - coeffs[i] = isCrCb ? coeffs_crb[i] : coeffs_yuv[i]; - } + selectYuvCoeffs(coeffs, isCrCb, coeffs_crb, coeffs_yuv); if (blueIdx==0) std::swap(coeffs[0], coeffs[2]); } @@ -495,7 +479,7 @@ struct RGB2YCrCb_i if(bidx) { - swap(sr0, sb0); swap(sr1, sb1); + v_swap(sr0, sb0); v_swap(sr1, sb1); } v_int32 cr00, cr01, cr10, cr11; @@ -579,10 +563,7 @@ template struct YCrCb2RGB_f { static const float coeffs_cbr[] = {CR2RF, CR2GF, CB2GF, CB2BF}; static const float coeffs_yuv[] = { V2RF, V2GF, U2GF, U2BF}; - for(int i = 0; i < 4; i++) - { - coeffs[i] = isCrCb ? coeffs_cbr[i] : coeffs_yuv[i]; - } + selectYuvCoeffs(coeffs, isCrCb, coeffs_cbr, coeffs_yuv); } void operator()(const _Tp* src, _Tp* dst, int n) const { @@ -622,10 +603,7 @@ struct YCrCb2RGB_f { static const float coeffs_cbr[] = {CR2RF, CR2GF, CB2GF, CB2BF}; static const float coeffs_yuv[] = { V2RF, V2GF, U2GF, U2BF}; - for(int i = 0; i < 4; i++) - { - coeffs[i] = isCrCb ? coeffs_cbr[i] : coeffs_yuv[i]; - } + selectYuvCoeffs(coeffs, isCrCb, coeffs_cbr, coeffs_yuv); } void operator()(const float* src, float* dst, int n) const @@ -659,7 +637,7 @@ struct YCrCb2RGB_f r = v_fma(cr, vc0, y); if(bidx) - swap(r, b); + v_swap(r, b); if(dcn == 3) v_store_interleave(dst, b, g, r); @@ -699,10 +677,7 @@ template struct YCrCb2RGB_i { static const int coeffs_crb[] = { CR2RI, CR2GI, CB2GI, CB2BI}; static const int coeffs_yuv[] = { V2RI, V2GI, U2GI, U2BI }; - for(int i = 0; i < 4; i++) - { - coeffs[i] = isCrCb ? coeffs_crb[i] : coeffs_yuv[i]; - } + selectYuvCoeffs(coeffs, isCrCb, coeffs_crb, coeffs_yuv); } void operator()(const _Tp* src, _Tp* dst, int n) const @@ -746,10 +721,7 @@ struct YCrCb2RGB_i { static const int coeffs_crb[] = { CR2RI, CR2GI, CB2GI, CB2BI}; static const int coeffs_yuv[] = { V2RI, V2GI, U2GI, U2BI }; - for(int i = 0; i < 4; i++) - { - coeffs[i] = isCrCb ? coeffs_crb[i] : coeffs_yuv[i]; - } + selectYuvCoeffs(coeffs, isCrCb, coeffs_crb, coeffs_yuv); } void operator()(const uchar* src, uchar* dst, int n) const @@ -849,7 +821,7 @@ struct YCrCb2RGB_i r = v_pack_u(r0, r1); if(bidx) - swap(r, b); + v_swap(r, b); if(dcn == 3) { @@ -897,10 +869,7 @@ struct YCrCb2RGB_i { static const int coeffs_crb[] = { CR2RI, CR2GI, CB2GI, CB2BI}; static const int coeffs_yuv[] = { V2RI, V2GI, U2GI, U2BI }; - for(int i = 0; i < 4; i++) - { - coeffs[i] = isCrCb ? coeffs_crb[i] : coeffs_yuv[i]; - } + selectYuvCoeffs(coeffs, isCrCb, coeffs_crb, coeffs_yuv); } void operator()(const ushort* src, ushort* dst, int n) const @@ -976,7 +945,7 @@ struct YCrCb2RGB_i r = v_pack_u(r0, r1); if(bidx) - swap(r, b); + v_swap(r, b); if(dcn == 3) { @@ -1191,6 +1160,74 @@ static inline void cvtYuv42xxp2RGB8(const uchar u, const uchar v, } } +#if (CV_SIMD || CV_SIMD_SCALABLE) +// shared SIMD body for YUV420 sp/p -> RGB: u,v + 4 luma vectors -> two interleaved RGB rows +template +static CV_ALWAYS_INLINE void storeYUV420block(const v_uint8& u, const v_uint8& v, + const v_uint8& vy0, const v_uint8& vy1, + const v_uint8& vy2, const v_uint8& vy3, + const v_uint8& a, int vsize, uchar* row1, uchar* row2) +{ + v_int32 ruv0, ruv1, ruv2, ruv3, + guv0, guv1, guv2, guv3, + buv0, buv1, buv2, buv3; + uvToRGBuv(u, v, + ruv0, ruv1, ruv2, ruv3, + guv0, guv1, guv2, guv3, + buv0, buv1, buv2, buv3); + + v_uint8 r0, r1, r2, r3, g0, g1, g2, g3, b0, b1, b2, b3; + + auto call_yRGBuvToRGBA = [&](const v_uint8& vy, v_uint8& r, v_uint8& g, v_uint8& b) { + yRGBuvToRGBA(vy, + ruv0, ruv1, ruv2, ruv3, + guv0, guv1, guv2, guv3, + buv0, buv1, buv2, buv3, + r, g, b); + }; + call_yRGBuvToRGBA(vy0, r0, g0, b0); + call_yRGBuvToRGBA(vy1, r1, g1, b1); + call_yRGBuvToRGBA(vy2, r2, g2, b2); + call_yRGBuvToRGBA(vy3, r3, g3, b3); + + if(bIdx) + { + v_swap(r0, b0); + v_swap(r1, b1); + v_swap(r2, b2); + v_swap(r3, b3); + } + + // [r0...], [r1...] => [r0, r1, r0, r1...], [r0, r1, r0, r1...] + v_uint8 r0_0, r0_1, r1_0, r1_1; + v_zip(r0, r1, r0_0, r0_1); + v_zip(r2, r3, r1_0, r1_1); + v_uint8 g0_0, g0_1, g1_0, g1_1; + v_zip(g0, g1, g0_0, g0_1); + v_zip(g2, g3, g1_0, g1_1); + v_uint8 b0_0, b0_1, b1_0, b1_1; + v_zip(b0, b1, b0_0, b0_1); + v_zip(b2, b3, b1_0, b1_1); + + if(dcn == 4) + { + v_store_interleave(row1 + 0*vsize, b0_0, g0_0, r0_0, a); + v_store_interleave(row1 + 4*vsize, b0_1, g0_1, r0_1, a); + + v_store_interleave(row2 + 0*vsize, b1_0, g1_0, r1_0, a); + v_store_interleave(row2 + 4*vsize, b1_1, g1_1, r1_1, a); + } + else //dcn == 3 + { + v_store_interleave(row1 + 0*vsize, b0_0, g0_0, r0_0); + v_store_interleave(row1 + 3*vsize, b0_1, g0_1, r0_1); + + v_store_interleave(row2 + 0*vsize, b1_0, g1_0, r1_0); + v_store_interleave(row2 + 3*vsize, b1_1, g1_1, r1_1); + } +} +#endif + // bIdx is 0 or 2, uIdx is 0 or 1, dcn is 3 or 4 template struct YUV420sp2RGB8Invoker : ParallelLoopBody @@ -1233,70 +1270,14 @@ struct YUV420sp2RGB8Invoker : ParallelLoopBody if(uIdx) { - swap(u, v); + v_swap(u, v); } v_uint8 vy0, vy1, vy2, vy3; v_load_deinterleave(y1 + i, vy0, vy1); v_load_deinterleave(y2 + i, vy2, vy3); - v_int32 ruv0, ruv1, ruv2, ruv3, - guv0, guv1, guv2, guv3, - buv0, buv1, buv2, buv3; - uvToRGBuv(u, v, - ruv0, ruv1, ruv2, ruv3, - guv0, guv1, guv2, guv3, - buv0, buv1, buv2, buv3); - - v_uint8 r0, r1, r2, r3, g0, g1, g2, g3, b0, b1, b2, b3; - - auto call_yRGBuvToRGBA = [&](const v_uint8& vy, v_uint8& r, v_uint8& g, v_uint8& b) { - yRGBuvToRGBA(vy, - ruv0, ruv1, ruv2, ruv3, - guv0, guv1, guv2, guv3, - buv0, buv1, buv2, buv3, - r, g, b); - }; - call_yRGBuvToRGBA(vy0, r0, g0, b0); - call_yRGBuvToRGBA(vy1, r1, g1, b1); - call_yRGBuvToRGBA(vy2, r2, g2, b2); - call_yRGBuvToRGBA(vy3, r3, g3, b3); - - if(bIdx) - { - swap(r0, b0); - swap(r1, b1); - swap(r2, b2); - swap(r3, b3); - } - - // [r0...], [r1...] => [r0, r1, r0, r1...], [r0, r1, r0, r1...] - v_uint8 r0_0, r0_1, r1_0, r1_1; - v_zip(r0, r1, r0_0, r0_1); - v_zip(r2, r3, r1_0, r1_1); - v_uint8 g0_0, g0_1, g1_0, g1_1; - v_zip(g0, g1, g0_0, g0_1); - v_zip(g2, g3, g1_0, g1_1); - v_uint8 b0_0, b0_1, b1_0, b1_1; - v_zip(b0, b1, b0_0, b0_1); - v_zip(b2, b3, b1_0, b1_1); - - if(dcn == 4) - { - v_store_interleave(row1 + 0*vsize, b0_0, g0_0, r0_0, a); - v_store_interleave(row1 + 4*vsize, b0_1, g0_1, r0_1, a); - - v_store_interleave(row2 + 0*vsize, b1_0, g1_0, r1_0, a); - v_store_interleave(row2 + 4*vsize, b1_1, g1_1, r1_1, a); - } - else //dcn == 3 - { - v_store_interleave(row1 + 0*vsize, b0_0, g0_0, r0_0); - v_store_interleave(row1 + 3*vsize, b0_1, g0_1, r0_1); - - v_store_interleave(row2 + 0*vsize, b1_0, g1_0, r1_0); - v_store_interleave(row2 + 3*vsize, b1_1, g1_1, r1_1); - } + storeYUV420block(u, v, vy0, vy1, vy2, vy3, a, vsize, row1, row2); } vx_cleanup(); #endif @@ -1368,63 +1349,7 @@ struct YUV420p2RGB8Invoker : ParallelLoopBody v_load_deinterleave(y1 + 2*i, vy0, vy1); v_load_deinterleave(y2 + 2*i, vy2, vy3); - v_int32 ruv0, ruv1, ruv2, ruv3, - guv0, guv1, guv2, guv3, - buv0, buv1, buv2, buv3; - uvToRGBuv(u, v, - ruv0, ruv1, ruv2, ruv3, - guv0, guv1, guv2, guv3, - buv0, buv1, buv2, buv3); - - v_uint8 r0, r1, r2, r3, g0, g1, g2, g3, b0, b1, b2, b3; - - auto call_yRGBuvToRGBA = [&](const v_uint8& vy, v_uint8& r, v_uint8& g, v_uint8& b) { - yRGBuvToRGBA(vy, - ruv0, ruv1, ruv2, ruv3, - guv0, guv1, guv2, guv3, - buv0, buv1, buv2, buv3, - r, g, b); - }; - call_yRGBuvToRGBA(vy0, r0, g0, b0); - call_yRGBuvToRGBA(vy1, r1, g1, b1); - call_yRGBuvToRGBA(vy2, r2, g2, b2); - call_yRGBuvToRGBA(vy3, r3, g3, b3); - - if(bIdx) - { - swap(r0, b0); - swap(r1, b1); - swap(r2, b2); - swap(r3, b3); - } - - // [r0...], [r1...] => [r0, r1, r0, r1...], [r0, r1, r0, r1...] - v_uint8 r0_0, r0_1, r1_0, r1_1; - v_zip(r0, r1, r0_0, r0_1); - v_zip(r2, r3, r1_0, r1_1); - v_uint8 g0_0, g0_1, g1_0, g1_1; - v_zip(g0, g1, g0_0, g0_1); - v_zip(g2, g3, g1_0, g1_1); - v_uint8 b0_0, b0_1, b1_0, b1_1; - v_zip(b0, b1, b0_0, b0_1); - v_zip(b2, b3, b1_0, b1_1); - - if(dcn == 4) - { - v_store_interleave(row1 + 0*vsize, b0_0, g0_0, r0_0, a); - v_store_interleave(row1 + 4*vsize, b0_1, g0_1, r0_1, a); - - v_store_interleave(row2 + 0*vsize, b1_0, g1_0, r1_0, a); - v_store_interleave(row2 + 4*vsize, b1_1, g1_1, r1_1, a); - } - else //dcn == 3 - { - v_store_interleave(row1 + 0*vsize, b0_0, g0_0, r0_0); - v_store_interleave(row1 + 3*vsize, b0_1, g0_1, r0_1); - - v_store_interleave(row2 + 0*vsize, b1_0, g1_0, r1_0); - v_store_interleave(row2 + 3*vsize, b1_1, g1_1, r1_1); - } + storeYUV420block(u, v, vy0, vy1, vy2, vy3, a, vsize, row1, row2); } vx_cleanup(); #endif @@ -1632,7 +1557,7 @@ struct RGB8toYUV420pInvoker: public ParallelLoopBody if(swapBlue) { - swap(b0, r0); swap(b1, r1); + v_swap(b0, r0); v_swap(b1, r1); } v_uint8 y0, y1; @@ -1650,7 +1575,7 @@ struct RGB8toYUV420pInvoker: public ParallelLoopBody if(swapUV) { - swap(u, v); + v_swap(u, v); } if(interleave) @@ -1680,7 +1605,7 @@ struct RGB8toYUV420pInvoker: public ParallelLoopBody if(swapBlue) { - swap(b0, r0); swap(b1, r1); + v_swap(b0, r0); v_swap(b1, r1); } uchar y0 = rgbToY42x(r0, g0, b0); @@ -1695,7 +1620,7 @@ struct RGB8toYUV420pInvoker: public ParallelLoopBody rgbToUV42x(r0, g0, b0, uu, vv); if(swapUV) { - swap(uu, vv); + v_swap(uu, vv); } if(interleave) @@ -1776,7 +1701,7 @@ struct YUV422toRGB8Invoker : ParallelLoopBody v_load_deinterleave(yuv_src + i, vy0, u, vy1, v); if(uIdx == 1) // YVYU { - swap(u, v); + v_swap(u, v); } } @@ -1804,8 +1729,8 @@ struct YUV422toRGB8Invoker : ParallelLoopBody if(bIdx) { - swap(r0, b0); - swap(r1, b1); + v_swap(r0, b0); + v_swap(r1, b1); } // [r0...], [r1...] => [r0, r1, r0, r1...], [r0, r1, r0, r1...] @@ -1899,6 +1824,77 @@ static inline void RGB2UV(const uchar r1, const uchar g1, const uchar b1, v = saturate_cast(((1 << (RGB2YUV422_SHIFT-1)) + v_) >> RGB2YUV422_SHIFT); } +#if (CV_SIMD || CV_SIMD_SCALABLE) +// SIMD RGB2Y: v_dotprod (pmaddwd) keeps the multiply in 16-bit, avoiding emulated 32-bit mul on pre-SSE4.1 +static inline v_uint8 v_RGB2Y(const v_uint8& r, const v_uint8& g, const v_uint8& b) +{ + v_int16 crg, cb, dummy; + v_zip(vx_setall_s16((short)R2Y422), vx_setall_s16((short)G2Y422), crg, dummy); + v_zip(vx_setall_s16((short)B2Y422), vx_setall_s16(0), cb, dummy); + v_int32 vbias = vx_setall_s32((1 << RGB2YUV422_SHIFT) * 16 + (1 << (RGB2YUV422_SHIFT - 1))); + v_int16 vzero = vx_setzero_s16(); + + v_uint16 r0, r1, g0, g1, b0, b1; + v_expand(r, r0, r1); v_expand(g, g0, g1); v_expand(b, b0, b1); + v_int16 sr0 = v_reinterpret_as_s16(r0), sr1 = v_reinterpret_as_s16(r1); + v_int16 sg0 = v_reinterpret_as_s16(g0), sg1 = v_reinterpret_as_s16(g1); + v_int16 sb0 = v_reinterpret_as_s16(b0), sb1 = v_reinterpret_as_s16(b1); + + v_int16 rg00, rg01, rg10, rg11, bz00, bz01, bz10, bz11; + v_zip(sr0, sg0, rg00, rg01); v_zip(sr1, sg1, rg10, rg11); + v_zip(sb0, vzero, bz00, bz01); v_zip(sb1, vzero, bz10, bz11); + + v_uint32 y00, y01, y10, y11; + y00 = v_shr(v_reinterpret_as_u32(v_add(v_add(v_dotprod(rg00, crg), v_dotprod(bz00, cb)), vbias))); + y01 = v_shr(v_reinterpret_as_u32(v_add(v_add(v_dotprod(rg01, crg), v_dotprod(bz01, cb)), vbias))); + y10 = v_shr(v_reinterpret_as_u32(v_add(v_add(v_dotprod(rg10, crg), v_dotprod(bz10, cb)), vbias))); + y11 = v_shr(v_reinterpret_as_u32(v_add(v_add(v_dotprod(rg11, crg), v_dotprod(bz11, cb)), vbias))); + + return v_pack(v_pack(y00, y01), v_pack(y10, y11)); +} + +// SIMD RGB2UV (same v_dotprod approach); (r0,g0,b0) is the first pixel of each pair, (r1,g1,b1) the second +static inline void v_RGB2UV(const v_uint8& r0, const v_uint8& g0, const v_uint8& b0, + const v_uint8& r1, const v_uint8& g1, const v_uint8& b1, + v_uint8& u, v_uint8& v) +{ + v_int16 cu_rg, cu_b, cv_rg, cv_b, dummy; + v_zip(vx_setall_s16((short)R2U422), vx_setall_s16((short)G2U422), cu_rg, dummy); + v_zip(vx_setall_s16((short)B2U422), vx_setall_s16(0), cu_b, dummy); + v_zip(vx_setall_s16((short)B2U422), vx_setall_s16((short)G2V422), cv_rg, dummy); + v_zip(vx_setall_s16((short)B2V422), vx_setall_s16(0), cv_b, dummy); + v_int32 vbias = vx_setall_s32((1 << (RGB2YUV422_SHIFT - 1)) * 256 + (1 << (RGB2YUV422_SHIFT - 1))); + v_int16 vzero = vx_setzero_s16(); + + v_uint16 r0a, r0b, r1a, r1b, g0a, g0b, g1a, g1b, b0a, b0b, b1a, b1b; + v_expand(r0, r0a, r0b); v_expand(r1, r1a, r1b); + v_expand(g0, g0a, g0b); v_expand(g1, g1a, g1b); + v_expand(b0, b0a, b0b); v_expand(b1, b1a, b1b); + + // per-pair sums sr=r0+r1, sg=g0+g1, sb=b0+b1 (max 510, fits s16) + v_int16 sr0 = v_reinterpret_as_s16(v_add(r0a, r1a)), sr1 = v_reinterpret_as_s16(v_add(r0b, r1b)); + v_int16 sg0 = v_reinterpret_as_s16(v_add(g0a, g1a)), sg1 = v_reinterpret_as_s16(v_add(g0b, g1b)); + v_int16 sb0 = v_reinterpret_as_s16(v_add(b0a, b1a)), sb1 = v_reinterpret_as_s16(v_add(b0b, b1b)); + + v_int16 rg00, rg01, rg10, rg11, bz00, bz01, bz10, bz11; + v_zip(sr0, sg0, rg00, rg01); v_zip(sr1, sg1, rg10, rg11); + v_zip(sb0, vzero, bz00, bz01); v_zip(sb1, vzero, bz10, bz11); + + v_int32 uq00, uq01, uq10, uq11, vq00, vq01, vq10, vq11; + uq00 = v_shr(v_add(v_add(v_dotprod(rg00, cu_rg), v_dotprod(bz00, cu_b)), vbias)); + uq01 = v_shr(v_add(v_add(v_dotprod(rg01, cu_rg), v_dotprod(bz01, cu_b)), vbias)); + uq10 = v_shr(v_add(v_add(v_dotprod(rg10, cu_rg), v_dotprod(bz10, cu_b)), vbias)); + uq11 = v_shr(v_add(v_add(v_dotprod(rg11, cu_rg), v_dotprod(bz11, cu_b)), vbias)); + vq00 = v_shr(v_add(v_add(v_dotprod(rg00, cv_rg), v_dotprod(bz00, cv_b)), vbias)); + vq01 = v_shr(v_add(v_add(v_dotprod(rg01, cv_rg), v_dotprod(bz01, cv_b)), vbias)); + vq10 = v_shr(v_add(v_add(v_dotprod(rg10, cv_rg), v_dotprod(bz10, cv_b)), vbias)); + vq11 = v_shr(v_add(v_add(v_dotprod(rg11, cv_rg), v_dotprod(bz11, cv_b)), vbias)); + + u = v_pack_u(v_pack(uq00, uq01), v_pack(uq10, uq11)); + v = v_pack_u(v_pack(vq00, vq01), v_pack(vq10, vq11)); +} +#endif + template static inline void cvtRGB82Yuv422(const uchar r1, const uchar g1, const uchar b1, const uchar r2, const uchar g2, const uchar b2, @@ -1946,6 +1942,49 @@ struct RGB8toYUV422Invoker : ParallelLoopBody { uchar* row = dst_data + (dst_step) * j; int i = 0; +#if (CV_SIMD || CV_SIMD_SCALABLE) + const int vsize = VTraits::vlanes(); + v_uint16 lowByte = vx_setall_u16(0x00ff); + // process 2*vsize source pixels -> vsize pairs -> 4*vsize output bytes + for( ; i <= scn*width - 2*vsize*scn; i += 2*vsize*scn, row += 4*vsize ) + { + v_uint8 c0lo, glo, c2lo, alo, c0hi, ghi, c2hi, ahi; + if(scn == 4) + { + v_load_deinterleave(rgb_src + i + 0*vsize*scn, c0lo, glo, c2lo, alo); + v_load_deinterleave(rgb_src + i + 1*vsize*scn, c0hi, ghi, c2hi, ahi); + } + else // scn == 3 + { + v_load_deinterleave(rgb_src + i + 0*vsize*scn, c0lo, glo, c2lo); + v_load_deinterleave(rgb_src + i + 1*vsize*scn, c0hi, ghi, c2hi); + } + + v_uint8 rlo = (bIdx == 0) ? c2lo : c0lo, blo = (bIdx == 0) ? c0lo : c2lo; + v_uint8 rhi = (bIdx == 0) ? c2hi : c0hi, bhi = (bIdx == 0) ? c0hi : c2hi; + + // split each chunk into even/odd pixels (the two members of every pair) + v_uint8 rEven = v_pack(v_and(v_reinterpret_as_u16(rlo), lowByte), v_and(v_reinterpret_as_u16(rhi), lowByte)); + v_uint8 gEven = v_pack(v_and(v_reinterpret_as_u16(glo), lowByte), v_and(v_reinterpret_as_u16(ghi), lowByte)); + v_uint8 bEven = v_pack(v_and(v_reinterpret_as_u16(blo), lowByte), v_and(v_reinterpret_as_u16(bhi), lowByte)); + v_uint8 rOdd = v_pack(v_shr<8>(v_reinterpret_as_u16(rlo)), v_shr<8>(v_reinterpret_as_u16(rhi))); + v_uint8 gOdd = v_pack(v_shr<8>(v_reinterpret_as_u16(glo)), v_shr<8>(v_reinterpret_as_u16(ghi))); + v_uint8 bOdd = v_pack(v_shr<8>(v_reinterpret_as_u16(blo)), v_shr<8>(v_reinterpret_as_u16(bhi))); + + v_uint8 yEven = v_RGB2Y(rEven, gEven, bEven); + v_uint8 yOdd = v_RGB2Y(rOdd, gOdd, bOdd); + v_uint8 u, v; + v_RGB2UV(rEven, gEven, bEven, rOdd, gOdd, bOdd, u, v); + + if(yIdx == 1) // UYVY + v_store_interleave(row, u, yEven, v, yOdd); + else if(uIdx == 0) // YUYV + v_store_interleave(row, yEven, u, yOdd, v); + else // YVYU + v_store_interleave(row, yEven, v, yOdd, u); + } + vx_cleanup(); +#endif for (; i < scn * width; i += (scn << 1), row += 4) { const uchar r1 = rgb_src[i+ridx], g1 = rgb_src[i+1], b1 = rgb_src[i+bIdx]; @@ -1981,12 +2020,12 @@ void cvtBGRtoYUV(const uchar * src_data, size_t src_step, CV_INSTRUMENT_REGION(); 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)); - else if( depth == CV_16U ) - CvtColorLoop(src_data, src_step, dst_data, dst_step, width, height, RGB2YCrCb_i(scn, blueIdx, isCbCr)); - else - CvtColorLoop(src_data, src_step, dst_data, dst_step, width, height, RGB2YCrCb_f(scn, blueIdx, isCbCr)); + CvtColorLoopDepth(src_data, src_step, dst_data, dst_step, width, height, depth, + [&](auto t){ using T = decltype(t); + if constexpr (std::is_same::value) + return RGB2YCrCb_f(scn, blueIdx, isCbCr); + else + return RGB2YCrCb_i(scn, blueIdx, isCbCr); }); } void cvtYUVtoBGR(const uchar * src_data, size_t src_step, @@ -1997,12 +2036,12 @@ void cvtYUVtoBGR(const uchar * src_data, size_t src_step, CV_INSTRUMENT_REGION(); 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)); - else if( depth == CV_16U ) - CvtColorLoop(src_data, src_step, dst_data, dst_step, width, height, YCrCb2RGB_i(dcn, blueIdx, isCbCr)); - else - CvtColorLoop(src_data, src_step, dst_data, dst_step, width, height, YCrCb2RGB_f(dcn, blueIdx, isCbCr)); + CvtColorLoopDepth(src_data, src_step, dst_data, dst_step, width, height, depth, + [&](auto t){ using T = decltype(t); + if constexpr (std::is_same::value) + return YCrCb2RGB_f(dcn, blueIdx, isCbCr); + else + return YCrCb2RGB_i(dcn, blueIdx, isCbCr); }); } // 4:2:0, two planes: Y, UV interleaved