1 /*M///////////////////////////////////////////////////////////////////////////////////////
3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
5 // By downloading, copying, installing or using the software you agree to this license.
6 // If you do not agree to this license, do not download, install,
7 // copy or use the software.
11 // For Open Source Computer Vision Library
13 // Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
14 // Copyright (C) 2009-2010, Willow Garage Inc., all rights reserved.
15 // Third party copyrights are property of their respective owners.
17 // Redistribution and use in source and binary forms, with or without modification,
18 // are permitted provided that the following conditions are met:
20 // * Redistribution's of source code must retain the above copyright notice,
21 // this list of conditions and the following disclaimer.
23 // * Redistribution's in binary form must reproduce the above copyright notice,
24 // this list of conditions and the following disclaimer in the documentation
25 // and/or other materials provided with the distribution.
27 // * The name of the copyright holders may not be used to endorse or promote products
28 // derived from this software without specific prior written permission.
30 // This software is provided by the copyright holders and contributors "as is" and
31 // any express or implied warranties, including, but not limited to, the implied
32 // warranties of merchantability and fitness for a particular purpose are disclaimed.
33 // In no event shall the Intel Corporation or contributors be liable for any direct,
34 // indirect, incidental, special, exemplary, or consequential damages
35 // (including, but not limited to, procurement of substitute goods or services;
36 // loss of use, data, or profits; or business interruption) however caused
37 // and on any theory of liability, whether in contract, strict liability,
38 // or tort (including negligence or otherwise) arising in any way out of
39 // the use of this software, even if advised of the possibility of such damage.
43 /********************************* COPYRIGHT NOTICE *******************************\
44 The function for RGB to Lab conversion is based on the MATLAB script
45 RGB2Lab.m translated by Mark Ruzon from C code by Yossi Rubner, 23 September 1997.
46 See the page [http://vision.stanford.edu/~ruzon/software/rgblab.html]
47 \**********************************************************************************/
49 /********************************* COPYRIGHT NOTICE *******************************\
50 Original code for Bayer->BGR/RGB conversion is provided by Dirk Schaefer
51 from MD-Mathematische Dienste GmbH. Below is the copyright notice:
53 IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
54 By downloading, copying, installing or using the software you agree
55 to this license. If you do not agree to this license, do not download,
56 install, copy or use the software.
58 Contributors License Agreement:
61 MD-Mathematische Dienste GmbH
67 Redistribution and use in source and binary forms,
68 with or without modification, are permitted provided
69 that the following conditions are met:
71 Redistributions of source code must retain
72 the above copyright notice, this list of conditions and the following disclaimer.
73 Redistributions in binary form must reproduce the above copyright notice,
74 this list of conditions and the following disclaimer in the documentation
75 and/or other materials provided with the distribution.
76 The name of Contributor may not be used to endorse or promote products
77 derived from this software without specific prior written permission.
79 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
80 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
81 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
82 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE
83 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
84 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
85 OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
86 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
87 STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
88 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
89 THE POSSIBILITY OF SUCH DAMAGE.
90 \**********************************************************************************/
92 #include "precomp.hpp"
93 #include "opencl_kernels.hpp"
96 #define CV_DESCALE(x,n) (((x) + (1 << ((n)-1))) >> (n))
98 #if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
100 #define MAX_IPP16u 65535
101 #define MAX_IPP32f 1.0
102 static IppStatus sts = ippInit();
108 // computes cubic spline coefficients for a function: (xi=i, yi=f[i]), i=0..n
109 template<typename _Tp> static void splineBuild(const _Tp* f, int n, _Tp* tab)
113 tab[0] = tab[1] = (_Tp)0;
115 for(i = 1; i < n-1; i++)
117 _Tp t = 3*(f[i+1] - 2*f[i] + f[i-1]);
118 _Tp l = 1/(4 - tab[(i-1)*4]);
119 tab[i*4] = l; tab[i*4+1] = (t - tab[(i-1)*4+1])*l;
122 for(i = n-1; i >= 0; i--)
124 _Tp c = tab[i*4+1] - tab[i*4]*cn;
125 _Tp b = f[i+1] - f[i] - (cn + c*2)*(_Tp)0.3333333333333333;
126 _Tp d = (cn - c)*(_Tp)0.3333333333333333;
127 tab[i*4] = f[i]; tab[i*4+1] = b;
128 tab[i*4+2] = c; tab[i*4+3] = d;
133 // interpolates value of a function at x, 0 <= x <= n using a cubic spline.
134 template<typename _Tp> static inline _Tp splineInterpolate(_Tp x, const _Tp* tab, int n)
136 // don't touch this function without urgent need - some versions of gcc fail to inline it correctly
137 int ix = std::min(std::max(int(x), 0), n-1);
140 return ((tab[3]*x + tab[2])*x + tab[1])*x + tab[0];
144 template<typename _Tp> struct ColorChannel
146 typedef float worktype_f;
147 static _Tp max() { return std::numeric_limits<_Tp>::max(); }
148 static _Tp half() { return (_Tp)(max()/2 + 1); }
151 template<> struct ColorChannel<float>
153 typedef float worktype_f;
154 static float max() { return 1.f; }
155 static float half() { return 0.5f; }
158 /*template<> struct ColorChannel<double>
160 typedef double worktype_f;
161 static double max() { return 1.; }
162 static double half() { return 0.5; }
166 ///////////////////////////// Top-level template function ////////////////////////////////
168 template <typename Cvt>
169 class CvtColorLoop_Invoker : public ParallelLoopBody
171 typedef typename Cvt::channel_type _Tp;
174 CvtColorLoop_Invoker(const Mat& _src, Mat& _dst, const Cvt& _cvt) :
175 ParallelLoopBody(), src(_src), dst(_dst), cvt(_cvt)
179 virtual void operator()(const Range& range) const
181 const uchar* yS = src.ptr<uchar>(range.start);
182 uchar* yD = dst.ptr<uchar>(range.start);
184 for( int i = range.start; i < range.end; ++i, yS += src.step, yD += dst.step )
185 cvt((const _Tp*)yS, (_Tp*)yD, src.cols);
193 const CvtColorLoop_Invoker& operator= (const CvtColorLoop_Invoker&);
196 template <typename Cvt>
197 void CvtColorLoop(const Mat& src, Mat& dst, const Cvt& cvt)
199 parallel_for_(Range(0, src.rows), CvtColorLoop_Invoker<Cvt>(src, dst, cvt), src.total()/(double)(1<<16) );
202 #if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
204 typedef IppStatus (CV_STDCALL* ippiReorderFunc)(const void *, int, void *, int, IppiSize, const int *);
205 typedef IppStatus (CV_STDCALL* ippiGeneralFunc)(const void *, int, void *, int, IppiSize);
206 typedef IppStatus (CV_STDCALL* ippiColor2GrayFunc)(const void *, int, void *, int, IppiSize, const Ipp32f *);
208 template <typename Cvt>
209 class CvtColorIPPLoop_Invoker :
210 public ParallelLoopBody
214 CvtColorIPPLoop_Invoker(const Mat& _src, Mat& _dst, const Cvt& _cvt, bool *_ok) :
215 ParallelLoopBody(), src(_src), dst(_dst), cvt(_cvt), ok(_ok)
220 virtual void operator()(const Range& range) const
222 const void *yS = src.ptr<uchar>(range.start);
223 void *yD = dst.ptr<uchar>(range.start);
224 if( !cvt(yS, (int)src.step[0], yD, (int)dst.step[0], src.cols, range.end - range.start) )
234 const CvtColorIPPLoop_Invoker& operator= (const CvtColorIPPLoop_Invoker&);
237 template <typename Cvt>
238 bool CvtColorIPPLoop(const Mat& src, Mat& dst, const Cvt& cvt)
241 parallel_for_(Range(0, src.rows), CvtColorIPPLoop_Invoker<Cvt>(src, dst, cvt, &ok), src.total()/(double)(1<<16) );
245 template <typename Cvt>
246 bool CvtColorIPPLoopCopy(Mat& src, Mat& dst, const Cvt& cvt)
250 if( src.data == dst.data )
256 parallel_for_(Range(0, source.rows), CvtColorIPPLoop_Invoker<Cvt>(source, dst, cvt, &ok),
257 source.total()/(double)(1<<16) );
261 static IppStatus CV_STDCALL ippiSwapChannels_8u_C3C4Rf(const Ipp8u* pSrc, int srcStep, Ipp8u* pDst, int dstStep,
262 IppiSize roiSize, const int *dstOrder)
264 return ippiSwapChannels_8u_C3C4R(pSrc, srcStep, pDst, dstStep, roiSize, dstOrder, MAX_IPP8u);
267 static IppStatus CV_STDCALL ippiSwapChannels_16u_C3C4Rf(const Ipp16u* pSrc, int srcStep, Ipp16u* pDst, int dstStep,
268 IppiSize roiSize, const int *dstOrder)
270 return ippiSwapChannels_16u_C3C4R(pSrc, srcStep, pDst, dstStep, roiSize, dstOrder, MAX_IPP16u);
273 static IppStatus CV_STDCALL ippiSwapChannels_32f_C3C4Rf(const Ipp32f* pSrc, int srcStep, Ipp32f* pDst, int dstStep,
274 IppiSize roiSize, const int *dstOrder)
276 return ippiSwapChannels_32f_C3C4R(pSrc, srcStep, pDst, dstStep, roiSize, dstOrder, MAX_IPP32f);
279 static ippiReorderFunc ippiSwapChannelsC3C4RTab[] =
281 (ippiReorderFunc)ippiSwapChannels_8u_C3C4Rf, 0, (ippiReorderFunc)ippiSwapChannels_16u_C3C4Rf, 0,
282 0, (ippiReorderFunc)ippiSwapChannels_32f_C3C4Rf, 0, 0
285 static ippiGeneralFunc ippiCopyAC4C3RTab[] =
287 (ippiGeneralFunc)ippiCopy_8u_AC4C3R, 0, (ippiGeneralFunc)ippiCopy_16u_AC4C3R, 0,
288 0, (ippiGeneralFunc)ippiCopy_32f_AC4C3R, 0, 0
291 static ippiReorderFunc ippiSwapChannelsC4C3RTab[] =
293 (ippiReorderFunc)ippiSwapChannels_8u_C4C3R, 0, (ippiReorderFunc)ippiSwapChannels_16u_C4C3R, 0,
294 0, (ippiReorderFunc)ippiSwapChannels_32f_C4C3R, 0, 0
297 static ippiReorderFunc ippiSwapChannelsC3RTab[] =
299 (ippiReorderFunc)ippiSwapChannels_8u_C3R, 0, (ippiReorderFunc)ippiSwapChannels_16u_C3R, 0,
300 0, (ippiReorderFunc)ippiSwapChannels_32f_C3R, 0, 0
303 #if IPP_VERSION_X100 >= 801
304 static ippiReorderFunc ippiSwapChannelsC4RTab[] =
306 (ippiReorderFunc)ippiSwapChannels_8u_C4R, 0, (ippiReorderFunc)ippiSwapChannels_16u_C4R, 0,
307 0, (ippiReorderFunc)ippiSwapChannels_32f_C4R, 0, 0
311 static ippiColor2GrayFunc ippiColor2GrayC3Tab[] =
313 (ippiColor2GrayFunc)ippiColorToGray_8u_C3C1R, 0, (ippiColor2GrayFunc)ippiColorToGray_16u_C3C1R, 0,
314 0, (ippiColor2GrayFunc)ippiColorToGray_32f_C3C1R, 0, 0
317 static ippiColor2GrayFunc ippiColor2GrayC4Tab[] =
319 (ippiColor2GrayFunc)ippiColorToGray_8u_AC4C1R, 0, (ippiColor2GrayFunc)ippiColorToGray_16u_AC4C1R, 0,
320 0, (ippiColor2GrayFunc)ippiColorToGray_32f_AC4C1R, 0, 0
323 static ippiGeneralFunc ippiRGB2GrayC3Tab[] =
325 (ippiGeneralFunc)ippiRGBToGray_8u_C3C1R, 0, (ippiGeneralFunc)ippiRGBToGray_16u_C3C1R, 0,
326 0, (ippiGeneralFunc)ippiRGBToGray_32f_C3C1R, 0, 0
329 static ippiGeneralFunc ippiRGB2GrayC4Tab[] =
331 (ippiGeneralFunc)ippiRGBToGray_8u_AC4C1R, 0, (ippiGeneralFunc)ippiRGBToGray_16u_AC4C1R, 0,
332 0, (ippiGeneralFunc)ippiRGBToGray_32f_AC4C1R, 0, 0
335 static ippiGeneralFunc ippiCopyP3C3RTab[] =
337 (ippiGeneralFunc)ippiCopy_8u_P3C3R, 0, (ippiGeneralFunc)ippiCopy_16u_P3C3R, 0,
338 0, (ippiGeneralFunc)ippiCopy_32f_P3C3R, 0, 0
341 static ippiGeneralFunc ippiRGB2XYZTab[] =
343 (ippiGeneralFunc)ippiRGBToXYZ_8u_C3R, 0, (ippiGeneralFunc)ippiRGBToXYZ_16u_C3R, 0,
344 0, (ippiGeneralFunc)ippiRGBToXYZ_32f_C3R, 0, 0
347 static ippiGeneralFunc ippiXYZ2RGBTab[] =
349 (ippiGeneralFunc)ippiXYZToRGB_8u_C3R, 0, (ippiGeneralFunc)ippiXYZToRGB_16u_C3R, 0,
350 0, (ippiGeneralFunc)ippiXYZToRGB_32f_C3R, 0, 0
353 static ippiGeneralFunc ippiRGB2HSVTab[] =
355 (ippiGeneralFunc)ippiRGBToHSV_8u_C3R, 0, (ippiGeneralFunc)ippiRGBToHSV_16u_C3R, 0,
359 static ippiGeneralFunc ippiHSV2RGBTab[] =
361 (ippiGeneralFunc)ippiHSVToRGB_8u_C3R, 0, (ippiGeneralFunc)ippiHSVToRGB_16u_C3R, 0,
365 static ippiGeneralFunc ippiRGB2HLSTab[] =
367 (ippiGeneralFunc)ippiRGBToHLS_8u_C3R, 0, (ippiGeneralFunc)ippiRGBToHLS_16u_C3R, 0,
368 0, (ippiGeneralFunc)ippiRGBToHLS_32f_C3R, 0, 0
371 static ippiGeneralFunc ippiHLS2RGBTab[] =
373 (ippiGeneralFunc)ippiHLSToRGB_8u_C3R, 0, (ippiGeneralFunc)ippiHLSToRGB_16u_C3R, 0,
374 0, (ippiGeneralFunc)ippiHLSToRGB_32f_C3R, 0, 0
377 #if !defined(HAVE_IPP_ICV_ONLY) && 0
378 static ippiGeneralFunc ippiRGBToLUVTab[] =
380 (ippiGeneralFunc)ippiRGBToLUV_8u_C3R, 0, (ippiGeneralFunc)ippiRGBToLUV_16u_C3R, 0,
381 0, (ippiGeneralFunc)ippiRGBToLUV_32f_C3R, 0, 0
384 static ippiGeneralFunc ippiLUVToRGBTab[] =
386 (ippiGeneralFunc)ippiLUVToRGB_8u_C3R, 0, (ippiGeneralFunc)ippiLUVToRGB_16u_C3R, 0,
387 0, (ippiGeneralFunc)ippiLUVToRGB_32f_C3R, 0, 0
391 struct IPPGeneralFunctor
393 IPPGeneralFunctor(ippiGeneralFunc _func) : func(_func){}
394 bool operator()(const void *src, int srcStep, void *dst, int dstStep, int cols, int rows) const
396 return func ? func(src, srcStep, dst, dstStep, ippiSize(cols, rows)) >= 0 : false;
399 ippiGeneralFunc func;
402 struct IPPReorderFunctor
404 IPPReorderFunctor(ippiReorderFunc _func, int _order0, int _order1, int _order2) : func(_func)
411 bool operator()(const void *src, int srcStep, void *dst, int dstStep, int cols, int rows) const
413 return func ? func(src, srcStep, dst, dstStep, ippiSize(cols, rows), order) >= 0 : false;
416 ippiReorderFunc func;
420 struct IPPColor2GrayFunctor
422 IPPColor2GrayFunctor(ippiColor2GrayFunc _func) :
429 bool operator()(const void *src, int srcStep, void *dst, int dstStep, int cols, int rows) const
431 return func ? func(src, srcStep, dst, dstStep, ippiSize(cols, rows), coeffs) >= 0 : false;
434 ippiColor2GrayFunc func;
438 struct IPPGray2BGRFunctor
440 IPPGray2BGRFunctor(ippiGeneralFunc _func) :
445 bool operator()(const void *src, int srcStep, void *dst, int dstStep, int cols, int rows) const
450 const void* srcarray[3] = { src, src, src };
451 return func(srcarray, srcStep, dst, dstStep, ippiSize(cols, rows)) >= 0;
454 ippiGeneralFunc func;
457 struct IPPGray2BGRAFunctor
459 IPPGray2BGRAFunctor(ippiGeneralFunc _func1, ippiReorderFunc _func2, int _depth) :
460 func1(_func1), func2(_func2), depth(_depth)
464 bool operator()(const void *src, int srcStep, void *dst, int dstStep, int cols, int rows) const
466 if (func1 == 0 || func2 == 0)
469 const void* srcarray[3] = { src, src, src };
470 Mat temp(rows, cols, CV_MAKETYPE(depth, 3));
471 if(func1(srcarray, srcStep, temp.data, (int)temp.step[0], ippiSize(cols, rows)) < 0)
473 int order[4] = {0, 1, 2, 3};
474 return func2(temp.data, (int)temp.step[0], dst, dstStep, ippiSize(cols, rows), order) >= 0;
477 ippiGeneralFunc func1;
478 ippiReorderFunc func2;
482 struct IPPReorderGeneralFunctor
484 IPPReorderGeneralFunctor(ippiReorderFunc _func1, ippiGeneralFunc _func2, int _order0, int _order1, int _order2, int _depth) :
485 func1(_func1), func2(_func2), depth(_depth)
492 bool operator()(const void *src, int srcStep, void *dst, int dstStep, int cols, int rows) const
494 if (func1 == 0 || func2 == 0)
498 temp.create(rows, cols, CV_MAKETYPE(depth, 3));
499 if(func1(src, srcStep, temp.data, (int)temp.step[0], ippiSize(cols, rows), order) < 0)
501 return func2(temp.data, (int)temp.step[0], dst, dstStep, ippiSize(cols, rows)) >= 0;
504 ippiReorderFunc func1;
505 ippiGeneralFunc func2;
510 struct IPPGeneralReorderFunctor
512 IPPGeneralReorderFunctor(ippiGeneralFunc _func1, ippiReorderFunc _func2, int _order0, int _order1, int _order2, int _depth) :
513 func1(_func1), func2(_func2), depth(_depth)
520 bool operator()(const void *src, int srcStep, void *dst, int dstStep, int cols, int rows) const
522 if (func1 == 0 || func2 == 0)
526 temp.create(rows, cols, CV_MAKETYPE(depth, 3));
527 if(func1(src, srcStep, temp.data, (int)temp.step[0], ippiSize(cols, rows)) < 0)
529 return func2(temp.data, (int)temp.step[0], dst, dstStep, ippiSize(cols, rows), order) >= 0;
532 ippiGeneralFunc func1;
533 ippiReorderFunc func2;
540 ////////////////// Various 3/4-channel to 3/4-channel RGB transformations /////////////////
542 template<typename _Tp> struct RGB2RGB
544 typedef _Tp channel_type;
546 RGB2RGB(int _srccn, int _dstcn, int _blueIdx) : srccn(_srccn), dstcn(_dstcn), blueIdx(_blueIdx) {}
547 void operator()(const _Tp* src, _Tp* dst, int n) const
549 int scn = srccn, dcn = dstcn, bidx = blueIdx;
553 for( int i = 0; i < n; i += 3, src += scn )
555 _Tp t0 = src[bidx], t1 = src[1], t2 = src[bidx ^ 2];
556 dst[i] = t0; dst[i+1] = t1; dst[i+2] = t2;
562 _Tp alpha = ColorChannel<_Tp>::max();
563 for( int i = 0; i < n; i += 3, dst += 4 )
565 _Tp t0 = src[i], t1 = src[i+1], t2 = src[i+2];
566 dst[bidx] = t0; dst[1] = t1; dst[bidx^2] = t2; dst[3] = alpha;
572 for( int i = 0; i < n; i += 4 )
574 _Tp t0 = src[i], t1 = src[i+1], t2 = src[i+2], t3 = src[i+3];
575 dst[i] = t2; dst[i+1] = t1; dst[i+2] = t0; dst[i+3] = t3;
580 int srccn, dstcn, blueIdx;
583 /////////// Transforming 16-bit (565 or 555) RGB to/from 24/32-bit (888[8]) RGB //////////
587 typedef uchar channel_type;
589 RGB5x52RGB(int _dstcn, int _blueIdx, int _greenBits)
590 : dstcn(_dstcn), blueIdx(_blueIdx), greenBits(_greenBits) {}
592 void operator()(const uchar* src, uchar* dst, int n) const
594 int dcn = dstcn, bidx = blueIdx;
596 for( int i = 0; i < n; i++, dst += dcn )
598 unsigned t = ((const ushort*)src)[i];
599 dst[bidx] = (uchar)(t << 3);
600 dst[1] = (uchar)((t >> 3) & ~3);
601 dst[bidx ^ 2] = (uchar)((t >> 8) & ~7);
606 for( int i = 0; i < n; i++, dst += dcn )
608 unsigned t = ((const ushort*)src)[i];
609 dst[bidx] = (uchar)(t << 3);
610 dst[1] = (uchar)((t >> 2) & ~7);
611 dst[bidx ^ 2] = (uchar)((t >> 7) & ~7);
613 dst[3] = t & 0x8000 ? 255 : 0;
617 int dstcn, blueIdx, greenBits;
623 typedef uchar channel_type;
625 RGB2RGB5x5(int _srccn, int _blueIdx, int _greenBits)
626 : srccn(_srccn), blueIdx(_blueIdx), greenBits(_greenBits) {}
628 void operator()(const uchar* src, uchar* dst, int n) const
630 int scn = srccn, bidx = blueIdx;
632 for( int i = 0; i < n; i++, src += scn )
634 ((ushort*)dst)[i] = (ushort)((src[bidx] >> 3)|((src[1]&~3) << 3)|((src[bidx^2]&~7) << 8));
637 for( int i = 0; i < n; i++, src += 3 )
639 ((ushort*)dst)[i] = (ushort)((src[bidx] >> 3)|((src[1]&~7) << 2)|((src[bidx^2]&~7) << 7));
642 for( int i = 0; i < n; i++, src += 4 )
644 ((ushort*)dst)[i] = (ushort)((src[bidx] >> 3)|((src[1]&~7) << 2)|
645 ((src[bidx^2]&~7) << 7)|(src[3] ? 0x8000 : 0));
649 int srccn, blueIdx, greenBits;
652 ///////////////////////////////// Color to/from Grayscale ////////////////////////////////
654 template<typename _Tp>
657 typedef _Tp channel_type;
659 Gray2RGB(int _dstcn) : dstcn(_dstcn) {}
660 void operator()(const _Tp* src, _Tp* dst, int n) const
663 for( int i = 0; i < n; i++, dst += 3 )
665 dst[0] = dst[1] = dst[2] = src[i];
669 _Tp alpha = ColorChannel<_Tp>::max();
670 for( int i = 0; i < n; i++, dst += 4 )
672 dst[0] = dst[1] = dst[2] = src[i];
684 typedef uchar channel_type;
686 Gray2RGB5x5(int _greenBits) : greenBits(_greenBits) {}
687 void operator()(const uchar* src, uchar* dst, int n) const
690 for( int i = 0; i < n; i++ )
693 ((ushort*)dst)[i] = (ushort)((t >> 3)|((t & ~3) << 3)|((t & ~7) << 8));
696 for( int i = 0; i < n; i++ )
699 ((ushort*)dst)[i] = (ushort)(t|(t << 5)|(t << 10));
723 typedef uchar channel_type;
725 RGB5x52Gray(int _greenBits) : greenBits(_greenBits) {}
726 void operator()(const uchar* src, uchar* dst, int n) const
729 for( int i = 0; i < n; i++ )
731 int t = ((ushort*)src)[i];
732 dst[i] = (uchar)CV_DESCALE(((t << 3) & 0xf8)*B2Y +
733 ((t >> 3) & 0xfc)*G2Y +
734 ((t >> 8) & 0xf8)*R2Y, yuv_shift);
737 for( int i = 0; i < n; i++ )
739 int t = ((ushort*)src)[i];
740 dst[i] = (uchar)CV_DESCALE(((t << 3) & 0xf8)*B2Y +
741 ((t >> 2) & 0xf8)*G2Y +
742 ((t >> 7) & 0xf8)*R2Y, yuv_shift);
749 template<typename _Tp> struct RGB2Gray
751 typedef _Tp channel_type;
753 RGB2Gray(int _srccn, int blueIdx, const float* _coeffs) : srccn(_srccn)
755 static const float coeffs0[] = { 0.299f, 0.587f, 0.114f };
756 memcpy( coeffs, _coeffs ? _coeffs : coeffs0, 3*sizeof(coeffs[0]) );
758 std::swap(coeffs[0], coeffs[2]);
761 void operator()(const _Tp* src, _Tp* dst, int n) const
764 float cb = coeffs[0], cg = coeffs[1], cr = coeffs[2];
765 for(int i = 0; i < n; i++, src += scn)
766 dst[i] = saturate_cast<_Tp>(src[0]*cb + src[1]*cg + src[2]*cr);
773 template<> struct RGB2Gray<uchar>
775 typedef uchar channel_type;
777 RGB2Gray(int _srccn, int blueIdx, const int* coeffs) : srccn(_srccn)
779 const int coeffs0[] = { R2Y, G2Y, B2Y };
780 if(!coeffs) coeffs = coeffs0;
782 int b = 0, g = 0, r = (1 << (yuv_shift-1));
783 int db = coeffs[blueIdx^2], dg = coeffs[1], dr = coeffs[blueIdx];
785 for( int i = 0; i < 256; i++, b += db, g += dg, r += dr )
792 void operator()(const uchar* src, uchar* dst, int n) const
795 const int* _tab = tab;
796 for(int i = 0; i < n; i++, src += scn)
797 dst[i] = (uchar)((_tab[src[0]] + _tab[src[1]+256] + _tab[src[2]+512]) >> yuv_shift);
804 template<> struct RGB2Gray<ushort>
806 typedef ushort channel_type;
808 RGB2Gray(int _srccn, int blueIdx, const int* _coeffs) : srccn(_srccn)
810 static const int coeffs0[] = { R2Y, G2Y, B2Y };
811 memcpy(coeffs, _coeffs ? _coeffs : coeffs0, 3*sizeof(coeffs[0]));
813 std::swap(coeffs[0], coeffs[2]);
816 void operator()(const ushort* src, ushort* dst, int n) const
818 int scn = srccn, cb = coeffs[0], cg = coeffs[1], cr = coeffs[2];
819 for(int i = 0; i < n; i++, src += scn)
820 dst[i] = (ushort)CV_DESCALE((unsigned)(src[0]*cb + src[1]*cg + src[2]*cr), yuv_shift);
827 ///////////////////////////////////// RGB <-> YCrCb //////////////////////////////////////
829 template<typename _Tp> struct RGB2YCrCb_f
831 typedef _Tp channel_type;
833 RGB2YCrCb_f(int _srccn, int _blueIdx, const float* _coeffs) : srccn(_srccn), blueIdx(_blueIdx)
835 static const float coeffs0[] = {0.299f, 0.587f, 0.114f, 0.713f, 0.564f};
836 memcpy(coeffs, _coeffs ? _coeffs : coeffs0, 5*sizeof(coeffs[0]));
837 if(blueIdx==0) std::swap(coeffs[0], coeffs[2]);
840 void operator()(const _Tp* src, _Tp* dst, int n) const
842 int scn = srccn, bidx = blueIdx;
843 const _Tp delta = ColorChannel<_Tp>::half();
844 float C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2], C3 = coeffs[3], C4 = coeffs[4];
846 for(int i = 0; i < n; i += 3, src += scn)
848 _Tp Y = saturate_cast<_Tp>(src[0]*C0 + src[1]*C1 + src[2]*C2);
849 _Tp Cr = saturate_cast<_Tp>((src[bidx^2] - Y)*C3 + delta);
850 _Tp Cb = saturate_cast<_Tp>((src[bidx] - Y)*C4 + delta);
851 dst[i] = Y; dst[i+1] = Cr; dst[i+2] = Cb;
859 template<typename _Tp> struct RGB2YCrCb_i
861 typedef _Tp channel_type;
863 RGB2YCrCb_i(int _srccn, int _blueIdx, const int* _coeffs)
864 : srccn(_srccn), blueIdx(_blueIdx)
866 static const int coeffs0[] = {R2Y, G2Y, B2Y, 11682, 9241};
867 memcpy(coeffs, _coeffs ? _coeffs : coeffs0, 5*sizeof(coeffs[0]));
868 if(blueIdx==0) std::swap(coeffs[0], coeffs[2]);
870 void operator()(const _Tp* src, _Tp* dst, int n) const
872 int scn = srccn, bidx = blueIdx;
873 int C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2], C3 = coeffs[3], C4 = coeffs[4];
874 int delta = ColorChannel<_Tp>::half()*(1 << yuv_shift);
876 for(int i = 0; i < n; i += 3, src += scn)
878 int Y = CV_DESCALE(src[0]*C0 + src[1]*C1 + src[2]*C2, yuv_shift);
879 int Cr = CV_DESCALE((src[bidx^2] - Y)*C3 + delta, yuv_shift);
880 int Cb = CV_DESCALE((src[bidx] - Y)*C4 + delta, yuv_shift);
881 dst[i] = saturate_cast<_Tp>(Y);
882 dst[i+1] = saturate_cast<_Tp>(Cr);
883 dst[i+2] = saturate_cast<_Tp>(Cb);
891 template<typename _Tp> struct YCrCb2RGB_f
893 typedef _Tp channel_type;
895 YCrCb2RGB_f(int _dstcn, int _blueIdx, const float* _coeffs)
896 : dstcn(_dstcn), blueIdx(_blueIdx)
898 static const float coeffs0[] = {1.403f, -0.714f, -0.344f, 1.773f};
899 memcpy(coeffs, _coeffs ? _coeffs : coeffs0, 4*sizeof(coeffs[0]));
901 void operator()(const _Tp* src, _Tp* dst, int n) const
903 int dcn = dstcn, bidx = blueIdx;
904 const _Tp delta = ColorChannel<_Tp>::half(), alpha = ColorChannel<_Tp>::max();
905 float C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2], C3 = coeffs[3];
907 for(int i = 0; i < n; i += 3, dst += dcn)
913 _Tp b = saturate_cast<_Tp>(Y + (Cb - delta)*C3);
914 _Tp g = saturate_cast<_Tp>(Y + (Cb - delta)*C2 + (Cr - delta)*C1);
915 _Tp r = saturate_cast<_Tp>(Y + (Cr - delta)*C0);
917 dst[bidx] = b; dst[1] = g; dst[bidx^2] = r;
927 template<typename _Tp> struct YCrCb2RGB_i
929 typedef _Tp channel_type;
931 YCrCb2RGB_i(int _dstcn, int _blueIdx, const int* _coeffs)
932 : dstcn(_dstcn), blueIdx(_blueIdx)
934 static const int coeffs0[] = {22987, -11698, -5636, 29049};
935 memcpy(coeffs, _coeffs ? _coeffs : coeffs0, 4*sizeof(coeffs[0]));
938 void operator()(const _Tp* src, _Tp* dst, int n) const
940 int dcn = dstcn, bidx = blueIdx;
941 const _Tp delta = ColorChannel<_Tp>::half(), alpha = ColorChannel<_Tp>::max();
942 int C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2], C3 = coeffs[3];
944 for(int i = 0; i < n; i += 3, dst += dcn)
950 int b = Y + CV_DESCALE((Cb - delta)*C3, yuv_shift);
951 int g = Y + CV_DESCALE((Cb - delta)*C2 + (Cr - delta)*C1, yuv_shift);
952 int r = Y + CV_DESCALE((Cr - delta)*C0, yuv_shift);
954 dst[bidx] = saturate_cast<_Tp>(b);
955 dst[1] = saturate_cast<_Tp>(g);
956 dst[bidx^2] = saturate_cast<_Tp>(r);
966 ////////////////////////////////////// RGB <-> XYZ ///////////////////////////////////////
968 static const float sRGB2XYZ_D65[] =
970 0.412453f, 0.357580f, 0.180423f,
971 0.212671f, 0.715160f, 0.072169f,
972 0.019334f, 0.119193f, 0.950227f
975 static const float XYZ2sRGB_D65[] =
977 3.240479f, -1.53715f, -0.498535f,
978 -0.969256f, 1.875991f, 0.041556f,
979 0.055648f, -0.204043f, 1.057311f
982 template<typename _Tp> struct RGB2XYZ_f
984 typedef _Tp channel_type;
986 RGB2XYZ_f(int _srccn, int blueIdx, const float* _coeffs) : srccn(_srccn)
988 memcpy(coeffs, _coeffs ? _coeffs : sRGB2XYZ_D65, 9*sizeof(coeffs[0]));
991 std::swap(coeffs[0], coeffs[2]);
992 std::swap(coeffs[3], coeffs[5]);
993 std::swap(coeffs[6], coeffs[8]);
996 void operator()(const _Tp* src, _Tp* dst, int n) const
999 float C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2],
1000 C3 = coeffs[3], C4 = coeffs[4], C5 = coeffs[5],
1001 C6 = coeffs[6], C7 = coeffs[7], C8 = coeffs[8];
1004 for(int i = 0; i < n; i += 3, src += scn)
1006 _Tp X = saturate_cast<_Tp>(src[0]*C0 + src[1]*C1 + src[2]*C2);
1007 _Tp Y = saturate_cast<_Tp>(src[0]*C3 + src[1]*C4 + src[2]*C5);
1008 _Tp Z = saturate_cast<_Tp>(src[0]*C6 + src[1]*C7 + src[2]*C8);
1009 dst[i] = X; dst[i+1] = Y; dst[i+2] = Z;
1017 template<typename _Tp> struct RGB2XYZ_i
1019 typedef _Tp channel_type;
1021 RGB2XYZ_i(int _srccn, int blueIdx, const float* _coeffs) : srccn(_srccn)
1023 static const int coeffs0[] =
1029 for( int i = 0; i < 9; i++ )
1030 coeffs[i] = _coeffs ? cvRound(_coeffs[i]*(1 << xyz_shift)) : coeffs0[i];
1033 std::swap(coeffs[0], coeffs[2]);
1034 std::swap(coeffs[3], coeffs[5]);
1035 std::swap(coeffs[6], coeffs[8]);
1038 void operator()(const _Tp* src, _Tp* dst, int n) const
1041 int C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2],
1042 C3 = coeffs[3], C4 = coeffs[4], C5 = coeffs[5],
1043 C6 = coeffs[6], C7 = coeffs[7], C8 = coeffs[8];
1045 for(int i = 0; i < n; i += 3, src += scn)
1047 int X = CV_DESCALE(src[0]*C0 + src[1]*C1 + src[2]*C2, xyz_shift);
1048 int Y = CV_DESCALE(src[0]*C3 + src[1]*C4 + src[2]*C5, xyz_shift);
1049 int Z = CV_DESCALE(src[0]*C6 + src[1]*C7 + src[2]*C8, xyz_shift);
1050 dst[i] = saturate_cast<_Tp>(X); dst[i+1] = saturate_cast<_Tp>(Y);
1051 dst[i+2] = saturate_cast<_Tp>(Z);
1059 template<typename _Tp> struct XYZ2RGB_f
1061 typedef _Tp channel_type;
1063 XYZ2RGB_f(int _dstcn, int _blueIdx, const float* _coeffs)
1064 : dstcn(_dstcn), blueIdx(_blueIdx)
1066 memcpy(coeffs, _coeffs ? _coeffs : XYZ2sRGB_D65, 9*sizeof(coeffs[0]));
1069 std::swap(coeffs[0], coeffs[6]);
1070 std::swap(coeffs[1], coeffs[7]);
1071 std::swap(coeffs[2], coeffs[8]);
1075 void operator()(const _Tp* src, _Tp* dst, int n) const
1078 _Tp alpha = ColorChannel<_Tp>::max();
1079 float C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2],
1080 C3 = coeffs[3], C4 = coeffs[4], C5 = coeffs[5],
1081 C6 = coeffs[6], C7 = coeffs[7], C8 = coeffs[8];
1083 for(int i = 0; i < n; i += 3, dst += dcn)
1085 _Tp B = saturate_cast<_Tp>(src[i]*C0 + src[i+1]*C1 + src[i+2]*C2);
1086 _Tp G = saturate_cast<_Tp>(src[i]*C3 + src[i+1]*C4 + src[i+2]*C5);
1087 _Tp R = saturate_cast<_Tp>(src[i]*C6 + src[i+1]*C7 + src[i+2]*C8);
1088 dst[0] = B; dst[1] = G; dst[2] = R;
1098 template<typename _Tp> struct XYZ2RGB_i
1100 typedef _Tp channel_type;
1102 XYZ2RGB_i(int _dstcn, int _blueIdx, const int* _coeffs)
1103 : dstcn(_dstcn), blueIdx(_blueIdx)
1105 static const int coeffs0[] =
1107 13273, -6296, -2042,
1111 for(int i = 0; i < 9; i++)
1112 coeffs[i] = _coeffs ? cvRound(_coeffs[i]*(1 << xyz_shift)) : coeffs0[i];
1116 std::swap(coeffs[0], coeffs[6]);
1117 std::swap(coeffs[1], coeffs[7]);
1118 std::swap(coeffs[2], coeffs[8]);
1121 void operator()(const _Tp* src, _Tp* dst, int n) const
1124 _Tp alpha = ColorChannel<_Tp>::max();
1125 int C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2],
1126 C3 = coeffs[3], C4 = coeffs[4], C5 = coeffs[5],
1127 C6 = coeffs[6], C7 = coeffs[7], C8 = coeffs[8];
1129 for(int i = 0; i < n; i += 3, dst += dcn)
1131 int B = CV_DESCALE(src[i]*C0 + src[i+1]*C1 + src[i+2]*C2, xyz_shift);
1132 int G = CV_DESCALE(src[i]*C3 + src[i+1]*C4 + src[i+2]*C5, xyz_shift);
1133 int R = CV_DESCALE(src[i]*C6 + src[i+1]*C7 + src[i+2]*C8, xyz_shift);
1134 dst[0] = saturate_cast<_Tp>(B); dst[1] = saturate_cast<_Tp>(G);
1135 dst[2] = saturate_cast<_Tp>(R);
1145 ////////////////////////////////////// RGB <-> HSV ///////////////////////////////////////
1150 typedef uchar channel_type;
1152 RGB2HSV_b(int _srccn, int _blueIdx, int _hrange)
1153 : srccn(_srccn), blueIdx(_blueIdx), hrange(_hrange)
1155 CV_Assert( hrange == 180 || hrange == 256 );
1158 void operator()(const uchar* src, uchar* dst, int n) const
1160 int i, bidx = blueIdx, scn = srccn;
1161 const int hsv_shift = 12;
1163 static int sdiv_table[256];
1164 static int hdiv_table180[256];
1165 static int hdiv_table256[256];
1166 static volatile bool initialized = false;
1169 const int* hdiv_table = hr == 180 ? hdiv_table180 : hdiv_table256;
1174 sdiv_table[0] = hdiv_table180[0] = hdiv_table256[0] = 0;
1175 for( i = 1; i < 256; i++ )
1177 sdiv_table[i] = saturate_cast<int>((255 << hsv_shift)/(1.*i));
1178 hdiv_table180[i] = saturate_cast<int>((180 << hsv_shift)/(6.*i));
1179 hdiv_table256[i] = saturate_cast<int>((256 << hsv_shift)/(6.*i));
1184 for( i = 0; i < n; i += 3, src += scn )
1186 int b = src[bidx], g = src[1], r = src[bidx^2];
1191 CV_CALC_MAX_8U( v, g );
1192 CV_CALC_MAX_8U( v, r );
1193 CV_CALC_MIN_8U( vmin, g );
1194 CV_CALC_MIN_8U( vmin, r );
1197 vr = v == r ? -1 : 0;
1198 vg = v == g ? -1 : 0;
1200 s = (diff * sdiv_table[v] + (1 << (hsv_shift-1))) >> hsv_shift;
1201 h = (vr & (g - b)) +
1202 (~vr & ((vg & (b - r + 2 * diff)) + ((~vg) & (r - g + 4 * diff))));
1203 h = (h * hdiv_table[diff] + (1 << (hsv_shift-1))) >> hsv_shift;
1204 h += h < 0 ? hr : 0;
1206 dst[i] = saturate_cast<uchar>(h);
1207 dst[i+1] = (uchar)s;
1208 dst[i+2] = (uchar)v;
1212 int srccn, blueIdx, hrange;
1218 typedef float channel_type;
1220 RGB2HSV_f(int _srccn, int _blueIdx, float _hrange)
1221 : srccn(_srccn), blueIdx(_blueIdx), hrange(_hrange) {}
1223 void operator()(const float* src, float* dst, int n) const
1225 int i, bidx = blueIdx, scn = srccn;
1226 float hscale = hrange*(1.f/360.f);
1229 for( i = 0; i < n; i += 3, src += scn )
1231 float b = src[bidx], g = src[1], r = src[bidx^2];
1239 if( vmin > g ) vmin = g;
1240 if( vmin > b ) vmin = b;
1243 s = diff/(float)(fabs(v) + FLT_EPSILON);
1244 diff = (float)(60./(diff + FLT_EPSILON));
1248 h = (b - r)*diff + 120.f;
1250 h = (r - g)*diff + 240.f;
1252 if( h < 0 ) h += 360.f;
1267 typedef float channel_type;
1269 HSV2RGB_f(int _dstcn, int _blueIdx, float _hrange)
1270 : dstcn(_dstcn), blueIdx(_blueIdx), hscale(6.f/_hrange) {}
1272 void operator()(const float* src, float* dst, int n) const
1274 int i, bidx = blueIdx, dcn = dstcn;
1275 float _hscale = hscale;
1276 float alpha = ColorChannel<float>::max();
1279 for( i = 0; i < n; i += 3, dst += dcn )
1281 float h = src[i], s = src[i+1], v = src[i+2];
1288 static const int sector_data[][3]=
1289 {{1,3,0}, {1,0,2}, {3,0,1}, {0,2,1}, {0,1,3}, {2,1,0}};
1294 do h += 6; while( h < 0 );
1296 do h -= 6; while( h >= 6 );
1297 sector = cvFloor(h);
1299 if( (unsigned)sector >= 6u )
1306 tab[1] = v*(1.f - s);
1307 tab[2] = v*(1.f - s*h);
1308 tab[3] = v*(1.f - s*(1.f - h));
1310 b = tab[sector_data[sector][0]];
1311 g = tab[sector_data[sector][1]];
1312 r = tab[sector_data[sector][2]];
1330 typedef uchar channel_type;
1332 HSV2RGB_b(int _dstcn, int _blueIdx, int _hrange)
1333 : dstcn(_dstcn), cvt(3, _blueIdx, (float)_hrange)
1336 void operator()(const uchar* src, uchar* dst, int n) const
1338 int i, j, dcn = dstcn;
1339 uchar alpha = ColorChannel<uchar>::max();
1340 float buf[3*BLOCK_SIZE];
1342 for( i = 0; i < n; i += BLOCK_SIZE, src += BLOCK_SIZE*3 )
1344 int dn = std::min(n - i, (int)BLOCK_SIZE);
1346 for( j = 0; j < dn*3; j += 3 )
1349 buf[j+1] = src[j+1]*(1.f/255.f);
1350 buf[j+2] = src[j+2]*(1.f/255.f);
1354 for( j = 0; j < dn*3; j += 3, dst += dcn )
1356 dst[0] = saturate_cast<uchar>(buf[j]*255.f);
1357 dst[1] = saturate_cast<uchar>(buf[j+1]*255.f);
1358 dst[2] = saturate_cast<uchar>(buf[j+2]*255.f);
1370 ///////////////////////////////////// RGB <-> HLS ////////////////////////////////////////
1374 typedef float channel_type;
1376 RGB2HLS_f(int _srccn, int _blueIdx, float _hrange)
1377 : srccn(_srccn), blueIdx(_blueIdx), hrange(_hrange) {}
1379 void operator()(const float* src, float* dst, int n) const
1381 int i, bidx = blueIdx, scn = srccn;
1382 float hscale = hrange*(1.f/360.f);
1385 for( i = 0; i < n; i += 3, src += scn )
1387 float b = src[bidx], g = src[1], r = src[bidx^2];
1388 float h = 0.f, s = 0.f, l;
1389 float vmin, vmax, diff;
1392 if( vmax < g ) vmax = g;
1393 if( vmax < b ) vmax = b;
1394 if( vmin > g ) vmin = g;
1395 if( vmin > b ) vmin = b;
1398 l = (vmax + vmin)*0.5f;
1400 if( diff > FLT_EPSILON )
1402 s = l < 0.5f ? diff/(vmax + vmin) : diff/(2 - vmax - vmin);
1407 else if( vmax == g )
1408 h = (b - r)*diff + 120.f;
1410 h = (r - g)*diff + 240.f;
1412 if( h < 0.f ) h += 360.f;
1428 typedef uchar channel_type;
1430 RGB2HLS_b(int _srccn, int _blueIdx, int _hrange)
1431 : srccn(_srccn), cvt(3, _blueIdx, (float)_hrange) {}
1433 void operator()(const uchar* src, uchar* dst, int n) const
1435 int i, j, scn = srccn;
1436 float buf[3*BLOCK_SIZE];
1438 for( i = 0; i < n; i += BLOCK_SIZE, dst += BLOCK_SIZE*3 )
1440 int dn = std::min(n - i, (int)BLOCK_SIZE);
1442 for( j = 0; j < dn*3; j += 3, src += scn )
1444 buf[j] = src[0]*(1.f/255.f);
1445 buf[j+1] = src[1]*(1.f/255.f);
1446 buf[j+2] = src[2]*(1.f/255.f);
1450 for( j = 0; j < dn*3; j += 3 )
1452 dst[j] = saturate_cast<uchar>(buf[j]);
1453 dst[j+1] = saturate_cast<uchar>(buf[j+1]*255.f);
1454 dst[j+2] = saturate_cast<uchar>(buf[j+2]*255.f);
1466 typedef float channel_type;
1468 HLS2RGB_f(int _dstcn, int _blueIdx, float _hrange)
1469 : dstcn(_dstcn), blueIdx(_blueIdx), hscale(6.f/_hrange) {}
1471 void operator()(const float* src, float* dst, int n) const
1473 int i, bidx = blueIdx, dcn = dstcn;
1474 float _hscale = hscale;
1475 float alpha = ColorChannel<float>::max();
1478 for( i = 0; i < n; i += 3, dst += dcn )
1480 float h = src[i], l = src[i+1], s = src[i+2];
1487 static const int sector_data[][3]=
1488 {{1,3,0}, {1,0,2}, {3,0,1}, {0,2,1}, {0,1,3}, {2,1,0}};
1492 float p2 = l <= 0.5f ? l*(1 + s) : l + s - l*s;
1493 float p1 = 2*l - p2;
1497 do h += 6; while( h < 0 );
1499 do h -= 6; while( h >= 6 );
1501 assert( 0 <= h && h < 6 );
1502 sector = cvFloor(h);
1507 tab[2] = p1 + (p2 - p1)*(1-h);
1508 tab[3] = p1 + (p2 - p1)*h;
1510 b = tab[sector_data[sector][0]];
1511 g = tab[sector_data[sector][1]];
1512 r = tab[sector_data[sector][2]];
1530 typedef uchar channel_type;
1532 HLS2RGB_b(int _dstcn, int _blueIdx, int _hrange)
1533 : dstcn(_dstcn), cvt(3, _blueIdx, (float)_hrange)
1536 void operator()(const uchar* src, uchar* dst, int n) const
1538 int i, j, dcn = dstcn;
1539 uchar alpha = ColorChannel<uchar>::max();
1540 float buf[3*BLOCK_SIZE];
1542 for( i = 0; i < n; i += BLOCK_SIZE, src += BLOCK_SIZE*3 )
1544 int dn = std::min(n - i, (int)BLOCK_SIZE);
1546 for( j = 0; j < dn*3; j += 3 )
1549 buf[j+1] = src[j+1]*(1.f/255.f);
1550 buf[j+2] = src[j+2]*(1.f/255.f);
1554 for( j = 0; j < dn*3; j += 3, dst += dcn )
1556 dst[0] = saturate_cast<uchar>(buf[j]*255.f);
1557 dst[1] = saturate_cast<uchar>(buf[j+1]*255.f);
1558 dst[2] = saturate_cast<uchar>(buf[j+2]*255.f);
1570 ///////////////////////////////////// RGB <-> L*a*b* /////////////////////////////////////
1572 static const float D65[] = { 0.950456f, 1.f, 1.088754f };
1574 enum { LAB_CBRT_TAB_SIZE = 1024, GAMMA_TAB_SIZE = 1024 };
1575 static float LabCbrtTab[LAB_CBRT_TAB_SIZE*4];
1576 static const float LabCbrtTabScale = LAB_CBRT_TAB_SIZE/1.5f;
1578 static float sRGBGammaTab[GAMMA_TAB_SIZE*4], sRGBInvGammaTab[GAMMA_TAB_SIZE*4];
1579 static const float GammaTabScale = (float)GAMMA_TAB_SIZE;
1581 static ushort sRGBGammaTab_b[256], linearGammaTab_b[256];
1583 #define lab_shift xyz_shift
1584 #define gamma_shift 3
1585 #define lab_shift2 (lab_shift + gamma_shift)
1586 #define LAB_CBRT_TAB_SIZE_B (256*3/2*(1<<gamma_shift))
1587 static ushort LabCbrtTab_b[LAB_CBRT_TAB_SIZE_B];
1589 static void initLabTabs()
1591 static bool initialized = false;
1594 float f[LAB_CBRT_TAB_SIZE+1], g[GAMMA_TAB_SIZE+1], ig[GAMMA_TAB_SIZE+1], scale = 1.f/LabCbrtTabScale;
1596 for(i = 0; i <= LAB_CBRT_TAB_SIZE; i++)
1599 f[i] = x < 0.008856f ? x*7.787f + 0.13793103448275862f : cvCbrt(x);
1601 splineBuild(f, LAB_CBRT_TAB_SIZE, LabCbrtTab);
1603 scale = 1.f/GammaTabScale;
1604 for(i = 0; i <= GAMMA_TAB_SIZE; i++)
1607 g[i] = x <= 0.04045f ? x*(1.f/12.92f) : (float)std::pow((double)(x + 0.055)*(1./1.055), 2.4);
1608 ig[i] = x <= 0.0031308 ? x*12.92f : (float)(1.055*std::pow((double)x, 1./2.4) - 0.055);
1610 splineBuild(g, GAMMA_TAB_SIZE, sRGBGammaTab);
1611 splineBuild(ig, GAMMA_TAB_SIZE, sRGBInvGammaTab);
1613 for(i = 0; i < 256; i++)
1615 float x = i*(1.f/255.f);
1616 sRGBGammaTab_b[i] = saturate_cast<ushort>(255.f*(1 << gamma_shift)*(x <= 0.04045f ? x*(1.f/12.92f) : (float)std::pow((double)(x + 0.055)*(1./1.055), 2.4)));
1617 linearGammaTab_b[i] = (ushort)(i*(1 << gamma_shift));
1620 for(i = 0; i < LAB_CBRT_TAB_SIZE_B; i++)
1622 float x = i*(1.f/(255.f*(1 << gamma_shift)));
1623 LabCbrtTab_b[i] = saturate_cast<ushort>((1 << lab_shift2)*(x < 0.008856f ? x*7.787f + 0.13793103448275862f : cvCbrt(x)));
1631 typedef uchar channel_type;
1633 RGB2Lab_b(int _srccn, int blueIdx, const float* _coeffs,
1634 const float* _whitept, bool _srgb)
1635 : srccn(_srccn), srgb(_srgb)
1637 static volatile int _3 = 3;
1641 _coeffs = sRGB2XYZ_D65;
1647 (1 << lab_shift)/_whitept[0],
1648 (float)(1 << lab_shift),
1649 (1 << lab_shift)/_whitept[2]
1652 for( int i = 0; i < _3; i++ )
1654 coeffs[i*3+(blueIdx^2)] = cvRound(_coeffs[i*3]*scale[i]);
1655 coeffs[i*3+1] = cvRound(_coeffs[i*3+1]*scale[i]);
1656 coeffs[i*3+blueIdx] = cvRound(_coeffs[i*3+2]*scale[i]);
1658 CV_Assert( coeffs[i] >= 0 && coeffs[i*3+1] >= 0 && coeffs[i*3+2] >= 0 &&
1659 coeffs[i*3] + coeffs[i*3+1] + coeffs[i*3+2] < 2*(1 << lab_shift) );
1663 void operator()(const uchar* src, uchar* dst, int n) const
1665 const int Lscale = (116*255+50)/100;
1666 const int Lshift = -((16*255*(1 << lab_shift2) + 50)/100);
1667 const ushort* tab = srgb ? sRGBGammaTab_b : linearGammaTab_b;
1669 int C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2],
1670 C3 = coeffs[3], C4 = coeffs[4], C5 = coeffs[5],
1671 C6 = coeffs[6], C7 = coeffs[7], C8 = coeffs[8];
1674 for( i = 0; i < n; i += 3, src += scn )
1676 int R = tab[src[0]], G = tab[src[1]], B = tab[src[2]];
1677 int fX = LabCbrtTab_b[CV_DESCALE(R*C0 + G*C1 + B*C2, lab_shift)];
1678 int fY = LabCbrtTab_b[CV_DESCALE(R*C3 + G*C4 + B*C5, lab_shift)];
1679 int fZ = LabCbrtTab_b[CV_DESCALE(R*C6 + G*C7 + B*C8, lab_shift)];
1681 int L = CV_DESCALE( Lscale*fY + Lshift, lab_shift2 );
1682 int a = CV_DESCALE( 500*(fX - fY) + 128*(1 << lab_shift2), lab_shift2 );
1683 int b = CV_DESCALE( 200*(fY - fZ) + 128*(1 << lab_shift2), lab_shift2 );
1685 dst[i] = saturate_cast<uchar>(L);
1686 dst[i+1] = saturate_cast<uchar>(a);
1687 dst[i+2] = saturate_cast<uchar>(b);
1697 #define clip(value) \
1698 value < 0.0f ? 0.0f : value > 1.0f ? 1.0f : value;
1702 typedef float channel_type;
1704 RGB2Lab_f(int _srccn, int blueIdx, const float* _coeffs,
1705 const float* _whitept, bool _srgb)
1706 : srccn(_srccn), srgb(_srgb)
1708 volatile int _3 = 3;
1712 _coeffs = sRGB2XYZ_D65;
1716 float scale[] = { 1.0f / _whitept[0], 1.0f, 1.0f / _whitept[2] };
1718 for( int i = 0; i < _3; i++ )
1721 coeffs[j + (blueIdx ^ 2)] = _coeffs[j] * scale[i];
1722 coeffs[j + 1] = _coeffs[j + 1] * scale[i];
1723 coeffs[j + blueIdx] = _coeffs[j + 2] * scale[i];
1725 CV_Assert( coeffs[j] >= 0 && coeffs[j + 1] >= 0 && coeffs[j + 2] >= 0 &&
1726 coeffs[j] + coeffs[j + 1] + coeffs[j + 2] < 1.5f*LabCbrtTabScale );
1730 void operator()(const float* src, float* dst, int n) const
1733 float gscale = GammaTabScale;
1734 const float* gammaTab = srgb ? sRGBGammaTab : 0;
1735 float C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2],
1736 C3 = coeffs[3], C4 = coeffs[4], C5 = coeffs[5],
1737 C6 = coeffs[6], C7 = coeffs[7], C8 = coeffs[8];
1740 static const float _1_3 = 1.0f / 3.0f;
1741 static const float _a = 16.0f / 116.0f;
1742 for (i = 0; i < n; i += 3, src += scn )
1744 float R = clip(src[0]);
1745 float G = clip(src[1]);
1746 float B = clip(src[2]);
1750 R = splineInterpolate(R * gscale, gammaTab, GAMMA_TAB_SIZE);
1751 G = splineInterpolate(G * gscale, gammaTab, GAMMA_TAB_SIZE);
1752 B = splineInterpolate(B * gscale, gammaTab, GAMMA_TAB_SIZE);
1754 float X = R*C0 + G*C1 + B*C2;
1755 float Y = R*C3 + G*C4 + B*C5;
1756 float Z = R*C6 + G*C7 + B*C8;
1758 float FX = X > 0.008856f ? std::pow(X, _1_3) : (7.787f * X + _a);
1759 float FY = Y > 0.008856f ? std::pow(Y, _1_3) : (7.787f * Y + _a);
1760 float FZ = Z > 0.008856f ? std::pow(Z, _1_3) : (7.787f * Z + _a);
1762 float L = Y > 0.008856f ? (116.f * FY - 16.f) : (903.3f * Y);
1763 float a = 500.f * (FX - FY);
1764 float b = 200.f * (FY - FZ);
1779 typedef float channel_type;
1781 Lab2RGB_f( int _dstcn, int blueIdx, const float* _coeffs,
1782 const float* _whitept, bool _srgb )
1783 : dstcn(_dstcn), srgb(_srgb)
1788 _coeffs = XYZ2sRGB_D65;
1792 for( int i = 0; i < 3; i++ )
1794 coeffs[i+(blueIdx^2)*3] = _coeffs[i]*_whitept[i];
1795 coeffs[i+3] = _coeffs[i+3]*_whitept[i];
1796 coeffs[i+blueIdx*3] = _coeffs[i+6]*_whitept[i];
1800 void operator()(const float* src, float* dst, int n) const
1803 const float* gammaTab = srgb ? sRGBInvGammaTab : 0;
1804 float gscale = GammaTabScale;
1805 float C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2],
1806 C3 = coeffs[3], C4 = coeffs[4], C5 = coeffs[5],
1807 C6 = coeffs[6], C7 = coeffs[7], C8 = coeffs[8];
1808 float alpha = ColorChannel<float>::max();
1811 static const float lThresh = 0.008856f * 903.3f;
1812 static const float fThresh = 7.787f * 0.008856f + 16.0f / 116.0f;
1813 for (i = 0; i < n; i += 3, dst += dcn)
1816 float ai = src[i + 1];
1817 float bi = src[i + 2];
1823 fy = 7.787f * y + 16.0f / 116.0f;
1827 fy = (li + 16.0f) / 116.0f;
1831 float fxz[] = { ai / 500.0f + fy, fy - bi / 200.0f };
1833 for (int j = 0; j < 2; j++)
1834 if (fxz[j] <= fThresh)
1835 fxz[j] = (fxz[j] - 16.0f / 116.0f) / 7.787f;
1837 fxz[j] = fxz[j] * fxz[j] * fxz[j];
1840 float x = fxz[0], z = fxz[1];
1841 float ro = C0 * x + C1 * y + C2 * z;
1842 float go = C3 * x + C4 * y + C5 * z;
1843 float bo = C6 * x + C7 * y + C8 * z;
1850 ro = splineInterpolate(ro * gscale, gammaTab, GAMMA_TAB_SIZE);
1851 go = splineInterpolate(go * gscale, gammaTab, GAMMA_TAB_SIZE);
1852 bo = splineInterpolate(bo * gscale, gammaTab, GAMMA_TAB_SIZE);
1855 dst[0] = ro, dst[1] = go, dst[2] = bo;
1870 typedef uchar channel_type;
1872 Lab2RGB_b( int _dstcn, int blueIdx, const float* _coeffs,
1873 const float* _whitept, bool _srgb )
1874 : dstcn(_dstcn), cvt(3, blueIdx, _coeffs, _whitept, _srgb ) {}
1876 void operator()(const uchar* src, uchar* dst, int n) const
1878 int i, j, dcn = dstcn;
1879 uchar alpha = ColorChannel<uchar>::max();
1880 float buf[3*BLOCK_SIZE];
1882 for( i = 0; i < n; i += BLOCK_SIZE, src += BLOCK_SIZE*3 )
1884 int dn = std::min(n - i, (int)BLOCK_SIZE);
1886 for( j = 0; j < dn*3; j += 3 )
1888 buf[j] = src[j]*(100.f/255.f);
1889 buf[j+1] = (float)(src[j+1] - 128);
1890 buf[j+2] = (float)(src[j+2] - 128);
1894 for( j = 0; j < dn*3; j += 3, dst += dcn )
1896 dst[0] = saturate_cast<uchar>(buf[j]*255.f);
1897 dst[1] = saturate_cast<uchar>(buf[j+1]*255.f);
1898 dst[2] = saturate_cast<uchar>(buf[j+2]*255.f);
1910 ///////////////////////////////////// RGB <-> L*u*v* /////////////////////////////////////
1914 typedef float channel_type;
1916 RGB2Luv_f( int _srccn, int blueIdx, const float* _coeffs,
1917 const float* whitept, bool _srgb )
1918 : srccn(_srccn), srgb(_srgb)
1923 if(!_coeffs) _coeffs = sRGB2XYZ_D65;
1924 if(!whitept) whitept = D65;
1926 for( i = 0; i < 3; i++ )
1928 coeffs[i*3] = _coeffs[i*3];
1929 coeffs[i*3+1] = _coeffs[i*3+1];
1930 coeffs[i*3+2] = _coeffs[i*3+2];
1932 std::swap(coeffs[i*3], coeffs[i*3+2]);
1933 CV_Assert( coeffs[i*3] >= 0 && coeffs[i*3+1] >= 0 && coeffs[i*3+2] >= 0 &&
1934 coeffs[i*3] + coeffs[i*3+1] + coeffs[i*3+2] < 1.5f );
1937 float d = 1.f/(whitept[0] + whitept[1]*15 + whitept[2]*3);
1938 un = 4*whitept[0]*d;
1939 vn = 9*whitept[1]*d;
1941 CV_Assert(whitept[1] == 1.f);
1944 void operator()(const float* src, float* dst, int n) const
1947 float gscale = GammaTabScale;
1948 const float* gammaTab = srgb ? sRGBGammaTab : 0;
1949 float C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2],
1950 C3 = coeffs[3], C4 = coeffs[4], C5 = coeffs[5],
1951 C6 = coeffs[6], C7 = coeffs[7], C8 = coeffs[8];
1952 float _un = 13*un, _vn = 13*vn;
1955 for( i = 0; i < n; i += 3, src += scn )
1957 float R = src[0], G = src[1], B = src[2];
1960 R = splineInterpolate(R*gscale, gammaTab, GAMMA_TAB_SIZE);
1961 G = splineInterpolate(G*gscale, gammaTab, GAMMA_TAB_SIZE);
1962 B = splineInterpolate(B*gscale, gammaTab, GAMMA_TAB_SIZE);
1965 float X = R*C0 + G*C1 + B*C2;
1966 float Y = R*C3 + G*C4 + B*C5;
1967 float Z = R*C6 + G*C7 + B*C8;
1969 float L = splineInterpolate(Y*LabCbrtTabScale, LabCbrtTab, LAB_CBRT_TAB_SIZE);
1972 float d = (4*13) / std::max(X + 15 * Y + 3 * Z, FLT_EPSILON);
1973 float u = L*(X*d - _un);
1974 float v = L*((9*0.25f)*Y*d - _vn);
1976 dst[i] = L; dst[i+1] = u; dst[i+2] = v;
1981 float coeffs[9], un, vn;
1988 typedef float channel_type;
1990 Luv2RGB_f( int _dstcn, int blueIdx, const float* _coeffs,
1991 const float* whitept, bool _srgb )
1992 : dstcn(_dstcn), srgb(_srgb)
1996 if(!_coeffs) _coeffs = XYZ2sRGB_D65;
1997 if(!whitept) whitept = D65;
1999 for( int i = 0; i < 3; i++ )
2001 coeffs[i+(blueIdx^2)*3] = _coeffs[i];
2002 coeffs[i+3] = _coeffs[i+3];
2003 coeffs[i+blueIdx*3] = _coeffs[i+6];
2006 float d = 1.f/(whitept[0] + whitept[1]*15 + whitept[2]*3);
2007 un = 4*whitept[0]*d;
2008 vn = 9*whitept[1]*d;
2010 CV_Assert(whitept[1] == 1.f);
2013 void operator()(const float* src, float* dst, int n) const
2016 const float* gammaTab = srgb ? sRGBInvGammaTab : 0;
2017 float gscale = GammaTabScale;
2018 float C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2],
2019 C3 = coeffs[3], C4 = coeffs[4], C5 = coeffs[5],
2020 C6 = coeffs[6], C7 = coeffs[7], C8 = coeffs[8];
2021 float alpha = ColorChannel<float>::max();
2022 float _un = un, _vn = vn;
2025 for( i = 0; i < n; i += 3, dst += dcn )
2027 float L = src[i], u = src[i+1], v = src[i+2], d, X, Y, Z;
2028 Y = (L + 16.f) * (1.f/116.f);
2034 X = 2.25f * u * Y * iv ;
2035 Z = (12 - 3 * u - 20 * v) * Y * 0.25f * iv;
2037 float R = X*C0 + Y*C1 + Z*C2;
2038 float G = X*C3 + Y*C4 + Z*C5;
2039 float B = X*C6 + Y*C7 + Z*C8;
2043 R = splineInterpolate(R*gscale, gammaTab, GAMMA_TAB_SIZE);
2044 G = splineInterpolate(G*gscale, gammaTab, GAMMA_TAB_SIZE);
2045 B = splineInterpolate(B*gscale, gammaTab, GAMMA_TAB_SIZE);
2048 dst[0] = R; dst[1] = G; dst[2] = B;
2055 float coeffs[9], un, vn;
2062 typedef uchar channel_type;
2064 RGB2Luv_b( int _srccn, int blueIdx, const float* _coeffs,
2065 const float* _whitept, bool _srgb )
2066 : srccn(_srccn), cvt(3, blueIdx, _coeffs, _whitept, _srgb) {}
2068 void operator()(const uchar* src, uchar* dst, int n) const
2070 int i, j, scn = srccn;
2071 float buf[3*BLOCK_SIZE];
2073 for( i = 0; i < n; i += BLOCK_SIZE, dst += BLOCK_SIZE*3 )
2075 int dn = std::min(n - i, (int)BLOCK_SIZE);
2077 for( j = 0; j < dn*3; j += 3, src += scn )
2079 buf[j] = src[0]*(1.f/255.f);
2080 buf[j+1] = (float)(src[1]*(1.f/255.f));
2081 buf[j+2] = (float)(src[2]*(1.f/255.f));
2085 for( j = 0; j < dn*3; j += 3 )
2087 dst[j] = saturate_cast<uchar>(buf[j]*2.55f);
2088 dst[j+1] = saturate_cast<uchar>(buf[j+1]*0.72033898305084743f + 96.525423728813564f);
2089 dst[j+2] = saturate_cast<uchar>(buf[j+2]*0.99609375f + 139.453125f);
2101 typedef uchar channel_type;
2103 Luv2RGB_b( int _dstcn, int blueIdx, const float* _coeffs,
2104 const float* _whitept, bool _srgb )
2105 : dstcn(_dstcn), cvt(3, blueIdx, _coeffs, _whitept, _srgb ) {}
2107 void operator()(const uchar* src, uchar* dst, int n) const
2109 int i, j, dcn = dstcn;
2110 uchar alpha = ColorChannel<uchar>::max();
2111 float buf[3*BLOCK_SIZE];
2113 for( i = 0; i < n; i += BLOCK_SIZE, src += BLOCK_SIZE*3 )
2115 int dn = std::min(n - i, (int)BLOCK_SIZE);
2117 for( j = 0; j < dn*3; j += 3 )
2119 buf[j] = src[j]*(100.f/255.f);
2120 buf[j+1] = (float)(src[j+1]*1.388235294117647f - 134.f);
2121 buf[j+2] = (float)(src[j+2]*1.003921568627451f - 140.f);
2125 for( j = 0; j < dn*3; j += 3, dst += dcn )
2127 dst[0] = saturate_cast<uchar>(buf[j]*255.f);
2128 dst[1] = saturate_cast<uchar>(buf[j+1]*255.f);
2129 dst[2] = saturate_cast<uchar>(buf[j+2]*255.f);
2141 ///////////////////////////////////// YUV420 -> RGB /////////////////////////////////////
2143 const int ITUR_BT_601_CY = 1220542;
2144 const int ITUR_BT_601_CUB = 2116026;
2145 const int ITUR_BT_601_CUG = -409993;
2146 const int ITUR_BT_601_CVG = -852492;
2147 const int ITUR_BT_601_CVR = 1673527;
2148 const int ITUR_BT_601_SHIFT = 20;
2150 // Coefficients for RGB to YUV420p conversion
2151 const int ITUR_BT_601_CRY = 269484;
2152 const int ITUR_BT_601_CGY = 528482;
2153 const int ITUR_BT_601_CBY = 102760;
2154 const int ITUR_BT_601_CRU = -155188;
2155 const int ITUR_BT_601_CGU = -305135;
2156 const int ITUR_BT_601_CBU = 460324;
2157 const int ITUR_BT_601_CGV = -385875;
2158 const int ITUR_BT_601_CBV = -74448;
2160 template<int bIdx, int uIdx>
2161 struct YUV420sp2RGB888Invoker : ParallelLoopBody
2164 const uchar* my1, *muv;
2167 YUV420sp2RGB888Invoker(Mat* _dst, int _stride, const uchar* _y1, const uchar* _uv)
2168 : dst(_dst), my1(_y1), muv(_uv), width(_dst->cols), stride(_stride) {}
2170 void operator()(const Range& range) const
2172 int rangeBegin = range.start * 2;
2173 int rangeEnd = range.end * 2;
2175 //R = 1.164(Y - 16) + 1.596(V - 128)
2176 //G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128)
2177 //B = 1.164(Y - 16) + 2.018(U - 128)
2179 //R = (1220542(Y - 16) + 1673527(V - 128) + (1 << 19)) >> 20
2180 //G = (1220542(Y - 16) - 852492(V - 128) - 409993(U - 128) + (1 << 19)) >> 20
2181 //B = (1220542(Y - 16) + 2116026(U - 128) + (1 << 19)) >> 20
2183 const uchar* y1 = my1 + rangeBegin * stride, *uv = muv + rangeBegin * stride / 2;
2185 #ifdef HAVE_TEGRA_OPTIMIZATION
2186 if(tegra::cvtYUV4202RGB(bIdx, uIdx, 3, y1, uv, stride, dst->ptr<uchar>(rangeBegin), dst->step, rangeEnd - rangeBegin, dst->cols))
2190 for (int j = rangeBegin; j < rangeEnd; j += 2, y1 += stride * 2, uv += stride)
2192 uchar* row1 = dst->ptr<uchar>(j);
2193 uchar* row2 = dst->ptr<uchar>(j + 1);
2194 const uchar* y2 = y1 + stride;
2196 for (int i = 0; i < width; i += 2, row1 += 6, row2 += 6)
2198 int u = int(uv[i + 0 + uIdx]) - 128;
2199 int v = int(uv[i + 1 - uIdx]) - 128;
2201 int ruv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVR * v;
2202 int guv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVG * v + ITUR_BT_601_CUG * u;
2203 int buv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CUB * u;
2205 int y00 = std::max(0, int(y1[i]) - 16) * ITUR_BT_601_CY;
2206 row1[2-bIdx] = saturate_cast<uchar>((y00 + ruv) >> ITUR_BT_601_SHIFT);
2207 row1[1] = saturate_cast<uchar>((y00 + guv) >> ITUR_BT_601_SHIFT);
2208 row1[bIdx] = saturate_cast<uchar>((y00 + buv) >> ITUR_BT_601_SHIFT);
2210 int y01 = std::max(0, int(y1[i + 1]) - 16) * ITUR_BT_601_CY;
2211 row1[5-bIdx] = saturate_cast<uchar>((y01 + ruv) >> ITUR_BT_601_SHIFT);
2212 row1[4] = saturate_cast<uchar>((y01 + guv) >> ITUR_BT_601_SHIFT);
2213 row1[3+bIdx] = saturate_cast<uchar>((y01 + buv) >> ITUR_BT_601_SHIFT);
2215 int y10 = std::max(0, int(y2[i]) - 16) * ITUR_BT_601_CY;
2216 row2[2-bIdx] = saturate_cast<uchar>((y10 + ruv) >> ITUR_BT_601_SHIFT);
2217 row2[1] = saturate_cast<uchar>((y10 + guv) >> ITUR_BT_601_SHIFT);
2218 row2[bIdx] = saturate_cast<uchar>((y10 + buv) >> ITUR_BT_601_SHIFT);
2220 int y11 = std::max(0, int(y2[i + 1]) - 16) * ITUR_BT_601_CY;
2221 row2[5-bIdx] = saturate_cast<uchar>((y11 + ruv) >> ITUR_BT_601_SHIFT);
2222 row2[4] = saturate_cast<uchar>((y11 + guv) >> ITUR_BT_601_SHIFT);
2223 row2[3+bIdx] = saturate_cast<uchar>((y11 + buv) >> ITUR_BT_601_SHIFT);
2229 template<int bIdx, int uIdx>
2230 struct YUV420sp2RGBA8888Invoker : ParallelLoopBody
2233 const uchar* my1, *muv;
2236 YUV420sp2RGBA8888Invoker(Mat* _dst, int _stride, const uchar* _y1, const uchar* _uv)
2237 : dst(_dst), my1(_y1), muv(_uv), width(_dst->cols), stride(_stride) {}
2239 void operator()(const Range& range) const
2241 int rangeBegin = range.start * 2;
2242 int rangeEnd = range.end * 2;
2244 //R = 1.164(Y - 16) + 1.596(V - 128)
2245 //G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128)
2246 //B = 1.164(Y - 16) + 2.018(U - 128)
2248 //R = (1220542(Y - 16) + 1673527(V - 128) + (1 << 19)) >> 20
2249 //G = (1220542(Y - 16) - 852492(V - 128) - 409993(U - 128) + (1 << 19)) >> 20
2250 //B = (1220542(Y - 16) + 2116026(U - 128) + (1 << 19)) >> 20
2252 const uchar* y1 = my1 + rangeBegin * stride, *uv = muv + rangeBegin * stride / 2;
2254 #ifdef HAVE_TEGRA_OPTIMIZATION
2255 if(tegra::cvtYUV4202RGB(bIdx, uIdx, 4, y1, uv, stride, dst->ptr<uchar>(rangeBegin), dst->step, rangeEnd - rangeBegin, dst->cols))
2259 for (int j = rangeBegin; j < rangeEnd; j += 2, y1 += stride * 2, uv += stride)
2261 uchar* row1 = dst->ptr<uchar>(j);
2262 uchar* row2 = dst->ptr<uchar>(j + 1);
2263 const uchar* y2 = y1 + stride;
2265 for (int i = 0; i < width; i += 2, row1 += 8, row2 += 8)
2267 int u = int(uv[i + 0 + uIdx]) - 128;
2268 int v = int(uv[i + 1 - uIdx]) - 128;
2270 int ruv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVR * v;
2271 int guv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVG * v + ITUR_BT_601_CUG * u;
2272 int buv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CUB * u;
2274 int y00 = std::max(0, int(y1[i]) - 16) * ITUR_BT_601_CY;
2275 row1[2-bIdx] = saturate_cast<uchar>((y00 + ruv) >> ITUR_BT_601_SHIFT);
2276 row1[1] = saturate_cast<uchar>((y00 + guv) >> ITUR_BT_601_SHIFT);
2277 row1[bIdx] = saturate_cast<uchar>((y00 + buv) >> ITUR_BT_601_SHIFT);
2278 row1[3] = uchar(0xff);
2280 int y01 = std::max(0, int(y1[i + 1]) - 16) * ITUR_BT_601_CY;
2281 row1[6-bIdx] = saturate_cast<uchar>((y01 + ruv) >> ITUR_BT_601_SHIFT);
2282 row1[5] = saturate_cast<uchar>((y01 + guv) >> ITUR_BT_601_SHIFT);
2283 row1[4+bIdx] = saturate_cast<uchar>((y01 + buv) >> ITUR_BT_601_SHIFT);
2284 row1[7] = uchar(0xff);
2286 int y10 = std::max(0, int(y2[i]) - 16) * ITUR_BT_601_CY;
2287 row2[2-bIdx] = saturate_cast<uchar>((y10 + ruv) >> ITUR_BT_601_SHIFT);
2288 row2[1] = saturate_cast<uchar>((y10 + guv) >> ITUR_BT_601_SHIFT);
2289 row2[bIdx] = saturate_cast<uchar>((y10 + buv) >> ITUR_BT_601_SHIFT);
2290 row2[3] = uchar(0xff);
2292 int y11 = std::max(0, int(y2[i + 1]) - 16) * ITUR_BT_601_CY;
2293 row2[6-bIdx] = saturate_cast<uchar>((y11 + ruv) >> ITUR_BT_601_SHIFT);
2294 row2[5] = saturate_cast<uchar>((y11 + guv) >> ITUR_BT_601_SHIFT);
2295 row2[4+bIdx] = saturate_cast<uchar>((y11 + buv) >> ITUR_BT_601_SHIFT);
2296 row2[7] = uchar(0xff);
2303 struct YUV420p2RGB888Invoker : ParallelLoopBody
2306 const uchar* my1, *mu, *mv;
2308 int ustepIdx, vstepIdx;
2310 YUV420p2RGB888Invoker(Mat* _dst, int _stride, const uchar* _y1, const uchar* _u, const uchar* _v, int _ustepIdx, int _vstepIdx)
2311 : dst(_dst), my1(_y1), mu(_u), mv(_v), width(_dst->cols), stride(_stride), ustepIdx(_ustepIdx), vstepIdx(_vstepIdx) {}
2313 void operator()(const Range& range) const
2315 const int rangeBegin = range.start * 2;
2316 const int rangeEnd = range.end * 2;
2318 int uvsteps[2] = {width/2, stride - width/2};
2319 int usIdx = ustepIdx, vsIdx = vstepIdx;
2321 const uchar* y1 = my1 + rangeBegin * stride;
2322 const uchar* u1 = mu + (range.start / 2) * stride;
2323 const uchar* v1 = mv + (range.start / 2) * stride;
2325 if(range.start % 2 == 1)
2327 u1 += uvsteps[(usIdx++) & 1];
2328 v1 += uvsteps[(vsIdx++) & 1];
2331 for (int j = rangeBegin; j < rangeEnd; j += 2, y1 += stride * 2, u1 += uvsteps[(usIdx++) & 1], v1 += uvsteps[(vsIdx++) & 1])
2333 uchar* row1 = dst->ptr<uchar>(j);
2334 uchar* row2 = dst->ptr<uchar>(j + 1);
2335 const uchar* y2 = y1 + stride;
2337 for (int i = 0; i < width / 2; i += 1, row1 += 6, row2 += 6)
2339 int u = int(u1[i]) - 128;
2340 int v = int(v1[i]) - 128;
2342 int ruv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVR * v;
2343 int guv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVG * v + ITUR_BT_601_CUG * u;
2344 int buv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CUB * u;
2346 int y00 = std::max(0, int(y1[2 * i]) - 16) * ITUR_BT_601_CY;
2347 row1[2-bIdx] = saturate_cast<uchar>((y00 + ruv) >> ITUR_BT_601_SHIFT);
2348 row1[1] = saturate_cast<uchar>((y00 + guv) >> ITUR_BT_601_SHIFT);
2349 row1[bIdx] = saturate_cast<uchar>((y00 + buv) >> ITUR_BT_601_SHIFT);
2351 int y01 = std::max(0, int(y1[2 * i + 1]) - 16) * ITUR_BT_601_CY;
2352 row1[5-bIdx] = saturate_cast<uchar>((y01 + ruv) >> ITUR_BT_601_SHIFT);
2353 row1[4] = saturate_cast<uchar>((y01 + guv) >> ITUR_BT_601_SHIFT);
2354 row1[3+bIdx] = saturate_cast<uchar>((y01 + buv) >> ITUR_BT_601_SHIFT);
2356 int y10 = std::max(0, int(y2[2 * i]) - 16) * ITUR_BT_601_CY;
2357 row2[2-bIdx] = saturate_cast<uchar>((y10 + ruv) >> ITUR_BT_601_SHIFT);
2358 row2[1] = saturate_cast<uchar>((y10 + guv) >> ITUR_BT_601_SHIFT);
2359 row2[bIdx] = saturate_cast<uchar>((y10 + buv) >> ITUR_BT_601_SHIFT);
2361 int y11 = std::max(0, int(y2[2 * i + 1]) - 16) * ITUR_BT_601_CY;
2362 row2[5-bIdx] = saturate_cast<uchar>((y11 + ruv) >> ITUR_BT_601_SHIFT);
2363 row2[4] = saturate_cast<uchar>((y11 + guv) >> ITUR_BT_601_SHIFT);
2364 row2[3+bIdx] = saturate_cast<uchar>((y11 + buv) >> ITUR_BT_601_SHIFT);
2371 struct YUV420p2RGBA8888Invoker : ParallelLoopBody
2374 const uchar* my1, *mu, *mv;
2376 int ustepIdx, vstepIdx;
2378 YUV420p2RGBA8888Invoker(Mat* _dst, int _stride, const uchar* _y1, const uchar* _u, const uchar* _v, int _ustepIdx, int _vstepIdx)
2379 : dst(_dst), my1(_y1), mu(_u), mv(_v), width(_dst->cols), stride(_stride), ustepIdx(_ustepIdx), vstepIdx(_vstepIdx) {}
2381 void operator()(const Range& range) const
2383 int rangeBegin = range.start * 2;
2384 int rangeEnd = range.end * 2;
2386 int uvsteps[2] = {width/2, stride - width/2};
2387 int usIdx = ustepIdx, vsIdx = vstepIdx;
2389 const uchar* y1 = my1 + rangeBegin * stride;
2390 const uchar* u1 = mu + (range.start / 2) * stride;
2391 const uchar* v1 = mv + (range.start / 2) * stride;
2393 if(range.start % 2 == 1)
2395 u1 += uvsteps[(usIdx++) & 1];
2396 v1 += uvsteps[(vsIdx++) & 1];
2399 for (int j = rangeBegin; j < rangeEnd; j += 2, y1 += stride * 2, u1 += uvsteps[(usIdx++) & 1], v1 += uvsteps[(vsIdx++) & 1])
2401 uchar* row1 = dst->ptr<uchar>(j);
2402 uchar* row2 = dst->ptr<uchar>(j + 1);
2403 const uchar* y2 = y1 + stride;
2405 for (int i = 0; i < width / 2; i += 1, row1 += 8, row2 += 8)
2407 int u = int(u1[i]) - 128;
2408 int v = int(v1[i]) - 128;
2410 int ruv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVR * v;
2411 int guv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVG * v + ITUR_BT_601_CUG * u;
2412 int buv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CUB * u;
2414 int y00 = std::max(0, int(y1[2 * i]) - 16) * ITUR_BT_601_CY;
2415 row1[2-bIdx] = saturate_cast<uchar>((y00 + ruv) >> ITUR_BT_601_SHIFT);
2416 row1[1] = saturate_cast<uchar>((y00 + guv) >> ITUR_BT_601_SHIFT);
2417 row1[bIdx] = saturate_cast<uchar>((y00 + buv) >> ITUR_BT_601_SHIFT);
2418 row1[3] = uchar(0xff);
2420 int y01 = std::max(0, int(y1[2 * i + 1]) - 16) * ITUR_BT_601_CY;
2421 row1[6-bIdx] = saturate_cast<uchar>((y01 + ruv) >> ITUR_BT_601_SHIFT);
2422 row1[5] = saturate_cast<uchar>((y01 + guv) >> ITUR_BT_601_SHIFT);
2423 row1[4+bIdx] = saturate_cast<uchar>((y01 + buv) >> ITUR_BT_601_SHIFT);
2424 row1[7] = uchar(0xff);
2426 int y10 = std::max(0, int(y2[2 * i]) - 16) * ITUR_BT_601_CY;
2427 row2[2-bIdx] = saturate_cast<uchar>((y10 + ruv) >> ITUR_BT_601_SHIFT);
2428 row2[1] = saturate_cast<uchar>((y10 + guv) >> ITUR_BT_601_SHIFT);
2429 row2[bIdx] = saturate_cast<uchar>((y10 + buv) >> ITUR_BT_601_SHIFT);
2430 row2[3] = uchar(0xff);
2432 int y11 = std::max(0, int(y2[2 * i + 1]) - 16) * ITUR_BT_601_CY;
2433 row2[6-bIdx] = saturate_cast<uchar>((y11 + ruv) >> ITUR_BT_601_SHIFT);
2434 row2[5] = saturate_cast<uchar>((y11 + guv) >> ITUR_BT_601_SHIFT);
2435 row2[4+bIdx] = saturate_cast<uchar>((y11 + buv) >> ITUR_BT_601_SHIFT);
2436 row2[7] = uchar(0xff);
2442 #define MIN_SIZE_FOR_PARALLEL_YUV420_CONVERSION (320*240)
2444 template<int bIdx, int uIdx>
2445 inline void cvtYUV420sp2RGB(Mat& _dst, int _stride, const uchar* _y1, const uchar* _uv)
2447 YUV420sp2RGB888Invoker<bIdx, uIdx> converter(&_dst, _stride, _y1, _uv);
2448 if (_dst.total() >= MIN_SIZE_FOR_PARALLEL_YUV420_CONVERSION)
2449 parallel_for_(Range(0, _dst.rows/2), converter);
2451 converter(Range(0, _dst.rows/2));
2454 template<int bIdx, int uIdx>
2455 inline void cvtYUV420sp2RGBA(Mat& _dst, int _stride, const uchar* _y1, const uchar* _uv)
2457 YUV420sp2RGBA8888Invoker<bIdx, uIdx> converter(&_dst, _stride, _y1, _uv);
2458 if (_dst.total() >= MIN_SIZE_FOR_PARALLEL_YUV420_CONVERSION)
2459 parallel_for_(Range(0, _dst.rows/2), converter);
2461 converter(Range(0, _dst.rows/2));
2465 inline void cvtYUV420p2RGB(Mat& _dst, int _stride, const uchar* _y1, const uchar* _u, const uchar* _v, int ustepIdx, int vstepIdx)
2467 YUV420p2RGB888Invoker<bIdx> converter(&_dst, _stride, _y1, _u, _v, ustepIdx, vstepIdx);
2468 if (_dst.total() >= MIN_SIZE_FOR_PARALLEL_YUV420_CONVERSION)
2469 parallel_for_(Range(0, _dst.rows/2), converter);
2471 converter(Range(0, _dst.rows/2));
2475 inline void cvtYUV420p2RGBA(Mat& _dst, int _stride, const uchar* _y1, const uchar* _u, const uchar* _v, int ustepIdx, int vstepIdx)
2477 YUV420p2RGBA8888Invoker<bIdx> converter(&_dst, _stride, _y1, _u, _v, ustepIdx, vstepIdx);
2478 if (_dst.total() >= MIN_SIZE_FOR_PARALLEL_YUV420_CONVERSION)
2479 parallel_for_(Range(0, _dst.rows/2), converter);
2481 converter(Range(0, _dst.rows/2));
2484 ///////////////////////////////////// RGB -> YUV420p /////////////////////////////////////
2487 struct RGB888toYUV420pInvoker: public ParallelLoopBody
2489 RGB888toYUV420pInvoker( const Mat& src, Mat* dst, const int uIdx )
2494 void operator()(const Range& rowRange) const
2496 const int w = src_.cols;
2497 const int h = src_.rows;
2499 const int cn = src_.channels();
2500 for( int i = rowRange.start; i < rowRange.end; i++ )
2502 const uchar* row0 = src_.ptr<uchar>(2 * i);
2503 const uchar* row1 = src_.ptr<uchar>(2 * i + 1);
2505 uchar* y = dst_->ptr<uchar>(2*i);
2506 uchar* u = dst_->ptr<uchar>(h + i/2) + (i % 2) * (w/2);
2507 uchar* v = dst_->ptr<uchar>(h + (i + h/2)/2) + ((i + h/2) % 2) * (w/2);
2508 if( uIdx_ == 2 ) std::swap(u, v);
2510 for( int j = 0, k = 0; j < w * cn; j += 2 * cn, k++ )
2512 int r00 = row0[2-bIdx + j]; int g00 = row0[1 + j]; int b00 = row0[bIdx + j];
2513 int r01 = row0[2-bIdx + cn + j]; int g01 = row0[1 + cn + j]; int b01 = row0[bIdx + cn + j];
2514 int r10 = row1[2-bIdx + j]; int g10 = row1[1 + j]; int b10 = row1[bIdx + j];
2515 int r11 = row1[2-bIdx + cn + j]; int g11 = row1[1 + cn + j]; int b11 = row1[bIdx + cn + j];
2517 const int shifted16 = (16 << ITUR_BT_601_SHIFT);
2518 const int halfShift = (1 << (ITUR_BT_601_SHIFT - 1));
2519 int y00 = ITUR_BT_601_CRY * r00 + ITUR_BT_601_CGY * g00 + ITUR_BT_601_CBY * b00 + halfShift + shifted16;
2520 int y01 = ITUR_BT_601_CRY * r01 + ITUR_BT_601_CGY * g01 + ITUR_BT_601_CBY * b01 + halfShift + shifted16;
2521 int y10 = ITUR_BT_601_CRY * r10 + ITUR_BT_601_CGY * g10 + ITUR_BT_601_CBY * b10 + halfShift + shifted16;
2522 int y11 = ITUR_BT_601_CRY * r11 + ITUR_BT_601_CGY * g11 + ITUR_BT_601_CBY * b11 + halfShift + shifted16;
2524 y[2*k + 0] = saturate_cast<uchar>(y00 >> ITUR_BT_601_SHIFT);
2525 y[2*k + 1] = saturate_cast<uchar>(y01 >> ITUR_BT_601_SHIFT);
2526 y[2*k + dst_->step + 0] = saturate_cast<uchar>(y10 >> ITUR_BT_601_SHIFT);
2527 y[2*k + dst_->step + 1] = saturate_cast<uchar>(y11 >> ITUR_BT_601_SHIFT);
2529 const int shifted128 = (128 << ITUR_BT_601_SHIFT);
2530 int u00 = ITUR_BT_601_CRU * r00 + ITUR_BT_601_CGU * g00 + ITUR_BT_601_CBU * b00 + halfShift + shifted128;
2531 int v00 = ITUR_BT_601_CBU * r00 + ITUR_BT_601_CGV * g00 + ITUR_BT_601_CBV * b00 + halfShift + shifted128;
2533 u[k] = saturate_cast<uchar>(u00 >> ITUR_BT_601_SHIFT);
2534 v[k] = saturate_cast<uchar>(v00 >> ITUR_BT_601_SHIFT);
2539 static bool isFit( const Mat& src )
2541 return (src.total() >= 320*240);
2545 RGB888toYUV420pInvoker& operator=(const RGB888toYUV420pInvoker&);
2552 template<int bIdx, int uIdx>
2553 static void cvtRGBtoYUV420p(const Mat& src, Mat& dst)
2555 RGB888toYUV420pInvoker<bIdx> colorConverter(src, &dst, uIdx);
2556 if( RGB888toYUV420pInvoker<bIdx>::isFit(src) )
2557 parallel_for_(Range(0, src.rows/2), colorConverter);
2559 colorConverter(Range(0, src.rows/2));
2562 ///////////////////////////////////// YUV422 -> RGB /////////////////////////////////////
2564 template<int bIdx, int uIdx, int yIdx>
2565 struct YUV422toRGB888Invoker : ParallelLoopBody
2571 YUV422toRGB888Invoker(Mat* _dst, int _stride, const uchar* _yuv)
2572 : dst(_dst), src(_yuv), width(_dst->cols), stride(_stride) {}
2574 void operator()(const Range& range) const
2576 int rangeBegin = range.start;
2577 int rangeEnd = range.end;
2579 const int uidx = 1 - yIdx + uIdx * 2;
2580 const int vidx = (2 + uidx) % 4;
2581 const uchar* yuv_src = src + rangeBegin * stride;
2583 for (int j = rangeBegin; j < rangeEnd; j++, yuv_src += stride)
2585 uchar* row = dst->ptr<uchar>(j);
2587 for (int i = 0; i < 2 * width; i += 4, row += 6)
2589 int u = int(yuv_src[i + uidx]) - 128;
2590 int v = int(yuv_src[i + vidx]) - 128;
2592 int ruv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVR * v;
2593 int guv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVG * v + ITUR_BT_601_CUG * u;
2594 int buv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CUB * u;
2596 int y00 = std::max(0, int(yuv_src[i + yIdx]) - 16) * ITUR_BT_601_CY;
2597 row[2-bIdx] = saturate_cast<uchar>((y00 + ruv) >> ITUR_BT_601_SHIFT);
2598 row[1] = saturate_cast<uchar>((y00 + guv) >> ITUR_BT_601_SHIFT);
2599 row[bIdx] = saturate_cast<uchar>((y00 + buv) >> ITUR_BT_601_SHIFT);
2601 int y01 = std::max(0, int(yuv_src[i + yIdx + 2]) - 16) * ITUR_BT_601_CY;
2602 row[5-bIdx] = saturate_cast<uchar>((y01 + ruv) >> ITUR_BT_601_SHIFT);
2603 row[4] = saturate_cast<uchar>((y01 + guv) >> ITUR_BT_601_SHIFT);
2604 row[3+bIdx] = saturate_cast<uchar>((y01 + buv) >> ITUR_BT_601_SHIFT);
2610 template<int bIdx, int uIdx, int yIdx>
2611 struct YUV422toRGBA8888Invoker : ParallelLoopBody
2617 YUV422toRGBA8888Invoker(Mat* _dst, int _stride, const uchar* _yuv)
2618 : dst(_dst), src(_yuv), width(_dst->cols), stride(_stride) {}
2620 void operator()(const Range& range) const
2622 int rangeBegin = range.start;
2623 int rangeEnd = range.end;
2625 const int uidx = 1 - yIdx + uIdx * 2;
2626 const int vidx = (2 + uidx) % 4;
2627 const uchar* yuv_src = src + rangeBegin * stride;
2629 for (int j = rangeBegin; j < rangeEnd; j++, yuv_src += stride)
2631 uchar* row = dst->ptr<uchar>(j);
2633 for (int i = 0; i < 2 * width; i += 4, row += 8)
2635 int u = int(yuv_src[i + uidx]) - 128;
2636 int v = int(yuv_src[i + vidx]) - 128;
2638 int ruv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVR * v;
2639 int guv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVG * v + ITUR_BT_601_CUG * u;
2640 int buv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CUB * u;
2642 int y00 = std::max(0, int(yuv_src[i + yIdx]) - 16) * ITUR_BT_601_CY;
2643 row[2-bIdx] = saturate_cast<uchar>((y00 + ruv) >> ITUR_BT_601_SHIFT);
2644 row[1] = saturate_cast<uchar>((y00 + guv) >> ITUR_BT_601_SHIFT);
2645 row[bIdx] = saturate_cast<uchar>((y00 + buv) >> ITUR_BT_601_SHIFT);
2646 row[3] = uchar(0xff);
2648 int y01 = std::max(0, int(yuv_src[i + yIdx + 2]) - 16) * ITUR_BT_601_CY;
2649 row[6-bIdx] = saturate_cast<uchar>((y01 + ruv) >> ITUR_BT_601_SHIFT);
2650 row[5] = saturate_cast<uchar>((y01 + guv) >> ITUR_BT_601_SHIFT);
2651 row[4+bIdx] = saturate_cast<uchar>((y01 + buv) >> ITUR_BT_601_SHIFT);
2652 row[7] = uchar(0xff);
2658 #define MIN_SIZE_FOR_PARALLEL_YUV422_CONVERSION (320*240)
2660 template<int bIdx, int uIdx, int yIdx>
2661 inline void cvtYUV422toRGB(Mat& _dst, int _stride, const uchar* _yuv)
2663 YUV422toRGB888Invoker<bIdx, uIdx, yIdx> converter(&_dst, _stride, _yuv);
2664 if (_dst.total() >= MIN_SIZE_FOR_PARALLEL_YUV422_CONVERSION)
2665 parallel_for_(Range(0, _dst.rows), converter);
2667 converter(Range(0, _dst.rows));
2670 template<int bIdx, int uIdx, int yIdx>
2671 inline void cvtYUV422toRGBA(Mat& _dst, int _stride, const uchar* _yuv)
2673 YUV422toRGBA8888Invoker<bIdx, uIdx, yIdx> converter(&_dst, _stride, _yuv);
2674 if (_dst.total() >= MIN_SIZE_FOR_PARALLEL_YUV422_CONVERSION)
2675 parallel_for_(Range(0, _dst.rows), converter);
2677 converter(Range(0, _dst.rows));
2680 /////////////////////////// RGBA <-> mRGBA (alpha premultiplied) //////////////
2682 template<typename _Tp>
2685 typedef _Tp channel_type;
2687 void operator()(const _Tp* src, _Tp* dst, int n) const
2689 _Tp max_val = ColorChannel<_Tp>::max();
2690 _Tp half_val = ColorChannel<_Tp>::half();
2691 for( int i = 0; i < n; i++ )
2698 *dst++ = (v0 * v3 + half_val) / max_val;
2699 *dst++ = (v1 * v3 + half_val) / max_val;
2700 *dst++ = (v2 * v3 + half_val) / max_val;
2707 template<typename _Tp>
2710 typedef _Tp channel_type;
2712 void operator()(const _Tp* src, _Tp* dst, int n) const
2714 _Tp max_val = ColorChannel<_Tp>::max();
2715 for( int i = 0; i < n; i++ )
2721 _Tp v3_half = v3 / 2;
2723 *dst++ = (v3==0)? 0 : (v0 * max_val + v3_half) / v3;
2724 *dst++ = (v3==0)? 0 : (v1 * max_val + v3_half) / v3;
2725 *dst++ = (v3==0)? 0 : (v2 * max_val + v3_half) / v3;
2733 #define DIVUP(total, grain) (((total) + (grain) - 1) / (grain))
2735 static bool ocl_cvtColor( InputArray _src, OutputArray _dst, int code, int dcn )
2738 UMat src = _src.getUMat(), dst;
2739 Size sz = src.size(), dstSz = sz;
2740 int scn = src.channels(), depth = src.depth(), bidx;
2741 int dims = 2, stripeSize = 1;
2742 size_t globalsize[] = { src.cols, src.rows };
2745 if (depth != CV_8U && depth != CV_16U && depth != CV_32F)
2748 cv::String opts = format("-D depth=%d -D scn=%d ", depth, scn);
2750 ocl::Device dev = ocl::Device::getDefault();
2752 if (dev.isIntel() && (dev.type() & ocl::Device::TYPE_GPU) &&
2753 !(code == CV_BGR2Luv || code == CV_RGB2Luv || code == CV_LBGR2Luv || code == CV_LRGB2Luv ||
2754 code == CV_Luv2BGR || code == CV_Luv2RGB || code == CV_Luv2LBGR || code == CV_Luv2LRGB))
2757 globalsize[1] = DIVUP(globalsize[1], pxPerWIy);
2758 opts += format("-D PIX_PER_WI_Y=%d ", pxPerWIy);
2762 case COLOR_BGR2BGRA: case COLOR_RGB2BGRA: case COLOR_BGRA2BGR:
2763 case COLOR_RGBA2BGR: case COLOR_RGB2BGR: case COLOR_BGRA2RGBA:
2765 CV_Assert(scn == 3 || scn == 4);
2766 dcn = code == COLOR_BGR2BGRA || code == COLOR_RGB2BGRA || code == COLOR_BGRA2RGBA ? 4 : 3;
2767 bool reverse = !(code == COLOR_BGR2BGRA || code == COLOR_BGRA2BGR);
2768 k.create("RGB", ocl::imgproc::cvtcolor_oclsrc,
2769 opts + format("-D dcn=%d -D bidx=0 -D %s", dcn,
2770 reverse ? "REVERSE" : "ORDER"));
2773 case COLOR_BGR5652BGR: case COLOR_BGR5552BGR: case COLOR_BGR5652RGB: case COLOR_BGR5552RGB:
2774 case COLOR_BGR5652BGRA: case COLOR_BGR5552BGRA: case COLOR_BGR5652RGBA: case COLOR_BGR5552RGBA:
2776 dcn = code == COLOR_BGR5652BGRA || code == COLOR_BGR5552BGRA || code == COLOR_BGR5652RGBA || code == COLOR_BGR5552RGBA ? 4 : 3;
2777 CV_Assert((dcn == 3 || dcn == 4) && scn == 2 && depth == CV_8U);
2778 bidx = code == COLOR_BGR5652BGR || code == COLOR_BGR5552BGR ||
2779 code == COLOR_BGR5652BGRA || code == COLOR_BGR5552BGRA ? 0 : 2;
2780 int greenbits = code == COLOR_BGR5652BGR || code == COLOR_BGR5652RGB ||
2781 code == COLOR_BGR5652BGRA || code == COLOR_BGR5652RGBA ? 6 : 5;
2782 k.create("RGB5x52RGB", ocl::imgproc::cvtcolor_oclsrc,
2783 opts + format("-D dcn=%d -D bidx=%d -D greenbits=%d", dcn, bidx, greenbits));
2786 case COLOR_BGR2BGR565: case COLOR_BGR2BGR555: case COLOR_RGB2BGR565: case COLOR_RGB2BGR555:
2787 case COLOR_BGRA2BGR565: case COLOR_BGRA2BGR555: case COLOR_RGBA2BGR565: case COLOR_RGBA2BGR555:
2789 CV_Assert((scn == 3 || scn == 4) && depth == CV_8U );
2790 bidx = code == COLOR_BGR2BGR565 || code == COLOR_BGR2BGR555 ||
2791 code == COLOR_BGRA2BGR565 || code == COLOR_BGRA2BGR555 ? 0 : 2;
2792 int greenbits = code == COLOR_BGR2BGR565 || code == COLOR_RGB2BGR565 ||
2793 code == COLOR_BGRA2BGR565 || code == COLOR_RGBA2BGR565 ? 6 : 5;
2795 k.create("RGB2RGB5x5", ocl::imgproc::cvtcolor_oclsrc,
2796 opts + format("-D dcn=2 -D bidx=%d -D greenbits=%d", bidx, greenbits));
2799 case COLOR_BGR5652GRAY: case COLOR_BGR5552GRAY:
2801 CV_Assert(scn == 2 && depth == CV_8U);
2803 int greenbits = code == COLOR_BGR5652GRAY ? 6 : 5;
2804 k.create("BGR5x52Gray", ocl::imgproc::cvtcolor_oclsrc,
2805 opts + format("-D dcn=1 -D bidx=0 -D greenbits=%d", greenbits));
2808 case COLOR_GRAY2BGR565: case COLOR_GRAY2BGR555:
2810 CV_Assert(scn == 1 && depth == CV_8U);
2812 int greenbits = code == COLOR_GRAY2BGR565 ? 6 : 5;
2813 k.create("Gray2BGR5x5", ocl::imgproc::cvtcolor_oclsrc,
2814 opts + format("-D dcn=2 -D bidx=0 -D greenbits=%d", greenbits));
2817 case COLOR_BGR2GRAY: case COLOR_BGRA2GRAY:
2818 case COLOR_RGB2GRAY: case COLOR_RGBA2GRAY:
2820 CV_Assert(scn == 3 || scn == 4);
2821 bidx = code == COLOR_BGR2GRAY || code == COLOR_BGRA2GRAY ? 0 : 2;
2823 k.create("RGB2Gray", ocl::imgproc::cvtcolor_oclsrc,
2824 opts + format("-D dcn=1 -D bidx=%d -D STRIPE_SIZE=%d",
2826 globalsize[0] = (src.cols + stripeSize-1)/stripeSize;
2829 case COLOR_GRAY2BGR:
2830 case COLOR_GRAY2BGRA:
2832 CV_Assert(scn == 1);
2833 dcn = code == COLOR_GRAY2BGRA ? 4 : 3;
2834 k.create("Gray2RGB", ocl::imgproc::cvtcolor_oclsrc,
2835 opts + format("-D bidx=0 -D dcn=%d", dcn));
2841 CV_Assert(scn == 3 || scn == 4);
2842 bidx = code == COLOR_RGB2YUV ? 0 : 2;
2844 k.create("RGB2YUV", ocl::imgproc::cvtcolor_oclsrc,
2845 opts + format("-D dcn=3 -D bidx=%d", bidx));
2851 if(dcn < 0) dcn = 3;
2852 CV_Assert(dcn == 3 || dcn == 4);
2853 bidx = code == COLOR_YUV2RGB ? 0 : 2;
2854 k.create("YUV2RGB", ocl::imgproc::cvtcolor_oclsrc,
2855 opts + format("-D dcn=%d -D bidx=%d", dcn, bidx));
2858 case COLOR_YUV2RGB_NV12: case COLOR_YUV2BGR_NV12:
2859 case COLOR_YUV2RGBA_NV12: case COLOR_YUV2BGRA_NV12:
2861 CV_Assert( scn == 1 );
2862 CV_Assert( sz.width % 2 == 0 && sz.height % 3 == 0 && depth == CV_8U );
2863 dcn = code == COLOR_YUV2BGRA_NV12 || code == COLOR_YUV2RGBA_NV12 ? 4 : 3;
2864 bidx = code == COLOR_YUV2BGRA_NV12 || code == COLOR_YUV2BGR_NV12 ? 0 : 2;
2866 dstSz = Size(sz.width, sz.height * 2 / 3);
2867 k.create("YUV2RGB_NV12", ocl::imgproc::cvtcolor_oclsrc,
2868 opts + format("-D dcn=%d -D bidx=%d", dcn, bidx));
2871 case COLOR_BGR2YCrCb:
2872 case COLOR_RGB2YCrCb:
2874 CV_Assert(scn == 3 || scn == 4);
2875 bidx = code == COLOR_BGR2YCrCb ? 0 : 2;
2877 k.create("RGB2YCrCb", ocl::imgproc::cvtcolor_oclsrc,
2878 opts + format("-D dcn=3 -D bidx=%d", bidx));
2881 case COLOR_YCrCb2BGR:
2882 case COLOR_YCrCb2RGB:
2886 CV_Assert(scn == 3 && (dcn == 3 || dcn == 4));
2887 bidx = code == COLOR_YCrCb2BGR ? 0 : 2;
2888 k.create("YCrCb2RGB", ocl::imgproc::cvtcolor_oclsrc,
2889 opts + format("-D dcn=%d -D bidx=%d", dcn, bidx));
2892 case COLOR_BGR2XYZ: case COLOR_RGB2XYZ:
2894 CV_Assert(scn == 3 || scn == 4);
2895 bidx = code == COLOR_BGR2XYZ ? 0 : 2;
2898 if (depth == CV_32F)
2902 0.412453f, 0.357580f, 0.180423f,
2903 0.212671f, 0.715160f, 0.072169f,
2904 0.019334f, 0.119193f, 0.950227f
2908 std::swap(coeffs[0], coeffs[2]);
2909 std::swap(coeffs[3], coeffs[5]);
2910 std::swap(coeffs[6], coeffs[8]);
2912 Mat(1, 9, CV_32FC1, &coeffs[0]).copyTo(c);
2924 std::swap(coeffs[0], coeffs[2]);
2925 std::swap(coeffs[3], coeffs[5]);
2926 std::swap(coeffs[6], coeffs[8]);
2928 Mat(1, 9, CV_32SC1, &coeffs[0]).copyTo(c);
2931 _dst.create(dstSz, CV_MAKETYPE(depth, 3));
2932 dst = _dst.getUMat();
2934 k.create("RGB2XYZ", ocl::imgproc::cvtcolor_oclsrc,
2935 opts + format("-D dcn=3 -D bidx=%d", bidx));
2938 k.args(ocl::KernelArg::ReadOnlyNoSize(src), ocl::KernelArg::WriteOnly(dst), ocl::KernelArg::PtrReadOnly(c));
2939 return k.run(2, globalsize, 0, false);
2941 case COLOR_XYZ2BGR: case COLOR_XYZ2RGB:
2945 CV_Assert(scn == 3 && (dcn == 3 || dcn == 4));
2946 bidx = code == COLOR_XYZ2BGR ? 0 : 2;
2949 if (depth == CV_32F)
2953 3.240479f, -1.53715f, -0.498535f,
2954 -0.969256f, 1.875991f, 0.041556f,
2955 0.055648f, -0.204043f, 1.057311f
2959 std::swap(coeffs[0], coeffs[6]);
2960 std::swap(coeffs[1], coeffs[7]);
2961 std::swap(coeffs[2], coeffs[8]);
2963 Mat(1, 9, CV_32FC1, &coeffs[0]).copyTo(c);
2969 13273, -6296, -2042,
2975 std::swap(coeffs[0], coeffs[6]);
2976 std::swap(coeffs[1], coeffs[7]);
2977 std::swap(coeffs[2], coeffs[8]);
2979 Mat(1, 9, CV_32SC1, &coeffs[0]).copyTo(c);
2982 _dst.create(dstSz, CV_MAKETYPE(depth, dcn));
2983 dst = _dst.getUMat();
2985 k.create("XYZ2RGB", ocl::imgproc::cvtcolor_oclsrc,
2986 opts + format("-D dcn=%d -D bidx=%d", dcn, bidx));
2989 k.args(ocl::KernelArg::ReadOnlyNoSize(src), ocl::KernelArg::WriteOnly(dst), ocl::KernelArg::PtrReadOnly(c));
2990 return k.run(2, globalsize, 0, false);
2992 case COLOR_BGR2HSV: case COLOR_RGB2HSV: case COLOR_BGR2HSV_FULL: case COLOR_RGB2HSV_FULL:
2993 case COLOR_BGR2HLS: case COLOR_RGB2HLS: case COLOR_BGR2HLS_FULL: case COLOR_RGB2HLS_FULL:
2995 CV_Assert((scn == 3 || scn == 4) && (depth == CV_8U || depth == CV_32F));
2996 bidx = code == COLOR_BGR2HSV || code == COLOR_BGR2HLS ||
2997 code == COLOR_BGR2HSV_FULL || code == COLOR_BGR2HLS_FULL ? 0 : 2;
2998 int hrange = depth == CV_32F ? 360 : code == COLOR_BGR2HSV || code == COLOR_RGB2HSV ||
2999 code == COLOR_BGR2HLS || code == COLOR_RGB2HLS ? 180 : 256;
3000 bool is_hsv = code == COLOR_BGR2HSV || code == COLOR_RGB2HSV || code == COLOR_BGR2HSV_FULL || code == COLOR_RGB2HSV_FULL;
3001 String kernelName = String("RGB2") + (is_hsv ? "HSV" : "HLS");
3004 if (is_hsv && depth == CV_8U)
3006 static UMat sdiv_data;
3007 static UMat hdiv_data180;
3008 static UMat hdiv_data256;
3009 static int sdiv_table[256];
3010 static int hdiv_table180[256];
3011 static int hdiv_table256[256];
3012 static volatile bool initialized180 = false, initialized256 = false;
3013 volatile bool & initialized = hrange == 180 ? initialized180 : initialized256;
3017 int * const hdiv_table = hrange == 180 ? hdiv_table180 : hdiv_table256, hsv_shift = 12;
3018 UMat & hdiv_data = hrange == 180 ? hdiv_data180 : hdiv_data256;
3020 sdiv_table[0] = hdiv_table180[0] = hdiv_table256[0] = 0;
3022 int v = 255 << hsv_shift;
3023 if (!initialized180 && !initialized256)
3025 for(int i = 1; i < 256; i++ )
3026 sdiv_table[i] = saturate_cast<int>(v/(1.*i));
3027 Mat(1, 256, CV_32SC1, sdiv_table).copyTo(sdiv_data);
3030 v = hrange << hsv_shift;
3031 for (int i = 1; i < 256; i++ )
3032 hdiv_table[i] = saturate_cast<int>(v/(6.*i));
3034 Mat(1, 256, CV_32SC1, hdiv_table).copyTo(hdiv_data);
3038 _dst.create(dstSz, CV_8UC3);
3039 dst = _dst.getUMat();
3041 k.create("RGB2HSV", ocl::imgproc::cvtcolor_oclsrc,
3042 opts + format("-D hrange=%d -D bidx=%d -D dcn=3",
3047 k.args(ocl::KernelArg::ReadOnlyNoSize(src), ocl::KernelArg::WriteOnly(dst),
3048 ocl::KernelArg::PtrReadOnly(sdiv_data), hrange == 256 ? ocl::KernelArg::PtrReadOnly(hdiv_data256) :
3049 ocl::KernelArg::PtrReadOnly(hdiv_data180));
3051 return k.run(2, globalsize, NULL, false);
3054 k.create(kernelName.c_str(), ocl::imgproc::cvtcolor_oclsrc,
3055 opts + format("-D hscale=%ff -D bidx=%d -D dcn=3",
3056 hrange*(1.f/360.f), bidx));
3059 case COLOR_HSV2BGR: case COLOR_HSV2RGB: case COLOR_HSV2BGR_FULL: case COLOR_HSV2RGB_FULL:
3060 case COLOR_HLS2BGR: case COLOR_HLS2RGB: case COLOR_HLS2BGR_FULL: case COLOR_HLS2RGB_FULL:
3064 CV_Assert(scn == 3 && (dcn == 3 || dcn == 4) && (depth == CV_8U || depth == CV_32F));
3065 bidx = code == COLOR_HSV2BGR || code == COLOR_HLS2BGR ||
3066 code == COLOR_HSV2BGR_FULL || code == COLOR_HLS2BGR_FULL ? 0 : 2;
3067 int hrange = depth == CV_32F ? 360 : code == COLOR_HSV2BGR || code == COLOR_HSV2RGB ||
3068 code == COLOR_HLS2BGR || code == COLOR_HLS2RGB ? 180 : 255;
3069 bool is_hsv = code == COLOR_HSV2BGR || code == COLOR_HSV2RGB ||
3070 code == COLOR_HSV2BGR_FULL || code == COLOR_HSV2RGB_FULL;
3072 String kernelName = String(is_hsv ? "HSV" : "HLS") + "2RGB";
3073 k.create(kernelName.c_str(), ocl::imgproc::cvtcolor_oclsrc,
3074 opts + format("-D dcn=%d -D bidx=%d -D hrange=%d -D hscale=%ff",
3075 dcn, bidx, hrange, 6.f/hrange));
3078 case COLOR_RGBA2mRGBA: case COLOR_mRGBA2RGBA:
3080 CV_Assert(scn == 4 && depth == CV_8U);
3083 k.create(code == COLOR_RGBA2mRGBA ? "RGBA2mRGBA" : "mRGBA2RGBA", ocl::imgproc::cvtcolor_oclsrc,
3084 opts + "-D dcn=4 -D bidx=3");
3087 case CV_BGR2Lab: case CV_RGB2Lab: case CV_LBGR2Lab: case CV_LRGB2Lab:
3088 case CV_BGR2Luv: case CV_RGB2Luv: case CV_LBGR2Luv: case CV_LRGB2Luv:
3090 CV_Assert( (scn == 3 || scn == 4) && (depth == CV_8U || depth == CV_32F) );
3092 bidx = code == CV_BGR2Lab || code == CV_LBGR2Lab || code == CV_BGR2Luv || code == CV_LBGR2Luv ? 0 : 2;
3093 bool srgb = code == CV_BGR2Lab || code == CV_RGB2Lab || code == CV_RGB2Luv || code == CV_BGR2Luv;
3094 bool lab = code == CV_BGR2Lab || code == CV_RGB2Lab || code == CV_LBGR2Lab || code == CV_LRGB2Lab;
3098 k.create(format("BGR2%s", lab ? "Lab" : "Luv").c_str(),
3099 ocl::imgproc::cvtcolor_oclsrc,
3100 opts + format("-D dcn=%d -D bidx=%d%s",
3101 dcn, bidx, srgb ? " -D SRGB" : ""));
3107 _dst.create(dstSz, CV_MAKETYPE(depth, dcn));
3108 dst = _dst.getUMat();
3110 ocl::KernelArg srcarg = ocl::KernelArg::ReadOnlyNoSize(src),
3111 dstarg = ocl::KernelArg::WriteOnly(dst);
3113 if (depth == CV_8U && lab)
3115 static UMat usRGBGammaTab, ulinearGammaTab, uLabCbrtTab, ucoeffs;
3117 if (srgb && usRGBGammaTab.empty())
3118 Mat(1, 256, CV_16UC1, sRGBGammaTab_b).copyTo(usRGBGammaTab);
3119 else if (ulinearGammaTab.empty())
3120 Mat(1, 256, CV_16UC1, linearGammaTab_b).copyTo(ulinearGammaTab);
3121 if (uLabCbrtTab.empty())
3122 Mat(1, LAB_CBRT_TAB_SIZE_B, CV_16UC1, LabCbrtTab_b).copyTo(uLabCbrtTab);
3126 const float * const _coeffs = sRGB2XYZ_D65, * const _whitept = D65;
3127 const float scale[] =
3129 (1 << lab_shift)/_whitept[0],
3130 (float)(1 << lab_shift),
3131 (1 << lab_shift)/_whitept[2]
3134 for (int i = 0; i < 3; i++ )
3136 coeffs[i*3+(bidx^2)] = cvRound(_coeffs[i*3]*scale[i]);
3137 coeffs[i*3+1] = cvRound(_coeffs[i*3+1]*scale[i]);
3138 coeffs[i*3+bidx] = cvRound(_coeffs[i*3+2]*scale[i]);
3140 CV_Assert( coeffs[i] >= 0 && coeffs[i*3+1] >= 0 && coeffs[i*3+2] >= 0 &&
3141 coeffs[i*3] + coeffs[i*3+1] + coeffs[i*3+2] < 2*(1 << lab_shift) );
3143 Mat(1, 9, CV_32SC1, coeffs).copyTo(ucoeffs);
3146 const int Lscale = (116*255+50)/100;
3147 const int Lshift = -((16*255*(1 << lab_shift2) + 50)/100);
3149 k.args(srcarg, dstarg,
3150 ocl::KernelArg::PtrReadOnly(srgb ? usRGBGammaTab : ulinearGammaTab),
3151 ocl::KernelArg::PtrReadOnly(uLabCbrtTab), ocl::KernelArg::PtrReadOnly(ucoeffs),
3156 static UMat usRGBGammaTab, ucoeffs, uLabCbrtTab;
3158 if (srgb && usRGBGammaTab.empty())
3159 Mat(1, GAMMA_TAB_SIZE * 4, CV_32FC1, sRGBGammaTab).copyTo(usRGBGammaTab);
3160 if (!lab && uLabCbrtTab.empty())
3161 Mat(1, LAB_CBRT_TAB_SIZE * 4, CV_32FC1, LabCbrtTab).copyTo(uLabCbrtTab);
3165 const float * const _coeffs = sRGB2XYZ_D65, * const _whitept = D65;
3166 float scale[] = { 1.0f / _whitept[0], 1.0f, 1.0f / _whitept[2] };
3168 for (int i = 0; i < 3; i++)
3171 coeffs[j + (bidx ^ 2)] = _coeffs[j] * (lab ? scale[i] : 1);
3172 coeffs[j + 1] = _coeffs[j + 1] * (lab ? scale[i] : 1);
3173 coeffs[j + bidx] = _coeffs[j + 2] * (lab ? scale[i] : 1);
3175 CV_Assert( coeffs[j] >= 0 && coeffs[j + 1] >= 0 && coeffs[j + 2] >= 0 &&
3176 coeffs[j] + coeffs[j + 1] + coeffs[j + 2] < 1.5f*(lab ? LabCbrtTabScale : 1) );
3179 float d = 1.f/(_whitept[0] + _whitept[1]*15 + _whitept[2]*3);
3180 un = 13*4*_whitept[0]*d;
3181 vn = 13*9*_whitept[1]*d;
3183 Mat(1, 9, CV_32FC1, coeffs).copyTo(ucoeffs);
3186 float _1_3 = 1.0f / 3.0f, _a = 16.0f / 116.0f;
3187 ocl::KernelArg ucoeffsarg = ocl::KernelArg::PtrReadOnly(ucoeffs);
3192 k.args(srcarg, dstarg, ocl::KernelArg::PtrReadOnly(usRGBGammaTab),
3193 ucoeffsarg, _1_3, _a);
3195 k.args(srcarg, dstarg, ucoeffsarg, _1_3, _a);
3199 ocl::KernelArg LabCbrtTabarg = ocl::KernelArg::PtrReadOnly(uLabCbrtTab);
3201 k.args(srcarg, dstarg, ocl::KernelArg::PtrReadOnly(usRGBGammaTab),
3202 LabCbrtTabarg, ucoeffsarg, un, vn);
3204 k.args(srcarg, dstarg, LabCbrtTabarg, ucoeffsarg, un, vn);
3208 return k.run(dims, globalsize, NULL, false);
3210 case CV_Lab2BGR: case CV_Lab2RGB: case CV_Lab2LBGR: case CV_Lab2LRGB:
3211 case CV_Luv2BGR: case CV_Luv2RGB: case CV_Luv2LBGR: case CV_Luv2LRGB:
3215 CV_Assert( scn == 3 && (dcn == 3 || dcn == 4) && (depth == CV_8U || depth == CV_32F) );
3217 bidx = code == CV_Lab2BGR || code == CV_Lab2LBGR || code == CV_Luv2BGR || code == CV_Luv2LBGR ? 0 : 2;
3218 bool srgb = code == CV_Lab2BGR || code == CV_Lab2RGB || code == CV_Luv2BGR || code == CV_Luv2RGB;
3219 bool lab = code == CV_Lab2BGR || code == CV_Lab2RGB || code == CV_Lab2LBGR || code == CV_Lab2LRGB;
3222 k.create(format("%s2BGR", lab ? "Lab" : "Luv").c_str(),
3223 ocl::imgproc::cvtcolor_oclsrc,
3224 opts + format("-D dcn=%d -D bidx=%d%s",
3225 dcn, bidx, srgb ? " -D SRGB" : ""));
3230 static UMat ucoeffs, usRGBInvGammaTab;
3232 if (srgb && usRGBInvGammaTab.empty())
3233 Mat(1, GAMMA_TAB_SIZE*4, CV_32FC1, sRGBInvGammaTab).copyTo(usRGBInvGammaTab);
3237 const float * const _coeffs = XYZ2sRGB_D65, * const _whitept = D65;
3239 for( int i = 0; i < 3; i++ )
3241 coeffs[i+(bidx^2)*3] = _coeffs[i] * (lab ? _whitept[i] : 1);
3242 coeffs[i+3] = _coeffs[i+3] * (lab ? _whitept[i] : 1);
3243 coeffs[i+bidx*3] = _coeffs[i+6] * (lab ? _whitept[i] : 1);
3246 float d = 1.f/(_whitept[0] + _whitept[1]*15 + _whitept[2]*3);
3247 un = 4*_whitept[0]*d;
3248 vn = 9*_whitept[1]*d;
3250 Mat(1, 9, CV_32FC1, coeffs).copyTo(ucoeffs);
3253 _dst.create(sz, CV_MAKETYPE(depth, dcn));
3254 dst = _dst.getUMat();
3256 float lThresh = 0.008856f * 903.3f;
3257 float fThresh = 7.787f * 0.008856f + 16.0f / 116.0f;
3259 ocl::KernelArg srcarg = ocl::KernelArg::ReadOnlyNoSize(src),
3260 dstarg = ocl::KernelArg::WriteOnly(dst),
3261 coeffsarg = ocl::KernelArg::PtrReadOnly(ucoeffs);
3266 k.args(srcarg, dstarg, ocl::KernelArg::PtrReadOnly(usRGBInvGammaTab),
3267 coeffsarg, lThresh, fThresh);
3269 k.args(srcarg, dstarg, coeffsarg, lThresh, fThresh);
3274 k.args(srcarg, dstarg, ocl::KernelArg::PtrReadOnly(usRGBInvGammaTab),
3277 k.args(srcarg, dstarg, coeffsarg, un, vn);
3280 return k.run(dims, globalsize, NULL, false);
3288 _dst.create(dstSz, CV_MAKETYPE(depth, dcn));
3289 dst = _dst.getUMat();
3290 k.args(ocl::KernelArg::ReadOnlyNoSize(src), ocl::KernelArg::WriteOnly(dst));
3291 ok = k.run(dims, globalsize, NULL, false);
3300 //////////////////////////////////////////////////////////////////////////////////////////
3301 // The main function //
3302 //////////////////////////////////////////////////////////////////////////////////////////
3304 void cv::cvtColor( InputArray _src, OutputArray _dst, int code, int dcn )
3306 int stype = _src.type();
3307 int scn = CV_MAT_CN(stype), depth = CV_MAT_DEPTH(stype), bidx;
3309 CV_OCL_RUN( _src.dims() <= 2 && _dst.isUMat() && !(depth == CV_8U && (code == CV_Luv2BGR || code == CV_Luv2RGB)),
3310 ocl_cvtColor(_src, _dst, code, dcn) )
3312 Mat src = _src.getMat(), dst;
3313 Size sz = src.size();
3315 CV_Assert( depth == CV_8U || depth == CV_16U || depth == CV_32F );
3319 case CV_BGR2BGRA: case CV_RGB2BGRA: case CV_BGRA2BGR:
3320 case CV_RGBA2BGR: case CV_RGB2BGR: case CV_BGRA2RGBA:
3321 CV_Assert( scn == 3 || scn == 4 );
3322 dcn = code == CV_BGR2BGRA || code == CV_RGB2BGRA || code == CV_BGRA2RGBA ? 4 : 3;
3323 bidx = code == CV_BGR2BGRA || code == CV_BGRA2BGR ? 0 : 2;
3325 _dst.create( sz, CV_MAKETYPE(depth, dcn));
3326 dst = _dst.getMat();
3328 #if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
3329 if( code == CV_BGR2BGRA)
3331 if ( CvtColorIPPLoop(src, dst, IPPReorderFunctor(ippiSwapChannelsC3C4RTab[depth], 0, 1, 2)) )
3333 setIppErrorStatus();
3335 else if( code == CV_BGRA2BGR )
3337 if ( CvtColorIPPLoop(src, dst, IPPGeneralFunctor(ippiCopyAC4C3RTab[depth])) )
3339 setIppErrorStatus();
3341 else if( code == CV_BGR2RGBA )
3343 if( CvtColorIPPLoop(src, dst, IPPReorderFunctor(ippiSwapChannelsC3C4RTab[depth], 2, 1, 0)) )
3345 setIppErrorStatus();
3347 else if( code == CV_RGBA2BGR )
3349 if( CvtColorIPPLoop(src, dst, IPPReorderFunctor(ippiSwapChannelsC4C3RTab[depth], 2, 1, 0)) )
3351 setIppErrorStatus();
3353 else if( code == CV_RGB2BGR )
3355 if( CvtColorIPPLoopCopy(src, dst, IPPReorderFunctor(ippiSwapChannelsC3RTab[depth], 2, 1, 0)) )
3357 setIppErrorStatus();
3359 #if IPP_VERSION_X100 >= 801
3360 else if( code == CV_RGBA2BGRA )
3362 if( CvtColorIPPLoopCopy(src, dst, IPPReorderFunctor(ippiSwapChannelsC4RTab[depth], 2, 1, 0)) )
3364 setIppErrorStatus();
3369 if( depth == CV_8U )
3371 #ifdef HAVE_TEGRA_OPTIMIZATION
3372 if(!tegra::cvtBGR2RGB(src, dst, bidx))
3374 CvtColorLoop(src, dst, RGB2RGB<uchar>(scn, dcn, bidx));
3376 else if( depth == CV_16U )
3377 CvtColorLoop(src, dst, RGB2RGB<ushort>(scn, dcn, bidx));
3379 CvtColorLoop(src, dst, RGB2RGB<float>(scn, dcn, bidx));
3382 case CV_BGR2BGR565: case CV_BGR2BGR555: case CV_RGB2BGR565: case CV_RGB2BGR555:
3383 case CV_BGRA2BGR565: case CV_BGRA2BGR555: case CV_RGBA2BGR565: case CV_RGBA2BGR555:
3384 CV_Assert( (scn == 3 || scn == 4) && depth == CV_8U );
3385 _dst.create(sz, CV_8UC2);
3386 dst = _dst.getMat();
3389 CV_SUPPRESS_DEPRECATED_START
3391 if (code == CV_BGR2BGR565 && scn == 3)
3393 if (CvtColorIPPLoop(src, dst, IPPGeneralFunctor((ippiGeneralFunc)ippiBGRToBGR565_8u16u_C3R)))
3395 setIppErrorStatus();
3399 if (code == CV_BGRA2BGR565 && scn == 4)
3401 if (CvtColorIPPLoopCopy(src, dst,
3402 IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth],
3403 (ippiGeneralFunc)ippiBGRToBGR565_8u16u_C3R, 0, 1, 2, depth)))
3405 setIppErrorStatus();
3407 else if (code == CV_RGB2BGR565 && scn == 3)
3409 if( CvtColorIPPLoopCopy(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC3RTab[depth],
3410 (ippiGeneralFunc)ippiBGRToBGR565_8u16u_C3R, 2, 1, 0, depth)) )
3412 setIppErrorStatus();
3414 else if (code == CV_RGBA2BGR565 && scn == 4)
3416 if( CvtColorIPPLoopCopy(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth],
3417 (ippiGeneralFunc)ippiBGRToBGR565_8u16u_C3R, 2, 1, 0, depth)) )
3419 setIppErrorStatus();
3421 CV_SUPPRESS_DEPRECATED_END
3424 #ifdef HAVE_TEGRA_OPTIMIZATION
3425 if(code == CV_BGR2BGR565 || code == CV_BGRA2BGR565 || code == CV_RGB2BGR565 || code == CV_RGBA2BGR565)
3426 if(tegra::cvtRGB2RGB565(src, dst, code == CV_RGB2BGR565 || code == CV_RGBA2BGR565 ? 0 : 2))
3430 CvtColorLoop(src, dst, RGB2RGB5x5(scn,
3431 code == CV_BGR2BGR565 || code == CV_BGR2BGR555 ||
3432 code == CV_BGRA2BGR565 || code == CV_BGRA2BGR555 ? 0 : 2,
3433 code == CV_BGR2BGR565 || code == CV_RGB2BGR565 ||
3434 code == CV_BGRA2BGR565 || code == CV_RGBA2BGR565 ? 6 : 5 // green bits
3438 case CV_BGR5652BGR: case CV_BGR5552BGR: case CV_BGR5652RGB: case CV_BGR5552RGB:
3439 case CV_BGR5652BGRA: case CV_BGR5552BGRA: case CV_BGR5652RGBA: case CV_BGR5552RGBA:
3440 if(dcn <= 0) dcn = (code==CV_BGR5652BGRA || code==CV_BGR5552BGRA || code==CV_BGR5652RGBA || code==CV_BGR5552RGBA) ? 4 : 3;
3441 CV_Assert( (dcn == 3 || dcn == 4) && scn == 2 && depth == CV_8U );
3442 _dst.create(sz, CV_MAKETYPE(depth, dcn));
3443 dst = _dst.getMat();
3446 CV_SUPPRESS_DEPRECATED_START
3447 if (code == CV_BGR5652BGR && dcn == 3)
3449 if (CvtColorIPPLoop(src, dst, IPPGeneralFunctor((ippiGeneralFunc)ippiBGR565ToBGR_16u8u_C3R)))
3451 setIppErrorStatus();
3453 else if (code == CV_BGR5652RGB && dcn == 3)
3455 if (CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor((ippiGeneralFunc)ippiBGR565ToBGR_16u8u_C3R,
3456 ippiSwapChannelsC3RTab[depth], 2, 1, 0, depth)))
3458 setIppErrorStatus();
3460 else if (code == CV_BGR5652BGRA && dcn == 4)
3462 if (CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor((ippiGeneralFunc)ippiBGR565ToBGR_16u8u_C3R,
3463 ippiSwapChannelsC3C4RTab[depth], 0, 1, 2, depth)))
3465 setIppErrorStatus();
3467 else if (code == CV_BGR5652RGBA && dcn == 4)
3469 if (CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor((ippiGeneralFunc)ippiBGR565ToBGR_16u8u_C3R,
3470 ippiSwapChannelsC3C4RTab[depth], 2, 1, 0, depth)))
3472 setIppErrorStatus();
3474 CV_SUPPRESS_DEPRECATED_END
3477 CvtColorLoop(src, dst, RGB5x52RGB(dcn,
3478 code == CV_BGR5652BGR || code == CV_BGR5552BGR ||
3479 code == CV_BGR5652BGRA || code == CV_BGR5552BGRA ? 0 : 2, // blue idx
3480 code == CV_BGR5652BGR || code == CV_BGR5652RGB ||
3481 code == CV_BGR5652BGRA || code == CV_BGR5652RGBA ? 6 : 5 // green bits
3485 case CV_BGR2GRAY: case CV_BGRA2GRAY: case CV_RGB2GRAY: case CV_RGBA2GRAY:
3486 CV_Assert( scn == 3 || scn == 4 );
3487 _dst.create(sz, CV_MAKETYPE(depth, 1));
3488 dst = _dst.getMat();
3490 #if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
3491 if( code == CV_BGR2GRAY && depth == CV_32F )
3493 if( CvtColorIPPLoop(src, dst, IPPColor2GrayFunctor(ippiColor2GrayC3Tab[depth])) )
3495 setIppErrorStatus();
3497 else if( code == CV_RGB2GRAY && depth == CV_32F )
3499 if( CvtColorIPPLoop(src, dst, IPPGeneralFunctor(ippiRGB2GrayC3Tab[depth])) )
3501 setIppErrorStatus();
3503 else if( code == CV_BGRA2GRAY && depth == CV_32F )
3505 if( CvtColorIPPLoop(src, dst, IPPColor2GrayFunctor(ippiColor2GrayC4Tab[depth])) )
3507 setIppErrorStatus();
3509 else if( code == CV_RGBA2GRAY && depth == CV_32F )
3511 if( CvtColorIPPLoop(src, dst, IPPGeneralFunctor(ippiRGB2GrayC4Tab[depth])) )
3513 setIppErrorStatus();
3517 bidx = code == CV_BGR2GRAY || code == CV_BGRA2GRAY ? 0 : 2;
3519 if( depth == CV_8U )
3521 #ifdef HAVE_TEGRA_OPTIMIZATION
3522 if(!tegra::cvtRGB2Gray(src, dst, bidx))
3524 CvtColorLoop(src, dst, RGB2Gray<uchar>(scn, bidx, 0));
3526 else if( depth == CV_16U )
3527 CvtColorLoop(src, dst, RGB2Gray<ushort>(scn, bidx, 0));
3529 CvtColorLoop(src, dst, RGB2Gray<float>(scn, bidx, 0));
3532 case CV_BGR5652GRAY: case CV_BGR5552GRAY:
3533 CV_Assert( scn == 2 && depth == CV_8U );
3534 _dst.create(sz, CV_8UC1);
3535 dst = _dst.getMat();
3537 CvtColorLoop(src, dst, RGB5x52Gray(code == CV_BGR5652GRAY ? 6 : 5));
3540 case CV_GRAY2BGR: case CV_GRAY2BGRA:
3541 if( dcn <= 0 ) dcn = (code==CV_GRAY2BGRA) ? 4 : 3;
3542 CV_Assert( scn == 1 && (dcn == 3 || dcn == 4));
3543 _dst.create(sz, CV_MAKETYPE(depth, dcn));
3544 dst = _dst.getMat();
3546 #if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
3547 if( code == CV_GRAY2BGR )
3549 if( CvtColorIPPLoop(src, dst, IPPGray2BGRFunctor(ippiCopyP3C3RTab[depth])) )
3551 setIppErrorStatus();
3553 else if( code == CV_GRAY2BGRA )
3555 if( CvtColorIPPLoop(src, dst, IPPGray2BGRAFunctor(ippiCopyP3C3RTab[depth], ippiSwapChannelsC3C4RTab[depth], depth)) )
3557 setIppErrorStatus();
3562 if( depth == CV_8U )
3564 #ifdef HAVE_TEGRA_OPTIMIZATION
3565 if(!tegra::cvtGray2RGB(src, dst))
3567 CvtColorLoop(src, dst, Gray2RGB<uchar>(dcn));
3569 else if( depth == CV_16U )
3570 CvtColorLoop(src, dst, Gray2RGB<ushort>(dcn));
3572 CvtColorLoop(src, dst, Gray2RGB<float>(dcn));
3575 case CV_GRAY2BGR565: case CV_GRAY2BGR555:
3576 CV_Assert( scn == 1 && depth == CV_8U );
3577 _dst.create(sz, CV_8UC2);
3578 dst = _dst.getMat();
3580 CvtColorLoop(src, dst, Gray2RGB5x5(code == CV_GRAY2BGR565 ? 6 : 5));
3583 case CV_BGR2YCrCb: case CV_RGB2YCrCb:
3584 case CV_BGR2YUV: case CV_RGB2YUV:
3586 CV_Assert( scn == 3 || scn == 4 );
3587 bidx = code == CV_BGR2YCrCb || code == CV_BGR2YUV ? 0 : 2;
3588 static const float yuv_f[] = { 0.114f, 0.587f, 0.299f, 0.492f, 0.877f };
3589 static const int yuv_i[] = { B2Y, G2Y, R2Y, 8061, 14369 };
3590 const float* coeffs_f = code == CV_BGR2YCrCb || code == CV_RGB2YCrCb ? 0 : yuv_f;
3591 const int* coeffs_i = code == CV_BGR2YCrCb || code == CV_RGB2YCrCb ? 0 : yuv_i;
3593 _dst.create(sz, CV_MAKETYPE(depth, 3));
3594 dst = _dst.getMat();
3596 #if defined HAVE_IPP && 0
3597 if (code == CV_RGB2YUV && scn == 3 && depth == CV_8U)
3599 if (CvtColorIPPLoop(src, dst, IPPGeneralFunctor((ippiGeneralFunc)ippiRGBToYUV_8u_C3R)))
3601 setIppErrorStatus();
3603 else if (code == CV_BGR2YUV && scn == 3 && depth == CV_8U)
3605 if (CvtColorIPPLoop(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC3RTab[depth],
3606 (ippiGeneralFunc)ippiRGBToYUV_8u_C3R, 2, 1, 0, depth)))
3608 setIppErrorStatus();
3610 else if (code == CV_RGB2YUV && scn == 4 && depth == CV_8U)
3612 if (CvtColorIPPLoop(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth],
3613 (ippiGeneralFunc)ippiRGBToYUV_8u_C3R, 0, 1, 2, depth)))
3615 setIppErrorStatus();
3617 else if (code == CV_BGR2YUV && scn == 4 && depth == CV_8U)
3619 if (CvtColorIPPLoop(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth],
3620 (ippiGeneralFunc)ippiRGBToYUV_8u_C3R, 2, 1, 0, depth)))
3622 setIppErrorStatus();
3626 if( depth == CV_8U )
3628 #ifdef HAVE_TEGRA_OPTIMIZATION
3629 if((code == CV_RGB2YCrCb || code == CV_BGR2YCrCb) && tegra::cvtRGB2YCrCb(src, dst, bidx))
3632 CvtColorLoop(src, dst, RGB2YCrCb_i<uchar>(scn, bidx, coeffs_i));
3634 else if( depth == CV_16U )
3635 CvtColorLoop(src, dst, RGB2YCrCb_i<ushort>(scn, bidx, coeffs_i));
3637 CvtColorLoop(src, dst, RGB2YCrCb_f<float>(scn, bidx, coeffs_f));
3641 case CV_YCrCb2BGR: case CV_YCrCb2RGB:
3642 case CV_YUV2BGR: case CV_YUV2RGB:
3644 if( dcn <= 0 ) dcn = 3;
3645 CV_Assert( scn == 3 && (dcn == 3 || dcn == 4) );
3646 bidx = code == CV_YCrCb2BGR || code == CV_YUV2BGR ? 0 : 2;
3647 static const float yuv_f[] = { 2.032f, -0.395f, -0.581f, 1.140f };
3648 static const int yuv_i[] = { 33292, -6472, -9519, 18678 };
3649 const float* coeffs_f = code == CV_YCrCb2BGR || code == CV_YCrCb2RGB ? 0 : yuv_f;
3650 const int* coeffs_i = code == CV_YCrCb2BGR || code == CV_YCrCb2RGB ? 0 : yuv_i;
3652 _dst.create(sz, CV_MAKETYPE(depth, dcn));
3653 dst = _dst.getMat();
3655 #if defined HAVE_IPP && 0
3656 if (code == CV_YUV2RGB && dcn == 3 && depth == CV_8U)
3658 if (CvtColorIPPLoop(src, dst, IPPGeneralFunctor((ippiGeneralFunc)ippiYUVToRGB_8u_C3R)))
3660 setIppErrorStatus();
3662 else if (code == CV_YUV2BGR && dcn == 3 && depth == CV_8U)
3664 if (CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor((ippiGeneralFunc)ippiYUVToRGB_8u_C3R,
3665 ippiSwapChannelsC3RTab[depth], 2, 1, 0, depth)))
3667 setIppErrorStatus();
3669 else if (code == CV_YUV2RGB && dcn == 4 && depth == CV_8U)
3671 if (CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor((ippiGeneralFunc)ippiYUVToRGB_8u_C3R,
3672 ippiSwapChannelsC3C4RTab[depth], 0, 1, 2, depth)))
3674 setIppErrorStatus();
3676 else if (code == CV_YUV2BGR && dcn == 4 && depth == CV_8U)
3678 if (CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor((ippiGeneralFunc)ippiYUVToRGB_8u_C3R,
3679 ippiSwapChannelsC3C4RTab[depth], 2, 1, 0, depth)))
3681 setIppErrorStatus();
3685 if( depth == CV_8U )
3686 CvtColorLoop(src, dst, YCrCb2RGB_i<uchar>(dcn, bidx, coeffs_i));
3687 else if( depth == CV_16U )
3688 CvtColorLoop(src, dst, YCrCb2RGB_i<ushort>(dcn, bidx, coeffs_i));
3690 CvtColorLoop(src, dst, YCrCb2RGB_f<float>(dcn, bidx, coeffs_f));
3694 case CV_BGR2XYZ: case CV_RGB2XYZ:
3695 CV_Assert( scn == 3 || scn == 4 );
3696 bidx = code == CV_BGR2XYZ ? 0 : 2;
3698 _dst.create(sz, CV_MAKETYPE(depth, 3));
3699 dst = _dst.getMat();
3701 #if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
3702 if( code == CV_BGR2XYZ && scn == 3 && depth != CV_32F )
3704 if( CvtColorIPPLoopCopy(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC3RTab[depth], ippiRGB2XYZTab[depth], 2, 1, 0, depth)) )
3706 setIppErrorStatus();
3708 else if( code == CV_BGR2XYZ && scn == 4 && depth != CV_32F )
3710 if( CvtColorIPPLoop(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], ippiRGB2XYZTab[depth], 2, 1, 0, depth)) )
3712 setIppErrorStatus();
3714 else if( code == CV_RGB2XYZ && scn == 3 && depth != CV_32F )
3716 if( CvtColorIPPLoopCopy(src, dst, IPPGeneralFunctor(ippiRGB2XYZTab[depth])) )
3718 setIppErrorStatus();
3720 else if( code == CV_RGB2XYZ && scn == 4 && depth != CV_32F )
3722 if( CvtColorIPPLoop(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], ippiRGB2XYZTab[depth], 0, 1, 2, depth)) )
3724 setIppErrorStatus();
3728 if( depth == CV_8U )
3729 CvtColorLoop(src, dst, RGB2XYZ_i<uchar>(scn, bidx, 0));
3730 else if( depth == CV_16U )
3731 CvtColorLoop(src, dst, RGB2XYZ_i<ushort>(scn, bidx, 0));
3733 CvtColorLoop(src, dst, RGB2XYZ_f<float>(scn, bidx, 0));
3736 case CV_XYZ2BGR: case CV_XYZ2RGB:
3737 if( dcn <= 0 ) dcn = 3;
3738 CV_Assert( scn == 3 && (dcn == 3 || dcn == 4) );
3739 bidx = code == CV_XYZ2BGR ? 0 : 2;
3741 _dst.create(sz, CV_MAKETYPE(depth, dcn));
3742 dst = _dst.getMat();
3744 #if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
3745 if( code == CV_XYZ2BGR && dcn == 3 && depth != CV_32F )
3747 if( CvtColorIPPLoopCopy(src, dst, IPPGeneralReorderFunctor(ippiXYZ2RGBTab[depth], ippiSwapChannelsC3RTab[depth], 2, 1, 0, depth)) )
3749 setIppErrorStatus();
3751 else if( code == CV_XYZ2BGR && dcn == 4 && depth != CV_32F )
3753 if( CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor(ippiXYZ2RGBTab[depth], ippiSwapChannelsC3C4RTab[depth], 2, 1, 0, depth)) )
3755 setIppErrorStatus();
3757 if( code == CV_XYZ2RGB && dcn == 3 && depth != CV_32F )
3759 if( CvtColorIPPLoopCopy(src, dst, IPPGeneralFunctor(ippiXYZ2RGBTab[depth])) )
3761 setIppErrorStatus();
3763 else if( code == CV_XYZ2RGB && dcn == 4 && depth != CV_32F )
3765 if( CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor(ippiXYZ2RGBTab[depth], ippiSwapChannelsC3C4RTab[depth], 0, 1, 2, depth)) )
3767 setIppErrorStatus();
3771 if( depth == CV_8U )
3772 CvtColorLoop(src, dst, XYZ2RGB_i<uchar>(dcn, bidx, 0));
3773 else if( depth == CV_16U )
3774 CvtColorLoop(src, dst, XYZ2RGB_i<ushort>(dcn, bidx, 0));
3776 CvtColorLoop(src, dst, XYZ2RGB_f<float>(dcn, bidx, 0));
3779 case CV_BGR2HSV: case CV_RGB2HSV: case CV_BGR2HSV_FULL: case CV_RGB2HSV_FULL:
3780 case CV_BGR2HLS: case CV_RGB2HLS: case CV_BGR2HLS_FULL: case CV_RGB2HLS_FULL:
3782 CV_Assert( (scn == 3 || scn == 4) && (depth == CV_8U || depth == CV_32F) );
3783 bidx = code == CV_BGR2HSV || code == CV_BGR2HLS ||
3784 code == CV_BGR2HSV_FULL || code == CV_BGR2HLS_FULL ? 0 : 2;
3785 int hrange = depth == CV_32F ? 360 : code == CV_BGR2HSV || code == CV_RGB2HSV ||
3786 code == CV_BGR2HLS || code == CV_RGB2HLS ? 180 : 256;
3788 _dst.create(sz, CV_MAKETYPE(depth, 3));
3789 dst = _dst.getMat();
3791 #if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
3792 if( depth == CV_8U || depth == CV_16U )
3794 if( code == CV_BGR2HSV_FULL && scn == 3 )
3796 if( CvtColorIPPLoopCopy(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC3RTab[depth], ippiRGB2HSVTab[depth], 2, 1, 0, depth)) )
3798 setIppErrorStatus();
3800 else if( code == CV_BGR2HSV_FULL && scn == 4 )
3802 if( CvtColorIPPLoop(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], ippiRGB2HSVTab[depth], 2, 1, 0, depth)) )
3804 setIppErrorStatus();
3806 else if( code == CV_RGB2HSV_FULL && scn == 3 && depth == CV_16U )
3808 if( CvtColorIPPLoopCopy(src, dst, IPPGeneralFunctor(ippiRGB2HSVTab[depth])) )
3810 setIppErrorStatus();
3812 else if( code == CV_RGB2HSV_FULL && scn == 4 )
3814 if( CvtColorIPPLoop(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], ippiRGB2HSVTab[depth], 0, 1, 2, depth)) )
3816 setIppErrorStatus();
3818 else if( code == CV_BGR2HLS_FULL && scn == 3 )
3820 if( CvtColorIPPLoopCopy(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC3RTab[depth], ippiRGB2HLSTab[depth], 2, 1, 0, depth)) )
3822 setIppErrorStatus();
3824 else if( code == CV_BGR2HLS_FULL && scn == 4 )
3826 if( CvtColorIPPLoop(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], ippiRGB2HLSTab[depth], 2, 1, 0, depth)) )
3828 setIppErrorStatus();
3830 else if( code == CV_RGB2HLS_FULL && scn == 3 )
3832 if( CvtColorIPPLoopCopy(src, dst, IPPGeneralFunctor(ippiRGB2HLSTab[depth])) )
3834 setIppErrorStatus();
3836 else if( code == CV_RGB2HLS_FULL && scn == 4 )
3838 if( CvtColorIPPLoop(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], ippiRGB2HLSTab[depth], 0, 1, 2, depth)) )
3840 setIppErrorStatus();
3845 if( code == CV_BGR2HSV || code == CV_RGB2HSV ||
3846 code == CV_BGR2HSV_FULL || code == CV_RGB2HSV_FULL )
3848 #ifdef HAVE_TEGRA_OPTIMIZATION
3849 if(tegra::cvtRGB2HSV(src, dst, bidx, hrange))
3852 if( depth == CV_8U )
3853 CvtColorLoop(src, dst, RGB2HSV_b(scn, bidx, hrange));
3855 CvtColorLoop(src, dst, RGB2HSV_f(scn, bidx, (float)hrange));
3859 if( depth == CV_8U )
3860 CvtColorLoop(src, dst, RGB2HLS_b(scn, bidx, hrange));
3862 CvtColorLoop(src, dst, RGB2HLS_f(scn, bidx, (float)hrange));
3867 case CV_HSV2BGR: case CV_HSV2RGB: case CV_HSV2BGR_FULL: case CV_HSV2RGB_FULL:
3868 case CV_HLS2BGR: case CV_HLS2RGB: case CV_HLS2BGR_FULL: case CV_HLS2RGB_FULL:
3870 if( dcn <= 0 ) dcn = 3;
3871 CV_Assert( scn == 3 && (dcn == 3 || dcn == 4) && (depth == CV_8U || depth == CV_32F) );
3872 bidx = code == CV_HSV2BGR || code == CV_HLS2BGR ||
3873 code == CV_HSV2BGR_FULL || code == CV_HLS2BGR_FULL ? 0 : 2;
3874 int hrange = depth == CV_32F ? 360 : code == CV_HSV2BGR || code == CV_HSV2RGB ||
3875 code == CV_HLS2BGR || code == CV_HLS2RGB ? 180 : 255;
3877 _dst.create(sz, CV_MAKETYPE(depth, dcn));
3878 dst = _dst.getMat();
3880 #if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
3881 if( depth == CV_8U || depth == CV_16U )
3883 if( code == CV_HSV2BGR_FULL && dcn == 3 )
3885 if( CvtColorIPPLoopCopy(src, dst, IPPGeneralReorderFunctor(ippiHSV2RGBTab[depth], ippiSwapChannelsC3RTab[depth], 2, 1, 0, depth)) )
3887 setIppErrorStatus();
3889 else if( code == CV_HSV2BGR_FULL && dcn == 4 )
3891 if( CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor(ippiHSV2RGBTab[depth], ippiSwapChannelsC3C4RTab[depth], 2, 1, 0, depth)) )
3893 setIppErrorStatus();
3895 else if( code == CV_HSV2RGB_FULL && dcn == 3 )
3897 if( CvtColorIPPLoopCopy(src, dst, IPPGeneralFunctor(ippiHSV2RGBTab[depth])) )
3899 setIppErrorStatus();
3901 else if( code == CV_HSV2RGB_FULL && dcn == 4 )
3903 if( CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor(ippiHSV2RGBTab[depth], ippiSwapChannelsC3C4RTab[depth], 0, 1, 2, depth)) )
3905 setIppErrorStatus();
3907 else if( code == CV_HLS2BGR_FULL && dcn == 3 )
3909 if( CvtColorIPPLoopCopy(src, dst, IPPGeneralReorderFunctor(ippiHLS2RGBTab[depth], ippiSwapChannelsC3RTab[depth], 2, 1, 0, depth)) )
3911 setIppErrorStatus();
3913 else if( code == CV_HLS2BGR_FULL && dcn == 4 )
3915 if( CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor(ippiHLS2RGBTab[depth], ippiSwapChannelsC3C4RTab[depth], 2, 1, 0, depth)) )
3917 setIppErrorStatus();
3919 else if( code == CV_HLS2RGB_FULL && dcn == 3 )
3921 if( CvtColorIPPLoopCopy(src, dst, IPPGeneralFunctor(ippiHLS2RGBTab[depth])) )
3923 setIppErrorStatus();
3925 else if( code == CV_HLS2RGB_FULL && dcn == 4 )
3927 if( CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor(ippiHLS2RGBTab[depth], ippiSwapChannelsC3C4RTab[depth], 0, 1, 2, depth)) )
3929 setIppErrorStatus();
3934 if( code == CV_HSV2BGR || code == CV_HSV2RGB ||
3935 code == CV_HSV2BGR_FULL || code == CV_HSV2RGB_FULL )
3937 if( depth == CV_8U )
3938 CvtColorLoop(src, dst, HSV2RGB_b(dcn, bidx, hrange));
3940 CvtColorLoop(src, dst, HSV2RGB_f(dcn, bidx, (float)hrange));
3944 if( depth == CV_8U )
3945 CvtColorLoop(src, dst, HLS2RGB_b(dcn, bidx, hrange));
3947 CvtColorLoop(src, dst, HLS2RGB_f(dcn, bidx, (float)hrange));
3952 case CV_BGR2Lab: case CV_RGB2Lab: case CV_LBGR2Lab: case CV_LRGB2Lab:
3953 case CV_BGR2Luv: case CV_RGB2Luv: case CV_LBGR2Luv: case CV_LRGB2Luv:
3955 CV_Assert( (scn == 3 || scn == 4) && (depth == CV_8U || depth == CV_32F) );
3956 bidx = code == CV_BGR2Lab || code == CV_BGR2Luv ||
3957 code == CV_LBGR2Lab || code == CV_LBGR2Luv ? 0 : 2;
3958 bool srgb = code == CV_BGR2Lab || code == CV_RGB2Lab ||
3959 code == CV_BGR2Luv || code == CV_RGB2Luv;
3961 _dst.create(sz, CV_MAKETYPE(depth, 3));
3962 dst = _dst.getMat();
3966 if (code == CV_LBGR2Lab && scn == 3 && depth == CV_8U)
3968 if (CvtColorIPPLoop(src, dst, IPPGeneralFunctor((ippiGeneralFunc)ippiBGRToLab_8u_C3R)))
3970 setIppErrorStatus();
3972 else if (code == CV_LBGR2Lab && scn == 4 && depth == CV_8U)
3974 if (CvtColorIPPLoop(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth],
3975 (ippiGeneralFunc)ippiBGRToLab_8u_C3R, 0, 1, 2, depth)))
3977 setIppErrorStatus();
3980 if (code == CV_LRGB2Lab && scn == 3 && depth == CV_8U) // slower than OpenCV
3982 if (CvtColorIPPLoop(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC3RTab[depth],
3983 (ippiGeneralFunc)ippiBGRToLab_8u_C3R, 2, 1, 0, depth)))
3985 setIppErrorStatus();
3987 else if (code == CV_LRGB2Lab && scn == 4 && depth == CV_8U) // slower than OpenCV
3989 if (CvtColorIPPLoop(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth],
3990 (ippiGeneralFunc)ippiBGRToLab_8u_C3R, 2, 1, 0, depth)))
3992 setIppErrorStatus();
3994 else if (code == CV_LRGB2Luv && scn == 3)
3996 if (CvtColorIPPLoop(src, dst, IPPGeneralFunctor(ippiRGBToLUVTab[depth])))
3998 setIppErrorStatus();
4000 else if (code == CV_LRGB2Luv && scn == 4)
4002 if (CvtColorIPPLoop(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth],
4003 ippiRGBToLUVTab[depth], 0, 1, 2, depth)))
4005 setIppErrorStatus();
4007 else if (code == CV_LBGR2Luv && scn == 3)
4009 if (CvtColorIPPLoop(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC3RTab[depth],
4010 ippiRGBToLUVTab[depth], 2, 1, 0, depth)))
4012 setIppErrorStatus();
4014 else if (code == CV_LBGR2Luv && scn == 4)
4016 if (CvtColorIPPLoop(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth],
4017 ippiRGBToLUVTab[depth], 2, 1, 0, depth)))
4019 setIppErrorStatus();
4024 if( code == CV_BGR2Lab || code == CV_RGB2Lab ||
4025 code == CV_LBGR2Lab || code == CV_LRGB2Lab )
4027 if( depth == CV_8U )
4028 CvtColorLoop(src, dst, RGB2Lab_b(scn, bidx, 0, 0, srgb));
4030 CvtColorLoop(src, dst, RGB2Lab_f(scn, bidx, 0, 0, srgb));
4034 if( depth == CV_8U )
4035 CvtColorLoop(src, dst, RGB2Luv_b(scn, bidx, 0, 0, srgb));
4037 CvtColorLoop(src, dst, RGB2Luv_f(scn, bidx, 0, 0, srgb));
4042 case CV_Lab2BGR: case CV_Lab2RGB: case CV_Lab2LBGR: case CV_Lab2LRGB:
4043 case CV_Luv2BGR: case CV_Luv2RGB: case CV_Luv2LBGR: case CV_Luv2LRGB:
4045 if( dcn <= 0 ) dcn = 3;
4046 CV_Assert( scn == 3 && (dcn == 3 || dcn == 4) && (depth == CV_8U || depth == CV_32F) );
4047 bidx = code == CV_Lab2BGR || code == CV_Luv2BGR ||
4048 code == CV_Lab2LBGR || code == CV_Luv2LBGR ? 0 : 2;
4049 bool srgb = code == CV_Lab2BGR || code == CV_Lab2RGB ||
4050 code == CV_Luv2BGR || code == CV_Luv2RGB;
4052 _dst.create(sz, CV_MAKETYPE(depth, dcn));
4053 dst = _dst.getMat();
4055 #if defined HAVE_IPP && 0
4056 if( code == CV_Lab2LBGR && dcn == 3 && depth == CV_8U)
4058 if( CvtColorIPPLoop(src, dst, IPPGeneralFunctor((ippiGeneralFunc)ippiLabToBGR_8u_C3R)) )
4060 setIppErrorStatus();
4062 else if( code == CV_Lab2LBGR && dcn == 4 && depth == CV_8U )
4064 if( CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor((ippiGeneralFunc)ippiLabToBGR_8u_C3R,
4065 ippiSwapChannelsC3C4RTab[depth], 0, 1, 2, depth)) )
4067 setIppErrorStatus();
4069 if( code == CV_Lab2LRGB && dcn == 3 && depth == CV_8U )
4071 if( CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor((ippiGeneralFunc)ippiLabToBGR_8u_C3R,
4072 ippiSwapChannelsC3RTab[depth], 2, 1, 0, depth)) )
4074 setIppErrorStatus();
4076 else if( code == CV_Lab2LRGB && dcn == 4 && depth == CV_8U )
4078 if( CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor((ippiGeneralFunc)ippiLabToBGR_8u_C3R,
4079 ippiSwapChannelsC3C4RTab[depth], 2, 1, 0, depth)) )
4081 setIppErrorStatus();
4083 if( code == CV_Luv2LRGB && dcn == 3 )
4085 if( CvtColorIPPLoop(src, dst, IPPGeneralFunctor(ippiLUVToRGBTab[depth])) )
4088 else if( code == CV_Luv2LRGB && dcn == 4 )
4090 if( CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor(ippiLUVToRGBTab[depth],
4091 ippiSwapChannelsC3C4RTab[depth], 0, 1, 2, depth)) )
4094 if( code == CV_Luv2LBGR && dcn == 3 )
4096 if( CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor(ippiLUVToRGBTab[depth],
4097 ippiSwapChannelsC3RTab[depth], 2, 1, 0, depth)) )
4100 else if( code == CV_Luv2LBGR && dcn == 4 )
4102 if( CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor(ippiLUVToRGBTab[depth],
4103 ippiSwapChannelsC3C4RTab[depth], 2, 1, 0, depth)) )
4108 if( code == CV_Lab2BGR || code == CV_Lab2RGB ||
4109 code == CV_Lab2LBGR || code == CV_Lab2LRGB )
4111 if( depth == CV_8U )
4112 CvtColorLoop(src, dst, Lab2RGB_b(dcn, bidx, 0, 0, srgb));
4114 CvtColorLoop(src, dst, Lab2RGB_f(dcn, bidx, 0, 0, srgb));
4118 if( depth == CV_8U )
4119 CvtColorLoop(src, dst, Luv2RGB_b(dcn, bidx, 0, 0, srgb));
4121 CvtColorLoop(src, dst, Luv2RGB_f(dcn, bidx, 0, 0, srgb));
4126 case CV_BayerBG2GRAY: case CV_BayerGB2GRAY: case CV_BayerRG2GRAY: case CV_BayerGR2GRAY:
4127 case CV_BayerBG2BGR: case CV_BayerGB2BGR: case CV_BayerRG2BGR: case CV_BayerGR2BGR:
4128 case CV_BayerBG2BGR_VNG: case CV_BayerGB2BGR_VNG: case CV_BayerRG2BGR_VNG: case CV_BayerGR2BGR_VNG:
4129 case CV_BayerBG2BGR_EA: case CV_BayerGB2BGR_EA: case CV_BayerRG2BGR_EA: case CV_BayerGR2BGR_EA:
4130 demosaicing(src, _dst, code, dcn);
4133 case CV_YUV2BGR_NV21: case CV_YUV2RGB_NV21: case CV_YUV2BGR_NV12: case CV_YUV2RGB_NV12:
4134 case CV_YUV2BGRA_NV21: case CV_YUV2RGBA_NV21: case CV_YUV2BGRA_NV12: case CV_YUV2RGBA_NV12:
4136 // http://www.fourcc.org/yuv.php#NV21 == yuv420sp -> a plane of 8 bit Y samples followed by an interleaved V/U plane containing 8 bit 2x2 subsampled chroma samples
4137 // http://www.fourcc.org/yuv.php#NV12 -> a plane of 8 bit Y samples followed by an interleaved U/V plane containing 8 bit 2x2 subsampled colour difference samples
4139 if (dcn <= 0) dcn = (code==CV_YUV420sp2BGRA || code==CV_YUV420sp2RGBA || code==CV_YUV2BGRA_NV12 || code==CV_YUV2RGBA_NV12) ? 4 : 3;
4140 const int bIdx = (code==CV_YUV2BGR_NV21 || code==CV_YUV2BGRA_NV21 || code==CV_YUV2BGR_NV12 || code==CV_YUV2BGRA_NV12) ? 0 : 2;
4141 const int uIdx = (code==CV_YUV2BGR_NV21 || code==CV_YUV2BGRA_NV21 || code==CV_YUV2RGB_NV21 || code==CV_YUV2RGBA_NV21) ? 1 : 0;
4143 CV_Assert( dcn == 3 || dcn == 4 );
4144 CV_Assert( sz.width % 2 == 0 && sz.height % 3 == 0 && depth == CV_8U );
4146 Size dstSz(sz.width, sz.height * 2 / 3);
4147 _dst.create(dstSz, CV_MAKETYPE(depth, dcn));
4148 dst = _dst.getMat();
4150 int srcstep = (int)src.step;
4151 const uchar* y = src.ptr();
4152 const uchar* uv = y + srcstep * dstSz.height;
4154 switch(dcn*100 + bIdx * 10 + uIdx)
4156 case 300: cvtYUV420sp2RGB<0, 0> (dst, srcstep, y, uv); break;
4157 case 301: cvtYUV420sp2RGB<0, 1> (dst, srcstep, y, uv); break;
4158 case 320: cvtYUV420sp2RGB<2, 0> (dst, srcstep, y, uv); break;
4159 case 321: cvtYUV420sp2RGB<2, 1> (dst, srcstep, y, uv); break;
4160 case 400: cvtYUV420sp2RGBA<0, 0>(dst, srcstep, y, uv); break;
4161 case 401: cvtYUV420sp2RGBA<0, 1>(dst, srcstep, y, uv); break;
4162 case 420: cvtYUV420sp2RGBA<2, 0>(dst, srcstep, y, uv); break;
4163 case 421: cvtYUV420sp2RGBA<2, 1>(dst, srcstep, y, uv); break;
4164 default: CV_Error( CV_StsBadFlag, "Unknown/unsupported color conversion code" ); break;
4168 case CV_YUV2BGR_YV12: case CV_YUV2RGB_YV12: case CV_YUV2BGRA_YV12: case CV_YUV2RGBA_YV12:
4169 case CV_YUV2BGR_IYUV: case CV_YUV2RGB_IYUV: case CV_YUV2BGRA_IYUV: case CV_YUV2RGBA_IYUV:
4171 //http://www.fourcc.org/yuv.php#YV12 == yuv420p -> It comprises an NxM Y plane followed by (N/2)x(M/2) V and U planes.
4172 //http://www.fourcc.org/yuv.php#IYUV == I420 -> It comprises an NxN Y plane followed by (N/2)x(N/2) U and V planes
4174 if (dcn <= 0) dcn = (code==CV_YUV2BGRA_YV12 || code==CV_YUV2RGBA_YV12 || code==CV_YUV2RGBA_IYUV || code==CV_YUV2BGRA_IYUV) ? 4 : 3;
4175 const int bIdx = (code==CV_YUV2BGR_YV12 || code==CV_YUV2BGRA_YV12 || code==CV_YUV2BGR_IYUV || code==CV_YUV2BGRA_IYUV) ? 0 : 2;
4176 const int uIdx = (code==CV_YUV2BGR_YV12 || code==CV_YUV2RGB_YV12 || code==CV_YUV2BGRA_YV12 || code==CV_YUV2RGBA_YV12) ? 1 : 0;
4178 CV_Assert( dcn == 3 || dcn == 4 );
4179 CV_Assert( sz.width % 2 == 0 && sz.height % 3 == 0 && depth == CV_8U );
4181 Size dstSz(sz.width, sz.height * 2 / 3);
4182 _dst.create(dstSz, CV_MAKETYPE(depth, dcn));
4183 dst = _dst.getMat();
4185 int srcstep = (int)src.step;
4186 const uchar* y = src.ptr();
4187 const uchar* u = y + srcstep * dstSz.height;
4188 const uchar* v = y + srcstep * (dstSz.height + dstSz.height/4) + (dstSz.width/2) * ((dstSz.height % 4)/2);
4191 int vstepIdx = dstSz.height % 4 == 2 ? 1 : 0;
4193 if(uIdx == 1) { std::swap(u ,v), std::swap(ustepIdx, vstepIdx); }
4195 switch(dcn*10 + bIdx)
4197 case 30: cvtYUV420p2RGB<0>(dst, srcstep, y, u, v, ustepIdx, vstepIdx); break;
4198 case 32: cvtYUV420p2RGB<2>(dst, srcstep, y, u, v, ustepIdx, vstepIdx); break;
4199 case 40: cvtYUV420p2RGBA<0>(dst, srcstep, y, u, v, ustepIdx, vstepIdx); break;
4200 case 42: cvtYUV420p2RGBA<2>(dst, srcstep, y, u, v, ustepIdx, vstepIdx); break;
4201 default: CV_Error( CV_StsBadFlag, "Unknown/unsupported color conversion code" ); break;
4205 case CV_YUV2GRAY_420:
4207 if (dcn <= 0) dcn = 1;
4209 CV_Assert( dcn == 1 );
4210 CV_Assert( sz.width % 2 == 0 && sz.height % 3 == 0 && depth == CV_8U );
4212 Size dstSz(sz.width, sz.height * 2 / 3);
4213 _dst.create(dstSz, CV_MAKETYPE(depth, dcn));
4214 dst = _dst.getMat();
4216 src(Range(0, dstSz.height), Range::all()).copyTo(dst);
4219 case CV_RGB2YUV_YV12: case CV_BGR2YUV_YV12: case CV_RGBA2YUV_YV12: case CV_BGRA2YUV_YV12:
4220 case CV_RGB2YUV_IYUV: case CV_BGR2YUV_IYUV: case CV_RGBA2YUV_IYUV: case CV_BGRA2YUV_IYUV:
4222 if (dcn <= 0) dcn = 1;
4223 const int bIdx = (code == CV_BGR2YUV_IYUV || code == CV_BGRA2YUV_IYUV || code == CV_BGR2YUV_YV12 || code == CV_BGRA2YUV_YV12) ? 0 : 2;
4224 const int uIdx = (code == CV_BGR2YUV_IYUV || code == CV_BGRA2YUV_IYUV || code == CV_RGB2YUV_IYUV || code == CV_RGBA2YUV_IYUV) ? 1 : 2;
4226 CV_Assert( (scn == 3 || scn == 4) && depth == CV_8U );
4227 CV_Assert( dcn == 1 );
4228 CV_Assert( sz.width % 2 == 0 && sz.height % 2 == 0 );
4230 Size dstSz(sz.width, sz.height / 2 * 3);
4231 _dst.create(dstSz, CV_MAKETYPE(depth, dcn));
4232 dst = _dst.getMat();
4234 switch(bIdx + uIdx*10)
4236 case 10: cvtRGBtoYUV420p<0, 1>(src, dst); break;
4237 case 12: cvtRGBtoYUV420p<2, 1>(src, dst); break;
4238 case 20: cvtRGBtoYUV420p<0, 2>(src, dst); break;
4239 case 22: cvtRGBtoYUV420p<2, 2>(src, dst); break;
4240 default: CV_Error( CV_StsBadFlag, "Unknown/unsupported color conversion code" ); break;
4244 case CV_YUV2RGB_UYVY: case CV_YUV2BGR_UYVY: case CV_YUV2RGBA_UYVY: case CV_YUV2BGRA_UYVY:
4245 case CV_YUV2RGB_YUY2: case CV_YUV2BGR_YUY2: case CV_YUV2RGB_YVYU: case CV_YUV2BGR_YVYU:
4246 case CV_YUV2RGBA_YUY2: case CV_YUV2BGRA_YUY2: case CV_YUV2RGBA_YVYU: case CV_YUV2BGRA_YVYU:
4248 //http://www.fourcc.org/yuv.php#UYVY
4249 //http://www.fourcc.org/yuv.php#YUY2
4250 //http://www.fourcc.org/yuv.php#YVYU
4252 if (dcn <= 0) dcn = (code==CV_YUV2RGBA_UYVY || code==CV_YUV2BGRA_UYVY || code==CV_YUV2RGBA_YUY2 || code==CV_YUV2BGRA_YUY2 || code==CV_YUV2RGBA_YVYU || code==CV_YUV2BGRA_YVYU) ? 4 : 3;
4253 const int bIdx = (code==CV_YUV2BGR_UYVY || code==CV_YUV2BGRA_UYVY || code==CV_YUV2BGR_YUY2 || code==CV_YUV2BGRA_YUY2 || code==CV_YUV2BGR_YVYU || code==CV_YUV2BGRA_YVYU) ? 0 : 2;
4254 const int ycn = (code==CV_YUV2RGB_UYVY || code==CV_YUV2BGR_UYVY || code==CV_YUV2RGBA_UYVY || code==CV_YUV2BGRA_UYVY) ? 1 : 0;
4255 const int uIdx = (code==CV_YUV2RGB_YVYU || code==CV_YUV2BGR_YVYU || code==CV_YUV2RGBA_YVYU || code==CV_YUV2BGRA_YVYU) ? 1 : 0;
4257 CV_Assert( dcn == 3 || dcn == 4 );
4258 CV_Assert( scn == 2 && depth == CV_8U );
4260 _dst.create(sz, CV_8UC(dcn));
4261 dst = _dst.getMat();
4263 switch(dcn*1000 + bIdx*100 + uIdx*10 + ycn)
4265 case 3000: cvtYUV422toRGB<0,0,0>(dst, (int)src.step, src.ptr<uchar>()); break;
4266 case 3001: cvtYUV422toRGB<0,0,1>(dst, (int)src.step, src.ptr<uchar>()); break;
4267 case 3010: cvtYUV422toRGB<0,1,0>(dst, (int)src.step, src.ptr<uchar>()); break;
4268 case 3011: cvtYUV422toRGB<0,1,1>(dst, (int)src.step, src.ptr<uchar>()); break;
4269 case 3200: cvtYUV422toRGB<2,0,0>(dst, (int)src.step, src.ptr<uchar>()); break;
4270 case 3201: cvtYUV422toRGB<2,0,1>(dst, (int)src.step, src.ptr<uchar>()); break;
4271 case 3210: cvtYUV422toRGB<2,1,0>(dst, (int)src.step, src.ptr<uchar>()); break;
4272 case 3211: cvtYUV422toRGB<2,1,1>(dst, (int)src.step, src.ptr<uchar>()); break;
4273 case 4000: cvtYUV422toRGBA<0,0,0>(dst, (int)src.step, src.ptr<uchar>()); break;
4274 case 4001: cvtYUV422toRGBA<0,0,1>(dst, (int)src.step, src.ptr<uchar>()); break;
4275 case 4010: cvtYUV422toRGBA<0,1,0>(dst, (int)src.step, src.ptr<uchar>()); break;
4276 case 4011: cvtYUV422toRGBA<0,1,1>(dst, (int)src.step, src.ptr<uchar>()); break;
4277 case 4200: cvtYUV422toRGBA<2,0,0>(dst, (int)src.step, src.ptr<uchar>()); break;
4278 case 4201: cvtYUV422toRGBA<2,0,1>(dst, (int)src.step, src.ptr<uchar>()); break;
4279 case 4210: cvtYUV422toRGBA<2,1,0>(dst, (int)src.step, src.ptr<uchar>()); break;
4280 case 4211: cvtYUV422toRGBA<2,1,1>(dst, (int)src.step, src.ptr<uchar>()); break;
4281 default: CV_Error( CV_StsBadFlag, "Unknown/unsupported color conversion code" ); break;
4285 case CV_YUV2GRAY_UYVY: case CV_YUV2GRAY_YUY2:
4287 if (dcn <= 0) dcn = 1;
4289 CV_Assert( dcn == 1 );
4290 CV_Assert( scn == 2 && depth == CV_8U );
4292 extractChannel(_src, _dst, code == CV_YUV2GRAY_UYVY ? 1 : 0);
4297 if (dcn <= 0) dcn = 4;
4298 CV_Assert( scn == 4 && dcn == 4 );
4300 _dst.create(sz, CV_MAKETYPE(depth, dcn));
4301 dst = _dst.getMat();
4303 if( depth == CV_8U )
4305 #if defined(HAVE_IPP)
4306 if (CvtColorIPPLoop(src, dst, IPPGeneralFunctor((ippiGeneralFunc)ippiAlphaPremul_8u_AC4R)))
4308 setIppErrorStatus();
4310 CvtColorLoop(src, dst, RGBA2mRGBA<uchar>());
4314 CV_Error( CV_StsBadArg, "Unsupported image depth" );
4320 if (dcn <= 0) dcn = 4;
4321 CV_Assert( scn == 4 && dcn == 4 );
4323 _dst.create(sz, CV_MAKETYPE(depth, dcn));
4324 dst = _dst.getMat();
4326 if( depth == CV_8U )
4327 CvtColorLoop(src, dst, mRGBA2RGBA<uchar>());
4330 CV_Error( CV_StsBadArg, "Unsupported image depth" );
4335 CV_Error( CV_StsBadFlag, "Unknown/unsupported color conversion code" );
4340 cvCvtColor( const CvArr* srcarr, CvArr* dstarr, int code )
4342 cv::Mat src = cv::cvarrToMat(srcarr), dst0 = cv::cvarrToMat(dstarr), dst = dst0;
4343 CV_Assert( src.depth() == dst.depth() );
4345 cv::cvtColor(src, dst, code, dst.channels());
4346 CV_Assert( dst.data == dst0.data );