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_imgproc.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.ptr(), (int)temp.step[0], ippiSize(cols, rows)) < 0)
473 int order[4] = {0, 1, 2, 3};
474 return func2(temp.ptr(), (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.ptr(), (int)temp.step[0], ippiSize(cols, rows), order) < 0)
501 return func2(temp.ptr(), (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.ptr(), (int)temp.step[0], ippiSize(cols, rows)) < 0)
529 return func2(temp.ptr(), (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;
2041 R = std::min(std::max(R, 0.f), 1.f);
2042 G = std::min(std::max(G, 0.f), 1.f);
2043 B = std::min(std::max(B, 0.f), 1.f);
2047 R = splineInterpolate(R*gscale, gammaTab, GAMMA_TAB_SIZE);
2048 G = splineInterpolate(G*gscale, gammaTab, GAMMA_TAB_SIZE);
2049 B = splineInterpolate(B*gscale, gammaTab, GAMMA_TAB_SIZE);
2052 dst[0] = R; dst[1] = G; dst[2] = B;
2059 float coeffs[9], un, vn;
2066 typedef uchar channel_type;
2068 RGB2Luv_b( int _srccn, int blueIdx, const float* _coeffs,
2069 const float* _whitept, bool _srgb )
2070 : srccn(_srccn), cvt(3, blueIdx, _coeffs, _whitept, _srgb) {}
2072 void operator()(const uchar* src, uchar* dst, int n) const
2074 int i, j, scn = srccn;
2075 float buf[3*BLOCK_SIZE];
2077 for( i = 0; i < n; i += BLOCK_SIZE, dst += BLOCK_SIZE*3 )
2079 int dn = std::min(n - i, (int)BLOCK_SIZE);
2081 for( j = 0; j < dn*3; j += 3, src += scn )
2083 buf[j] = src[0]*(1.f/255.f);
2084 buf[j+1] = (float)(src[1]*(1.f/255.f));
2085 buf[j+2] = (float)(src[2]*(1.f/255.f));
2089 for( j = 0; j < dn*3; j += 3 )
2091 dst[j] = saturate_cast<uchar>(buf[j]*2.55f);
2092 dst[j+1] = saturate_cast<uchar>(buf[j+1]*0.72033898305084743f + 96.525423728813564f);
2093 dst[j+2] = saturate_cast<uchar>(buf[j+2]*0.99609375f + 139.453125f);
2105 typedef uchar channel_type;
2107 Luv2RGB_b( int _dstcn, int blueIdx, const float* _coeffs,
2108 const float* _whitept, bool _srgb )
2109 : dstcn(_dstcn), cvt(3, blueIdx, _coeffs, _whitept, _srgb ) {}
2111 void operator()(const uchar* src, uchar* dst, int n) const
2113 int i, j, dcn = dstcn;
2114 uchar alpha = ColorChannel<uchar>::max();
2115 float buf[3*BLOCK_SIZE];
2117 for( i = 0; i < n; i += BLOCK_SIZE, src += BLOCK_SIZE*3 )
2119 int dn = std::min(n - i, (int)BLOCK_SIZE);
2121 for( j = 0; j < dn*3; j += 3 )
2123 buf[j] = src[j]*(100.f/255.f);
2124 buf[j+1] = (float)(src[j+1]*1.388235294117647f - 134.f);
2125 buf[j+2] = (float)(src[j+2]*1.003921568627451f - 140.f);
2129 for( j = 0; j < dn*3; j += 3, dst += dcn )
2131 dst[0] = saturate_cast<uchar>(buf[j]*255.f);
2132 dst[1] = saturate_cast<uchar>(buf[j+1]*255.f);
2133 dst[2] = saturate_cast<uchar>(buf[j+2]*255.f);
2145 ///////////////////////////////////// YUV420 -> RGB /////////////////////////////////////
2147 const int ITUR_BT_601_CY = 1220542;
2148 const int ITUR_BT_601_CUB = 2116026;
2149 const int ITUR_BT_601_CUG = -409993;
2150 const int ITUR_BT_601_CVG = -852492;
2151 const int ITUR_BT_601_CVR = 1673527;
2152 const int ITUR_BT_601_SHIFT = 20;
2154 // Coefficients for RGB to YUV420p conversion
2155 const int ITUR_BT_601_CRY = 269484;
2156 const int ITUR_BT_601_CGY = 528482;
2157 const int ITUR_BT_601_CBY = 102760;
2158 const int ITUR_BT_601_CRU = -155188;
2159 const int ITUR_BT_601_CGU = -305135;
2160 const int ITUR_BT_601_CBU = 460324;
2161 const int ITUR_BT_601_CGV = -385875;
2162 const int ITUR_BT_601_CBV = -74448;
2164 template<int bIdx, int uIdx>
2165 struct YUV420sp2RGB888Invoker : ParallelLoopBody
2168 const uchar* my1, *muv;
2171 YUV420sp2RGB888Invoker(Mat* _dst, int _stride, const uchar* _y1, const uchar* _uv)
2172 : dst(_dst), my1(_y1), muv(_uv), width(_dst->cols), stride(_stride) {}
2174 void operator()(const Range& range) const
2176 int rangeBegin = range.start * 2;
2177 int rangeEnd = range.end * 2;
2179 //R = 1.164(Y - 16) + 1.596(V - 128)
2180 //G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128)
2181 //B = 1.164(Y - 16) + 2.018(U - 128)
2183 //R = (1220542(Y - 16) + 1673527(V - 128) + (1 << 19)) >> 20
2184 //G = (1220542(Y - 16) - 852492(V - 128) - 409993(U - 128) + (1 << 19)) >> 20
2185 //B = (1220542(Y - 16) + 2116026(U - 128) + (1 << 19)) >> 20
2187 const uchar* y1 = my1 + rangeBegin * stride, *uv = muv + rangeBegin * stride / 2;
2189 #ifdef HAVE_TEGRA_OPTIMIZATION
2190 if(tegra::cvtYUV4202RGB(bIdx, uIdx, 3, y1, uv, stride, dst->ptr<uchar>(rangeBegin), dst->step, rangeEnd - rangeBegin, dst->cols))
2194 for (int j = rangeBegin; j < rangeEnd; j += 2, y1 += stride * 2, uv += stride)
2196 uchar* row1 = dst->ptr<uchar>(j);
2197 uchar* row2 = dst->ptr<uchar>(j + 1);
2198 const uchar* y2 = y1 + stride;
2200 for (int i = 0; i < width; i += 2, row1 += 6, row2 += 6)
2202 int u = int(uv[i + 0 + uIdx]) - 128;
2203 int v = int(uv[i + 1 - uIdx]) - 128;
2205 int ruv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVR * v;
2206 int guv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVG * v + ITUR_BT_601_CUG * u;
2207 int buv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CUB * u;
2209 int y00 = std::max(0, int(y1[i]) - 16) * ITUR_BT_601_CY;
2210 row1[2-bIdx] = saturate_cast<uchar>((y00 + ruv) >> ITUR_BT_601_SHIFT);
2211 row1[1] = saturate_cast<uchar>((y00 + guv) >> ITUR_BT_601_SHIFT);
2212 row1[bIdx] = saturate_cast<uchar>((y00 + buv) >> ITUR_BT_601_SHIFT);
2214 int y01 = std::max(0, int(y1[i + 1]) - 16) * ITUR_BT_601_CY;
2215 row1[5-bIdx] = saturate_cast<uchar>((y01 + ruv) >> ITUR_BT_601_SHIFT);
2216 row1[4] = saturate_cast<uchar>((y01 + guv) >> ITUR_BT_601_SHIFT);
2217 row1[3+bIdx] = saturate_cast<uchar>((y01 + buv) >> ITUR_BT_601_SHIFT);
2219 int y10 = std::max(0, int(y2[i]) - 16) * ITUR_BT_601_CY;
2220 row2[2-bIdx] = saturate_cast<uchar>((y10 + ruv) >> ITUR_BT_601_SHIFT);
2221 row2[1] = saturate_cast<uchar>((y10 + guv) >> ITUR_BT_601_SHIFT);
2222 row2[bIdx] = saturate_cast<uchar>((y10 + buv) >> ITUR_BT_601_SHIFT);
2224 int y11 = std::max(0, int(y2[i + 1]) - 16) * ITUR_BT_601_CY;
2225 row2[5-bIdx] = saturate_cast<uchar>((y11 + ruv) >> ITUR_BT_601_SHIFT);
2226 row2[4] = saturate_cast<uchar>((y11 + guv) >> ITUR_BT_601_SHIFT);
2227 row2[3+bIdx] = saturate_cast<uchar>((y11 + buv) >> ITUR_BT_601_SHIFT);
2233 template<int bIdx, int uIdx>
2234 struct YUV420sp2RGBA8888Invoker : ParallelLoopBody
2237 const uchar* my1, *muv;
2240 YUV420sp2RGBA8888Invoker(Mat* _dst, int _stride, const uchar* _y1, const uchar* _uv)
2241 : dst(_dst), my1(_y1), muv(_uv), width(_dst->cols), stride(_stride) {}
2243 void operator()(const Range& range) const
2245 int rangeBegin = range.start * 2;
2246 int rangeEnd = range.end * 2;
2248 //R = 1.164(Y - 16) + 1.596(V - 128)
2249 //G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128)
2250 //B = 1.164(Y - 16) + 2.018(U - 128)
2252 //R = (1220542(Y - 16) + 1673527(V - 128) + (1 << 19)) >> 20
2253 //G = (1220542(Y - 16) - 852492(V - 128) - 409993(U - 128) + (1 << 19)) >> 20
2254 //B = (1220542(Y - 16) + 2116026(U - 128) + (1 << 19)) >> 20
2256 const uchar* y1 = my1 + rangeBegin * stride, *uv = muv + rangeBegin * stride / 2;
2258 #ifdef HAVE_TEGRA_OPTIMIZATION
2259 if(tegra::cvtYUV4202RGB(bIdx, uIdx, 4, y1, uv, stride, dst->ptr<uchar>(rangeBegin), dst->step, rangeEnd - rangeBegin, dst->cols))
2263 for (int j = rangeBegin; j < rangeEnd; j += 2, y1 += stride * 2, uv += stride)
2265 uchar* row1 = dst->ptr<uchar>(j);
2266 uchar* row2 = dst->ptr<uchar>(j + 1);
2267 const uchar* y2 = y1 + stride;
2269 for (int i = 0; i < width; i += 2, row1 += 8, row2 += 8)
2271 int u = int(uv[i + 0 + uIdx]) - 128;
2272 int v = int(uv[i + 1 - uIdx]) - 128;
2274 int ruv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVR * v;
2275 int guv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVG * v + ITUR_BT_601_CUG * u;
2276 int buv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CUB * u;
2278 int y00 = std::max(0, int(y1[i]) - 16) * ITUR_BT_601_CY;
2279 row1[2-bIdx] = saturate_cast<uchar>((y00 + ruv) >> ITUR_BT_601_SHIFT);
2280 row1[1] = saturate_cast<uchar>((y00 + guv) >> ITUR_BT_601_SHIFT);
2281 row1[bIdx] = saturate_cast<uchar>((y00 + buv) >> ITUR_BT_601_SHIFT);
2282 row1[3] = uchar(0xff);
2284 int y01 = std::max(0, int(y1[i + 1]) - 16) * ITUR_BT_601_CY;
2285 row1[6-bIdx] = saturate_cast<uchar>((y01 + ruv) >> ITUR_BT_601_SHIFT);
2286 row1[5] = saturate_cast<uchar>((y01 + guv) >> ITUR_BT_601_SHIFT);
2287 row1[4+bIdx] = saturate_cast<uchar>((y01 + buv) >> ITUR_BT_601_SHIFT);
2288 row1[7] = uchar(0xff);
2290 int y10 = std::max(0, int(y2[i]) - 16) * ITUR_BT_601_CY;
2291 row2[2-bIdx] = saturate_cast<uchar>((y10 + ruv) >> ITUR_BT_601_SHIFT);
2292 row2[1] = saturate_cast<uchar>((y10 + guv) >> ITUR_BT_601_SHIFT);
2293 row2[bIdx] = saturate_cast<uchar>((y10 + buv) >> ITUR_BT_601_SHIFT);
2294 row2[3] = uchar(0xff);
2296 int y11 = std::max(0, int(y2[i + 1]) - 16) * ITUR_BT_601_CY;
2297 row2[6-bIdx] = saturate_cast<uchar>((y11 + ruv) >> ITUR_BT_601_SHIFT);
2298 row2[5] = saturate_cast<uchar>((y11 + guv) >> ITUR_BT_601_SHIFT);
2299 row2[4+bIdx] = saturate_cast<uchar>((y11 + buv) >> ITUR_BT_601_SHIFT);
2300 row2[7] = uchar(0xff);
2307 struct YUV420p2RGB888Invoker : ParallelLoopBody
2310 const uchar* my1, *mu, *mv;
2312 int ustepIdx, vstepIdx;
2314 YUV420p2RGB888Invoker(Mat* _dst, int _stride, const uchar* _y1, const uchar* _u, const uchar* _v, int _ustepIdx, int _vstepIdx)
2315 : dst(_dst), my1(_y1), mu(_u), mv(_v), width(_dst->cols), stride(_stride), ustepIdx(_ustepIdx), vstepIdx(_vstepIdx) {}
2317 void operator()(const Range& range) const
2319 const int rangeBegin = range.start * 2;
2320 const int rangeEnd = range.end * 2;
2322 int uvsteps[2] = {width/2, stride - width/2};
2323 int usIdx = ustepIdx, vsIdx = vstepIdx;
2325 const uchar* y1 = my1 + rangeBegin * stride;
2326 const uchar* u1 = mu + (range.start / 2) * stride;
2327 const uchar* v1 = mv + (range.start / 2) * stride;
2329 if(range.start % 2 == 1)
2331 u1 += uvsteps[(usIdx++) & 1];
2332 v1 += uvsteps[(vsIdx++) & 1];
2335 for (int j = rangeBegin; j < rangeEnd; j += 2, y1 += stride * 2, u1 += uvsteps[(usIdx++) & 1], v1 += uvsteps[(vsIdx++) & 1])
2337 uchar* row1 = dst->ptr<uchar>(j);
2338 uchar* row2 = dst->ptr<uchar>(j + 1);
2339 const uchar* y2 = y1 + stride;
2341 for (int i = 0; i < width / 2; i += 1, row1 += 6, row2 += 6)
2343 int u = int(u1[i]) - 128;
2344 int v = int(v1[i]) - 128;
2346 int ruv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVR * v;
2347 int guv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVG * v + ITUR_BT_601_CUG * u;
2348 int buv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CUB * u;
2350 int y00 = std::max(0, int(y1[2 * i]) - 16) * ITUR_BT_601_CY;
2351 row1[2-bIdx] = saturate_cast<uchar>((y00 + ruv) >> ITUR_BT_601_SHIFT);
2352 row1[1] = saturate_cast<uchar>((y00 + guv) >> ITUR_BT_601_SHIFT);
2353 row1[bIdx] = saturate_cast<uchar>((y00 + buv) >> ITUR_BT_601_SHIFT);
2355 int y01 = std::max(0, int(y1[2 * i + 1]) - 16) * ITUR_BT_601_CY;
2356 row1[5-bIdx] = saturate_cast<uchar>((y01 + ruv) >> ITUR_BT_601_SHIFT);
2357 row1[4] = saturate_cast<uchar>((y01 + guv) >> ITUR_BT_601_SHIFT);
2358 row1[3+bIdx] = saturate_cast<uchar>((y01 + buv) >> ITUR_BT_601_SHIFT);
2360 int y10 = std::max(0, int(y2[2 * i]) - 16) * ITUR_BT_601_CY;
2361 row2[2-bIdx] = saturate_cast<uchar>((y10 + ruv) >> ITUR_BT_601_SHIFT);
2362 row2[1] = saturate_cast<uchar>((y10 + guv) >> ITUR_BT_601_SHIFT);
2363 row2[bIdx] = saturate_cast<uchar>((y10 + buv) >> ITUR_BT_601_SHIFT);
2365 int y11 = std::max(0, int(y2[2 * i + 1]) - 16) * ITUR_BT_601_CY;
2366 row2[5-bIdx] = saturate_cast<uchar>((y11 + ruv) >> ITUR_BT_601_SHIFT);
2367 row2[4] = saturate_cast<uchar>((y11 + guv) >> ITUR_BT_601_SHIFT);
2368 row2[3+bIdx] = saturate_cast<uchar>((y11 + buv) >> ITUR_BT_601_SHIFT);
2375 struct YUV420p2RGBA8888Invoker : ParallelLoopBody
2378 const uchar* my1, *mu, *mv;
2380 int ustepIdx, vstepIdx;
2382 YUV420p2RGBA8888Invoker(Mat* _dst, int _stride, const uchar* _y1, const uchar* _u, const uchar* _v, int _ustepIdx, int _vstepIdx)
2383 : dst(_dst), my1(_y1), mu(_u), mv(_v), width(_dst->cols), stride(_stride), ustepIdx(_ustepIdx), vstepIdx(_vstepIdx) {}
2385 void operator()(const Range& range) const
2387 int rangeBegin = range.start * 2;
2388 int rangeEnd = range.end * 2;
2390 int uvsteps[2] = {width/2, stride - width/2};
2391 int usIdx = ustepIdx, vsIdx = vstepIdx;
2393 const uchar* y1 = my1 + rangeBegin * stride;
2394 const uchar* u1 = mu + (range.start / 2) * stride;
2395 const uchar* v1 = mv + (range.start / 2) * stride;
2397 if(range.start % 2 == 1)
2399 u1 += uvsteps[(usIdx++) & 1];
2400 v1 += uvsteps[(vsIdx++) & 1];
2403 for (int j = rangeBegin; j < rangeEnd; j += 2, y1 += stride * 2, u1 += uvsteps[(usIdx++) & 1], v1 += uvsteps[(vsIdx++) & 1])
2405 uchar* row1 = dst->ptr<uchar>(j);
2406 uchar* row2 = dst->ptr<uchar>(j + 1);
2407 const uchar* y2 = y1 + stride;
2409 for (int i = 0; i < width / 2; i += 1, row1 += 8, row2 += 8)
2411 int u = int(u1[i]) - 128;
2412 int v = int(v1[i]) - 128;
2414 int ruv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVR * v;
2415 int guv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVG * v + ITUR_BT_601_CUG * u;
2416 int buv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CUB * u;
2418 int y00 = std::max(0, int(y1[2 * i]) - 16) * ITUR_BT_601_CY;
2419 row1[2-bIdx] = saturate_cast<uchar>((y00 + ruv) >> ITUR_BT_601_SHIFT);
2420 row1[1] = saturate_cast<uchar>((y00 + guv) >> ITUR_BT_601_SHIFT);
2421 row1[bIdx] = saturate_cast<uchar>((y00 + buv) >> ITUR_BT_601_SHIFT);
2422 row1[3] = uchar(0xff);
2424 int y01 = std::max(0, int(y1[2 * i + 1]) - 16) * ITUR_BT_601_CY;
2425 row1[6-bIdx] = saturate_cast<uchar>((y01 + ruv) >> ITUR_BT_601_SHIFT);
2426 row1[5] = saturate_cast<uchar>((y01 + guv) >> ITUR_BT_601_SHIFT);
2427 row1[4+bIdx] = saturate_cast<uchar>((y01 + buv) >> ITUR_BT_601_SHIFT);
2428 row1[7] = uchar(0xff);
2430 int y10 = std::max(0, int(y2[2 * i]) - 16) * ITUR_BT_601_CY;
2431 row2[2-bIdx] = saturate_cast<uchar>((y10 + ruv) >> ITUR_BT_601_SHIFT);
2432 row2[1] = saturate_cast<uchar>((y10 + guv) >> ITUR_BT_601_SHIFT);
2433 row2[bIdx] = saturate_cast<uchar>((y10 + buv) >> ITUR_BT_601_SHIFT);
2434 row2[3] = uchar(0xff);
2436 int y11 = std::max(0, int(y2[2 * i + 1]) - 16) * ITUR_BT_601_CY;
2437 row2[6-bIdx] = saturate_cast<uchar>((y11 + ruv) >> ITUR_BT_601_SHIFT);
2438 row2[5] = saturate_cast<uchar>((y11 + guv) >> ITUR_BT_601_SHIFT);
2439 row2[4+bIdx] = saturate_cast<uchar>((y11 + buv) >> ITUR_BT_601_SHIFT);
2440 row2[7] = uchar(0xff);
2446 #define MIN_SIZE_FOR_PARALLEL_YUV420_CONVERSION (320*240)
2448 template<int bIdx, int uIdx>
2449 inline void cvtYUV420sp2RGB(Mat& _dst, int _stride, const uchar* _y1, const uchar* _uv)
2451 YUV420sp2RGB888Invoker<bIdx, uIdx> converter(&_dst, _stride, _y1, _uv);
2452 if (_dst.total() >= MIN_SIZE_FOR_PARALLEL_YUV420_CONVERSION)
2453 parallel_for_(Range(0, _dst.rows/2), converter);
2455 converter(Range(0, _dst.rows/2));
2458 template<int bIdx, int uIdx>
2459 inline void cvtYUV420sp2RGBA(Mat& _dst, int _stride, const uchar* _y1, const uchar* _uv)
2461 YUV420sp2RGBA8888Invoker<bIdx, uIdx> converter(&_dst, _stride, _y1, _uv);
2462 if (_dst.total() >= MIN_SIZE_FOR_PARALLEL_YUV420_CONVERSION)
2463 parallel_for_(Range(0, _dst.rows/2), converter);
2465 converter(Range(0, _dst.rows/2));
2469 inline void cvtYUV420p2RGB(Mat& _dst, int _stride, const uchar* _y1, const uchar* _u, const uchar* _v, int ustepIdx, int vstepIdx)
2471 YUV420p2RGB888Invoker<bIdx> converter(&_dst, _stride, _y1, _u, _v, ustepIdx, vstepIdx);
2472 if (_dst.total() >= MIN_SIZE_FOR_PARALLEL_YUV420_CONVERSION)
2473 parallel_for_(Range(0, _dst.rows/2), converter);
2475 converter(Range(0, _dst.rows/2));
2479 inline void cvtYUV420p2RGBA(Mat& _dst, int _stride, const uchar* _y1, const uchar* _u, const uchar* _v, int ustepIdx, int vstepIdx)
2481 YUV420p2RGBA8888Invoker<bIdx> converter(&_dst, _stride, _y1, _u, _v, ustepIdx, vstepIdx);
2482 if (_dst.total() >= MIN_SIZE_FOR_PARALLEL_YUV420_CONVERSION)
2483 parallel_for_(Range(0, _dst.rows/2), converter);
2485 converter(Range(0, _dst.rows/2));
2488 ///////////////////////////////////// RGB -> YUV420p /////////////////////////////////////
2491 struct RGB888toYUV420pInvoker: public ParallelLoopBody
2493 RGB888toYUV420pInvoker( const Mat& src, Mat* dst, const int uIdx )
2498 void operator()(const Range& rowRange) const
2500 const int w = src_.cols;
2501 const int h = src_.rows;
2503 const int cn = src_.channels();
2504 for( int i = rowRange.start; i < rowRange.end; i++ )
2506 const uchar* row0 = src_.ptr<uchar>(2 * i);
2507 const uchar* row1 = src_.ptr<uchar>(2 * i + 1);
2509 uchar* y = dst_->ptr<uchar>(2*i);
2510 uchar* u = dst_->ptr<uchar>(h + i/2) + (i % 2) * (w/2);
2511 uchar* v = dst_->ptr<uchar>(h + (i + h/2)/2) + ((i + h/2) % 2) * (w/2);
2512 if( uIdx_ == 2 ) std::swap(u, v);
2514 for( int j = 0, k = 0; j < w * cn; j += 2 * cn, k++ )
2516 int r00 = row0[2-bIdx + j]; int g00 = row0[1 + j]; int b00 = row0[bIdx + j];
2517 int r01 = row0[2-bIdx + cn + j]; int g01 = row0[1 + cn + j]; int b01 = row0[bIdx + cn + j];
2518 int r10 = row1[2-bIdx + j]; int g10 = row1[1 + j]; int b10 = row1[bIdx + j];
2519 int r11 = row1[2-bIdx + cn + j]; int g11 = row1[1 + cn + j]; int b11 = row1[bIdx + cn + j];
2521 const int shifted16 = (16 << ITUR_BT_601_SHIFT);
2522 const int halfShift = (1 << (ITUR_BT_601_SHIFT - 1));
2523 int y00 = ITUR_BT_601_CRY * r00 + ITUR_BT_601_CGY * g00 + ITUR_BT_601_CBY * b00 + halfShift + shifted16;
2524 int y01 = ITUR_BT_601_CRY * r01 + ITUR_BT_601_CGY * g01 + ITUR_BT_601_CBY * b01 + halfShift + shifted16;
2525 int y10 = ITUR_BT_601_CRY * r10 + ITUR_BT_601_CGY * g10 + ITUR_BT_601_CBY * b10 + halfShift + shifted16;
2526 int y11 = ITUR_BT_601_CRY * r11 + ITUR_BT_601_CGY * g11 + ITUR_BT_601_CBY * b11 + halfShift + shifted16;
2528 y[2*k + 0] = saturate_cast<uchar>(y00 >> ITUR_BT_601_SHIFT);
2529 y[2*k + 1] = saturate_cast<uchar>(y01 >> ITUR_BT_601_SHIFT);
2530 y[2*k + dst_->step + 0] = saturate_cast<uchar>(y10 >> ITUR_BT_601_SHIFT);
2531 y[2*k + dst_->step + 1] = saturate_cast<uchar>(y11 >> ITUR_BT_601_SHIFT);
2533 const int shifted128 = (128 << ITUR_BT_601_SHIFT);
2534 int u00 = ITUR_BT_601_CRU * r00 + ITUR_BT_601_CGU * g00 + ITUR_BT_601_CBU * b00 + halfShift + shifted128;
2535 int v00 = ITUR_BT_601_CBU * r00 + ITUR_BT_601_CGV * g00 + ITUR_BT_601_CBV * b00 + halfShift + shifted128;
2537 u[k] = saturate_cast<uchar>(u00 >> ITUR_BT_601_SHIFT);
2538 v[k] = saturate_cast<uchar>(v00 >> ITUR_BT_601_SHIFT);
2543 static bool isFit( const Mat& src )
2545 return (src.total() >= 320*240);
2549 RGB888toYUV420pInvoker& operator=(const RGB888toYUV420pInvoker&);
2556 template<int bIdx, int uIdx>
2557 static void cvtRGBtoYUV420p(const Mat& src, Mat& dst)
2559 RGB888toYUV420pInvoker<bIdx> colorConverter(src, &dst, uIdx);
2560 if( RGB888toYUV420pInvoker<bIdx>::isFit(src) )
2561 parallel_for_(Range(0, src.rows/2), colorConverter);
2563 colorConverter(Range(0, src.rows/2));
2566 ///////////////////////////////////// YUV422 -> RGB /////////////////////////////////////
2568 template<int bIdx, int uIdx, int yIdx>
2569 struct YUV422toRGB888Invoker : ParallelLoopBody
2575 YUV422toRGB888Invoker(Mat* _dst, int _stride, const uchar* _yuv)
2576 : dst(_dst), src(_yuv), width(_dst->cols), stride(_stride) {}
2578 void operator()(const Range& range) const
2580 int rangeBegin = range.start;
2581 int rangeEnd = range.end;
2583 const int uidx = 1 - yIdx + uIdx * 2;
2584 const int vidx = (2 + uidx) % 4;
2585 const uchar* yuv_src = src + rangeBegin * stride;
2587 for (int j = rangeBegin; j < rangeEnd; j++, yuv_src += stride)
2589 uchar* row = dst->ptr<uchar>(j);
2591 for (int i = 0; i < 2 * width; i += 4, row += 6)
2593 int u = int(yuv_src[i + uidx]) - 128;
2594 int v = int(yuv_src[i + vidx]) - 128;
2596 int ruv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVR * v;
2597 int guv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVG * v + ITUR_BT_601_CUG * u;
2598 int buv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CUB * u;
2600 int y00 = std::max(0, int(yuv_src[i + yIdx]) - 16) * ITUR_BT_601_CY;
2601 row[2-bIdx] = saturate_cast<uchar>((y00 + ruv) >> ITUR_BT_601_SHIFT);
2602 row[1] = saturate_cast<uchar>((y00 + guv) >> ITUR_BT_601_SHIFT);
2603 row[bIdx] = saturate_cast<uchar>((y00 + buv) >> ITUR_BT_601_SHIFT);
2605 int y01 = std::max(0, int(yuv_src[i + yIdx + 2]) - 16) * ITUR_BT_601_CY;
2606 row[5-bIdx] = saturate_cast<uchar>((y01 + ruv) >> ITUR_BT_601_SHIFT);
2607 row[4] = saturate_cast<uchar>((y01 + guv) >> ITUR_BT_601_SHIFT);
2608 row[3+bIdx] = saturate_cast<uchar>((y01 + buv) >> ITUR_BT_601_SHIFT);
2614 template<int bIdx, int uIdx, int yIdx>
2615 struct YUV422toRGBA8888Invoker : ParallelLoopBody
2621 YUV422toRGBA8888Invoker(Mat* _dst, int _stride, const uchar* _yuv)
2622 : dst(_dst), src(_yuv), width(_dst->cols), stride(_stride) {}
2624 void operator()(const Range& range) const
2626 int rangeBegin = range.start;
2627 int rangeEnd = range.end;
2629 const int uidx = 1 - yIdx + uIdx * 2;
2630 const int vidx = (2 + uidx) % 4;
2631 const uchar* yuv_src = src + rangeBegin * stride;
2633 for (int j = rangeBegin; j < rangeEnd; j++, yuv_src += stride)
2635 uchar* row = dst->ptr<uchar>(j);
2637 for (int i = 0; i < 2 * width; i += 4, row += 8)
2639 int u = int(yuv_src[i + uidx]) - 128;
2640 int v = int(yuv_src[i + vidx]) - 128;
2642 int ruv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVR * v;
2643 int guv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVG * v + ITUR_BT_601_CUG * u;
2644 int buv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CUB * u;
2646 int y00 = std::max(0, int(yuv_src[i + yIdx]) - 16) * ITUR_BT_601_CY;
2647 row[2-bIdx] = saturate_cast<uchar>((y00 + ruv) >> ITUR_BT_601_SHIFT);
2648 row[1] = saturate_cast<uchar>((y00 + guv) >> ITUR_BT_601_SHIFT);
2649 row[bIdx] = saturate_cast<uchar>((y00 + buv) >> ITUR_BT_601_SHIFT);
2650 row[3] = uchar(0xff);
2652 int y01 = std::max(0, int(yuv_src[i + yIdx + 2]) - 16) * ITUR_BT_601_CY;
2653 row[6-bIdx] = saturate_cast<uchar>((y01 + ruv) >> ITUR_BT_601_SHIFT);
2654 row[5] = saturate_cast<uchar>((y01 + guv) >> ITUR_BT_601_SHIFT);
2655 row[4+bIdx] = saturate_cast<uchar>((y01 + buv) >> ITUR_BT_601_SHIFT);
2656 row[7] = uchar(0xff);
2662 #define MIN_SIZE_FOR_PARALLEL_YUV422_CONVERSION (320*240)
2664 template<int bIdx, int uIdx, int yIdx>
2665 inline void cvtYUV422toRGB(Mat& _dst, int _stride, const uchar* _yuv)
2667 YUV422toRGB888Invoker<bIdx, uIdx, yIdx> converter(&_dst, _stride, _yuv);
2668 if (_dst.total() >= MIN_SIZE_FOR_PARALLEL_YUV422_CONVERSION)
2669 parallel_for_(Range(0, _dst.rows), converter);
2671 converter(Range(0, _dst.rows));
2674 template<int bIdx, int uIdx, int yIdx>
2675 inline void cvtYUV422toRGBA(Mat& _dst, int _stride, const uchar* _yuv)
2677 YUV422toRGBA8888Invoker<bIdx, uIdx, yIdx> converter(&_dst, _stride, _yuv);
2678 if (_dst.total() >= MIN_SIZE_FOR_PARALLEL_YUV422_CONVERSION)
2679 parallel_for_(Range(0, _dst.rows), converter);
2681 converter(Range(0, _dst.rows));
2684 /////////////////////////// RGBA <-> mRGBA (alpha premultiplied) //////////////
2686 template<typename _Tp>
2689 typedef _Tp channel_type;
2691 void operator()(const _Tp* src, _Tp* dst, int n) const
2693 _Tp max_val = ColorChannel<_Tp>::max();
2694 _Tp half_val = ColorChannel<_Tp>::half();
2695 for( int i = 0; i < n; i++ )
2702 *dst++ = (v0 * v3 + half_val) / max_val;
2703 *dst++ = (v1 * v3 + half_val) / max_val;
2704 *dst++ = (v2 * v3 + half_val) / max_val;
2711 template<typename _Tp>
2714 typedef _Tp channel_type;
2716 void operator()(const _Tp* src, _Tp* dst, int n) const
2718 _Tp max_val = ColorChannel<_Tp>::max();
2719 for( int i = 0; i < n; i++ )
2725 _Tp v3_half = v3 / 2;
2727 *dst++ = (v3==0)? 0 : (v0 * max_val + v3_half) / v3;
2728 *dst++ = (v3==0)? 0 : (v1 * max_val + v3_half) / v3;
2729 *dst++ = (v3==0)? 0 : (v2 * max_val + v3_half) / v3;
2737 static bool ocl_cvtColor( InputArray _src, OutputArray _dst, int code, int dcn )
2740 UMat src = _src.getUMat(), dst;
2741 Size sz = src.size(), dstSz = sz;
2742 int scn = src.channels(), depth = src.depth(), bidx;
2743 int dims = 2, stripeSize = 1;
2746 if (depth != CV_8U && depth != CV_16U && depth != CV_32F)
2749 ocl::Device dev = ocl::Device::getDefault();
2750 int pxPerWIy = dev.isIntel() && (dev.type() & ocl::Device::TYPE_GPU) ? 4 : 1;
2752 size_t globalsize[] = { src.cols, (src.rows + pxPerWIy - 1) / pxPerWIy };
2753 cv::String opts = format("-D depth=%d -D scn=%d -D PIX_PER_WI_Y=%d ",
2754 depth, scn, pxPerWIy);
2758 case COLOR_BGR2BGRA: case COLOR_RGB2BGRA: case COLOR_BGRA2BGR:
2759 case COLOR_RGBA2BGR: case COLOR_RGB2BGR: case COLOR_BGRA2RGBA:
2761 CV_Assert(scn == 3 || scn == 4);
2762 dcn = code == COLOR_BGR2BGRA || code == COLOR_RGB2BGRA || code == COLOR_BGRA2RGBA ? 4 : 3;
2763 bool reverse = !(code == COLOR_BGR2BGRA || code == COLOR_BGRA2BGR);
2764 k.create("RGB", ocl::imgproc::cvtcolor_oclsrc,
2765 opts + format("-D dcn=%d -D bidx=0 -D %s", dcn,
2766 reverse ? "REVERSE" : "ORDER"));
2769 case COLOR_BGR5652BGR: case COLOR_BGR5552BGR: case COLOR_BGR5652RGB: case COLOR_BGR5552RGB:
2770 case COLOR_BGR5652BGRA: case COLOR_BGR5552BGRA: case COLOR_BGR5652RGBA: case COLOR_BGR5552RGBA:
2772 dcn = code == COLOR_BGR5652BGRA || code == COLOR_BGR5552BGRA || code == COLOR_BGR5652RGBA || code == COLOR_BGR5552RGBA ? 4 : 3;
2773 CV_Assert((dcn == 3 || dcn == 4) && scn == 2 && depth == CV_8U);
2774 bidx = code == COLOR_BGR5652BGR || code == COLOR_BGR5552BGR ||
2775 code == COLOR_BGR5652BGRA || code == COLOR_BGR5552BGRA ? 0 : 2;
2776 int greenbits = code == COLOR_BGR5652BGR || code == COLOR_BGR5652RGB ||
2777 code == COLOR_BGR5652BGRA || code == COLOR_BGR5652RGBA ? 6 : 5;
2778 k.create("RGB5x52RGB", ocl::imgproc::cvtcolor_oclsrc,
2779 opts + format("-D dcn=%d -D bidx=%d -D greenbits=%d", dcn, bidx, greenbits));
2782 case COLOR_BGR2BGR565: case COLOR_BGR2BGR555: case COLOR_RGB2BGR565: case COLOR_RGB2BGR555:
2783 case COLOR_BGRA2BGR565: case COLOR_BGRA2BGR555: case COLOR_RGBA2BGR565: case COLOR_RGBA2BGR555:
2785 CV_Assert((scn == 3 || scn == 4) && depth == CV_8U );
2786 bidx = code == COLOR_BGR2BGR565 || code == COLOR_BGR2BGR555 ||
2787 code == COLOR_BGRA2BGR565 || code == COLOR_BGRA2BGR555 ? 0 : 2;
2788 int greenbits = code == COLOR_BGR2BGR565 || code == COLOR_RGB2BGR565 ||
2789 code == COLOR_BGRA2BGR565 || code == COLOR_RGBA2BGR565 ? 6 : 5;
2791 k.create("RGB2RGB5x5", ocl::imgproc::cvtcolor_oclsrc,
2792 opts + format("-D dcn=2 -D bidx=%d -D greenbits=%d", bidx, greenbits));
2795 case COLOR_BGR5652GRAY: case COLOR_BGR5552GRAY:
2797 CV_Assert(scn == 2 && depth == CV_8U);
2799 int greenbits = code == COLOR_BGR5652GRAY ? 6 : 5;
2800 k.create("BGR5x52Gray", ocl::imgproc::cvtcolor_oclsrc,
2801 opts + format("-D dcn=1 -D bidx=0 -D greenbits=%d", greenbits));
2804 case COLOR_GRAY2BGR565: case COLOR_GRAY2BGR555:
2806 CV_Assert(scn == 1 && depth == CV_8U);
2808 int greenbits = code == COLOR_GRAY2BGR565 ? 6 : 5;
2809 k.create("Gray2BGR5x5", ocl::imgproc::cvtcolor_oclsrc,
2810 opts + format("-D dcn=2 -D bidx=0 -D greenbits=%d", greenbits));
2813 case COLOR_BGR2GRAY: case COLOR_BGRA2GRAY:
2814 case COLOR_RGB2GRAY: case COLOR_RGBA2GRAY:
2816 CV_Assert(scn == 3 || scn == 4);
2817 bidx = code == COLOR_BGR2GRAY || code == COLOR_BGRA2GRAY ? 0 : 2;
2819 k.create("RGB2Gray", ocl::imgproc::cvtcolor_oclsrc,
2820 opts + format("-D dcn=1 -D bidx=%d -D STRIPE_SIZE=%d",
2822 globalsize[0] = (src.cols + stripeSize-1)/stripeSize;
2825 case COLOR_GRAY2BGR:
2826 case COLOR_GRAY2BGRA:
2828 CV_Assert(scn == 1);
2829 dcn = code == COLOR_GRAY2BGRA ? 4 : 3;
2830 k.create("Gray2RGB", ocl::imgproc::cvtcolor_oclsrc,
2831 opts + format("-D bidx=0 -D dcn=%d", dcn));
2837 CV_Assert(scn == 3 || scn == 4);
2838 bidx = code == COLOR_RGB2YUV ? 0 : 2;
2840 k.create("RGB2YUV", ocl::imgproc::cvtcolor_oclsrc,
2841 opts + format("-D dcn=3 -D bidx=%d", bidx));
2847 if(dcn < 0) dcn = 3;
2848 CV_Assert(dcn == 3 || dcn == 4);
2849 bidx = code == COLOR_YUV2RGB ? 0 : 2;
2850 k.create("YUV2RGB", ocl::imgproc::cvtcolor_oclsrc,
2851 opts + format("-D dcn=%d -D bidx=%d", dcn, bidx));
2854 case COLOR_YUV2RGB_NV12: case COLOR_YUV2BGR_NV12:
2855 case COLOR_YUV2RGBA_NV12: case COLOR_YUV2BGRA_NV12:
2857 CV_Assert( scn == 1 );
2858 CV_Assert( sz.width % 2 == 0 && sz.height % 3 == 0 && depth == CV_8U );
2859 dcn = code == COLOR_YUV2BGRA_NV12 || code == COLOR_YUV2RGBA_NV12 ? 4 : 3;
2860 bidx = code == COLOR_YUV2BGRA_NV12 || code == COLOR_YUV2BGR_NV12 ? 0 : 2;
2862 dstSz = Size(sz.width, sz.height * 2 / 3);
2863 k.create("YUV2RGB_NV12", ocl::imgproc::cvtcolor_oclsrc,
2864 opts + format("-D dcn=%d -D bidx=%d", dcn, bidx));
2867 case COLOR_BGR2YCrCb:
2868 case COLOR_RGB2YCrCb:
2870 CV_Assert(scn == 3 || scn == 4);
2871 bidx = code == COLOR_BGR2YCrCb ? 0 : 2;
2873 k.create("RGB2YCrCb", ocl::imgproc::cvtcolor_oclsrc,
2874 opts + format("-D dcn=3 -D bidx=%d", bidx));
2877 case COLOR_YCrCb2BGR:
2878 case COLOR_YCrCb2RGB:
2882 CV_Assert(scn == 3 && (dcn == 3 || dcn == 4));
2883 bidx = code == COLOR_YCrCb2BGR ? 0 : 2;
2884 k.create("YCrCb2RGB", ocl::imgproc::cvtcolor_oclsrc,
2885 opts + format("-D dcn=%d -D bidx=%d", dcn, bidx));
2888 case COLOR_BGR2XYZ: case COLOR_RGB2XYZ:
2890 CV_Assert(scn == 3 || scn == 4);
2891 bidx = code == COLOR_BGR2XYZ ? 0 : 2;
2894 if (depth == CV_32F)
2898 0.412453f, 0.357580f, 0.180423f,
2899 0.212671f, 0.715160f, 0.072169f,
2900 0.019334f, 0.119193f, 0.950227f
2904 std::swap(coeffs[0], coeffs[2]);
2905 std::swap(coeffs[3], coeffs[5]);
2906 std::swap(coeffs[6], coeffs[8]);
2908 Mat(1, 9, CV_32FC1, &coeffs[0]).copyTo(c);
2920 std::swap(coeffs[0], coeffs[2]);
2921 std::swap(coeffs[3], coeffs[5]);
2922 std::swap(coeffs[6], coeffs[8]);
2924 Mat(1, 9, CV_32SC1, &coeffs[0]).copyTo(c);
2927 _dst.create(dstSz, CV_MAKETYPE(depth, 3));
2928 dst = _dst.getUMat();
2930 k.create("RGB2XYZ", ocl::imgproc::cvtcolor_oclsrc,
2931 opts + format("-D dcn=3 -D bidx=%d", bidx));
2934 k.args(ocl::KernelArg::ReadOnlyNoSize(src), ocl::KernelArg::WriteOnly(dst), ocl::KernelArg::PtrReadOnly(c));
2935 return k.run(2, globalsize, 0, false);
2937 case COLOR_XYZ2BGR: case COLOR_XYZ2RGB:
2941 CV_Assert(scn == 3 && (dcn == 3 || dcn == 4));
2942 bidx = code == COLOR_XYZ2BGR ? 0 : 2;
2945 if (depth == CV_32F)
2949 3.240479f, -1.53715f, -0.498535f,
2950 -0.969256f, 1.875991f, 0.041556f,
2951 0.055648f, -0.204043f, 1.057311f
2955 std::swap(coeffs[0], coeffs[6]);
2956 std::swap(coeffs[1], coeffs[7]);
2957 std::swap(coeffs[2], coeffs[8]);
2959 Mat(1, 9, CV_32FC1, &coeffs[0]).copyTo(c);
2965 13273, -6296, -2042,
2971 std::swap(coeffs[0], coeffs[6]);
2972 std::swap(coeffs[1], coeffs[7]);
2973 std::swap(coeffs[2], coeffs[8]);
2975 Mat(1, 9, CV_32SC1, &coeffs[0]).copyTo(c);
2978 _dst.create(dstSz, CV_MAKETYPE(depth, dcn));
2979 dst = _dst.getUMat();
2981 k.create("XYZ2RGB", ocl::imgproc::cvtcolor_oclsrc,
2982 opts + format("-D dcn=%d -D bidx=%d", dcn, bidx));
2985 k.args(ocl::KernelArg::ReadOnlyNoSize(src), ocl::KernelArg::WriteOnly(dst), ocl::KernelArg::PtrReadOnly(c));
2986 return k.run(2, globalsize, 0, false);
2988 case COLOR_BGR2HSV: case COLOR_RGB2HSV: case COLOR_BGR2HSV_FULL: case COLOR_RGB2HSV_FULL:
2989 case COLOR_BGR2HLS: case COLOR_RGB2HLS: case COLOR_BGR2HLS_FULL: case COLOR_RGB2HLS_FULL:
2991 CV_Assert((scn == 3 || scn == 4) && (depth == CV_8U || depth == CV_32F));
2992 bidx = code == COLOR_BGR2HSV || code == COLOR_BGR2HLS ||
2993 code == COLOR_BGR2HSV_FULL || code == COLOR_BGR2HLS_FULL ? 0 : 2;
2994 int hrange = depth == CV_32F ? 360 : code == COLOR_BGR2HSV || code == COLOR_RGB2HSV ||
2995 code == COLOR_BGR2HLS || code == COLOR_RGB2HLS ? 180 : 256;
2996 bool is_hsv = code == COLOR_BGR2HSV || code == COLOR_RGB2HSV || code == COLOR_BGR2HSV_FULL || code == COLOR_RGB2HSV_FULL;
2997 String kernelName = String("RGB2") + (is_hsv ? "HSV" : "HLS");
3000 if (is_hsv && depth == CV_8U)
3002 static UMat sdiv_data;
3003 static UMat hdiv_data180;
3004 static UMat hdiv_data256;
3005 static int sdiv_table[256];
3006 static int hdiv_table180[256];
3007 static int hdiv_table256[256];
3008 static volatile bool initialized180 = false, initialized256 = false;
3009 volatile bool & initialized = hrange == 180 ? initialized180 : initialized256;
3013 int * const hdiv_table = hrange == 180 ? hdiv_table180 : hdiv_table256, hsv_shift = 12;
3014 UMat & hdiv_data = hrange == 180 ? hdiv_data180 : hdiv_data256;
3016 sdiv_table[0] = hdiv_table180[0] = hdiv_table256[0] = 0;
3018 int v = 255 << hsv_shift;
3019 if (!initialized180 && !initialized256)
3021 for(int i = 1; i < 256; i++ )
3022 sdiv_table[i] = saturate_cast<int>(v/(1.*i));
3023 Mat(1, 256, CV_32SC1, sdiv_table).copyTo(sdiv_data);
3026 v = hrange << hsv_shift;
3027 for (int i = 1; i < 256; i++ )
3028 hdiv_table[i] = saturate_cast<int>(v/(6.*i));
3030 Mat(1, 256, CV_32SC1, hdiv_table).copyTo(hdiv_data);
3034 _dst.create(dstSz, CV_8UC3);
3035 dst = _dst.getUMat();
3037 k.create("RGB2HSV", ocl::imgproc::cvtcolor_oclsrc,
3038 opts + format("-D hrange=%d -D bidx=%d -D dcn=3",
3043 k.args(ocl::KernelArg::ReadOnlyNoSize(src), ocl::KernelArg::WriteOnly(dst),
3044 ocl::KernelArg::PtrReadOnly(sdiv_data), hrange == 256 ? ocl::KernelArg::PtrReadOnly(hdiv_data256) :
3045 ocl::KernelArg::PtrReadOnly(hdiv_data180));
3047 return k.run(2, globalsize, NULL, false);
3050 k.create(kernelName.c_str(), ocl::imgproc::cvtcolor_oclsrc,
3051 opts + format("-D hscale=%ff -D bidx=%d -D dcn=3",
3052 hrange*(1.f/360.f), bidx));
3055 case COLOR_HSV2BGR: case COLOR_HSV2RGB: case COLOR_HSV2BGR_FULL: case COLOR_HSV2RGB_FULL:
3056 case COLOR_HLS2BGR: case COLOR_HLS2RGB: case COLOR_HLS2BGR_FULL: case COLOR_HLS2RGB_FULL:
3060 CV_Assert(scn == 3 && (dcn == 3 || dcn == 4) && (depth == CV_8U || depth == CV_32F));
3061 bidx = code == COLOR_HSV2BGR || code == COLOR_HLS2BGR ||
3062 code == COLOR_HSV2BGR_FULL || code == COLOR_HLS2BGR_FULL ? 0 : 2;
3063 int hrange = depth == CV_32F ? 360 : code == COLOR_HSV2BGR || code == COLOR_HSV2RGB ||
3064 code == COLOR_HLS2BGR || code == COLOR_HLS2RGB ? 180 : 255;
3065 bool is_hsv = code == COLOR_HSV2BGR || code == COLOR_HSV2RGB ||
3066 code == COLOR_HSV2BGR_FULL || code == COLOR_HSV2RGB_FULL;
3068 String kernelName = String(is_hsv ? "HSV" : "HLS") + "2RGB";
3069 k.create(kernelName.c_str(), ocl::imgproc::cvtcolor_oclsrc,
3070 opts + format("-D dcn=%d -D bidx=%d -D hrange=%d -D hscale=%ff",
3071 dcn, bidx, hrange, 6.f/hrange));
3074 case COLOR_RGBA2mRGBA: case COLOR_mRGBA2RGBA:
3076 CV_Assert(scn == 4 && depth == CV_8U);
3079 k.create(code == COLOR_RGBA2mRGBA ? "RGBA2mRGBA" : "mRGBA2RGBA", ocl::imgproc::cvtcolor_oclsrc,
3080 opts + "-D dcn=4 -D bidx=3");
3083 case CV_BGR2Lab: case CV_RGB2Lab: case CV_LBGR2Lab: case CV_LRGB2Lab:
3084 case CV_BGR2Luv: case CV_RGB2Luv: case CV_LBGR2Luv: case CV_LRGB2Luv:
3086 CV_Assert( (scn == 3 || scn == 4) && (depth == CV_8U || depth == CV_32F) );
3088 bidx = code == CV_BGR2Lab || code == CV_LBGR2Lab || code == CV_BGR2Luv || code == CV_LBGR2Luv ? 0 : 2;
3089 bool srgb = code == CV_BGR2Lab || code == CV_RGB2Lab || code == CV_RGB2Luv || code == CV_BGR2Luv;
3090 bool lab = code == CV_BGR2Lab || code == CV_RGB2Lab || code == CV_LBGR2Lab || code == CV_LRGB2Lab;
3094 k.create(format("BGR2%s", lab ? "Lab" : "Luv").c_str(),
3095 ocl::imgproc::cvtcolor_oclsrc,
3096 opts + format("-D dcn=%d -D bidx=%d%s",
3097 dcn, bidx, srgb ? " -D SRGB" : ""));
3103 _dst.create(dstSz, CV_MAKETYPE(depth, dcn));
3104 dst = _dst.getUMat();
3106 ocl::KernelArg srcarg = ocl::KernelArg::ReadOnlyNoSize(src),
3107 dstarg = ocl::KernelArg::WriteOnly(dst);
3109 if (depth == CV_8U && lab)
3111 static UMat usRGBGammaTab, ulinearGammaTab, uLabCbrtTab, ucoeffs;
3113 if (srgb && usRGBGammaTab.empty())
3114 Mat(1, 256, CV_16UC1, sRGBGammaTab_b).copyTo(usRGBGammaTab);
3115 else if (ulinearGammaTab.empty())
3116 Mat(1, 256, CV_16UC1, linearGammaTab_b).copyTo(ulinearGammaTab);
3117 if (uLabCbrtTab.empty())
3118 Mat(1, LAB_CBRT_TAB_SIZE_B, CV_16UC1, LabCbrtTab_b).copyTo(uLabCbrtTab);
3122 const float * const _coeffs = sRGB2XYZ_D65, * const _whitept = D65;
3123 const float scale[] =
3125 (1 << lab_shift)/_whitept[0],
3126 (float)(1 << lab_shift),
3127 (1 << lab_shift)/_whitept[2]
3130 for (int i = 0; i < 3; i++ )
3132 coeffs[i*3+(bidx^2)] = cvRound(_coeffs[i*3]*scale[i]);
3133 coeffs[i*3+1] = cvRound(_coeffs[i*3+1]*scale[i]);
3134 coeffs[i*3+bidx] = cvRound(_coeffs[i*3+2]*scale[i]);
3136 CV_Assert( coeffs[i] >= 0 && coeffs[i*3+1] >= 0 && coeffs[i*3+2] >= 0 &&
3137 coeffs[i*3] + coeffs[i*3+1] + coeffs[i*3+2] < 2*(1 << lab_shift) );
3139 Mat(1, 9, CV_32SC1, coeffs).copyTo(ucoeffs);
3142 const int Lscale = (116*255+50)/100;
3143 const int Lshift = -((16*255*(1 << lab_shift2) + 50)/100);
3145 k.args(srcarg, dstarg,
3146 ocl::KernelArg::PtrReadOnly(srgb ? usRGBGammaTab : ulinearGammaTab),
3147 ocl::KernelArg::PtrReadOnly(uLabCbrtTab), ocl::KernelArg::PtrReadOnly(ucoeffs),
3152 static UMat usRGBGammaTab, ucoeffs, uLabCbrtTab;
3154 if (srgb && usRGBGammaTab.empty())
3155 Mat(1, GAMMA_TAB_SIZE * 4, CV_32FC1, sRGBGammaTab).copyTo(usRGBGammaTab);
3156 if (!lab && uLabCbrtTab.empty())
3157 Mat(1, LAB_CBRT_TAB_SIZE * 4, CV_32FC1, LabCbrtTab).copyTo(uLabCbrtTab);
3161 const float * const _coeffs = sRGB2XYZ_D65, * const _whitept = D65;
3162 float scale[] = { 1.0f / _whitept[0], 1.0f, 1.0f / _whitept[2] };
3164 for (int i = 0; i < 3; i++)
3167 coeffs[j + (bidx ^ 2)] = _coeffs[j] * (lab ? scale[i] : 1);
3168 coeffs[j + 1] = _coeffs[j + 1] * (lab ? scale[i] : 1);
3169 coeffs[j + bidx] = _coeffs[j + 2] * (lab ? scale[i] : 1);
3171 CV_Assert( coeffs[j] >= 0 && coeffs[j + 1] >= 0 && coeffs[j + 2] >= 0 &&
3172 coeffs[j] + coeffs[j + 1] + coeffs[j + 2] < 1.5f*(lab ? LabCbrtTabScale : 1) );
3175 float d = 1.f/(_whitept[0] + _whitept[1]*15 + _whitept[2]*3);
3176 un = 13*4*_whitept[0]*d;
3177 vn = 13*9*_whitept[1]*d;
3179 Mat(1, 9, CV_32FC1, coeffs).copyTo(ucoeffs);
3182 float _1_3 = 1.0f / 3.0f, _a = 16.0f / 116.0f;
3183 ocl::KernelArg ucoeffsarg = ocl::KernelArg::PtrReadOnly(ucoeffs);
3188 k.args(srcarg, dstarg, ocl::KernelArg::PtrReadOnly(usRGBGammaTab),
3189 ucoeffsarg, _1_3, _a);
3191 k.args(srcarg, dstarg, ucoeffsarg, _1_3, _a);
3195 ocl::KernelArg LabCbrtTabarg = ocl::KernelArg::PtrReadOnly(uLabCbrtTab);
3197 k.args(srcarg, dstarg, ocl::KernelArg::PtrReadOnly(usRGBGammaTab),
3198 LabCbrtTabarg, ucoeffsarg, un, vn);
3200 k.args(srcarg, dstarg, LabCbrtTabarg, ucoeffsarg, un, vn);
3204 return k.run(dims, globalsize, NULL, false);
3206 case CV_Lab2BGR: case CV_Lab2RGB: case CV_Lab2LBGR: case CV_Lab2LRGB:
3207 case CV_Luv2BGR: case CV_Luv2RGB: case CV_Luv2LBGR: case CV_Luv2LRGB:
3211 CV_Assert( scn == 3 && (dcn == 3 || dcn == 4) && (depth == CV_8U || depth == CV_32F) );
3213 bidx = code == CV_Lab2BGR || code == CV_Lab2LBGR || code == CV_Luv2BGR || code == CV_Luv2LBGR ? 0 : 2;
3214 bool srgb = code == CV_Lab2BGR || code == CV_Lab2RGB || code == CV_Luv2BGR || code == CV_Luv2RGB;
3215 bool lab = code == CV_Lab2BGR || code == CV_Lab2RGB || code == CV_Lab2LBGR || code == CV_Lab2LRGB;
3218 k.create(format("%s2BGR", lab ? "Lab" : "Luv").c_str(),
3219 ocl::imgproc::cvtcolor_oclsrc,
3220 opts + format("-D dcn=%d -D bidx=%d%s",
3221 dcn, bidx, srgb ? " -D SRGB" : ""));
3226 static UMat ucoeffs, usRGBInvGammaTab;
3228 if (srgb && usRGBInvGammaTab.empty())
3229 Mat(1, GAMMA_TAB_SIZE*4, CV_32FC1, sRGBInvGammaTab).copyTo(usRGBInvGammaTab);
3233 const float * const _coeffs = XYZ2sRGB_D65, * const _whitept = D65;
3235 for( int i = 0; i < 3; i++ )
3237 coeffs[i+(bidx^2)*3] = _coeffs[i] * (lab ? _whitept[i] : 1);
3238 coeffs[i+3] = _coeffs[i+3] * (lab ? _whitept[i] : 1);
3239 coeffs[i+bidx*3] = _coeffs[i+6] * (lab ? _whitept[i] : 1);
3242 float d = 1.f/(_whitept[0] + _whitept[1]*15 + _whitept[2]*3);
3243 un = 4*_whitept[0]*d;
3244 vn = 9*_whitept[1]*d;
3246 Mat(1, 9, CV_32FC1, coeffs).copyTo(ucoeffs);
3249 _dst.create(sz, CV_MAKETYPE(depth, dcn));
3250 dst = _dst.getUMat();
3252 float lThresh = 0.008856f * 903.3f;
3253 float fThresh = 7.787f * 0.008856f + 16.0f / 116.0f;
3255 ocl::KernelArg srcarg = ocl::KernelArg::ReadOnlyNoSize(src),
3256 dstarg = ocl::KernelArg::WriteOnly(dst),
3257 coeffsarg = ocl::KernelArg::PtrReadOnly(ucoeffs);
3262 k.args(srcarg, dstarg, ocl::KernelArg::PtrReadOnly(usRGBInvGammaTab),
3263 coeffsarg, lThresh, fThresh);
3265 k.args(srcarg, dstarg, coeffsarg, lThresh, fThresh);
3270 k.args(srcarg, dstarg, ocl::KernelArg::PtrReadOnly(usRGBInvGammaTab),
3273 k.args(srcarg, dstarg, coeffsarg, un, vn);
3276 return k.run(dims, globalsize, NULL, false);
3284 _dst.create(dstSz, CV_MAKETYPE(depth, dcn));
3285 dst = _dst.getUMat();
3286 k.args(ocl::KernelArg::ReadOnlyNoSize(src), ocl::KernelArg::WriteOnly(dst));
3287 ok = k.run(dims, globalsize, NULL, false);
3296 //////////////////////////////////////////////////////////////////////////////////////////
3297 // The main function //
3298 //////////////////////////////////////////////////////////////////////////////////////////
3300 void cv::cvtColor( InputArray _src, OutputArray _dst, int code, int dcn )
3302 int stype = _src.type();
3303 int scn = CV_MAT_CN(stype), depth = CV_MAT_DEPTH(stype), bidx;
3305 CV_OCL_RUN( _src.dims() <= 2 && _dst.isUMat() && !(depth == CV_8U && (code == CV_Luv2BGR || code == CV_Luv2RGB)),
3306 ocl_cvtColor(_src, _dst, code, dcn) )
3308 Mat src = _src.getMat(), dst;
3309 Size sz = src.size();
3311 CV_Assert( depth == CV_8U || depth == CV_16U || depth == CV_32F );
3315 case CV_BGR2BGRA: case CV_RGB2BGRA: case CV_BGRA2BGR:
3316 case CV_RGBA2BGR: case CV_RGB2BGR: case CV_BGRA2RGBA:
3317 CV_Assert( scn == 3 || scn == 4 );
3318 dcn = code == CV_BGR2BGRA || code == CV_RGB2BGRA || code == CV_BGRA2RGBA ? 4 : 3;
3319 bidx = code == CV_BGR2BGRA || code == CV_BGRA2BGR ? 0 : 2;
3321 _dst.create( sz, CV_MAKETYPE(depth, dcn));
3322 dst = _dst.getMat();
3324 #if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
3325 if( code == CV_BGR2BGRA)
3327 if ( CvtColorIPPLoop(src, dst, IPPReorderFunctor(ippiSwapChannelsC3C4RTab[depth], 0, 1, 2)) )
3329 setIppErrorStatus();
3331 else if( code == CV_BGRA2BGR )
3333 if ( CvtColorIPPLoop(src, dst, IPPGeneralFunctor(ippiCopyAC4C3RTab[depth])) )
3335 setIppErrorStatus();
3337 else if( code == CV_BGR2RGBA )
3339 if( CvtColorIPPLoop(src, dst, IPPReorderFunctor(ippiSwapChannelsC3C4RTab[depth], 2, 1, 0)) )
3341 setIppErrorStatus();
3343 else if( code == CV_RGBA2BGR )
3345 if( CvtColorIPPLoop(src, dst, IPPReorderFunctor(ippiSwapChannelsC4C3RTab[depth], 2, 1, 0)) )
3347 setIppErrorStatus();
3349 else if( code == CV_RGB2BGR )
3351 if( CvtColorIPPLoopCopy(src, dst, IPPReorderFunctor(ippiSwapChannelsC3RTab[depth], 2, 1, 0)) )
3353 setIppErrorStatus();
3355 #if IPP_VERSION_X100 >= 801
3356 else if( code == CV_RGBA2BGRA )
3358 if( CvtColorIPPLoopCopy(src, dst, IPPReorderFunctor(ippiSwapChannelsC4RTab[depth], 2, 1, 0)) )
3360 setIppErrorStatus();
3365 if( depth == CV_8U )
3367 #ifdef HAVE_TEGRA_OPTIMIZATION
3368 if(!tegra::cvtBGR2RGB(src, dst, bidx))
3370 CvtColorLoop(src, dst, RGB2RGB<uchar>(scn, dcn, bidx));
3372 else if( depth == CV_16U )
3373 CvtColorLoop(src, dst, RGB2RGB<ushort>(scn, dcn, bidx));
3375 CvtColorLoop(src, dst, RGB2RGB<float>(scn, dcn, bidx));
3378 case CV_BGR2BGR565: case CV_BGR2BGR555: case CV_RGB2BGR565: case CV_RGB2BGR555:
3379 case CV_BGRA2BGR565: case CV_BGRA2BGR555: case CV_RGBA2BGR565: case CV_RGBA2BGR555:
3380 CV_Assert( (scn == 3 || scn == 4) && depth == CV_8U );
3381 _dst.create(sz, CV_8UC2);
3382 dst = _dst.getMat();
3384 #if defined(HAVE_IPP) && 0 // breaks OCL accuracy tests
3385 CV_SUPPRESS_DEPRECATED_START
3387 if (code == CV_BGR2BGR565 && scn == 3)
3389 if (CvtColorIPPLoop(src, dst, IPPGeneralFunctor((ippiGeneralFunc)ippiBGRToBGR565_8u16u_C3R)))
3391 setIppErrorStatus();
3393 else if (code == CV_BGRA2BGR565 && scn == 4)
3395 if (CvtColorIPPLoopCopy(src, dst,
3396 IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth],
3397 (ippiGeneralFunc)ippiBGRToBGR565_8u16u_C3R, 0, 1, 2, depth)))
3399 setIppErrorStatus();
3401 else if (code == CV_RGB2BGR565 && scn == 3)
3403 if( CvtColorIPPLoopCopy(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC3RTab[depth],
3404 (ippiGeneralFunc)ippiBGRToBGR565_8u16u_C3R, 2, 1, 0, depth)) )
3406 setIppErrorStatus();
3408 else if (code == CV_RGBA2BGR565 && scn == 4)
3410 if( CvtColorIPPLoopCopy(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth],
3411 (ippiGeneralFunc)ippiBGRToBGR565_8u16u_C3R, 2, 1, 0, depth)) )
3413 setIppErrorStatus();
3415 CV_SUPPRESS_DEPRECATED_END
3418 #ifdef HAVE_TEGRA_OPTIMIZATION
3419 if(code == CV_BGR2BGR565 || code == CV_BGRA2BGR565 || code == CV_RGB2BGR565 || code == CV_RGBA2BGR565)
3420 if(tegra::cvtRGB2RGB565(src, dst, code == CV_RGB2BGR565 || code == CV_RGBA2BGR565 ? 0 : 2))
3424 CvtColorLoop(src, dst, RGB2RGB5x5(scn,
3425 code == CV_BGR2BGR565 || code == CV_BGR2BGR555 ||
3426 code == CV_BGRA2BGR565 || code == CV_BGRA2BGR555 ? 0 : 2,
3427 code == CV_BGR2BGR565 || code == CV_RGB2BGR565 ||
3428 code == CV_BGRA2BGR565 || code == CV_RGBA2BGR565 ? 6 : 5 // green bits
3432 case CV_BGR5652BGR: case CV_BGR5552BGR: case CV_BGR5652RGB: case CV_BGR5552RGB:
3433 case CV_BGR5652BGRA: case CV_BGR5552BGRA: case CV_BGR5652RGBA: case CV_BGR5552RGBA:
3434 if(dcn <= 0) dcn = (code==CV_BGR5652BGRA || code==CV_BGR5552BGRA || code==CV_BGR5652RGBA || code==CV_BGR5552RGBA) ? 4 : 3;
3435 CV_Assert( (dcn == 3 || dcn == 4) && scn == 2 && depth == CV_8U );
3436 _dst.create(sz, CV_MAKETYPE(depth, dcn));
3437 dst = _dst.getMat();
3440 CV_SUPPRESS_DEPRECATED_START
3441 if (code == CV_BGR5652BGR && dcn == 3)
3443 if (CvtColorIPPLoop(src, dst, IPPGeneralFunctor((ippiGeneralFunc)ippiBGR565ToBGR_16u8u_C3R)))
3445 setIppErrorStatus();
3447 else if (code == CV_BGR5652RGB && dcn == 3)
3449 if (CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor((ippiGeneralFunc)ippiBGR565ToBGR_16u8u_C3R,
3450 ippiSwapChannelsC3RTab[depth], 2, 1, 0, depth)))
3452 setIppErrorStatus();
3454 else if (code == CV_BGR5652BGRA && dcn == 4)
3456 if (CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor((ippiGeneralFunc)ippiBGR565ToBGR_16u8u_C3R,
3457 ippiSwapChannelsC3C4RTab[depth], 0, 1, 2, depth)))
3459 setIppErrorStatus();
3461 else if (code == CV_BGR5652RGBA && dcn == 4)
3463 if (CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor((ippiGeneralFunc)ippiBGR565ToBGR_16u8u_C3R,
3464 ippiSwapChannelsC3C4RTab[depth], 2, 1, 0, depth)))
3466 setIppErrorStatus();
3468 CV_SUPPRESS_DEPRECATED_END
3471 CvtColorLoop(src, dst, RGB5x52RGB(dcn,
3472 code == CV_BGR5652BGR || code == CV_BGR5552BGR ||
3473 code == CV_BGR5652BGRA || code == CV_BGR5552BGRA ? 0 : 2, // blue idx
3474 code == CV_BGR5652BGR || code == CV_BGR5652RGB ||
3475 code == CV_BGR5652BGRA || code == CV_BGR5652RGBA ? 6 : 5 // green bits
3479 case CV_BGR2GRAY: case CV_BGRA2GRAY: case CV_RGB2GRAY: case CV_RGBA2GRAY:
3480 CV_Assert( scn == 3 || scn == 4 );
3481 _dst.create(sz, CV_MAKETYPE(depth, 1));
3482 dst = _dst.getMat();
3484 #if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
3485 if( code == CV_BGR2GRAY && depth == CV_32F )
3487 if( CvtColorIPPLoop(src, dst, IPPColor2GrayFunctor(ippiColor2GrayC3Tab[depth])) )
3489 setIppErrorStatus();
3491 else if( code == CV_RGB2GRAY && depth == CV_32F )
3493 if( CvtColorIPPLoop(src, dst, IPPGeneralFunctor(ippiRGB2GrayC3Tab[depth])) )
3495 setIppErrorStatus();
3497 else if( code == CV_BGRA2GRAY && depth == CV_32F )
3499 if( CvtColorIPPLoop(src, dst, IPPColor2GrayFunctor(ippiColor2GrayC4Tab[depth])) )
3501 setIppErrorStatus();
3503 else if( code == CV_RGBA2GRAY && depth == CV_32F )
3505 if( CvtColorIPPLoop(src, dst, IPPGeneralFunctor(ippiRGB2GrayC4Tab[depth])) )
3507 setIppErrorStatus();
3511 bidx = code == CV_BGR2GRAY || code == CV_BGRA2GRAY ? 0 : 2;
3513 if( depth == CV_8U )
3515 #ifdef HAVE_TEGRA_OPTIMIZATION
3516 if(!tegra::cvtRGB2Gray(src, dst, bidx))
3518 CvtColorLoop(src, dst, RGB2Gray<uchar>(scn, bidx, 0));
3520 else if( depth == CV_16U )
3521 CvtColorLoop(src, dst, RGB2Gray<ushort>(scn, bidx, 0));
3523 CvtColorLoop(src, dst, RGB2Gray<float>(scn, bidx, 0));
3526 case CV_BGR5652GRAY: case CV_BGR5552GRAY:
3527 CV_Assert( scn == 2 && depth == CV_8U );
3528 _dst.create(sz, CV_8UC1);
3529 dst = _dst.getMat();
3531 CvtColorLoop(src, dst, RGB5x52Gray(code == CV_BGR5652GRAY ? 6 : 5));
3534 case CV_GRAY2BGR: case CV_GRAY2BGRA:
3535 if( dcn <= 0 ) dcn = (code==CV_GRAY2BGRA) ? 4 : 3;
3536 CV_Assert( scn == 1 && (dcn == 3 || dcn == 4));
3537 _dst.create(sz, CV_MAKETYPE(depth, dcn));
3538 dst = _dst.getMat();
3540 #if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
3541 if( code == CV_GRAY2BGR )
3543 if( CvtColorIPPLoop(src, dst, IPPGray2BGRFunctor(ippiCopyP3C3RTab[depth])) )
3545 setIppErrorStatus();
3547 else if( code == CV_GRAY2BGRA )
3549 if( CvtColorIPPLoop(src, dst, IPPGray2BGRAFunctor(ippiCopyP3C3RTab[depth], ippiSwapChannelsC3C4RTab[depth], depth)) )
3551 setIppErrorStatus();
3556 if( depth == CV_8U )
3558 #ifdef HAVE_TEGRA_OPTIMIZATION
3559 if(!tegra::cvtGray2RGB(src, dst))
3561 CvtColorLoop(src, dst, Gray2RGB<uchar>(dcn));
3563 else if( depth == CV_16U )
3564 CvtColorLoop(src, dst, Gray2RGB<ushort>(dcn));
3566 CvtColorLoop(src, dst, Gray2RGB<float>(dcn));
3569 case CV_GRAY2BGR565: case CV_GRAY2BGR555:
3570 CV_Assert( scn == 1 && depth == CV_8U );
3571 _dst.create(sz, CV_8UC2);
3572 dst = _dst.getMat();
3574 CvtColorLoop(src, dst, Gray2RGB5x5(code == CV_GRAY2BGR565 ? 6 : 5));
3577 case CV_BGR2YCrCb: case CV_RGB2YCrCb:
3578 case CV_BGR2YUV: case CV_RGB2YUV:
3580 CV_Assert( scn == 3 || scn == 4 );
3581 bidx = code == CV_BGR2YCrCb || code == CV_BGR2YUV ? 0 : 2;
3582 static const float yuv_f[] = { 0.114f, 0.587f, 0.299f, 0.492f, 0.877f };
3583 static const int yuv_i[] = { B2Y, G2Y, R2Y, 8061, 14369 };
3584 const float* coeffs_f = code == CV_BGR2YCrCb || code == CV_RGB2YCrCb ? 0 : yuv_f;
3585 const int* coeffs_i = code == CV_BGR2YCrCb || code == CV_RGB2YCrCb ? 0 : yuv_i;
3587 _dst.create(sz, CV_MAKETYPE(depth, 3));
3588 dst = _dst.getMat();
3590 #if defined HAVE_IPP && 0
3591 if (code == CV_RGB2YUV && scn == 3 && depth == CV_8U)
3593 if (CvtColorIPPLoop(src, dst, IPPGeneralFunctor((ippiGeneralFunc)ippiRGBToYUV_8u_C3R)))
3595 setIppErrorStatus();
3597 else if (code == CV_BGR2YUV && scn == 3 && depth == CV_8U)
3599 if (CvtColorIPPLoop(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC3RTab[depth],
3600 (ippiGeneralFunc)ippiRGBToYUV_8u_C3R, 2, 1, 0, depth)))
3602 setIppErrorStatus();
3604 else if (code == CV_RGB2YUV && scn == 4 && depth == CV_8U)
3606 if (CvtColorIPPLoop(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth],
3607 (ippiGeneralFunc)ippiRGBToYUV_8u_C3R, 0, 1, 2, depth)))
3609 setIppErrorStatus();
3611 else if (code == CV_BGR2YUV && scn == 4 && depth == CV_8U)
3613 if (CvtColorIPPLoop(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth],
3614 (ippiGeneralFunc)ippiRGBToYUV_8u_C3R, 2, 1, 0, depth)))
3616 setIppErrorStatus();
3620 if( depth == CV_8U )
3622 #ifdef HAVE_TEGRA_OPTIMIZATION
3623 if((code == CV_RGB2YCrCb || code == CV_BGR2YCrCb) && tegra::cvtRGB2YCrCb(src, dst, bidx))
3626 CvtColorLoop(src, dst, RGB2YCrCb_i<uchar>(scn, bidx, coeffs_i));
3628 else if( depth == CV_16U )
3629 CvtColorLoop(src, dst, RGB2YCrCb_i<ushort>(scn, bidx, coeffs_i));
3631 CvtColorLoop(src, dst, RGB2YCrCb_f<float>(scn, bidx, coeffs_f));
3635 case CV_YCrCb2BGR: case CV_YCrCb2RGB:
3636 case CV_YUV2BGR: case CV_YUV2RGB:
3638 if( dcn <= 0 ) dcn = 3;
3639 CV_Assert( scn == 3 && (dcn == 3 || dcn == 4) );
3640 bidx = code == CV_YCrCb2BGR || code == CV_YUV2BGR ? 0 : 2;
3641 static const float yuv_f[] = { 2.032f, -0.395f, -0.581f, 1.140f };
3642 static const int yuv_i[] = { 33292, -6472, -9519, 18678 };
3643 const float* coeffs_f = code == CV_YCrCb2BGR || code == CV_YCrCb2RGB ? 0 : yuv_f;
3644 const int* coeffs_i = code == CV_YCrCb2BGR || code == CV_YCrCb2RGB ? 0 : yuv_i;
3646 _dst.create(sz, CV_MAKETYPE(depth, dcn));
3647 dst = _dst.getMat();
3649 #if defined HAVE_IPP && 0
3650 if (code == CV_YUV2RGB && dcn == 3 && depth == CV_8U)
3652 if (CvtColorIPPLoop(src, dst, IPPGeneralFunctor((ippiGeneralFunc)ippiYUVToRGB_8u_C3R)))
3654 setIppErrorStatus();
3656 else if (code == CV_YUV2BGR && dcn == 3 && depth == CV_8U)
3658 if (CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor((ippiGeneralFunc)ippiYUVToRGB_8u_C3R,
3659 ippiSwapChannelsC3RTab[depth], 2, 1, 0, depth)))
3661 setIppErrorStatus();
3663 else if (code == CV_YUV2RGB && dcn == 4 && depth == CV_8U)
3665 if (CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor((ippiGeneralFunc)ippiYUVToRGB_8u_C3R,
3666 ippiSwapChannelsC3C4RTab[depth], 0, 1, 2, depth)))
3668 setIppErrorStatus();
3670 else if (code == CV_YUV2BGR && dcn == 4 && depth == CV_8U)
3672 if (CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor((ippiGeneralFunc)ippiYUVToRGB_8u_C3R,
3673 ippiSwapChannelsC3C4RTab[depth], 2, 1, 0, depth)))
3675 setIppErrorStatus();
3679 if( depth == CV_8U )
3680 CvtColorLoop(src, dst, YCrCb2RGB_i<uchar>(dcn, bidx, coeffs_i));
3681 else if( depth == CV_16U )
3682 CvtColorLoop(src, dst, YCrCb2RGB_i<ushort>(dcn, bidx, coeffs_i));
3684 CvtColorLoop(src, dst, YCrCb2RGB_f<float>(dcn, bidx, coeffs_f));
3688 case CV_BGR2XYZ: case CV_RGB2XYZ:
3689 CV_Assert( scn == 3 || scn == 4 );
3690 bidx = code == CV_BGR2XYZ ? 0 : 2;
3692 _dst.create(sz, CV_MAKETYPE(depth, 3));
3693 dst = _dst.getMat();
3695 #if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
3696 if( code == CV_BGR2XYZ && scn == 3 && depth != CV_32F )
3698 if( CvtColorIPPLoopCopy(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC3RTab[depth], ippiRGB2XYZTab[depth], 2, 1, 0, depth)) )
3700 setIppErrorStatus();
3702 else if( code == CV_BGR2XYZ && scn == 4 && depth != CV_32F )
3704 if( CvtColorIPPLoop(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], ippiRGB2XYZTab[depth], 2, 1, 0, depth)) )
3706 setIppErrorStatus();
3708 else if( code == CV_RGB2XYZ && scn == 3 && depth != CV_32F )
3710 if( CvtColorIPPLoopCopy(src, dst, IPPGeneralFunctor(ippiRGB2XYZTab[depth])) )
3712 setIppErrorStatus();
3714 else if( code == CV_RGB2XYZ && scn == 4 && depth != CV_32F )
3716 if( CvtColorIPPLoop(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], ippiRGB2XYZTab[depth], 0, 1, 2, depth)) )
3718 setIppErrorStatus();
3722 if( depth == CV_8U )
3723 CvtColorLoop(src, dst, RGB2XYZ_i<uchar>(scn, bidx, 0));
3724 else if( depth == CV_16U )
3725 CvtColorLoop(src, dst, RGB2XYZ_i<ushort>(scn, bidx, 0));
3727 CvtColorLoop(src, dst, RGB2XYZ_f<float>(scn, bidx, 0));
3730 case CV_XYZ2BGR: case CV_XYZ2RGB:
3731 if( dcn <= 0 ) dcn = 3;
3732 CV_Assert( scn == 3 && (dcn == 3 || dcn == 4) );
3733 bidx = code == CV_XYZ2BGR ? 0 : 2;
3735 _dst.create(sz, CV_MAKETYPE(depth, dcn));
3736 dst = _dst.getMat();
3738 #if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
3739 if( code == CV_XYZ2BGR && dcn == 3 && depth != CV_32F )
3741 if( CvtColorIPPLoopCopy(src, dst, IPPGeneralReorderFunctor(ippiXYZ2RGBTab[depth], ippiSwapChannelsC3RTab[depth], 2, 1, 0, depth)) )
3743 setIppErrorStatus();
3745 else if( code == CV_XYZ2BGR && dcn == 4 && depth != CV_32F )
3747 if( CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor(ippiXYZ2RGBTab[depth], ippiSwapChannelsC3C4RTab[depth], 2, 1, 0, depth)) )
3749 setIppErrorStatus();
3751 if( code == CV_XYZ2RGB && dcn == 3 && depth != CV_32F )
3753 if( CvtColorIPPLoopCopy(src, dst, IPPGeneralFunctor(ippiXYZ2RGBTab[depth])) )
3755 setIppErrorStatus();
3757 else if( code == CV_XYZ2RGB && dcn == 4 && depth != CV_32F )
3759 if( CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor(ippiXYZ2RGBTab[depth], ippiSwapChannelsC3C4RTab[depth], 0, 1, 2, depth)) )
3761 setIppErrorStatus();
3765 if( depth == CV_8U )
3766 CvtColorLoop(src, dst, XYZ2RGB_i<uchar>(dcn, bidx, 0));
3767 else if( depth == CV_16U )
3768 CvtColorLoop(src, dst, XYZ2RGB_i<ushort>(dcn, bidx, 0));
3770 CvtColorLoop(src, dst, XYZ2RGB_f<float>(dcn, bidx, 0));
3773 case CV_BGR2HSV: case CV_RGB2HSV: case CV_BGR2HSV_FULL: case CV_RGB2HSV_FULL:
3774 case CV_BGR2HLS: case CV_RGB2HLS: case CV_BGR2HLS_FULL: case CV_RGB2HLS_FULL:
3776 CV_Assert( (scn == 3 || scn == 4) && (depth == CV_8U || depth == CV_32F) );
3777 bidx = code == CV_BGR2HSV || code == CV_BGR2HLS ||
3778 code == CV_BGR2HSV_FULL || code == CV_BGR2HLS_FULL ? 0 : 2;
3779 int hrange = depth == CV_32F ? 360 : code == CV_BGR2HSV || code == CV_RGB2HSV ||
3780 code == CV_BGR2HLS || code == CV_RGB2HLS ? 180 : 256;
3782 _dst.create(sz, CV_MAKETYPE(depth, 3));
3783 dst = _dst.getMat();
3785 #if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
3786 if( depth == CV_8U || depth == CV_16U )
3788 #if 0 // breaks OCL accuracy tests
3789 if( code == CV_BGR2HSV_FULL && scn == 3 )
3791 if( CvtColorIPPLoopCopy(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC3RTab[depth], ippiRGB2HSVTab[depth], 2, 1, 0, depth)) )
3793 setIppErrorStatus();
3795 else if( code == CV_BGR2HSV_FULL && scn == 4 )
3797 if( CvtColorIPPLoop(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], ippiRGB2HSVTab[depth], 2, 1, 0, depth)) )
3799 setIppErrorStatus();
3801 else if( code == CV_RGB2HSV_FULL && scn == 4 )
3803 if( CvtColorIPPLoop(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], ippiRGB2HSVTab[depth], 0, 1, 2, depth)) )
3805 setIppErrorStatus();
3808 if( code == CV_RGB2HSV_FULL && scn == 3 && depth == CV_16U )
3810 if( CvtColorIPPLoopCopy(src, dst, IPPGeneralFunctor(ippiRGB2HSVTab[depth])) )
3812 setIppErrorStatus();
3814 else if( code == CV_BGR2HLS_FULL && scn == 3 )
3816 if( CvtColorIPPLoopCopy(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC3RTab[depth], ippiRGB2HLSTab[depth], 2, 1, 0, depth)) )
3818 setIppErrorStatus();
3820 else if( code == CV_BGR2HLS_FULL && scn == 4 )
3822 if( CvtColorIPPLoop(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], ippiRGB2HLSTab[depth], 2, 1, 0, depth)) )
3824 setIppErrorStatus();
3826 else if( code == CV_RGB2HLS_FULL && scn == 3 )
3828 if( CvtColorIPPLoopCopy(src, dst, IPPGeneralFunctor(ippiRGB2HLSTab[depth])) )
3830 setIppErrorStatus();
3832 else if( code == CV_RGB2HLS_FULL && scn == 4 )
3834 if( CvtColorIPPLoop(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], ippiRGB2HLSTab[depth], 0, 1, 2, depth)) )
3836 setIppErrorStatus();
3841 if( code == CV_BGR2HSV || code == CV_RGB2HSV ||
3842 code == CV_BGR2HSV_FULL || code == CV_RGB2HSV_FULL )
3844 #ifdef HAVE_TEGRA_OPTIMIZATION
3845 if(tegra::cvtRGB2HSV(src, dst, bidx, hrange))
3848 if( depth == CV_8U )
3849 CvtColorLoop(src, dst, RGB2HSV_b(scn, bidx, hrange));
3851 CvtColorLoop(src, dst, RGB2HSV_f(scn, bidx, (float)hrange));
3855 if( depth == CV_8U )
3856 CvtColorLoop(src, dst, RGB2HLS_b(scn, bidx, hrange));
3858 CvtColorLoop(src, dst, RGB2HLS_f(scn, bidx, (float)hrange));
3863 case CV_HSV2BGR: case CV_HSV2RGB: case CV_HSV2BGR_FULL: case CV_HSV2RGB_FULL:
3864 case CV_HLS2BGR: case CV_HLS2RGB: case CV_HLS2BGR_FULL: case CV_HLS2RGB_FULL:
3866 if( dcn <= 0 ) dcn = 3;
3867 CV_Assert( scn == 3 && (dcn == 3 || dcn == 4) && (depth == CV_8U || depth == CV_32F) );
3868 bidx = code == CV_HSV2BGR || code == CV_HLS2BGR ||
3869 code == CV_HSV2BGR_FULL || code == CV_HLS2BGR_FULL ? 0 : 2;
3870 int hrange = depth == CV_32F ? 360 : code == CV_HSV2BGR || code == CV_HSV2RGB ||
3871 code == CV_HLS2BGR || code == CV_HLS2RGB ? 180 : 255;
3873 _dst.create(sz, CV_MAKETYPE(depth, dcn));
3874 dst = _dst.getMat();
3876 #if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
3877 if( depth == CV_8U || depth == CV_16U )
3879 if( code == CV_HSV2BGR_FULL && dcn == 3 )
3881 if( CvtColorIPPLoopCopy(src, dst, IPPGeneralReorderFunctor(ippiHSV2RGBTab[depth], ippiSwapChannelsC3RTab[depth], 2, 1, 0, depth)) )
3883 setIppErrorStatus();
3885 else if( code == CV_HSV2BGR_FULL && dcn == 4 )
3887 if( CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor(ippiHSV2RGBTab[depth], ippiSwapChannelsC3C4RTab[depth], 2, 1, 0, depth)) )
3889 setIppErrorStatus();
3891 else if( code == CV_HSV2RGB_FULL && dcn == 3 )
3893 if( CvtColorIPPLoopCopy(src, dst, IPPGeneralFunctor(ippiHSV2RGBTab[depth])) )
3895 setIppErrorStatus();
3897 else if( code == CV_HSV2RGB_FULL && dcn == 4 )
3899 if( CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor(ippiHSV2RGBTab[depth], ippiSwapChannelsC3C4RTab[depth], 0, 1, 2, depth)) )
3901 setIppErrorStatus();
3903 else if( code == CV_HLS2BGR_FULL && dcn == 3 )
3905 if( CvtColorIPPLoopCopy(src, dst, IPPGeneralReorderFunctor(ippiHLS2RGBTab[depth], ippiSwapChannelsC3RTab[depth], 2, 1, 0, depth)) )
3907 setIppErrorStatus();
3909 else if( code == CV_HLS2BGR_FULL && dcn == 4 )
3911 if( CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor(ippiHLS2RGBTab[depth], ippiSwapChannelsC3C4RTab[depth], 2, 1, 0, depth)) )
3913 setIppErrorStatus();
3915 else if( code == CV_HLS2RGB_FULL && dcn == 3 )
3917 if( CvtColorIPPLoopCopy(src, dst, IPPGeneralFunctor(ippiHLS2RGBTab[depth])) )
3919 setIppErrorStatus();
3921 else if( code == CV_HLS2RGB_FULL && dcn == 4 )
3923 if( CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor(ippiHLS2RGBTab[depth], ippiSwapChannelsC3C4RTab[depth], 0, 1, 2, depth)) )
3925 setIppErrorStatus();
3930 if( code == CV_HSV2BGR || code == CV_HSV2RGB ||
3931 code == CV_HSV2BGR_FULL || code == CV_HSV2RGB_FULL )
3933 if( depth == CV_8U )
3934 CvtColorLoop(src, dst, HSV2RGB_b(dcn, bidx, hrange));
3936 CvtColorLoop(src, dst, HSV2RGB_f(dcn, bidx, (float)hrange));
3940 if( depth == CV_8U )
3941 CvtColorLoop(src, dst, HLS2RGB_b(dcn, bidx, hrange));
3943 CvtColorLoop(src, dst, HLS2RGB_f(dcn, bidx, (float)hrange));
3948 case CV_BGR2Lab: case CV_RGB2Lab: case CV_LBGR2Lab: case CV_LRGB2Lab:
3949 case CV_BGR2Luv: case CV_RGB2Luv: case CV_LBGR2Luv: case CV_LRGB2Luv:
3951 CV_Assert( (scn == 3 || scn == 4) && (depth == CV_8U || depth == CV_32F) );
3952 bidx = code == CV_BGR2Lab || code == CV_BGR2Luv ||
3953 code == CV_LBGR2Lab || code == CV_LBGR2Luv ? 0 : 2;
3954 bool srgb = code == CV_BGR2Lab || code == CV_RGB2Lab ||
3955 code == CV_BGR2Luv || code == CV_RGB2Luv;
3957 _dst.create(sz, CV_MAKETYPE(depth, 3));
3958 dst = _dst.getMat();
3962 if (code == CV_LBGR2Lab && scn == 3 && depth == CV_8U)
3964 if (CvtColorIPPLoop(src, dst, IPPGeneralFunctor((ippiGeneralFunc)ippiBGRToLab_8u_C3R)))
3966 setIppErrorStatus();
3968 else if (code == CV_LBGR2Lab && scn == 4 && depth == CV_8U)
3970 if (CvtColorIPPLoop(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth],
3971 (ippiGeneralFunc)ippiBGRToLab_8u_C3R, 0, 1, 2, depth)))
3973 setIppErrorStatus();
3976 if (code == CV_LRGB2Lab && scn == 3 && depth == CV_8U) // slower than OpenCV
3978 if (CvtColorIPPLoop(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC3RTab[depth],
3979 (ippiGeneralFunc)ippiBGRToLab_8u_C3R, 2, 1, 0, depth)))
3981 setIppErrorStatus();
3983 else if (code == CV_LRGB2Lab && scn == 4 && depth == CV_8U) // slower than OpenCV
3985 if (CvtColorIPPLoop(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth],
3986 (ippiGeneralFunc)ippiBGRToLab_8u_C3R, 2, 1, 0, depth)))
3988 setIppErrorStatus();
3990 else if (code == CV_LRGB2Luv && scn == 3)
3992 if (CvtColorIPPLoop(src, dst, IPPGeneralFunctor(ippiRGBToLUVTab[depth])))
3994 setIppErrorStatus();
3996 else if (code == CV_LRGB2Luv && scn == 4)
3998 if (CvtColorIPPLoop(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth],
3999 ippiRGBToLUVTab[depth], 0, 1, 2, depth)))
4001 setIppErrorStatus();
4003 else if (code == CV_LBGR2Luv && scn == 3)
4005 if (CvtColorIPPLoop(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC3RTab[depth],
4006 ippiRGBToLUVTab[depth], 2, 1, 0, depth)))
4008 setIppErrorStatus();
4010 else if (code == CV_LBGR2Luv && scn == 4)
4012 if (CvtColorIPPLoop(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth],
4013 ippiRGBToLUVTab[depth], 2, 1, 0, depth)))
4015 setIppErrorStatus();
4020 if( code == CV_BGR2Lab || code == CV_RGB2Lab ||
4021 code == CV_LBGR2Lab || code == CV_LRGB2Lab )
4023 if( depth == CV_8U )
4024 CvtColorLoop(src, dst, RGB2Lab_b(scn, bidx, 0, 0, srgb));
4026 CvtColorLoop(src, dst, RGB2Lab_f(scn, bidx, 0, 0, srgb));
4030 if( depth == CV_8U )
4031 CvtColorLoop(src, dst, RGB2Luv_b(scn, bidx, 0, 0, srgb));
4033 CvtColorLoop(src, dst, RGB2Luv_f(scn, bidx, 0, 0, srgb));
4038 case CV_Lab2BGR: case CV_Lab2RGB: case CV_Lab2LBGR: case CV_Lab2LRGB:
4039 case CV_Luv2BGR: case CV_Luv2RGB: case CV_Luv2LBGR: case CV_Luv2LRGB:
4041 if( dcn <= 0 ) dcn = 3;
4042 CV_Assert( scn == 3 && (dcn == 3 || dcn == 4) && (depth == CV_8U || depth == CV_32F) );
4043 bidx = code == CV_Lab2BGR || code == CV_Luv2BGR ||
4044 code == CV_Lab2LBGR || code == CV_Luv2LBGR ? 0 : 2;
4045 bool srgb = code == CV_Lab2BGR || code == CV_Lab2RGB ||
4046 code == CV_Luv2BGR || code == CV_Luv2RGB;
4048 _dst.create(sz, CV_MAKETYPE(depth, dcn));
4049 dst = _dst.getMat();
4051 #if defined HAVE_IPP && 0
4052 if( code == CV_Lab2LBGR && dcn == 3 && depth == CV_8U)
4054 if( CvtColorIPPLoop(src, dst, IPPGeneralFunctor((ippiGeneralFunc)ippiLabToBGR_8u_C3R)) )
4056 setIppErrorStatus();
4058 else if( code == CV_Lab2LBGR && dcn == 4 && depth == CV_8U )
4060 if( CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor((ippiGeneralFunc)ippiLabToBGR_8u_C3R,
4061 ippiSwapChannelsC3C4RTab[depth], 0, 1, 2, depth)) )
4063 setIppErrorStatus();
4065 if( code == CV_Lab2LRGB && dcn == 3 && depth == CV_8U )
4067 if( CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor((ippiGeneralFunc)ippiLabToBGR_8u_C3R,
4068 ippiSwapChannelsC3RTab[depth], 2, 1, 0, depth)) )
4070 setIppErrorStatus();
4072 else if( code == CV_Lab2LRGB && dcn == 4 && depth == CV_8U )
4074 if( CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor((ippiGeneralFunc)ippiLabToBGR_8u_C3R,
4075 ippiSwapChannelsC3C4RTab[depth], 2, 1, 0, depth)) )
4077 setIppErrorStatus();
4079 if( code == CV_Luv2LRGB && dcn == 3 )
4081 if( CvtColorIPPLoop(src, dst, IPPGeneralFunctor(ippiLUVToRGBTab[depth])) )
4084 else if( code == CV_Luv2LRGB && dcn == 4 )
4086 if( CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor(ippiLUVToRGBTab[depth],
4087 ippiSwapChannelsC3C4RTab[depth], 0, 1, 2, depth)) )
4090 if( code == CV_Luv2LBGR && dcn == 3 )
4092 if( CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor(ippiLUVToRGBTab[depth],
4093 ippiSwapChannelsC3RTab[depth], 2, 1, 0, depth)) )
4096 else if( code == CV_Luv2LBGR && dcn == 4 )
4098 if( CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor(ippiLUVToRGBTab[depth],
4099 ippiSwapChannelsC3C4RTab[depth], 2, 1, 0, depth)) )
4104 if( code == CV_Lab2BGR || code == CV_Lab2RGB ||
4105 code == CV_Lab2LBGR || code == CV_Lab2LRGB )
4107 if( depth == CV_8U )
4108 CvtColorLoop(src, dst, Lab2RGB_b(dcn, bidx, 0, 0, srgb));
4110 CvtColorLoop(src, dst, Lab2RGB_f(dcn, bidx, 0, 0, srgb));
4114 if( depth == CV_8U )
4115 CvtColorLoop(src, dst, Luv2RGB_b(dcn, bidx, 0, 0, srgb));
4117 CvtColorLoop(src, dst, Luv2RGB_f(dcn, bidx, 0, 0, srgb));
4122 case CV_BayerBG2GRAY: case CV_BayerGB2GRAY: case CV_BayerRG2GRAY: case CV_BayerGR2GRAY:
4123 case CV_BayerBG2BGR: case CV_BayerGB2BGR: case CV_BayerRG2BGR: case CV_BayerGR2BGR:
4124 case CV_BayerBG2BGR_VNG: case CV_BayerGB2BGR_VNG: case CV_BayerRG2BGR_VNG: case CV_BayerGR2BGR_VNG:
4125 case CV_BayerBG2BGR_EA: case CV_BayerGB2BGR_EA: case CV_BayerRG2BGR_EA: case CV_BayerGR2BGR_EA:
4126 demosaicing(src, _dst, code, dcn);
4129 case CV_YUV2BGR_NV21: case CV_YUV2RGB_NV21: case CV_YUV2BGR_NV12: case CV_YUV2RGB_NV12:
4130 case CV_YUV2BGRA_NV21: case CV_YUV2RGBA_NV21: case CV_YUV2BGRA_NV12: case CV_YUV2RGBA_NV12:
4132 // 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
4133 // 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
4135 if (dcn <= 0) dcn = (code==CV_YUV420sp2BGRA || code==CV_YUV420sp2RGBA || code==CV_YUV2BGRA_NV12 || code==CV_YUV2RGBA_NV12) ? 4 : 3;
4136 const int bIdx = (code==CV_YUV2BGR_NV21 || code==CV_YUV2BGRA_NV21 || code==CV_YUV2BGR_NV12 || code==CV_YUV2BGRA_NV12) ? 0 : 2;
4137 const int uIdx = (code==CV_YUV2BGR_NV21 || code==CV_YUV2BGRA_NV21 || code==CV_YUV2RGB_NV21 || code==CV_YUV2RGBA_NV21) ? 1 : 0;
4139 CV_Assert( dcn == 3 || dcn == 4 );
4140 CV_Assert( sz.width % 2 == 0 && sz.height % 3 == 0 && depth == CV_8U );
4142 Size dstSz(sz.width, sz.height * 2 / 3);
4143 _dst.create(dstSz, CV_MAKETYPE(depth, dcn));
4144 dst = _dst.getMat();
4146 int srcstep = (int)src.step;
4147 const uchar* y = src.ptr();
4148 const uchar* uv = y + srcstep * dstSz.height;
4150 switch(dcn*100 + bIdx * 10 + uIdx)
4152 case 300: cvtYUV420sp2RGB<0, 0> (dst, srcstep, y, uv); break;
4153 case 301: cvtYUV420sp2RGB<0, 1> (dst, srcstep, y, uv); break;
4154 case 320: cvtYUV420sp2RGB<2, 0> (dst, srcstep, y, uv); break;
4155 case 321: cvtYUV420sp2RGB<2, 1> (dst, srcstep, y, uv); break;
4156 case 400: cvtYUV420sp2RGBA<0, 0>(dst, srcstep, y, uv); break;
4157 case 401: cvtYUV420sp2RGBA<0, 1>(dst, srcstep, y, uv); break;
4158 case 420: cvtYUV420sp2RGBA<2, 0>(dst, srcstep, y, uv); break;
4159 case 421: cvtYUV420sp2RGBA<2, 1>(dst, srcstep, y, uv); break;
4160 default: CV_Error( CV_StsBadFlag, "Unknown/unsupported color conversion code" ); break;
4164 case CV_YUV2BGR_YV12: case CV_YUV2RGB_YV12: case CV_YUV2BGRA_YV12: case CV_YUV2RGBA_YV12:
4165 case CV_YUV2BGR_IYUV: case CV_YUV2RGB_IYUV: case CV_YUV2BGRA_IYUV: case CV_YUV2RGBA_IYUV:
4167 //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.
4168 //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
4170 if (dcn <= 0) dcn = (code==CV_YUV2BGRA_YV12 || code==CV_YUV2RGBA_YV12 || code==CV_YUV2RGBA_IYUV || code==CV_YUV2BGRA_IYUV) ? 4 : 3;
4171 const int bIdx = (code==CV_YUV2BGR_YV12 || code==CV_YUV2BGRA_YV12 || code==CV_YUV2BGR_IYUV || code==CV_YUV2BGRA_IYUV) ? 0 : 2;
4172 const int uIdx = (code==CV_YUV2BGR_YV12 || code==CV_YUV2RGB_YV12 || code==CV_YUV2BGRA_YV12 || code==CV_YUV2RGBA_YV12) ? 1 : 0;
4174 CV_Assert( dcn == 3 || dcn == 4 );
4175 CV_Assert( sz.width % 2 == 0 && sz.height % 3 == 0 && depth == CV_8U );
4177 Size dstSz(sz.width, sz.height * 2 / 3);
4178 _dst.create(dstSz, CV_MAKETYPE(depth, dcn));
4179 dst = _dst.getMat();
4181 int srcstep = (int)src.step;
4182 const uchar* y = src.ptr();
4183 const uchar* u = y + srcstep * dstSz.height;
4184 const uchar* v = y + srcstep * (dstSz.height + dstSz.height/4) + (dstSz.width/2) * ((dstSz.height % 4)/2);
4187 int vstepIdx = dstSz.height % 4 == 2 ? 1 : 0;
4189 if(uIdx == 1) { std::swap(u ,v), std::swap(ustepIdx, vstepIdx); }
4191 switch(dcn*10 + bIdx)
4193 case 30: cvtYUV420p2RGB<0>(dst, srcstep, y, u, v, ustepIdx, vstepIdx); break;
4194 case 32: cvtYUV420p2RGB<2>(dst, srcstep, y, u, v, ustepIdx, vstepIdx); break;
4195 case 40: cvtYUV420p2RGBA<0>(dst, srcstep, y, u, v, ustepIdx, vstepIdx); break;
4196 case 42: cvtYUV420p2RGBA<2>(dst, srcstep, y, u, v, ustepIdx, vstepIdx); break;
4197 default: CV_Error( CV_StsBadFlag, "Unknown/unsupported color conversion code" ); break;
4201 case CV_YUV2GRAY_420:
4203 if (dcn <= 0) dcn = 1;
4205 CV_Assert( dcn == 1 );
4206 CV_Assert( sz.width % 2 == 0 && sz.height % 3 == 0 && depth == CV_8U );
4208 Size dstSz(sz.width, sz.height * 2 / 3);
4209 _dst.create(dstSz, CV_MAKETYPE(depth, dcn));
4210 dst = _dst.getMat();
4211 #if defined HAVE_IPP
4212 if (ippStsNoErr == ippiCopy_8u_C1R(src.data, (int)src.step, dst.data, (int)dst.step,
4213 ippiSize(dstSz.width, dstSz.height)))
4215 setIppErrorStatus();
4217 src(Range(0, dstSz.height), Range::all()).copyTo(dst);
4220 case CV_RGB2YUV_YV12: case CV_BGR2YUV_YV12: case CV_RGBA2YUV_YV12: case CV_BGRA2YUV_YV12:
4221 case CV_RGB2YUV_IYUV: case CV_BGR2YUV_IYUV: case CV_RGBA2YUV_IYUV: case CV_BGRA2YUV_IYUV:
4223 if (dcn <= 0) dcn = 1;
4224 const int bIdx = (code == CV_BGR2YUV_IYUV || code == CV_BGRA2YUV_IYUV || code == CV_BGR2YUV_YV12 || code == CV_BGRA2YUV_YV12) ? 0 : 2;
4225 const int uIdx = (code == CV_BGR2YUV_IYUV || code == CV_BGRA2YUV_IYUV || code == CV_RGB2YUV_IYUV || code == CV_RGBA2YUV_IYUV) ? 1 : 2;
4227 CV_Assert( (scn == 3 || scn == 4) && depth == CV_8U );
4228 CV_Assert( dcn == 1 );
4229 CV_Assert( sz.width % 2 == 0 && sz.height % 2 == 0 );
4231 Size dstSz(sz.width, sz.height / 2 * 3);
4232 _dst.create(dstSz, CV_MAKETYPE(depth, dcn));
4233 dst = _dst.getMat();
4235 switch(bIdx + uIdx*10)
4237 case 10: cvtRGBtoYUV420p<0, 1>(src, dst); break;
4238 case 12: cvtRGBtoYUV420p<2, 1>(src, dst); break;
4239 case 20: cvtRGBtoYUV420p<0, 2>(src, dst); break;
4240 case 22: cvtRGBtoYUV420p<2, 2>(src, dst); break;
4241 default: CV_Error( CV_StsBadFlag, "Unknown/unsupported color conversion code" ); break;
4245 case CV_YUV2RGB_UYVY: case CV_YUV2BGR_UYVY: case CV_YUV2RGBA_UYVY: case CV_YUV2BGRA_UYVY:
4246 case CV_YUV2RGB_YUY2: case CV_YUV2BGR_YUY2: case CV_YUV2RGB_YVYU: case CV_YUV2BGR_YVYU:
4247 case CV_YUV2RGBA_YUY2: case CV_YUV2BGRA_YUY2: case CV_YUV2RGBA_YVYU: case CV_YUV2BGRA_YVYU:
4249 //http://www.fourcc.org/yuv.php#UYVY
4250 //http://www.fourcc.org/yuv.php#YUY2
4251 //http://www.fourcc.org/yuv.php#YVYU
4253 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;
4254 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;
4255 const int ycn = (code==CV_YUV2RGB_UYVY || code==CV_YUV2BGR_UYVY || code==CV_YUV2RGBA_UYVY || code==CV_YUV2BGRA_UYVY) ? 1 : 0;
4256 const int uIdx = (code==CV_YUV2RGB_YVYU || code==CV_YUV2BGR_YVYU || code==CV_YUV2RGBA_YVYU || code==CV_YUV2BGRA_YVYU) ? 1 : 0;
4258 CV_Assert( dcn == 3 || dcn == 4 );
4259 CV_Assert( scn == 2 && depth == CV_8U );
4261 _dst.create(sz, CV_8UC(dcn));
4262 dst = _dst.getMat();
4264 switch(dcn*1000 + bIdx*100 + uIdx*10 + ycn)
4266 case 3000: cvtYUV422toRGB<0,0,0>(dst, (int)src.step, src.ptr<uchar>()); break;
4267 case 3001: cvtYUV422toRGB<0,0,1>(dst, (int)src.step, src.ptr<uchar>()); break;
4268 case 3010: cvtYUV422toRGB<0,1,0>(dst, (int)src.step, src.ptr<uchar>()); break;
4269 case 3011: cvtYUV422toRGB<0,1,1>(dst, (int)src.step, src.ptr<uchar>()); break;
4270 case 3200: cvtYUV422toRGB<2,0,0>(dst, (int)src.step, src.ptr<uchar>()); break;
4271 case 3201: cvtYUV422toRGB<2,0,1>(dst, (int)src.step, src.ptr<uchar>()); break;
4272 case 3210: cvtYUV422toRGB<2,1,0>(dst, (int)src.step, src.ptr<uchar>()); break;
4273 case 3211: cvtYUV422toRGB<2,1,1>(dst, (int)src.step, src.ptr<uchar>()); break;
4274 case 4000: cvtYUV422toRGBA<0,0,0>(dst, (int)src.step, src.ptr<uchar>()); break;
4275 case 4001: cvtYUV422toRGBA<0,0,1>(dst, (int)src.step, src.ptr<uchar>()); break;
4276 case 4010: cvtYUV422toRGBA<0,1,0>(dst, (int)src.step, src.ptr<uchar>()); break;
4277 case 4011: cvtYUV422toRGBA<0,1,1>(dst, (int)src.step, src.ptr<uchar>()); break;
4278 case 4200: cvtYUV422toRGBA<2,0,0>(dst, (int)src.step, src.ptr<uchar>()); break;
4279 case 4201: cvtYUV422toRGBA<2,0,1>(dst, (int)src.step, src.ptr<uchar>()); break;
4280 case 4210: cvtYUV422toRGBA<2,1,0>(dst, (int)src.step, src.ptr<uchar>()); break;
4281 case 4211: cvtYUV422toRGBA<2,1,1>(dst, (int)src.step, src.ptr<uchar>()); break;
4282 default: CV_Error( CV_StsBadFlag, "Unknown/unsupported color conversion code" ); break;
4286 case CV_YUV2GRAY_UYVY: case CV_YUV2GRAY_YUY2:
4288 if (dcn <= 0) dcn = 1;
4290 CV_Assert( dcn == 1 );
4291 CV_Assert( scn == 2 && depth == CV_8U );
4293 extractChannel(_src, _dst, code == CV_YUV2GRAY_UYVY ? 1 : 0);
4298 if (dcn <= 0) dcn = 4;
4299 CV_Assert( scn == 4 && dcn == 4 );
4301 _dst.create(sz, CV_MAKETYPE(depth, dcn));
4302 dst = _dst.getMat();
4304 if( depth == CV_8U )
4306 #if defined(HAVE_IPP)
4307 if (CvtColorIPPLoop(src, dst, IPPGeneralFunctor((ippiGeneralFunc)ippiAlphaPremul_8u_AC4R)))
4309 setIppErrorStatus();
4311 CvtColorLoop(src, dst, RGBA2mRGBA<uchar>());
4315 CV_Error( CV_StsBadArg, "Unsupported image depth" );
4321 if (dcn <= 0) dcn = 4;
4322 CV_Assert( scn == 4 && dcn == 4 );
4324 _dst.create(sz, CV_MAKETYPE(depth, dcn));
4325 dst = _dst.getMat();
4327 if( depth == CV_8U )
4328 CvtColorLoop(src, dst, mRGBA2RGBA<uchar>());
4331 CV_Error( CV_StsBadArg, "Unsupported image depth" );
4336 CV_Error( CV_StsBadFlag, "Unknown/unsupported color conversion code" );
4341 cvCvtColor( const CvArr* srcarr, CvArr* dstarr, int code )
4343 cv::Mat src = cv::cvarrToMat(srcarr), dst0 = cv::cvarrToMat(dstarr), dst = dst0;
4344 CV_Assert( src.depth() == dst.depth() );
4346 cv::cvtColor(src, dst, code, dst.channels());
4347 CV_Assert( dst.data == dst0.data );