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"
99 // computes cubic spline coefficients for a function: (xi=i, yi=f[i]), i=0..n
100 template<typename _Tp> static void splineBuild(const _Tp* f, int n, _Tp* tab)
104 tab[0] = tab[1] = (_Tp)0;
106 for(i = 1; i < n-1; i++)
108 _Tp t = 3*(f[i+1] - 2*f[i] + f[i-1]);
109 _Tp l = 1/(4 - tab[(i-1)*4]);
110 tab[i*4] = l; tab[i*4+1] = (t - tab[(i-1)*4+1])*l;
113 for(i = n-1; i >= 0; i--)
115 _Tp c = tab[i*4+1] - tab[i*4]*cn;
116 _Tp b = f[i+1] - f[i] - (cn + c*2)*(_Tp)0.3333333333333333;
117 _Tp d = (cn - c)*(_Tp)0.3333333333333333;
118 tab[i*4] = f[i]; tab[i*4+1] = b;
119 tab[i*4+2] = c; tab[i*4+3] = d;
124 // interpolates value of a function at x, 0 <= x <= n using a cubic spline.
125 template<typename _Tp> static inline _Tp splineInterpolate(_Tp x, const _Tp* tab, int n)
127 // don't touch this function without urgent need - some versions of gcc fail to inline it correctly
128 int ix = std::min(std::max(int(x), 0), n-1);
131 return ((tab[3]*x + tab[2])*x + tab[1])*x + tab[0];
135 template<typename _Tp> struct ColorChannel
137 typedef float worktype_f;
138 static _Tp max() { return std::numeric_limits<_Tp>::max(); }
139 static _Tp half() { return (_Tp)(max()/2 + 1); }
142 template<> struct ColorChannel<float>
144 typedef float worktype_f;
145 static float max() { return 1.f; }
146 static float half() { return 0.5f; }
149 /*template<> struct ColorChannel<double>
151 typedef double worktype_f;
152 static double max() { return 1.; }
153 static double half() { return 0.5; }
157 ///////////////////////////// Top-level template function ////////////////////////////////
159 template <typename Cvt>
160 class CvtColorLoop_Invoker : public ParallelLoopBody
162 typedef typename Cvt::channel_type _Tp;
165 CvtColorLoop_Invoker(const Mat& _src, Mat& _dst, const Cvt& _cvt) :
166 ParallelLoopBody(), src(_src), dst(_dst), cvt(_cvt)
170 virtual void operator()(const Range& range) const
172 const uchar* yS = src.ptr<uchar>(range.start);
173 uchar* yD = dst.ptr<uchar>(range.start);
175 for( int i = range.start; i < range.end; ++i, yS += src.step, yD += dst.step )
176 cvt((const _Tp*)yS, (_Tp*)yD, src.cols);
184 const CvtColorLoop_Invoker& operator= (const CvtColorLoop_Invoker&);
187 template <typename Cvt>
188 void CvtColorLoop(const Mat& src, Mat& dst, const Cvt& cvt)
190 parallel_for_(Range(0, src.rows), CvtColorLoop_Invoker<Cvt>(src, dst, cvt), src.total()/(double)(1<<16) );
193 ////////////////// Various 3/4-channel to 3/4-channel RGB transformations /////////////////
195 template<typename _Tp> struct RGB2RGB
197 typedef _Tp channel_type;
199 RGB2RGB(int _srccn, int _dstcn, int _blueIdx) : srccn(_srccn), dstcn(_dstcn), blueIdx(_blueIdx) {}
200 void operator()(const _Tp* src, _Tp* dst, int n) const
202 int scn = srccn, dcn = dstcn, bidx = blueIdx;
206 for( int i = 0; i < n; i += 3, src += scn )
208 _Tp t0 = src[bidx], t1 = src[1], t2 = src[bidx ^ 2];
209 dst[i] = t0; dst[i+1] = t1; dst[i+2] = t2;
215 _Tp alpha = ColorChannel<_Tp>::max();
216 for( int i = 0; i < n; i += 3, dst += 4 )
218 _Tp t0 = src[i], t1 = src[i+1], t2 = src[i+2];
219 dst[bidx] = t0; dst[1] = t1; dst[bidx^2] = t2; dst[3] = alpha;
225 for( int i = 0; i < n; i += 4 )
227 _Tp t0 = src[i], t1 = src[i+1], t2 = src[i+2], t3 = src[i+3];
228 dst[i] = t2; dst[i+1] = t1; dst[i+2] = t0; dst[i+3] = t3;
233 int srccn, dstcn, blueIdx;
236 /////////// Transforming 16-bit (565 or 555) RGB to/from 24/32-bit (888[8]) RGB //////////
240 typedef uchar channel_type;
242 RGB5x52RGB(int _dstcn, int _blueIdx, int _greenBits)
243 : dstcn(_dstcn), blueIdx(_blueIdx), greenBits(_greenBits) {}
245 void operator()(const uchar* src, uchar* dst, int n) const
247 int dcn = dstcn, bidx = blueIdx;
249 for( int i = 0; i < n; i++, dst += dcn )
251 unsigned t = ((const ushort*)src)[i];
252 dst[bidx] = (uchar)(t << 3);
253 dst[1] = (uchar)((t >> 3) & ~3);
254 dst[bidx ^ 2] = (uchar)((t >> 8) & ~7);
259 for( int i = 0; i < n; i++, dst += dcn )
261 unsigned t = ((const ushort*)src)[i];
262 dst[bidx] = (uchar)(t << 3);
263 dst[1] = (uchar)((t >> 2) & ~7);
264 dst[bidx ^ 2] = (uchar)((t >> 7) & ~7);
266 dst[3] = t & 0x8000 ? 255 : 0;
270 int dstcn, blueIdx, greenBits;
276 typedef uchar channel_type;
278 RGB2RGB5x5(int _srccn, int _blueIdx, int _greenBits)
279 : srccn(_srccn), blueIdx(_blueIdx), greenBits(_greenBits) {}
281 void operator()(const uchar* src, uchar* dst, int n) const
283 int scn = srccn, bidx = blueIdx;
285 for( int i = 0; i < n; i++, src += scn )
287 ((ushort*)dst)[i] = (ushort)((src[bidx] >> 3)|((src[1]&~3) << 3)|((src[bidx^2]&~7) << 8));
290 for( int i = 0; i < n; i++, src += 3 )
292 ((ushort*)dst)[i] = (ushort)((src[bidx] >> 3)|((src[1]&~7) << 2)|((src[bidx^2]&~7) << 7));
295 for( int i = 0; i < n; i++, src += 4 )
297 ((ushort*)dst)[i] = (ushort)((src[bidx] >> 3)|((src[1]&~7) << 2)|
298 ((src[bidx^2]&~7) << 7)|(src[3] ? 0x8000 : 0));
302 int srccn, blueIdx, greenBits;
305 ///////////////////////////////// Color to/from Grayscale ////////////////////////////////
307 template<typename _Tp>
310 typedef _Tp channel_type;
312 Gray2RGB(int _dstcn) : dstcn(_dstcn) {}
313 void operator()(const _Tp* src, _Tp* dst, int n) const
316 for( int i = 0; i < n; i++, dst += 3 )
318 dst[0] = dst[1] = dst[2] = src[i];
322 _Tp alpha = ColorChannel<_Tp>::max();
323 for( int i = 0; i < n; i++, dst += 4 )
325 dst[0] = dst[1] = dst[2] = src[i];
337 typedef uchar channel_type;
339 Gray2RGB5x5(int _greenBits) : greenBits(_greenBits) {}
340 void operator()(const uchar* src, uchar* dst, int n) const
343 for( int i = 0; i < n; i++ )
346 ((ushort*)dst)[i] = (ushort)((t >> 3)|((t & ~3) << 3)|((t & ~7) << 8));
349 for( int i = 0; i < n; i++ )
352 ((ushort*)dst)[i] = (ushort)(t|(t << 5)|(t << 10));
376 typedef uchar channel_type;
378 RGB5x52Gray(int _greenBits) : greenBits(_greenBits) {}
379 void operator()(const uchar* src, uchar* dst, int n) const
382 for( int i = 0; i < n; i++ )
384 int t = ((ushort*)src)[i];
385 dst[i] = (uchar)CV_DESCALE(((t << 3) & 0xf8)*B2Y +
386 ((t >> 3) & 0xfc)*G2Y +
387 ((t >> 8) & 0xf8)*R2Y, yuv_shift);
390 for( int i = 0; i < n; i++ )
392 int t = ((ushort*)src)[i];
393 dst[i] = (uchar)CV_DESCALE(((t << 3) & 0xf8)*B2Y +
394 ((t >> 2) & 0xf8)*G2Y +
395 ((t >> 7) & 0xf8)*R2Y, yuv_shift);
402 template<typename _Tp> struct RGB2Gray
404 typedef _Tp channel_type;
406 RGB2Gray(int _srccn, int blueIdx, const float* _coeffs) : srccn(_srccn)
408 static const float coeffs0[] = { 0.299f, 0.587f, 0.114f };
409 memcpy( coeffs, _coeffs ? _coeffs : coeffs0, 3*sizeof(coeffs[0]) );
411 std::swap(coeffs[0], coeffs[2]);
414 void operator()(const _Tp* src, _Tp* dst, int n) const
417 float cb = coeffs[0], cg = coeffs[1], cr = coeffs[2];
418 for(int i = 0; i < n; i++, src += scn)
419 dst[i] = saturate_cast<_Tp>(src[0]*cb + src[1]*cg + src[2]*cr);
426 template<> struct RGB2Gray<uchar>
428 typedef uchar channel_type;
430 RGB2Gray<uchar>(int _srccn, int blueIdx, const int* coeffs) : srccn(_srccn)
432 const int coeffs0[] = { R2Y, G2Y, B2Y };
433 if(!coeffs) coeffs = coeffs0;
435 int b = 0, g = 0, r = (1 << (yuv_shift-1));
436 int db = coeffs[blueIdx^2], dg = coeffs[1], dr = coeffs[blueIdx];
438 for( int i = 0; i < 256; i++, b += db, g += dg, r += dr )
445 void operator()(const uchar* src, uchar* dst, int n) const
448 const int* _tab = tab;
449 for(int i = 0; i < n; i++, src += scn)
450 dst[i] = (uchar)((_tab[src[0]] + _tab[src[1]+256] + _tab[src[2]+512]) >> yuv_shift);
457 template<> struct RGB2Gray<ushort>
459 typedef ushort channel_type;
461 RGB2Gray<ushort>(int _srccn, int blueIdx, const int* _coeffs) : srccn(_srccn)
463 static const int coeffs0[] = { R2Y, G2Y, B2Y };
464 memcpy(coeffs, _coeffs ? _coeffs : coeffs0, 3*sizeof(coeffs[0]));
466 std::swap(coeffs[0], coeffs[2]);
469 void operator()(const ushort* src, ushort* dst, int n) const
471 int scn = srccn, cb = coeffs[0], cg = coeffs[1], cr = coeffs[2];
472 for(int i = 0; i < n; i++, src += scn)
473 dst[i] = (ushort)CV_DESCALE((unsigned)(src[0]*cb + src[1]*cg + src[2]*cr), yuv_shift);
480 ///////////////////////////////////// RGB <-> YCrCb //////////////////////////////////////
482 template<typename _Tp> struct RGB2YCrCb_f
484 typedef _Tp channel_type;
486 RGB2YCrCb_f(int _srccn, int _blueIdx, const float* _coeffs) : srccn(_srccn), blueIdx(_blueIdx)
488 static const float coeffs0[] = {0.299f, 0.587f, 0.114f, 0.713f, 0.564f};
489 memcpy(coeffs, _coeffs ? _coeffs : coeffs0, 5*sizeof(coeffs[0]));
490 if(blueIdx==0) std::swap(coeffs[0], coeffs[2]);
493 void operator()(const _Tp* src, _Tp* dst, int n) const
495 int scn = srccn, bidx = blueIdx;
496 const _Tp delta = ColorChannel<_Tp>::half();
497 float C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2], C3 = coeffs[3], C4 = coeffs[4];
499 for(int i = 0; i < n; i += 3, src += scn)
501 _Tp Y = saturate_cast<_Tp>(src[0]*C0 + src[1]*C1 + src[2]*C2);
502 _Tp Cr = saturate_cast<_Tp>((src[bidx^2] - Y)*C3 + delta);
503 _Tp Cb = saturate_cast<_Tp>((src[bidx] - Y)*C4 + delta);
504 dst[i] = Y; dst[i+1] = Cr; dst[i+2] = Cb;
512 template<typename _Tp> struct RGB2YCrCb_i
514 typedef _Tp channel_type;
516 RGB2YCrCb_i(int _srccn, int _blueIdx, const int* _coeffs)
517 : srccn(_srccn), blueIdx(_blueIdx)
519 static const int coeffs0[] = {R2Y, G2Y, B2Y, 11682, 9241};
520 memcpy(coeffs, _coeffs ? _coeffs : coeffs0, 5*sizeof(coeffs[0]));
521 if(blueIdx==0) std::swap(coeffs[0], coeffs[2]);
523 void operator()(const _Tp* src, _Tp* dst, int n) const
525 int scn = srccn, bidx = blueIdx;
526 int C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2], C3 = coeffs[3], C4 = coeffs[4];
527 int delta = ColorChannel<_Tp>::half()*(1 << yuv_shift);
529 for(int i = 0; i < n; i += 3, src += scn)
531 int Y = CV_DESCALE(src[0]*C0 + src[1]*C1 + src[2]*C2, yuv_shift);
532 int Cr = CV_DESCALE((src[bidx^2] - Y)*C3 + delta, yuv_shift);
533 int Cb = CV_DESCALE((src[bidx] - Y)*C4 + delta, yuv_shift);
534 dst[i] = saturate_cast<_Tp>(Y);
535 dst[i+1] = saturate_cast<_Tp>(Cr);
536 dst[i+2] = saturate_cast<_Tp>(Cb);
544 template<typename _Tp> struct YCrCb2RGB_f
546 typedef _Tp channel_type;
548 YCrCb2RGB_f(int _dstcn, int _blueIdx, const float* _coeffs)
549 : dstcn(_dstcn), blueIdx(_blueIdx)
551 static const float coeffs0[] = {1.403f, -0.714f, -0.344f, 1.773f};
552 memcpy(coeffs, _coeffs ? _coeffs : coeffs0, 4*sizeof(coeffs[0]));
554 void operator()(const _Tp* src, _Tp* dst, int n) const
556 int dcn = dstcn, bidx = blueIdx;
557 const _Tp delta = ColorChannel<_Tp>::half(), alpha = ColorChannel<_Tp>::max();
558 float C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2], C3 = coeffs[3];
560 for(int i = 0; i < n; i += 3, dst += dcn)
566 _Tp b = saturate_cast<_Tp>(Y + (Cb - delta)*C3);
567 _Tp g = saturate_cast<_Tp>(Y + (Cb - delta)*C2 + (Cr - delta)*C1);
568 _Tp r = saturate_cast<_Tp>(Y + (Cr - delta)*C0);
570 dst[bidx] = b; dst[1] = g; dst[bidx^2] = r;
580 template<typename _Tp> struct YCrCb2RGB_i
582 typedef _Tp channel_type;
584 YCrCb2RGB_i(int _dstcn, int _blueIdx, const int* _coeffs)
585 : dstcn(_dstcn), blueIdx(_blueIdx)
587 static const int coeffs0[] = {22987, -11698, -5636, 29049};
588 memcpy(coeffs, _coeffs ? _coeffs : coeffs0, 4*sizeof(coeffs[0]));
591 void operator()(const _Tp* src, _Tp* dst, int n) const
593 int dcn = dstcn, bidx = blueIdx;
594 const _Tp delta = ColorChannel<_Tp>::half(), alpha = ColorChannel<_Tp>::max();
595 int C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2], C3 = coeffs[3];
597 for(int i = 0; i < n; i += 3, dst += dcn)
603 int b = Y + CV_DESCALE((Cb - delta)*C3, yuv_shift);
604 int g = Y + CV_DESCALE((Cb - delta)*C2 + (Cr - delta)*C1, yuv_shift);
605 int r = Y + CV_DESCALE((Cr - delta)*C0, yuv_shift);
607 dst[bidx] = saturate_cast<_Tp>(b);
608 dst[1] = saturate_cast<_Tp>(g);
609 dst[bidx^2] = saturate_cast<_Tp>(r);
619 ////////////////////////////////////// RGB <-> XYZ ///////////////////////////////////////
621 static const float sRGB2XYZ_D65[] =
623 0.412453f, 0.357580f, 0.180423f,
624 0.212671f, 0.715160f, 0.072169f,
625 0.019334f, 0.119193f, 0.950227f
628 static const float XYZ2sRGB_D65[] =
630 3.240479f, -1.53715f, -0.498535f,
631 -0.969256f, 1.875991f, 0.041556f,
632 0.055648f, -0.204043f, 1.057311f
635 template<typename _Tp> struct RGB2XYZ_f
637 typedef _Tp channel_type;
639 RGB2XYZ_f(int _srccn, int blueIdx, const float* _coeffs) : srccn(_srccn)
641 memcpy(coeffs, _coeffs ? _coeffs : sRGB2XYZ_D65, 9*sizeof(coeffs[0]));
644 std::swap(coeffs[0], coeffs[2]);
645 std::swap(coeffs[3], coeffs[5]);
646 std::swap(coeffs[6], coeffs[8]);
649 void operator()(const _Tp* src, _Tp* dst, int n) const
652 float C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2],
653 C3 = coeffs[3], C4 = coeffs[4], C5 = coeffs[5],
654 C6 = coeffs[6], C7 = coeffs[7], C8 = coeffs[8];
657 for(int i = 0; i < n; i += 3, src += scn)
659 _Tp X = saturate_cast<_Tp>(src[0]*C0 + src[1]*C1 + src[2]*C2);
660 _Tp Y = saturate_cast<_Tp>(src[0]*C3 + src[1]*C4 + src[2]*C5);
661 _Tp Z = saturate_cast<_Tp>(src[0]*C6 + src[1]*C7 + src[2]*C8);
662 dst[i] = X; dst[i+1] = Y; dst[i+2] = Z;
670 template<typename _Tp> struct RGB2XYZ_i
672 typedef _Tp channel_type;
674 RGB2XYZ_i(int _srccn, int blueIdx, const float* _coeffs) : srccn(_srccn)
676 static const int coeffs0[] =
682 for( int i = 0; i < 9; i++ )
683 coeffs[i] = _coeffs ? cvRound(_coeffs[i]*(1 << xyz_shift)) : coeffs0[i];
686 std::swap(coeffs[0], coeffs[2]);
687 std::swap(coeffs[3], coeffs[5]);
688 std::swap(coeffs[6], coeffs[8]);
691 void operator()(const _Tp* src, _Tp* dst, int n) const
694 int C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2],
695 C3 = coeffs[3], C4 = coeffs[4], C5 = coeffs[5],
696 C6 = coeffs[6], C7 = coeffs[7], C8 = coeffs[8];
698 for(int i = 0; i < n; i += 3, src += scn)
700 int X = CV_DESCALE(src[0]*C0 + src[1]*C1 + src[2]*C2, xyz_shift);
701 int Y = CV_DESCALE(src[0]*C3 + src[1]*C4 + src[2]*C5, xyz_shift);
702 int Z = CV_DESCALE(src[0]*C6 + src[1]*C7 + src[2]*C8, xyz_shift);
703 dst[i] = saturate_cast<_Tp>(X); dst[i+1] = saturate_cast<_Tp>(Y);
704 dst[i+2] = saturate_cast<_Tp>(Z);
712 template<typename _Tp> struct XYZ2RGB_f
714 typedef _Tp channel_type;
716 XYZ2RGB_f(int _dstcn, int _blueIdx, const float* _coeffs)
717 : dstcn(_dstcn), blueIdx(_blueIdx)
719 memcpy(coeffs, _coeffs ? _coeffs : XYZ2sRGB_D65, 9*sizeof(coeffs[0]));
722 std::swap(coeffs[0], coeffs[6]);
723 std::swap(coeffs[1], coeffs[7]);
724 std::swap(coeffs[2], coeffs[8]);
728 void operator()(const _Tp* src, _Tp* dst, int n) const
731 _Tp alpha = ColorChannel<_Tp>::max();
732 float C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2],
733 C3 = coeffs[3], C4 = coeffs[4], C5 = coeffs[5],
734 C6 = coeffs[6], C7 = coeffs[7], C8 = coeffs[8];
736 for(int i = 0; i < n; i += 3, dst += dcn)
738 _Tp B = saturate_cast<_Tp>(src[i]*C0 + src[i+1]*C1 + src[i+2]*C2);
739 _Tp G = saturate_cast<_Tp>(src[i]*C3 + src[i+1]*C4 + src[i+2]*C5);
740 _Tp R = saturate_cast<_Tp>(src[i]*C6 + src[i+1]*C7 + src[i+2]*C8);
741 dst[0] = B; dst[1] = G; dst[2] = R;
751 template<typename _Tp> struct XYZ2RGB_i
753 typedef _Tp channel_type;
755 XYZ2RGB_i(int _dstcn, int _blueIdx, const int* _coeffs)
756 : dstcn(_dstcn), blueIdx(_blueIdx)
758 static const int coeffs0[] =
764 for(int i = 0; i < 9; i++)
765 coeffs[i] = _coeffs ? cvRound(_coeffs[i]*(1 << xyz_shift)) : coeffs0[i];
769 std::swap(coeffs[0], coeffs[6]);
770 std::swap(coeffs[1], coeffs[7]);
771 std::swap(coeffs[2], coeffs[8]);
774 void operator()(const _Tp* src, _Tp* dst, int n) const
777 _Tp alpha = ColorChannel<_Tp>::max();
778 int C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2],
779 C3 = coeffs[3], C4 = coeffs[4], C5 = coeffs[5],
780 C6 = coeffs[6], C7 = coeffs[7], C8 = coeffs[8];
782 for(int i = 0; i < n; i += 3, dst += dcn)
784 int B = CV_DESCALE(src[i]*C0 + src[i+1]*C1 + src[i+2]*C2, xyz_shift);
785 int G = CV_DESCALE(src[i]*C3 + src[i+1]*C4 + src[i+2]*C5, xyz_shift);
786 int R = CV_DESCALE(src[i]*C6 + src[i+1]*C7 + src[i+2]*C8, xyz_shift);
787 dst[0] = saturate_cast<_Tp>(B); dst[1] = saturate_cast<_Tp>(G);
788 dst[2] = saturate_cast<_Tp>(R);
798 ////////////////////////////////////// RGB <-> HSV ///////////////////////////////////////
803 typedef uchar channel_type;
805 RGB2HSV_b(int _srccn, int _blueIdx, int _hrange)
806 : srccn(_srccn), blueIdx(_blueIdx), hrange(_hrange)
808 CV_Assert( hrange == 180 || hrange == 256 );
811 void operator()(const uchar* src, uchar* dst, int n) const
813 int i, bidx = blueIdx, scn = srccn;
814 const int hsv_shift = 12;
816 static int sdiv_table[256];
817 static int hdiv_table180[256];
818 static int hdiv_table256[256];
819 static volatile bool initialized = false;
822 const int* hdiv_table = hr == 180 ? hdiv_table180 : hdiv_table256;
827 sdiv_table[0] = hdiv_table180[0] = hdiv_table256[0] = 0;
828 for( i = 1; i < 256; i++ )
830 sdiv_table[i] = saturate_cast<int>((255 << hsv_shift)/(1.*i));
831 hdiv_table180[i] = saturate_cast<int>((180 << hsv_shift)/(6.*i));
832 hdiv_table256[i] = saturate_cast<int>((256 << hsv_shift)/(6.*i));
837 for( i = 0; i < n; i += 3, src += scn )
839 int b = src[bidx], g = src[1], r = src[bidx^2];
844 CV_CALC_MAX_8U( v, g );
845 CV_CALC_MAX_8U( v, r );
846 CV_CALC_MIN_8U( vmin, g );
847 CV_CALC_MIN_8U( vmin, r );
850 vr = v == r ? -1 : 0;
851 vg = v == g ? -1 : 0;
853 s = (diff * sdiv_table[v] + (1 << (hsv_shift-1))) >> hsv_shift;
855 (~vr & ((vg & (b - r + 2 * diff)) + ((~vg) & (r - g + 4 * diff))));
856 h = (h * hdiv_table[diff] + (1 << (hsv_shift-1))) >> hsv_shift;
859 dst[i] = saturate_cast<uchar>(h);
865 int srccn, blueIdx, hrange;
871 typedef float channel_type;
873 RGB2HSV_f(int _srccn, int _blueIdx, float _hrange)
874 : srccn(_srccn), blueIdx(_blueIdx), hrange(_hrange) {}
876 void operator()(const float* src, float* dst, int n) const
878 int i, bidx = blueIdx, scn = srccn;
879 float hscale = hrange*(1.f/360.f);
882 for( i = 0; i < n; i += 3, src += scn )
884 float b = src[bidx], g = src[1], r = src[bidx^2];
892 if( vmin > g ) vmin = g;
893 if( vmin > b ) vmin = b;
896 s = diff/(float)(fabs(v) + FLT_EPSILON);
897 diff = (float)(60./(diff + FLT_EPSILON));
901 h = (b - r)*diff + 120.f;
903 h = (r - g)*diff + 240.f;
905 if( h < 0 ) h += 360.f;
920 typedef float channel_type;
922 HSV2RGB_f(int _dstcn, int _blueIdx, float _hrange)
923 : dstcn(_dstcn), blueIdx(_blueIdx), hscale(6.f/_hrange) {}
925 void operator()(const float* src, float* dst, int n) const
927 int i, bidx = blueIdx, dcn = dstcn;
928 float _hscale = hscale;
929 float alpha = ColorChannel<float>::max();
932 for( i = 0; i < n; i += 3, dst += dcn )
934 float h = src[i], s = src[i+1], v = src[i+2];
941 static const int sector_data[][3]=
942 {{1,3,0}, {1,0,2}, {3,0,1}, {0,2,1}, {0,1,3}, {2,1,0}};
947 do h += 6; while( h < 0 );
949 do h -= 6; while( h >= 6 );
952 if( (unsigned)sector >= 6u )
959 tab[1] = v*(1.f - s);
960 tab[2] = v*(1.f - s*h);
961 tab[3] = v*(1.f - s*(1.f - h));
963 b = tab[sector_data[sector][0]];
964 g = tab[sector_data[sector][1]];
965 r = tab[sector_data[sector][2]];
983 typedef uchar channel_type;
985 HSV2RGB_b(int _dstcn, int _blueIdx, int _hrange)
986 : dstcn(_dstcn), cvt(3, _blueIdx, (float)_hrange)
989 void operator()(const uchar* src, uchar* dst, int n) const
991 int i, j, dcn = dstcn;
992 uchar alpha = ColorChannel<uchar>::max();
993 float buf[3*BLOCK_SIZE];
995 for( i = 0; i < n; i += BLOCK_SIZE, src += BLOCK_SIZE*3 )
997 int dn = std::min(n - i, (int)BLOCK_SIZE);
999 for( j = 0; j < dn*3; j += 3 )
1002 buf[j+1] = src[j+1]*(1.f/255.f);
1003 buf[j+2] = src[j+2]*(1.f/255.f);
1007 for( j = 0; j < dn*3; j += 3, dst += dcn )
1009 dst[0] = saturate_cast<uchar>(buf[j]*255.f);
1010 dst[1] = saturate_cast<uchar>(buf[j+1]*255.f);
1011 dst[2] = saturate_cast<uchar>(buf[j+2]*255.f);
1023 ///////////////////////////////////// RGB <-> HLS ////////////////////////////////////////
1027 typedef float channel_type;
1029 RGB2HLS_f(int _srccn, int _blueIdx, float _hrange)
1030 : srccn(_srccn), blueIdx(_blueIdx), hrange(_hrange) {}
1032 void operator()(const float* src, float* dst, int n) const
1034 int i, bidx = blueIdx, scn = srccn;
1035 float hscale = hrange*(1.f/360.f);
1038 for( i = 0; i < n; i += 3, src += scn )
1040 float b = src[bidx], g = src[1], r = src[bidx^2];
1041 float h = 0.f, s = 0.f, l;
1042 float vmin, vmax, diff;
1045 if( vmax < g ) vmax = g;
1046 if( vmax < b ) vmax = b;
1047 if( vmin > g ) vmin = g;
1048 if( vmin > b ) vmin = b;
1051 l = (vmax + vmin)*0.5f;
1053 if( diff > FLT_EPSILON )
1055 s = l < 0.5f ? diff/(vmax + vmin) : diff/(2 - vmax - vmin);
1060 else if( vmax == g )
1061 h = (b - r)*diff + 120.f;
1063 h = (r - g)*diff + 240.f;
1065 if( h < 0.f ) h += 360.f;
1081 typedef uchar channel_type;
1083 RGB2HLS_b(int _srccn, int _blueIdx, int _hrange)
1084 : srccn(_srccn), cvt(3, _blueIdx, (float)_hrange) {}
1086 void operator()(const uchar* src, uchar* dst, int n) const
1088 int i, j, scn = srccn;
1089 float buf[3*BLOCK_SIZE];
1091 for( i = 0; i < n; i += BLOCK_SIZE, dst += BLOCK_SIZE*3 )
1093 int dn = std::min(n - i, (int)BLOCK_SIZE);
1095 for( j = 0; j < dn*3; j += 3, src += scn )
1097 buf[j] = src[0]*(1.f/255.f);
1098 buf[j+1] = src[1]*(1.f/255.f);
1099 buf[j+2] = src[2]*(1.f/255.f);
1103 for( j = 0; j < dn*3; j += 3 )
1105 dst[j] = saturate_cast<uchar>(buf[j]);
1106 dst[j+1] = saturate_cast<uchar>(buf[j+1]*255.f);
1107 dst[j+2] = saturate_cast<uchar>(buf[j+2]*255.f);
1119 typedef float channel_type;
1121 HLS2RGB_f(int _dstcn, int _blueIdx, float _hrange)
1122 : dstcn(_dstcn), blueIdx(_blueIdx), hscale(6.f/_hrange) {}
1124 void operator()(const float* src, float* dst, int n) const
1126 int i, bidx = blueIdx, dcn = dstcn;
1127 float _hscale = hscale;
1128 float alpha = ColorChannel<float>::max();
1131 for( i = 0; i < n; i += 3, dst += dcn )
1133 float h = src[i], l = src[i+1], s = src[i+2];
1140 static const int sector_data[][3]=
1141 {{1,3,0}, {1,0,2}, {3,0,1}, {0,2,1}, {0,1,3}, {2,1,0}};
1145 float p2 = l <= 0.5f ? l*(1 + s) : l + s - l*s;
1146 float p1 = 2*l - p2;
1150 do h += 6; while( h < 0 );
1152 do h -= 6; while( h >= 6 );
1154 assert( 0 <= h && h < 6 );
1155 sector = cvFloor(h);
1160 tab[2] = p1 + (p2 - p1)*(1-h);
1161 tab[3] = p1 + (p2 - p1)*h;
1163 b = tab[sector_data[sector][0]];
1164 g = tab[sector_data[sector][1]];
1165 r = tab[sector_data[sector][2]];
1183 typedef uchar channel_type;
1185 HLS2RGB_b(int _dstcn, int _blueIdx, int _hrange)
1186 : dstcn(_dstcn), cvt(3, _blueIdx, (float)_hrange)
1189 void operator()(const uchar* src, uchar* dst, int n) const
1191 int i, j, dcn = dstcn;
1192 uchar alpha = ColorChannel<uchar>::max();
1193 float buf[3*BLOCK_SIZE];
1195 for( i = 0; i < n; i += BLOCK_SIZE, src += BLOCK_SIZE*3 )
1197 int dn = std::min(n - i, (int)BLOCK_SIZE);
1199 for( j = 0; j < dn*3; j += 3 )
1202 buf[j+1] = src[j+1]*(1.f/255.f);
1203 buf[j+2] = src[j+2]*(1.f/255.f);
1207 for( j = 0; j < dn*3; j += 3, dst += dcn )
1209 dst[0] = saturate_cast<uchar>(buf[j]*255.f);
1210 dst[1] = saturate_cast<uchar>(buf[j+1]*255.f);
1211 dst[2] = saturate_cast<uchar>(buf[j+2]*255.f);
1223 ///////////////////////////////////// RGB <-> L*a*b* /////////////////////////////////////
1225 static const float D65[] = { 0.950456f, 1.f, 1.088754f };
1227 enum { LAB_CBRT_TAB_SIZE = 1024, GAMMA_TAB_SIZE = 1024 };
1228 static float LabCbrtTab[LAB_CBRT_TAB_SIZE*4];
1229 static const float LabCbrtTabScale = LAB_CBRT_TAB_SIZE/1.5f;
1231 static float sRGBGammaTab[GAMMA_TAB_SIZE*4], sRGBInvGammaTab[GAMMA_TAB_SIZE*4];
1232 static const float GammaTabScale = (float)GAMMA_TAB_SIZE;
1234 static ushort sRGBGammaTab_b[256], linearGammaTab_b[256];
1236 #define lab_shift xyz_shift
1237 #define gamma_shift 3
1238 #define lab_shift2 (lab_shift + gamma_shift)
1239 #define LAB_CBRT_TAB_SIZE_B (256*3/2*(1<<gamma_shift))
1240 static ushort LabCbrtTab_b[LAB_CBRT_TAB_SIZE_B];
1242 static void initLabTabs()
1244 static bool initialized = false;
1247 float f[LAB_CBRT_TAB_SIZE+1], g[GAMMA_TAB_SIZE+1], ig[GAMMA_TAB_SIZE+1], scale = 1.f/LabCbrtTabScale;
1249 for(i = 0; i <= LAB_CBRT_TAB_SIZE; i++)
1252 f[i] = x < 0.008856f ? x*7.787f + 0.13793103448275862f : cvCbrt(x);
1254 splineBuild(f, LAB_CBRT_TAB_SIZE, LabCbrtTab);
1256 scale = 1.f/GammaTabScale;
1257 for(i = 0; i <= GAMMA_TAB_SIZE; i++)
1260 g[i] = x <= 0.04045f ? x*(1.f/12.92f) : (float)pow((double)(x + 0.055)*(1./1.055), 2.4);
1261 ig[i] = x <= 0.0031308 ? x*12.92f : (float)(1.055*pow((double)x, 1./2.4) - 0.055);
1263 splineBuild(g, GAMMA_TAB_SIZE, sRGBGammaTab);
1264 splineBuild(ig, GAMMA_TAB_SIZE, sRGBInvGammaTab);
1266 for(i = 0; i < 256; i++)
1268 float x = i*(1.f/255.f);
1269 sRGBGammaTab_b[i] = saturate_cast<ushort>(255.f*(1 << gamma_shift)*(x <= 0.04045f ? x*(1.f/12.92f) : (float)pow((double)(x + 0.055)*(1./1.055), 2.4)));
1270 linearGammaTab_b[i] = (ushort)(i*(1 << gamma_shift));
1273 for(i = 0; i < LAB_CBRT_TAB_SIZE_B; i++)
1275 float x = i*(1.f/(255.f*(1 << gamma_shift)));
1276 LabCbrtTab_b[i] = saturate_cast<ushort>((1 << lab_shift2)*(x < 0.008856f ? x*7.787f + 0.13793103448275862f : cvCbrt(x)));
1284 typedef uchar channel_type;
1286 RGB2Lab_b(int _srccn, int blueIdx, const float* _coeffs,
1287 const float* _whitept, bool _srgb)
1288 : srccn(_srccn), srgb(_srgb)
1290 static volatile int _3 = 3;
1293 if(!_coeffs) _coeffs = sRGB2XYZ_D65;
1294 if(!_whitept) _whitept = D65;
1297 (1 << lab_shift)/_whitept[0],
1298 (float)(1 << lab_shift),
1299 (1 << lab_shift)/_whitept[2]
1302 for( int i = 0; i < _3; i++ )
1304 coeffs[i*3+(blueIdx^2)] = cvRound(_coeffs[i*3]*scale[i]);
1305 coeffs[i*3+1] = cvRound(_coeffs[i*3+1]*scale[i]);
1306 coeffs[i*3+blueIdx] = cvRound(_coeffs[i*3+2]*scale[i]);
1308 CV_Assert( coeffs[i] >= 0 && coeffs[i*3+1] >= 0 && coeffs[i*3+2] >= 0 &&
1309 coeffs[i*3] + coeffs[i*3+1] + coeffs[i*3+2] < 2*(1 << lab_shift) );
1313 void operator()(const uchar* src, uchar* dst, int n) const
1315 const int Lscale = (116*255+50)/100;
1316 const int Lshift = -((16*255*(1 << lab_shift2) + 50)/100);
1317 const ushort* tab = srgb ? sRGBGammaTab_b : linearGammaTab_b;
1319 int C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2],
1320 C3 = coeffs[3], C4 = coeffs[4], C5 = coeffs[5],
1321 C6 = coeffs[6], C7 = coeffs[7], C8 = coeffs[8];
1324 for( i = 0; i < n; i += 3, src += scn )
1326 int R = tab[src[0]], G = tab[src[1]], B = tab[src[2]];
1327 int fX = LabCbrtTab_b[CV_DESCALE(R*C0 + G*C1 + B*C2, lab_shift)];
1328 int fY = LabCbrtTab_b[CV_DESCALE(R*C3 + G*C4 + B*C5, lab_shift)];
1329 int fZ = LabCbrtTab_b[CV_DESCALE(R*C6 + G*C7 + B*C8, lab_shift)];
1331 int L = CV_DESCALE( Lscale*fY + Lshift, lab_shift2 );
1332 int a = CV_DESCALE( 500*(fX - fY) + 128*(1 << lab_shift2), lab_shift2 );
1333 int b = CV_DESCALE( 200*(fY - fZ) + 128*(1 << lab_shift2), lab_shift2 );
1335 dst[i] = saturate_cast<uchar>(L);
1336 dst[i+1] = saturate_cast<uchar>(a);
1337 dst[i+2] = saturate_cast<uchar>(b);
1347 #define clip(value) \
1348 value < 0.0f ? 0.0f : value > 1.0f ? 1.0f : value;
1352 typedef float channel_type;
1354 RGB2Lab_f(int _srccn, int blueIdx, const float* _coeffs,
1355 const float* _whitept, bool _srgb)
1356 : srccn(_srccn), srgb(_srgb)
1358 volatile int _3 = 3;
1362 _coeffs = sRGB2XYZ_D65;
1366 float scale[] = { 1.0f / _whitept[0], 1.0f, 1.0f / _whitept[2] };
1368 for( int i = 0; i < _3; i++ )
1371 coeffs[j + (blueIdx ^ 2)] = _coeffs[j] * scale[i];
1372 coeffs[j + 1] = _coeffs[j + 1] * scale[i];
1373 coeffs[j + blueIdx] = _coeffs[j + 2] * scale[i];
1375 CV_Assert( coeffs[j] >= 0 && coeffs[j + 1] >= 0 && coeffs[j + 2] >= 0 &&
1376 coeffs[j] + coeffs[j + 1] + coeffs[j + 2] < 1.5f*LabCbrtTabScale );
1380 void operator()(const float* src, float* dst, int n) const
1383 float gscale = GammaTabScale;
1384 const float* gammaTab = srgb ? sRGBGammaTab : 0;
1385 float C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2],
1386 C3 = coeffs[3], C4 = coeffs[4], C5 = coeffs[5],
1387 C6 = coeffs[6], C7 = coeffs[7], C8 = coeffs[8];
1390 static const float _1_3 = 1.0f / 3.0f;
1391 static const float _a = 16.0f / 116.0f;
1392 for (i = 0; i < n; i += 3, src += scn )
1394 float R = clip(src[0]);
1395 float G = clip(src[1]);
1396 float B = clip(src[2]);
1398 // CV_Assert(R >= 0.0f && R <= 1.0f);
1399 // CV_Assert(G >= 0.0f && G <= 1.0f);
1400 // CV_Assert(B >= 0.0f && B <= 1.0f);
1404 R = splineInterpolate(R * gscale, gammaTab, GAMMA_TAB_SIZE);
1405 G = splineInterpolate(G * gscale, gammaTab, GAMMA_TAB_SIZE);
1406 B = splineInterpolate(B * gscale, gammaTab, GAMMA_TAB_SIZE);
1408 float X = R*C0 + G*C1 + B*C2;
1409 float Y = R*C3 + G*C4 + B*C5;
1410 float Z = R*C6 + G*C7 + B*C8;
1412 float FX = X > 0.008856f ? pow(X, _1_3) : (7.787f * X + _a);
1413 float FY = Y > 0.008856f ? pow(Y, _1_3) : (7.787f * Y + _a);
1414 float FZ = Z > 0.008856f ? pow(Z, _1_3) : (7.787f * Z + _a);
1416 float L = Y > 0.008856f ? (116.f * FY - 16.f) : (903.3f * Y);
1417 float a = 500.f * (FX - FY);
1418 float b = 200.f * (FY - FZ);
1433 typedef float channel_type;
1435 Lab2RGB_f( int _dstcn, int blueIdx, const float* _coeffs,
1436 const float* _whitept, bool _srgb )
1437 : dstcn(_dstcn), srgb(_srgb), blueInd(blueIdx)
1442 _coeffs = XYZ2sRGB_D65;
1446 for( int i = 0; i < 3; i++ )
1448 coeffs[i+(blueIdx^2)*3] = _coeffs[i]*_whitept[i];
1449 coeffs[i+3] = _coeffs[i+3]*_whitept[i];
1450 coeffs[i+blueIdx*3] = _coeffs[i+6]*_whitept[i];
1454 void operator()(const float* src, float* dst, int n) const
1457 const float* gammaTab = srgb ? sRGBInvGammaTab : 0;
1458 float gscale = GammaTabScale;
1459 float C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2],
1460 C3 = coeffs[3], C4 = coeffs[4], C5 = coeffs[5],
1461 C6 = coeffs[6], C7 = coeffs[7], C8 = coeffs[8];
1462 float alpha = ColorChannel<float>::max();
1465 static const float lThresh = 0.008856f * 903.3f;
1466 static const float fThresh = 7.787f * 0.008856f + 16.0f / 116.0f;
1467 for (i = 0; i < n; i += 3, dst += dcn)
1470 float ai = src[i + 1];
1471 float bi = src[i + 2];
1477 fy = 7.787f * y + 16.0f / 116.0f;
1481 fy = (li + 16.0f) / 116.0f;
1485 float fxz[] = { ai / 500.0f + fy, fy - bi / 200.0f };
1487 for (int j = 0; j < 2; j++)
1488 if (fxz[j] <= fThresh)
1489 fxz[j] = (fxz[j] - 16.0f / 116.0f) / 7.787f;
1491 fxz[j] = fxz[j] * fxz[j] * fxz[j];
1494 float x = fxz[0], z = fxz[1];
1495 float ro = clip(C0 * x + C1 * y + C2 * z);
1496 float go = clip(C3 * x + C4 * y + C5 * z);
1497 float bo = clip(C6 * x + C7 * y + C8 * z);
1499 // CV_Assert(ro >= 0.0f && ro <= 1.0f);
1500 // CV_Assert(go >= 0.0f && go <= 1.0f);
1501 // CV_Assert(bo >= 0.0f && bo <= 1.0f);
1505 ro = splineInterpolate(ro * gscale, gammaTab, GAMMA_TAB_SIZE);
1506 go = splineInterpolate(go * gscale, gammaTab, GAMMA_TAB_SIZE);
1507 bo = splineInterpolate(bo * gscale, gammaTab, GAMMA_TAB_SIZE);
1510 dst[0] = ro, dst[1] = go, dst[2] = bo;
1526 typedef uchar channel_type;
1528 Lab2RGB_b( int _dstcn, int blueIdx, const float* _coeffs,
1529 const float* _whitept, bool _srgb )
1530 : dstcn(_dstcn), cvt(3, blueIdx, _coeffs, _whitept, _srgb ) {}
1532 void operator()(const uchar* src, uchar* dst, int n) const
1534 int i, j, dcn = dstcn;
1535 uchar alpha = ColorChannel<uchar>::max();
1536 float buf[3*BLOCK_SIZE];
1538 for( i = 0; i < n; i += BLOCK_SIZE, src += BLOCK_SIZE*3 )
1540 int dn = std::min(n - i, (int)BLOCK_SIZE);
1542 for( j = 0; j < dn*3; j += 3 )
1544 buf[j] = src[j]*(100.f/255.f);
1545 buf[j+1] = (float)(src[j+1] - 128);
1546 buf[j+2] = (float)(src[j+2] - 128);
1550 for( j = 0; j < dn*3; j += 3, dst += dcn )
1552 dst[0] = saturate_cast<uchar>(buf[j]*255.f);
1553 dst[1] = saturate_cast<uchar>(buf[j+1]*255.f);
1554 dst[2] = saturate_cast<uchar>(buf[j+2]*255.f);
1566 ///////////////////////////////////// RGB <-> L*u*v* /////////////////////////////////////
1570 typedef float channel_type;
1572 RGB2Luv_f( int _srccn, int blueIdx, const float* _coeffs,
1573 const float* whitept, bool _srgb )
1574 : srccn(_srccn), srgb(_srgb)
1579 if(!_coeffs) _coeffs = sRGB2XYZ_D65;
1580 if(!whitept) whitept = D65;
1582 for( i = 0; i < 3; i++ )
1584 coeffs[i*3] = _coeffs[i*3];
1585 coeffs[i*3+1] = _coeffs[i*3+1];
1586 coeffs[i*3+2] = _coeffs[i*3+2];
1588 std::swap(coeffs[i*3], coeffs[i*3+2]);
1589 CV_Assert( coeffs[i*3] >= 0 && coeffs[i*3+1] >= 0 && coeffs[i*3+2] >= 0 &&
1590 coeffs[i*3] + coeffs[i*3+1] + coeffs[i*3+2] < 1.5f );
1593 float d = 1.f/(whitept[0] + whitept[1]*15 + whitept[2]*3);
1594 un = 4*whitept[0]*d;
1595 vn = 9*whitept[1]*d;
1597 CV_Assert(whitept[1] == 1.f);
1600 void operator()(const float* src, float* dst, int n) const
1603 float gscale = GammaTabScale;
1604 const float* gammaTab = srgb ? sRGBGammaTab : 0;
1605 float C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2],
1606 C3 = coeffs[3], C4 = coeffs[4], C5 = coeffs[5],
1607 C6 = coeffs[6], C7 = coeffs[7], C8 = coeffs[8];
1608 float _un = 13*un, _vn = 13*vn;
1611 for( i = 0; i < n; i += 3, src += scn )
1613 float R = src[0], G = src[1], B = src[2];
1616 R = splineInterpolate(R*gscale, gammaTab, GAMMA_TAB_SIZE);
1617 G = splineInterpolate(G*gscale, gammaTab, GAMMA_TAB_SIZE);
1618 B = splineInterpolate(B*gscale, gammaTab, GAMMA_TAB_SIZE);
1621 float X = R*C0 + G*C1 + B*C2;
1622 float Y = R*C3 + G*C4 + B*C5;
1623 float Z = R*C6 + G*C7 + B*C8;
1625 float L = splineInterpolate(Y*LabCbrtTabScale, LabCbrtTab, LAB_CBRT_TAB_SIZE);
1628 float d = (4*13) / std::max(X + 15 * Y + 3 * Z, FLT_EPSILON);
1629 float u = L*(X*d - _un);
1630 float v = L*((9*0.25f)*Y*d - _vn);
1632 dst[i] = L; dst[i+1] = u; dst[i+2] = v;
1637 float coeffs[9], un, vn;
1644 typedef float channel_type;
1646 Luv2RGB_f( int _dstcn, int blueIdx, const float* _coeffs,
1647 const float* whitept, bool _srgb )
1648 : dstcn(_dstcn), srgb(_srgb)
1652 if(!_coeffs) _coeffs = XYZ2sRGB_D65;
1653 if(!whitept) whitept = D65;
1655 for( int i = 0; i < 3; i++ )
1657 coeffs[i+(blueIdx^2)*3] = _coeffs[i];
1658 coeffs[i+3] = _coeffs[i+3];
1659 coeffs[i+blueIdx*3] = _coeffs[i+6];
1662 float d = 1.f/(whitept[0] + whitept[1]*15 + whitept[2]*3);
1663 un = 4*whitept[0]*d;
1664 vn = 9*whitept[1]*d;
1666 CV_Assert(whitept[1] == 1.f);
1669 void operator()(const float* src, float* dst, int n) const
1672 const float* gammaTab = srgb ? sRGBInvGammaTab : 0;
1673 float gscale = GammaTabScale;
1674 float C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2],
1675 C3 = coeffs[3], C4 = coeffs[4], C5 = coeffs[5],
1676 C6 = coeffs[6], C7 = coeffs[7], C8 = coeffs[8];
1677 float alpha = ColorChannel<float>::max();
1678 float _un = un, _vn = vn;
1681 for( i = 0; i < n; i += 3, dst += dcn )
1683 float L = src[i], u = src[i+1], v = src[i+2], d, X, Y, Z;
1684 Y = (L + 16.f) * (1.f/116.f);
1690 X = 2.25f * u * Y * iv ;
1691 Z = (12 - 3 * u - 20 * v) * Y * 0.25f * iv;
1693 float R = X*C0 + Y*C1 + Z*C2;
1694 float G = X*C3 + Y*C4 + Z*C5;
1695 float B = X*C6 + Y*C7 + Z*C8;
1699 R = splineInterpolate(R*gscale, gammaTab, GAMMA_TAB_SIZE);
1700 G = splineInterpolate(G*gscale, gammaTab, GAMMA_TAB_SIZE);
1701 B = splineInterpolate(B*gscale, gammaTab, GAMMA_TAB_SIZE);
1704 dst[0] = R; dst[1] = G; dst[2] = B;
1711 float coeffs[9], un, vn;
1718 typedef uchar channel_type;
1720 RGB2Luv_b( int _srccn, int blueIdx, const float* _coeffs,
1721 const float* _whitept, bool _srgb )
1722 : srccn(_srccn), cvt(3, blueIdx, _coeffs, _whitept, _srgb) {}
1724 void operator()(const uchar* src, uchar* dst, int n) const
1726 int i, j, scn = srccn;
1727 float buf[3*BLOCK_SIZE];
1729 for( i = 0; i < n; i += BLOCK_SIZE, dst += BLOCK_SIZE*3 )
1731 int dn = std::min(n - i, (int)BLOCK_SIZE);
1733 for( j = 0; j < dn*3; j += 3, src += scn )
1735 buf[j] = src[0]*(1.f/255.f);
1736 buf[j+1] = (float)(src[1]*(1.f/255.f));
1737 buf[j+2] = (float)(src[2]*(1.f/255.f));
1741 for( j = 0; j < dn*3; j += 3 )
1743 dst[j] = saturate_cast<uchar>(buf[j]*2.55f);
1744 dst[j+1] = saturate_cast<uchar>(buf[j+1]*0.72033898305084743f + 96.525423728813564f);
1745 dst[j+2] = saturate_cast<uchar>(buf[j+2]*0.99609375f + 139.453125f);
1757 typedef uchar channel_type;
1759 Luv2RGB_b( int _dstcn, int blueIdx, const float* _coeffs,
1760 const float* _whitept, bool _srgb )
1761 : dstcn(_dstcn), cvt(3, blueIdx, _coeffs, _whitept, _srgb ) {}
1763 void operator()(const uchar* src, uchar* dst, int n) const
1765 int i, j, dcn = dstcn;
1766 uchar alpha = ColorChannel<uchar>::max();
1767 float buf[3*BLOCK_SIZE];
1769 for( i = 0; i < n; i += BLOCK_SIZE, src += BLOCK_SIZE*3 )
1771 int dn = std::min(n - i, (int)BLOCK_SIZE);
1773 for( j = 0; j < dn*3; j += 3 )
1775 buf[j] = src[j]*(100.f/255.f);
1776 buf[j+1] = (float)(src[j+1]*1.388235294117647f - 134.f);
1777 buf[j+2] = (float)(src[j+2]*1.003921568627451f - 140.f);
1781 for( j = 0; j < dn*3; j += 3, dst += dcn )
1783 dst[0] = saturate_cast<uchar>(buf[j]*255.f);
1784 dst[1] = saturate_cast<uchar>(buf[j+1]*255.f);
1785 dst[2] = saturate_cast<uchar>(buf[j+2]*255.f);
1797 //////////////////////////// Bayer Pattern -> RGB conversion /////////////////////////////
1799 template<typename T>
1800 class SIMDBayerStubInterpolator_
1803 int bayer2Gray(const T*, int, T*, int, int, int, int) const
1808 int bayer2RGB(const T*, int, T*, int, int) const
1815 class SIMDBayerInterpolator_8u
1818 SIMDBayerInterpolator_8u()
1820 use_simd = checkHardwareSupport(CV_CPU_SSE2);
1823 int bayer2Gray(const uchar* bayer, int bayer_step, uchar* dst,
1824 int width, int bcoeff, int gcoeff, int rcoeff) const
1829 __m128i _b2y = _mm_set1_epi16((short)(rcoeff*2));
1830 __m128i _g2y = _mm_set1_epi16((short)(gcoeff*2));
1831 __m128i _r2y = _mm_set1_epi16((short)(bcoeff*2));
1832 const uchar* bayer_end = bayer + width;
1834 for( ; bayer <= bayer_end - 18; bayer += 14, dst += 14 )
1836 __m128i r0 = _mm_loadu_si128((const __m128i*)bayer);
1837 __m128i r1 = _mm_loadu_si128((const __m128i*)(bayer+bayer_step));
1838 __m128i r2 = _mm_loadu_si128((const __m128i*)(bayer+bayer_step*2));
1840 __m128i b1 = _mm_add_epi16(_mm_srli_epi16(_mm_slli_epi16(r0, 8), 7),
1841 _mm_srli_epi16(_mm_slli_epi16(r2, 8), 7));
1842 __m128i b0 = _mm_add_epi16(b1, _mm_srli_si128(b1, 2));
1843 b1 = _mm_slli_epi16(_mm_srli_si128(b1, 2), 1);
1845 __m128i g0 = _mm_add_epi16(_mm_srli_epi16(r0, 7), _mm_srli_epi16(r2, 7));
1846 __m128i g1 = _mm_srli_epi16(_mm_slli_epi16(r1, 8), 7);
1847 g0 = _mm_add_epi16(g0, _mm_add_epi16(g1, _mm_srli_si128(g1, 2)));
1848 g1 = _mm_slli_epi16(_mm_srli_si128(g1, 2), 2);
1850 r0 = _mm_srli_epi16(r1, 8);
1851 r1 = _mm_slli_epi16(_mm_add_epi16(r0, _mm_srli_si128(r0, 2)), 2);
1852 r0 = _mm_slli_epi16(r0, 3);
1854 g0 = _mm_add_epi16(_mm_mulhi_epi16(b0, _b2y), _mm_mulhi_epi16(g0, _g2y));
1855 g1 = _mm_add_epi16(_mm_mulhi_epi16(b1, _b2y), _mm_mulhi_epi16(g1, _g2y));
1856 g0 = _mm_add_epi16(g0, _mm_mulhi_epi16(r0, _r2y));
1857 g1 = _mm_add_epi16(g1, _mm_mulhi_epi16(r1, _r2y));
1858 g0 = _mm_srli_epi16(g0, 2);
1859 g1 = _mm_srli_epi16(g1, 2);
1860 g0 = _mm_packus_epi16(g0, g0);
1861 g1 = _mm_packus_epi16(g1, g1);
1862 g0 = _mm_unpacklo_epi8(g0, g1);
1863 _mm_storeu_si128((__m128i*)dst, g0);
1866 return (int)(bayer - (bayer_end - width));
1869 int bayer2RGB(const uchar* bayer, int bayer_step, uchar* dst, int width, int blue) const
1874 B G B G | B G B G | B G B G | B G B G
1875 G R G R | G R G R | G R G R | G R G R
1876 B G B G | B G B G | B G B G | B G B G
1878 __m128i delta1 = _mm_set1_epi16(1), delta2 = _mm_set1_epi16(2);
1879 __m128i mask = _mm_set1_epi16(blue < 0 ? -1 : 0), z = _mm_setzero_si128();
1880 __m128i masklo = _mm_set1_epi16(0x00ff);
1881 const uchar* bayer_end = bayer + width;
1883 for( ; bayer <= bayer_end - 18; bayer += 14, dst += 42 )
1885 __m128i r0 = _mm_loadu_si128((const __m128i*)bayer);
1886 __m128i r1 = _mm_loadu_si128((const __m128i*)(bayer+bayer_step));
1887 __m128i r2 = _mm_loadu_si128((const __m128i*)(bayer+bayer_step*2));
1889 __m128i b1 = _mm_add_epi16(_mm_and_si128(r0, masklo), _mm_and_si128(r2, masklo));
1890 __m128i b0 = _mm_add_epi16(b1, _mm_srli_si128(b1, 2));
1891 b1 = _mm_srli_si128(b1, 2);
1892 b1 = _mm_srli_epi16(_mm_add_epi16(b1, delta1), 1);
1893 b0 = _mm_srli_epi16(_mm_add_epi16(b0, delta2), 2);
1894 b0 = _mm_packus_epi16(b0, b1);
1896 __m128i g0 = _mm_add_epi16(_mm_srli_epi16(r0, 8), _mm_srli_epi16(r2, 8));
1897 __m128i g1 = _mm_and_si128(r1, masklo);
1898 g0 = _mm_add_epi16(g0, _mm_add_epi16(g1, _mm_srli_si128(g1, 2)));
1899 g1 = _mm_srli_si128(g1, 2);
1900 g0 = _mm_srli_epi16(_mm_add_epi16(g0, delta2), 2);
1901 g0 = _mm_packus_epi16(g0, g1);
1903 r0 = _mm_srli_epi16(r1, 8);
1904 r1 = _mm_add_epi16(r0, _mm_srli_si128(r0, 2));
1905 r1 = _mm_srli_epi16(_mm_add_epi16(r1, delta1), 1);
1906 r0 = _mm_packus_epi16(r0, r1);
1908 b1 = _mm_and_si128(_mm_xor_si128(b0, r0), mask);
1909 b0 = _mm_xor_si128(b0, b1);
1910 r0 = _mm_xor_si128(r0, b1);
1913 b1 = _mm_unpackhi_epi8(b0, g0);
1914 // b0 g0 b2 g2 b4 g4 ....
1915 b0 = _mm_unpacklo_epi8(b0, g0);
1918 r1 = _mm_unpackhi_epi8(r0, z);
1919 // r0 0 r2 0 r4 0 ...
1920 r0 = _mm_unpacklo_epi8(r0, z);
1922 // 0 b0 g0 r0 0 b2 g2 r2 0 ...
1923 g0 = _mm_slli_si128(_mm_unpacklo_epi16(b0, r0), 1);
1924 // 0 b8 g8 r8 0 b10 g10 r10 0 ...
1925 g1 = _mm_slli_si128(_mm_unpackhi_epi16(b0, r0), 1);
1927 // b1 g1 r1 0 b3 g3 r3 ....
1928 r0 = _mm_unpacklo_epi16(b1, r1);
1930 r1 = _mm_unpackhi_epi16(b1, r1);
1932 b0 = _mm_srli_si128(_mm_unpacklo_epi32(g0, r0), 1);
1933 b1 = _mm_srli_si128(_mm_unpackhi_epi32(g0, r0), 1);
1935 _mm_storel_epi64((__m128i*)(dst-1+0), b0);
1936 _mm_storel_epi64((__m128i*)(dst-1+6*1), _mm_srli_si128(b0, 8));
1937 _mm_storel_epi64((__m128i*)(dst-1+6*2), b1);
1938 _mm_storel_epi64((__m128i*)(dst-1+6*3), _mm_srli_si128(b1, 8));
1940 g0 = _mm_srli_si128(_mm_unpacklo_epi32(g1, r1), 1);
1941 g1 = _mm_srli_si128(_mm_unpackhi_epi32(g1, r1), 1);
1943 _mm_storel_epi64((__m128i*)(dst-1+6*4), g0);
1944 _mm_storel_epi64((__m128i*)(dst-1+6*5), _mm_srli_si128(g0, 8));
1946 _mm_storel_epi64((__m128i*)(dst-1+6*6), g1);
1949 return (int)(bayer - (bayer_end - width));
1955 typedef SIMDBayerStubInterpolator_<uchar> SIMDBayerInterpolator_8u;
1958 template<typename T, class SIMDInterpolator>
1959 static void Bayer2Gray_( const Mat& srcmat, Mat& dstmat, int code )
1961 SIMDInterpolator vecOp;
1962 const int R2Y = 4899;
1963 const int G2Y = 9617;
1964 const int B2Y = 1868;
1965 const int SHIFT = 14;
1967 const T* bayer0 = (const T*)srcmat.data;
1968 int bayer_step = (int)(srcmat.step/sizeof(T));
1969 T* dst0 = (T*)dstmat.data;
1970 int dst_step = (int)(dstmat.step/sizeof(T));
1971 Size size = srcmat.size();
1972 int bcoeff = B2Y, rcoeff = R2Y;
1973 int start_with_green = code == CV_BayerGB2GRAY || code == CV_BayerGR2GRAY;
1976 if( code != CV_BayerBG2GRAY && code != CV_BayerGB2GRAY )
1979 std::swap(bcoeff, rcoeff);
1982 dst0 += dst_step + 1;
1986 for( ; size.height-- > 0; bayer0 += bayer_step, dst0 += dst_step )
1988 unsigned t0, t1, t2;
1989 const T* bayer = bayer0;
1991 const T* bayer_end = bayer + size.width;
1993 if( size.width <= 0 )
1995 dst[-1] = dst[size.width] = 0;
1999 if( start_with_green )
2001 t0 = (bayer[1] + bayer[bayer_step*2+1])*rcoeff;
2002 t1 = (bayer[bayer_step] + bayer[bayer_step+2])*bcoeff;
2003 t2 = bayer[bayer_step+1]*(2*G2Y);
2005 dst[0] = (T)CV_DESCALE(t0 + t1 + t2, SHIFT+1);
2010 int delta = vecOp.bayer2Gray(bayer, bayer_step, dst, size.width, bcoeff, G2Y, rcoeff);
2014 for( ; bayer <= bayer_end - 2; bayer += 2, dst += 2 )
2016 t0 = (bayer[0] + bayer[2] + bayer[bayer_step*2] + bayer[bayer_step*2+2])*rcoeff;
2017 t1 = (bayer[1] + bayer[bayer_step] + bayer[bayer_step+2] + bayer[bayer_step*2+1])*G2Y;
2018 t2 = bayer[bayer_step+1]*(4*bcoeff);
2019 dst[0] = (T)CV_DESCALE(t0 + t1 + t2, SHIFT+2);
2021 t0 = (bayer[2] + bayer[bayer_step*2+2])*rcoeff;
2022 t1 = (bayer[bayer_step+1] + bayer[bayer_step+3])*bcoeff;
2023 t2 = bayer[bayer_step+2]*(2*G2Y);
2024 dst[1] = (T)CV_DESCALE(t0 + t1 + t2, SHIFT+1);
2027 if( bayer < bayer_end )
2029 t0 = (bayer[0] + bayer[2] + bayer[bayer_step*2] + bayer[bayer_step*2+2])*rcoeff;
2030 t1 = (bayer[1] + bayer[bayer_step] + bayer[bayer_step+2] + bayer[bayer_step*2+1])*G2Y;
2031 t2 = bayer[bayer_step+1]*(4*bcoeff);
2032 dst[0] = (T)CV_DESCALE(t0 + t1 + t2, SHIFT+2);
2038 dst0[size.width] = dst0[size.width-1];
2041 std::swap(bcoeff, rcoeff);
2042 start_with_green = !start_with_green;
2045 size = dstmat.size();
2046 dst0 = (T*)dstmat.data;
2047 if( size.height > 2 )
2048 for( int i = 0; i < size.width; i++ )
2050 dst0[i] = dst0[i + dst_step];
2051 dst0[i + (size.height-1)*dst_step] = dst0[i + (size.height-2)*dst_step];
2054 for( int i = 0; i < size.width; i++ )
2056 dst0[i] = dst0[i + (size.height-1)*dst_step] = 0;
2060 template<typename T, class SIMDInterpolator>
2061 static void Bayer2RGB_( const Mat& srcmat, Mat& dstmat, int code )
2063 SIMDInterpolator vecOp;
2064 const T* bayer0 = (const T*)srcmat.data;
2065 int bayer_step = (int)(srcmat.step/sizeof(T));
2066 T* dst0 = (T*)dstmat.data;
2067 int dst_step = (int)(dstmat.step/sizeof(T));
2068 Size size = srcmat.size();
2069 int blue = code == CV_BayerBG2BGR || code == CV_BayerGB2BGR ? -1 : 1;
2070 int start_with_green = code == CV_BayerGB2BGR || code == CV_BayerGR2BGR;
2072 dst0 += dst_step + 3 + 1;
2076 for( ; size.height-- > 0; bayer0 += bayer_step, dst0 += dst_step )
2079 const T* bayer = bayer0;
2081 const T* bayer_end = bayer + size.width;
2083 if( size.width <= 0 )
2085 dst[-4] = dst[-3] = dst[-2] = dst[size.width*3-1] =
2086 dst[size.width*3] = dst[size.width*3+1] = 0;
2090 if( start_with_green )
2092 t0 = (bayer[1] + bayer[bayer_step*2+1] + 1) >> 1;
2093 t1 = (bayer[bayer_step] + bayer[bayer_step+2] + 1) >> 1;
2095 dst[0] = bayer[bayer_step+1];
2101 int delta = vecOp.bayer2RGB(bayer, bayer_step, dst, size.width, blue);
2107 for( ; bayer <= bayer_end - 2; bayer += 2, dst += 6 )
2109 t0 = (bayer[0] + bayer[2] + bayer[bayer_step*2] +
2110 bayer[bayer_step*2+2] + 2) >> 2;
2111 t1 = (bayer[1] + bayer[bayer_step] +
2112 bayer[bayer_step+2] + bayer[bayer_step*2+1]+2) >> 2;
2115 dst[1] = bayer[bayer_step+1];
2117 t0 = (bayer[2] + bayer[bayer_step*2+2] + 1) >> 1;
2118 t1 = (bayer[bayer_step+1] + bayer[bayer_step+3] + 1) >> 1;
2120 dst[3] = bayer[bayer_step+2];
2126 for( ; bayer <= bayer_end - 2; bayer += 2, dst += 6 )
2128 t0 = (bayer[0] + bayer[2] + bayer[bayer_step*2] +
2129 bayer[bayer_step*2+2] + 2) >> 2;
2130 t1 = (bayer[1] + bayer[bayer_step] +
2131 bayer[bayer_step+2] + bayer[bayer_step*2+1]+2) >> 2;
2134 dst[-1] = bayer[bayer_step+1];
2136 t0 = (bayer[2] + bayer[bayer_step*2+2] + 1) >> 1;
2137 t1 = (bayer[bayer_step+1] + bayer[bayer_step+3] + 1) >> 1;
2139 dst[3] = bayer[bayer_step+2];
2144 if( bayer < bayer_end )
2146 t0 = (bayer[0] + bayer[2] + bayer[bayer_step*2] +
2147 bayer[bayer_step*2+2] + 2) >> 2;
2148 t1 = (bayer[1] + bayer[bayer_step] +
2149 bayer[bayer_step+2] + bayer[bayer_step*2+1]+2) >> 2;
2152 dst[blue] = bayer[bayer_step+1];
2157 dst0[-4] = dst0[-1];
2160 dst0[size.width*3-1] = dst0[size.width*3-4];
2161 dst0[size.width*3] = dst0[size.width*3-3];
2162 dst0[size.width*3+1] = dst0[size.width*3-2];
2165 start_with_green = !start_with_green;
2168 size = dstmat.size();
2169 dst0 = (T*)dstmat.data;
2170 if( size.height > 2 )
2171 for( int i = 0; i < size.width*3; i++ )
2173 dst0[i] = dst0[i + dst_step];
2174 dst0[i + (size.height-1)*dst_step] = dst0[i + (size.height-2)*dst_step];
2177 for( int i = 0; i < size.width*3; i++ )
2179 dst0[i] = dst0[i + (size.height-1)*dst_step] = 0;
2184 /////////////////// Demosaicing using Variable Number of Gradients ///////////////////////
2186 static void Bayer2RGB_VNG_8u( const Mat& srcmat, Mat& dstmat, int code )
2188 const uchar* bayer = srcmat.data;
2189 int bstep = (int)srcmat.step;
2190 uchar* dst = dstmat.data;
2191 int dststep = (int)dstmat.step;
2192 Size size = srcmat.size();
2194 int blueIdx = code == CV_BayerBG2BGR_VNG || code == CV_BayerGB2BGR_VNG ? 0 : 2;
2195 bool greenCell0 = code != CV_BayerBG2BGR_VNG && code != CV_BayerRG2BGR_VNG;
2197 // for too small images use the simple interpolation algorithm
2198 if( MIN(size.width, size.height) < 8 )
2200 Bayer2RGB_<uchar, SIMDBayerInterpolator_8u>( srcmat, dstmat, code );
2204 const int brows = 3, bcn = 7;
2205 int N = size.width, N2 = N*2, N3 = N*3, N4 = N*4, N5 = N*5, N6 = N*6, N7 = N*7;
2206 int i, bufstep = N7*bcn;
2207 cv::AutoBuffer<ushort> _buf(bufstep*brows);
2208 ushort* buf = (ushort*)_buf;
2213 bool haveSSE = cv::checkHardwareSupport(CV_CPU_SSE2);
2214 #define _mm_absdiff_epu16(a,b) _mm_adds_epu16(_mm_subs_epu16(a, b), _mm_subs_epu16(b, a))
2217 for( int y = 2; y < size.height - 4; y++ )
2219 uchar* dstrow = dst + dststep*y + 6;
2222 for( int dy = (y == 2 ? -1 : 1); dy <= 1; dy++ )
2224 ushort* brow = buf + ((y + dy - 1)%brows)*bufstep + 1;
2225 srow = bayer + (y+dy)*bstep + 1;
2227 for( i = 0; i < bcn; i++ )
2228 brow[N*i-1] = brow[(N-2) + N*i] = 0;
2235 __m128i z = _mm_setzero_si128();
2236 for( ; i <= N-9; i += 8, srow += 8, brow += 8 )
2238 __m128i s1, s2, s3, s4, s6, s7, s8, s9;
2240 s1 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow-1-bstep)),z);
2241 s2 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow-bstep)),z);
2242 s3 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow+1-bstep)),z);
2244 s4 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow-1)),z);
2245 s6 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow+1)),z);
2247 s7 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow-1+bstep)),z);
2248 s8 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow+bstep)),z);
2249 s9 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow+1+bstep)),z);
2251 __m128i b0, b1, b2, b3, b4, b5, b6;
2253 b0 = _mm_adds_epu16(_mm_slli_epi16(_mm_absdiff_epu16(s2,s8),1),
2254 _mm_adds_epu16(_mm_absdiff_epu16(s1, s7),
2255 _mm_absdiff_epu16(s3, s9)));
2256 b1 = _mm_adds_epu16(_mm_slli_epi16(_mm_absdiff_epu16(s4,s6),1),
2257 _mm_adds_epu16(_mm_absdiff_epu16(s1, s3),
2258 _mm_absdiff_epu16(s7, s9)));
2259 b2 = _mm_slli_epi16(_mm_absdiff_epu16(s3,s7),1);
2260 b3 = _mm_slli_epi16(_mm_absdiff_epu16(s1,s9),1);
2262 _mm_storeu_si128((__m128i*)brow, b0);
2263 _mm_storeu_si128((__m128i*)(brow + N), b1);
2264 _mm_storeu_si128((__m128i*)(brow + N2), b2);
2265 _mm_storeu_si128((__m128i*)(brow + N3), b3);
2267 b4 = _mm_adds_epu16(b2,_mm_adds_epu16(_mm_absdiff_epu16(s2, s4),
2268 _mm_absdiff_epu16(s6, s8)));
2269 b5 = _mm_adds_epu16(b3,_mm_adds_epu16(_mm_absdiff_epu16(s2, s6),
2270 _mm_absdiff_epu16(s4, s8)));
2271 b6 = _mm_adds_epu16(_mm_adds_epu16(s2, s4), _mm_adds_epu16(s6, s8));
2272 b6 = _mm_srli_epi16(b6, 1);
2274 _mm_storeu_si128((__m128i*)(brow + N4), b4);
2275 _mm_storeu_si128((__m128i*)(brow + N5), b5);
2276 _mm_storeu_si128((__m128i*)(brow + N6), b6);
2281 for( ; i < N-1; i++, srow++, brow++ )
2283 brow[0] = (ushort)(std::abs(srow[-1-bstep] - srow[-1+bstep]) +
2284 std::abs(srow[-bstep] - srow[+bstep])*2 +
2285 std::abs(srow[1-bstep] - srow[1+bstep]));
2286 brow[N] = (ushort)(std::abs(srow[-1-bstep] - srow[1-bstep]) +
2287 std::abs(srow[-1] - srow[1])*2 +
2288 std::abs(srow[-1+bstep] - srow[1+bstep]));
2289 brow[N2] = (ushort)(std::abs(srow[+1-bstep] - srow[-1+bstep])*2);
2290 brow[N3] = (ushort)(std::abs(srow[-1-bstep] - srow[1+bstep])*2);
2291 brow[N4] = (ushort)(brow[N2] + std::abs(srow[-bstep] - srow[-1]) +
2292 std::abs(srow[+bstep] - srow[1]));
2293 brow[N5] = (ushort)(brow[N3] + std::abs(srow[-bstep] - srow[1]) +
2294 std::abs(srow[+bstep] - srow[-1]));
2295 brow[N6] = (ushort)((srow[-bstep] + srow[-1] + srow[1] + srow[+bstep])>>1);
2299 const ushort* brow0 = buf + ((y - 2) % brows)*bufstep + 2;
2300 const ushort* brow1 = buf + ((y - 1) % brows)*bufstep + 2;
2301 const ushort* brow2 = buf + (y % brows)*bufstep + 2;
2302 static const float scale[] = { 0.f, 0.5f, 0.25f, 0.1666666666667f, 0.125f, 0.1f, 0.08333333333f, 0.0714286f, 0.0625f };
2303 srow = bayer + y*bstep + 2;
2304 bool greenCell = greenCell0;
2308 int limit = !haveSSE ? N-2 : greenCell ? std::min(3, N-2) : 2;
2315 for( ; i < limit; i++, srow++, brow0++, brow1++, brow2++, dstrow += 3 )
2317 int gradN = brow0[0] + brow1[0];
2318 int gradS = brow1[0] + brow2[0];
2319 int gradW = brow1[N-1] + brow1[N];
2320 int gradE = brow1[N] + brow1[N+1];
2321 int minGrad = std::min(std::min(std::min(gradN, gradS), gradW), gradE);
2322 int maxGrad = std::max(std::max(std::max(gradN, gradS), gradW), gradE);
2327 int gradNE = brow0[N4+1] + brow1[N4];
2328 int gradSW = brow1[N4] + brow2[N4-1];
2329 int gradNW = brow0[N5-1] + brow1[N5];
2330 int gradSE = brow1[N5] + brow2[N5+1];
2332 minGrad = std::min(std::min(std::min(std::min(minGrad, gradNE), gradSW), gradNW), gradSE);
2333 maxGrad = std::max(std::max(std::max(std::max(maxGrad, gradNE), gradSW), gradNW), gradSE);
2334 int T = minGrad + MAX(maxGrad/2, 1);
2336 int Rs = 0, Gs = 0, Bs = 0, ng = 0;
2339 Rs += srow[-bstep*2] + srow[0];
2340 Gs += srow[-bstep]*2;
2341 Bs += srow[-bstep-1] + srow[-bstep+1];
2346 Rs += srow[bstep*2] + srow[0];
2347 Gs += srow[bstep]*2;
2348 Bs += srow[bstep-1] + srow[bstep+1];
2353 Rs += srow[-2] + srow[0];
2355 Bs += srow[-bstep-1] + srow[bstep-1];
2360 Rs += srow[2] + srow[0];
2362 Bs += srow[-bstep+1] + srow[bstep+1];
2367 Rs += srow[-bstep*2+2] + srow[0];
2369 Bs += srow[-bstep+1]*2;
2374 Rs += srow[bstep*2-2] + srow[0];
2376 Bs += srow[bstep-1]*2;
2381 Rs += srow[-bstep*2-2] + srow[0];
2383 Bs += srow[-bstep+1]*2;
2388 Rs += srow[bstep*2+2] + srow[0];
2390 Bs += srow[-bstep+1]*2;
2394 G = R + cvRound((Gs - Rs)*scale[ng]);
2395 B = R + cvRound((Bs - Rs)*scale[ng]);
2399 int gradNE = brow0[N2] + brow0[N2+1] + brow1[N2] + brow1[N2+1];
2400 int gradSW = brow1[N2] + brow1[N2-1] + brow2[N2] + brow2[N2-1];
2401 int gradNW = brow0[N3] + brow0[N3-1] + brow1[N3] + brow1[N3-1];
2402 int gradSE = brow1[N3] + brow1[N3+1] + brow2[N3] + brow2[N3+1];
2404 minGrad = std::min(std::min(std::min(std::min(minGrad, gradNE), gradSW), gradNW), gradSE);
2405 maxGrad = std::max(std::max(std::max(std::max(maxGrad, gradNE), gradSW), gradNW), gradSE);
2406 int T = minGrad + MAX(maxGrad/2, 1);
2408 int Rs = 0, Gs = 0, Bs = 0, ng = 0;
2411 Rs += srow[-bstep*2-1] + srow[-bstep*2+1];
2412 Gs += srow[-bstep*2] + srow[0];
2413 Bs += srow[-bstep]*2;
2418 Rs += srow[bstep*2-1] + srow[bstep*2+1];
2419 Gs += srow[bstep*2] + srow[0];
2420 Bs += srow[bstep]*2;
2426 Gs += srow[-2] + srow[0];
2427 Bs += srow[-bstep-2]+srow[bstep-2];
2433 Gs += srow[2] + srow[0];
2434 Bs += srow[-bstep+2]+srow[bstep+2];
2439 Rs += srow[-bstep*2+1] + srow[1];
2440 Gs += srow[-bstep+1]*2;
2441 Bs += srow[-bstep] + srow[-bstep+2];
2446 Rs += srow[bstep*2-1] + srow[-1];
2447 Gs += srow[bstep-1]*2;
2448 Bs += srow[bstep] + srow[bstep-2];
2453 Rs += srow[-bstep*2-1] + srow[-1];
2454 Gs += srow[-bstep-1]*2;
2455 Bs += srow[-bstep-2]+srow[-bstep];
2460 Rs += srow[bstep*2+1] + srow[1];
2461 Gs += srow[bstep+1]*2;
2462 Bs += srow[bstep+2]+srow[bstep];
2466 R = G + cvRound((Rs - Gs)*scale[ng]);
2467 B = G + cvRound((Bs - Gs)*scale[ng]);
2469 dstrow[blueIdx] = CV_CAST_8U(B);
2470 dstrow[1] = CV_CAST_8U(G);
2471 dstrow[blueIdx^2] = CV_CAST_8U(R);
2472 greenCell = !greenCell;
2479 __m128i emask = _mm_set1_epi32(0x0000ffff),
2480 omask = _mm_set1_epi32(0xffff0000),
2481 z = _mm_setzero_si128(),
2482 one = _mm_set1_epi16(1);
2483 __m128 _0_5 = _mm_set1_ps(0.5f);
2485 #define _mm_merge_epi16(a, b) _mm_or_si128(_mm_and_si128(a, emask), _mm_and_si128(b, omask)) //(aA_aA_aA_aA) * (bB_bB_bB_bB) => (bA_bA_bA_bA)
2486 #define _mm_cvtloepi16_ps(a) _mm_cvtepi32_ps(_mm_srai_epi32(_mm_unpacklo_epi16(a,a), 16)) //(1,2,3,4,5,6,7,8) => (1f,2f,3f,4f)
2487 #define _mm_cvthiepi16_ps(a) _mm_cvtepi32_ps(_mm_srai_epi32(_mm_unpackhi_epi16(a,a), 16)) //(1,2,3,4,5,6,7,8) => (5f,6f,7f,8f)
2488 #define _mm_loadl_u8_s16(ptr, offset) _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)((ptr) + (offset))), z) //load 8 uchars to 8 shorts
2490 // process 8 pixels at once
2491 for( ; i <= N - 10; i += 8, srow += 8, brow0 += 8, brow1 += 8, brow2 += 8 )
2493 //int gradN = brow0[0] + brow1[0];
2494 __m128i gradN = _mm_adds_epi16(_mm_loadu_si128((__m128i*)brow0), _mm_loadu_si128((__m128i*)brow1));
2496 //int gradS = brow1[0] + brow2[0];
2497 __m128i gradS = _mm_adds_epi16(_mm_loadu_si128((__m128i*)brow1), _mm_loadu_si128((__m128i*)brow2));
2499 //int gradW = brow1[N-1] + brow1[N];
2500 __m128i gradW = _mm_adds_epi16(_mm_loadu_si128((__m128i*)(brow1+N-1)), _mm_loadu_si128((__m128i*)(brow1+N)));
2502 //int gradE = brow1[N+1] + brow1[N];
2503 __m128i gradE = _mm_adds_epi16(_mm_loadu_si128((__m128i*)(brow1+N+1)), _mm_loadu_si128((__m128i*)(brow1+N)));
2505 //int minGrad = std::min(std::min(std::min(gradN, gradS), gradW), gradE);
2506 //int maxGrad = std::max(std::max(std::max(gradN, gradS), gradW), gradE);
2507 __m128i minGrad = _mm_min_epi16(_mm_min_epi16(gradN, gradS), _mm_min_epi16(gradW, gradE));
2508 __m128i maxGrad = _mm_max_epi16(_mm_max_epi16(gradN, gradS), _mm_max_epi16(gradW, gradE));
2510 __m128i grad0, grad1;
2512 //int gradNE = brow0[N4+1] + brow1[N4];
2513 //int gradNE = brow0[N2] + brow0[N2+1] + brow1[N2] + brow1[N2+1];
2514 grad0 = _mm_adds_epi16(_mm_loadu_si128((__m128i*)(brow0+N4+1)), _mm_loadu_si128((__m128i*)(brow1+N4)));
2515 grad1 = _mm_adds_epi16( _mm_adds_epi16(_mm_loadu_si128((__m128i*)(brow0+N2)), _mm_loadu_si128((__m128i*)(brow0+N2+1))),
2516 _mm_adds_epi16(_mm_loadu_si128((__m128i*)(brow1+N2)), _mm_loadu_si128((__m128i*)(brow1+N2+1))));
2517 __m128i gradNE = _mm_merge_epi16(grad0, grad1);
2519 //int gradSW = brow1[N4] + brow2[N4-1];
2520 //int gradSW = brow1[N2] + brow1[N2-1] + brow2[N2] + brow2[N2-1];
2521 grad0 = _mm_adds_epi16(_mm_loadu_si128((__m128i*)(brow2+N4-1)), _mm_loadu_si128((__m128i*)(brow1+N4)));
2522 grad1 = _mm_adds_epi16(_mm_adds_epi16(_mm_loadu_si128((__m128i*)(brow2+N2)), _mm_loadu_si128((__m128i*)(brow2+N2-1))),
2523 _mm_adds_epi16(_mm_loadu_si128((__m128i*)(brow1+N2)), _mm_loadu_si128((__m128i*)(brow1+N2-1))));
2524 __m128i gradSW = _mm_merge_epi16(grad0, grad1);
2526 minGrad = _mm_min_epi16(_mm_min_epi16(minGrad, gradNE), gradSW);
2527 maxGrad = _mm_max_epi16(_mm_max_epi16(maxGrad, gradNE), gradSW);
2529 //int gradNW = brow0[N5-1] + brow1[N5];
2530 //int gradNW = brow0[N3] + brow0[N3-1] + brow1[N3] + brow1[N3-1];
2531 grad0 = _mm_adds_epi16(_mm_loadu_si128((__m128i*)(brow0+N5-1)), _mm_loadu_si128((__m128i*)(brow1+N5)));
2532 grad1 = _mm_adds_epi16(_mm_adds_epi16(_mm_loadu_si128((__m128i*)(brow0+N3)), _mm_loadu_si128((__m128i*)(brow0+N3-1))),
2533 _mm_adds_epi16(_mm_loadu_si128((__m128i*)(brow1+N3)), _mm_loadu_si128((__m128i*)(brow1+N3-1))));
2534 __m128i gradNW = _mm_merge_epi16(grad0, grad1);
2536 //int gradSE = brow1[N5] + brow2[N5+1];
2537 //int gradSE = brow1[N3] + brow1[N3+1] + brow2[N3] + brow2[N3+1];
2538 grad0 = _mm_adds_epi16(_mm_loadu_si128((__m128i*)(brow2+N5+1)), _mm_loadu_si128((__m128i*)(brow1+N5)));
2539 grad1 = _mm_adds_epi16(_mm_adds_epi16(_mm_loadu_si128((__m128i*)(brow2+N3)), _mm_loadu_si128((__m128i*)(brow2+N3+1))),
2540 _mm_adds_epi16(_mm_loadu_si128((__m128i*)(brow1+N3)), _mm_loadu_si128((__m128i*)(brow1+N3+1))));
2541 __m128i gradSE = _mm_merge_epi16(grad0, grad1);
2543 minGrad = _mm_min_epi16(_mm_min_epi16(minGrad, gradNW), gradSE);
2544 maxGrad = _mm_max_epi16(_mm_max_epi16(maxGrad, gradNW), gradSE);
2546 //int T = minGrad + maxGrad/2;
2547 __m128i T = _mm_adds_epi16(_mm_max_epi16(_mm_srli_epi16(maxGrad, 1), one), minGrad);
2549 __m128i RGs = z, GRs = z, Bs = z, ng = z;
2551 __m128i x0 = _mm_loadl_u8_s16(srow, +0 );
2552 __m128i x1 = _mm_loadl_u8_s16(srow, -1 - bstep );
2553 __m128i x2 = _mm_loadl_u8_s16(srow, -1 - bstep*2);
2554 __m128i x3 = _mm_loadl_u8_s16(srow, - bstep );
2555 __m128i x4 = _mm_loadl_u8_s16(srow, +1 - bstep*2);
2556 __m128i x5 = _mm_loadl_u8_s16(srow, +1 - bstep );
2557 __m128i x6 = _mm_loadl_u8_s16(srow, +2 - bstep );
2558 __m128i x7 = _mm_loadl_u8_s16(srow, +1 );
2559 __m128i x8 = _mm_loadl_u8_s16(srow, +2 + bstep );
2560 __m128i x9 = _mm_loadl_u8_s16(srow, +1 + bstep );
2561 __m128i x10 = _mm_loadl_u8_s16(srow, +1 + bstep*2);
2562 __m128i x11 = _mm_loadl_u8_s16(srow, + bstep );
2563 __m128i x12 = _mm_loadl_u8_s16(srow, -1 + bstep*2);
2564 __m128i x13 = _mm_loadl_u8_s16(srow, -1 + bstep );
2565 __m128i x14 = _mm_loadl_u8_s16(srow, -2 + bstep );
2566 __m128i x15 = _mm_loadl_u8_s16(srow, -1 );
2567 __m128i x16 = _mm_loadl_u8_s16(srow, -2 - bstep );
2569 __m128i t0, t1, mask;
2571 // gradN ***********************************************
2572 mask = _mm_cmpgt_epi16(T, gradN); // mask = T>gradN
2573 ng = _mm_sub_epi16(ng, mask); // ng += (T>gradN)
2575 t0 = _mm_slli_epi16(x3, 1); // srow[-bstep]*2
2576 t1 = _mm_adds_epi16(_mm_loadl_u8_s16(srow, -bstep*2), x0); // srow[-bstep*2] + srow[0]
2578 // RGs += (srow[-bstep*2] + srow[0]) * (T>gradN)
2579 RGs = _mm_adds_epi16(RGs, _mm_and_si128(t1, mask));
2580 // GRs += {srow[-bstep]*2; (srow[-bstep*2-1] + srow[-bstep*2+1])} * (T>gradN)
2581 GRs = _mm_adds_epi16(GRs, _mm_and_si128(_mm_merge_epi16(t0, _mm_adds_epi16(x2,x4)), mask));
2582 // Bs += {(srow[-bstep-1]+srow[-bstep+1]); srow[-bstep]*2 } * (T>gradN)
2583 Bs = _mm_adds_epi16(Bs, _mm_and_si128(_mm_merge_epi16(_mm_adds_epi16(x1,x5), t0), mask));
2585 // gradNE **********************************************
2586 mask = _mm_cmpgt_epi16(T, gradNE); // mask = T>gradNE
2587 ng = _mm_sub_epi16(ng, mask); // ng += (T>gradNE)
2589 t0 = _mm_slli_epi16(x5, 1); // srow[-bstep+1]*2
2590 t1 = _mm_adds_epi16(_mm_loadl_u8_s16(srow, -bstep*2+2), x0); // srow[-bstep*2+2] + srow[0]
2592 // RGs += {(srow[-bstep*2+2] + srow[0]); srow[-bstep+1]*2} * (T>gradNE)
2593 RGs = _mm_adds_epi16(RGs, _mm_and_si128(_mm_merge_epi16(t1, t0), mask));
2594 // GRs += {brow0[N6+1]; (srow[-bstep*2+1] + srow[1])} * (T>gradNE)
2595 GRs = _mm_adds_epi16(GRs, _mm_and_si128(_mm_merge_epi16(_mm_loadu_si128((__m128i*)(brow0+N6+1)), _mm_adds_epi16(x4,x7)), mask));
2596 // Bs += {srow[-bstep+1]*2; (srow[-bstep] + srow[-bstep+2])} * (T>gradNE)
2597 Bs = _mm_adds_epi16(Bs, _mm_and_si128(_mm_merge_epi16(t0,_mm_adds_epi16(x3,x6)), mask));
2599 // gradE ***********************************************
2600 mask = _mm_cmpgt_epi16(T, gradE); // mask = T>gradE
2601 ng = _mm_sub_epi16(ng, mask); // ng += (T>gradE)
2603 t0 = _mm_slli_epi16(x7, 1); // srow[1]*2
2604 t1 = _mm_adds_epi16(_mm_loadl_u8_s16(srow, 2), x0); // srow[2] + srow[0]
2606 // RGs += (srow[2] + srow[0]) * (T>gradE)
2607 RGs = _mm_adds_epi16(RGs, _mm_and_si128(t1, mask));
2608 // GRs += (srow[1]*2) * (T>gradE)
2609 GRs = _mm_adds_epi16(GRs, _mm_and_si128(t0, mask));
2610 // Bs += {(srow[-bstep+1]+srow[bstep+1]); (srow[-bstep+2]+srow[bstep+2])} * (T>gradE)
2611 Bs = _mm_adds_epi16(Bs, _mm_and_si128(_mm_merge_epi16(_mm_adds_epi16(x5,x9), _mm_adds_epi16(x6,x8)), mask));
2613 // gradSE **********************************************
2614 mask = _mm_cmpgt_epi16(T, gradSE); // mask = T>gradSE
2615 ng = _mm_sub_epi16(ng, mask); // ng += (T>gradSE)
2617 t0 = _mm_slli_epi16(x9, 1); // srow[bstep+1]*2
2618 t1 = _mm_adds_epi16(_mm_loadl_u8_s16(srow, bstep*2+2), x0); // srow[bstep*2+2] + srow[0]
2620 // RGs += {(srow[bstep*2+2] + srow[0]); srow[bstep+1]*2} * (T>gradSE)
2621 RGs = _mm_adds_epi16(RGs, _mm_and_si128(_mm_merge_epi16(t1, t0), mask));
2622 // GRs += {brow2[N6+1]; (srow[1]+srow[bstep*2+1])} * (T>gradSE)
2623 GRs = _mm_adds_epi16(GRs, _mm_and_si128(_mm_merge_epi16(_mm_loadu_si128((__m128i*)(brow2+N6+1)), _mm_adds_epi16(x7,x10)), mask));
2624 // Bs += {srow[-bstep+1]*2; (srow[bstep+2]+srow[bstep])} * (T>gradSE)
2625 Bs = _mm_adds_epi16(Bs, _mm_and_si128(_mm_merge_epi16(_mm_slli_epi16(x5, 1), _mm_adds_epi16(x8,x11)), mask));
2627 // gradS ***********************************************
2628 mask = _mm_cmpgt_epi16(T, gradS); // mask = T>gradS
2629 ng = _mm_sub_epi16(ng, mask); // ng += (T>gradS)
2631 t0 = _mm_slli_epi16(x11, 1); // srow[bstep]*2
2632 t1 = _mm_adds_epi16(_mm_loadl_u8_s16(srow,bstep*2), x0); // srow[bstep*2]+srow[0]
2634 // RGs += (srow[bstep*2]+srow[0]) * (T>gradS)
2635 RGs = _mm_adds_epi16(RGs, _mm_and_si128(t1, mask));
2636 // GRs += {srow[bstep]*2; (srow[bstep*2+1]+srow[bstep*2-1])} * (T>gradS)
2637 GRs = _mm_adds_epi16(GRs, _mm_and_si128(_mm_merge_epi16(t0, _mm_adds_epi16(x10,x12)), mask));
2638 // Bs += {(srow[bstep+1]+srow[bstep-1]); srow[bstep]*2} * (T>gradS)
2639 Bs = _mm_adds_epi16(Bs, _mm_and_si128(_mm_merge_epi16(_mm_adds_epi16(x9,x13), t0), mask));
2641 // gradSW **********************************************
2642 mask = _mm_cmpgt_epi16(T, gradSW); // mask = T>gradSW
2643 ng = _mm_sub_epi16(ng, mask); // ng += (T>gradSW)
2645 t0 = _mm_slli_epi16(x13, 1); // srow[bstep-1]*2
2646 t1 = _mm_adds_epi16(_mm_loadl_u8_s16(srow, bstep*2-2), x0); // srow[bstep*2-2]+srow[0]
2648 // RGs += {(srow[bstep*2-2]+srow[0]); srow[bstep-1]*2} * (T>gradSW)
2649 RGs = _mm_adds_epi16(RGs, _mm_and_si128(_mm_merge_epi16(t1, t0), mask));
2650 // GRs += {brow2[N6-1]; (srow[bstep*2-1]+srow[-1])} * (T>gradSW)
2651 GRs = _mm_adds_epi16(GRs, _mm_and_si128(_mm_merge_epi16(_mm_loadu_si128((__m128i*)(brow2+N6-1)), _mm_adds_epi16(x12,x15)), mask));
2652 // Bs += {srow[bstep-1]*2; (srow[bstep]+srow[bstep-2])} * (T>gradSW)
2653 Bs = _mm_adds_epi16(Bs, _mm_and_si128(_mm_merge_epi16(t0,_mm_adds_epi16(x11,x14)), mask));
2655 // gradW ***********************************************
2656 mask = _mm_cmpgt_epi16(T, gradW); // mask = T>gradW
2657 ng = _mm_sub_epi16(ng, mask); // ng += (T>gradW)
2659 t0 = _mm_slli_epi16(x15, 1); // srow[-1]*2
2660 t1 = _mm_adds_epi16(_mm_loadl_u8_s16(srow, -2), x0); // srow[-2]+srow[0]
2662 // RGs += (srow[-2]+srow[0]) * (T>gradW)
2663 RGs = _mm_adds_epi16(RGs, _mm_and_si128(t1, mask));
2664 // GRs += (srow[-1]*2) * (T>gradW)
2665 GRs = _mm_adds_epi16(GRs, _mm_and_si128(t0, mask));
2666 // Bs += {(srow[-bstep-1]+srow[bstep-1]); (srow[bstep-2]+srow[-bstep-2])} * (T>gradW)
2667 Bs = _mm_adds_epi16(Bs, _mm_and_si128(_mm_merge_epi16(_mm_adds_epi16(x1,x13), _mm_adds_epi16(x14,x16)), mask));
2669 // gradNW **********************************************
2670 mask = _mm_cmpgt_epi16(T, gradNW); // mask = T>gradNW
2671 ng = _mm_sub_epi16(ng, mask); // ng += (T>gradNW)
2673 t0 = _mm_slli_epi16(x1, 1); // srow[-bstep-1]*2
2674 t1 = _mm_adds_epi16(_mm_loadl_u8_s16(srow,-bstep*2-2), x0); // srow[-bstep*2-2]+srow[0]
2676 // RGs += {(srow[-bstep*2-2]+srow[0]); srow[-bstep-1]*2} * (T>gradNW)
2677 RGs = _mm_adds_epi16(RGs, _mm_and_si128(_mm_merge_epi16(t1, t0), mask));
2678 // GRs += {brow0[N6-1]; (srow[-bstep*2-1]+srow[-1])} * (T>gradNW)
2679 GRs = _mm_adds_epi16(GRs, _mm_and_si128(_mm_merge_epi16(_mm_loadu_si128((__m128i*)(brow0+N6-1)), _mm_adds_epi16(x2,x15)), mask));
2680 // Bs += {srow[-bstep-1]*2; (srow[-bstep]+srow[-bstep-2])} * (T>gradNW)
2681 Bs = _mm_adds_epi16(Bs, _mm_and_si128(_mm_merge_epi16(_mm_slli_epi16(x5, 1),_mm_adds_epi16(x3,x16)), mask));
2683 __m128 ngf0 = _mm_div_ps(_0_5, _mm_cvtloepi16_ps(ng));
2684 __m128 ngf1 = _mm_div_ps(_0_5, _mm_cvthiepi16_ps(ng));
2686 // now interpolate r, g & b
2687 t0 = _mm_subs_epi16(GRs, RGs);
2688 t1 = _mm_subs_epi16(Bs, RGs);
2690 t0 = _mm_add_epi16(x0, _mm_packs_epi32(
2691 _mm_cvtps_epi32(_mm_mul_ps(_mm_cvtloepi16_ps(t0), ngf0)),
2692 _mm_cvtps_epi32(_mm_mul_ps(_mm_cvthiepi16_ps(t0), ngf1))));
2694 t1 = _mm_add_epi16(x0, _mm_packs_epi32(
2695 _mm_cvtps_epi32(_mm_mul_ps(_mm_cvtloepi16_ps(t1), ngf0)),
2696 _mm_cvtps_epi32(_mm_mul_ps(_mm_cvthiepi16_ps(t1), ngf1))));
2698 x1 = _mm_merge_epi16(x0, t0);
2699 x2 = _mm_merge_epi16(t0, x0);
2701 uchar R[8], G[8], B[8];
2703 _mm_storel_epi64(blueIdx ? (__m128i*)B : (__m128i*)R, _mm_packus_epi16(x1, z));
2704 _mm_storel_epi64((__m128i*)G, _mm_packus_epi16(x2, z));
2705 _mm_storel_epi64(blueIdx ? (__m128i*)R : (__m128i*)B, _mm_packus_epi16(t1, z));
2707 for( int j = 0; j < 8; j++, dstrow += 3 )
2709 dstrow[0] = B[j]; dstrow[1] = G[j]; dstrow[2] = R[j];
2718 for( i = 0; i < 6; i++ )
2720 dst[dststep*y + 5 - i] = dst[dststep*y + 8 - i];
2721 dst[dststep*y + (N - 2)*3 + i] = dst[dststep*y + (N - 3)*3 + i];
2724 greenCell0 = !greenCell0;
2728 for( i = 0; i < size.width*3; i++ )
2730 dst[i] = dst[i + dststep] = dst[i + dststep*2];
2731 dst[i + dststep*(size.height-4)] =
2732 dst[i + dststep*(size.height-3)] =
2733 dst[i + dststep*(size.height-2)] =
2734 dst[i + dststep*(size.height-1)] = dst[i + dststep*(size.height-5)];
2738 ///////////////////////////////////// YUV420 -> RGB /////////////////////////////////////
2740 const int ITUR_BT_601_CY = 1220542;
2741 const int ITUR_BT_601_CUB = 2116026;
2742 const int ITUR_BT_601_CUG = -409993;
2743 const int ITUR_BT_601_CVG = -852492;
2744 const int ITUR_BT_601_CVR = 1673527;
2745 const int ITUR_BT_601_SHIFT = 20;
2747 // Coefficients for RGB to YUV420p conversion
2748 const int ITUR_BT_601_CRY = 269484;
2749 const int ITUR_BT_601_CGY = 528482;
2750 const int ITUR_BT_601_CBY = 102760;
2751 const int ITUR_BT_601_CRU = -155188;
2752 const int ITUR_BT_601_CGU = -305135;
2753 const int ITUR_BT_601_CBU = 460324;
2754 const int ITUR_BT_601_CGV = -385875;
2755 const int ITUR_BT_601_CBV = -74448;
2757 template<int bIdx, int uIdx>
2758 struct YUV420sp2RGB888Invoker : ParallelLoopBody
2761 const uchar* my1, *muv;
2764 YUV420sp2RGB888Invoker(Mat* _dst, int _stride, const uchar* _y1, const uchar* _uv)
2765 : dst(_dst), my1(_y1), muv(_uv), width(_dst->cols), stride(_stride) {}
2767 void operator()(const Range& range) const
2769 int rangeBegin = range.start * 2;
2770 int rangeEnd = range.end * 2;
2772 //R = 1.164(Y - 16) + 1.596(V - 128)
2773 //G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128)
2774 //B = 1.164(Y - 16) + 2.018(U - 128)
2776 //R = (1220542(Y - 16) + 1673527(V - 128) + (1 << 19)) >> 20
2777 //G = (1220542(Y - 16) - 852492(V - 128) - 409993(U - 128) + (1 << 19)) >> 20
2778 //B = (1220542(Y - 16) + 2116026(U - 128) + (1 << 19)) >> 20
2780 const uchar* y1 = my1 + rangeBegin * stride, *uv = muv + rangeBegin * stride / 2;
2782 #ifdef HAVE_TEGRA_OPTIMIZATION
2783 if(tegra::cvtYUV4202RGB(bIdx, uIdx, 3, y1, uv, stride, dst->ptr<uchar>(rangeBegin), dst->step, rangeEnd - rangeBegin, dst->cols))
2787 for (int j = rangeBegin; j < rangeEnd; j += 2, y1 += stride * 2, uv += stride)
2789 uchar* row1 = dst->ptr<uchar>(j);
2790 uchar* row2 = dst->ptr<uchar>(j + 1);
2791 const uchar* y2 = y1 + stride;
2793 for (int i = 0; i < width; i += 2, row1 += 6, row2 += 6)
2795 int u = int(uv[i + 0 + uIdx]) - 128;
2796 int v = int(uv[i + 1 - uIdx]) - 128;
2798 int ruv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVR * v;
2799 int guv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVG * v + ITUR_BT_601_CUG * u;
2800 int buv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CUB * u;
2802 int y00 = std::max(0, int(y1[i]) - 16) * ITUR_BT_601_CY;
2803 row1[2-bIdx] = saturate_cast<uchar>((y00 + ruv) >> ITUR_BT_601_SHIFT);
2804 row1[1] = saturate_cast<uchar>((y00 + guv) >> ITUR_BT_601_SHIFT);
2805 row1[bIdx] = saturate_cast<uchar>((y00 + buv) >> ITUR_BT_601_SHIFT);
2807 int y01 = std::max(0, int(y1[i + 1]) - 16) * ITUR_BT_601_CY;
2808 row1[5-bIdx] = saturate_cast<uchar>((y01 + ruv) >> ITUR_BT_601_SHIFT);
2809 row1[4] = saturate_cast<uchar>((y01 + guv) >> ITUR_BT_601_SHIFT);
2810 row1[3+bIdx] = saturate_cast<uchar>((y01 + buv) >> ITUR_BT_601_SHIFT);
2812 int y10 = std::max(0, int(y2[i]) - 16) * ITUR_BT_601_CY;
2813 row2[2-bIdx] = saturate_cast<uchar>((y10 + ruv) >> ITUR_BT_601_SHIFT);
2814 row2[1] = saturate_cast<uchar>((y10 + guv) >> ITUR_BT_601_SHIFT);
2815 row2[bIdx] = saturate_cast<uchar>((y10 + buv) >> ITUR_BT_601_SHIFT);
2817 int y11 = std::max(0, int(y2[i + 1]) - 16) * ITUR_BT_601_CY;
2818 row2[5-bIdx] = saturate_cast<uchar>((y11 + ruv) >> ITUR_BT_601_SHIFT);
2819 row2[4] = saturate_cast<uchar>((y11 + guv) >> ITUR_BT_601_SHIFT);
2820 row2[3+bIdx] = saturate_cast<uchar>((y11 + buv) >> ITUR_BT_601_SHIFT);
2826 template<int bIdx, int uIdx>
2827 struct YUV420sp2RGBA8888Invoker : ParallelLoopBody
2830 const uchar* my1, *muv;
2833 YUV420sp2RGBA8888Invoker(Mat* _dst, int _stride, const uchar* _y1, const uchar* _uv)
2834 : dst(_dst), my1(_y1), muv(_uv), width(_dst->cols), stride(_stride) {}
2836 void operator()(const Range& range) const
2838 int rangeBegin = range.start * 2;
2839 int rangeEnd = range.end * 2;
2841 //R = 1.164(Y - 16) + 1.596(V - 128)
2842 //G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128)
2843 //B = 1.164(Y - 16) + 2.018(U - 128)
2845 //R = (1220542(Y - 16) + 1673527(V - 128) + (1 << 19)) >> 20
2846 //G = (1220542(Y - 16) - 852492(V - 128) - 409993(U - 128) + (1 << 19)) >> 20
2847 //B = (1220542(Y - 16) + 2116026(U - 128) + (1 << 19)) >> 20
2849 const uchar* y1 = my1 + rangeBegin * stride, *uv = muv + rangeBegin * stride / 2;
2851 #ifdef HAVE_TEGRA_OPTIMIZATION
2852 if(tegra::cvtYUV4202RGB(bIdx, uIdx, 4, y1, uv, stride, dst->ptr<uchar>(rangeBegin), dst->step, rangeEnd - rangeBegin, dst->cols))
2856 for (int j = rangeBegin; j < rangeEnd; j += 2, y1 += stride * 2, uv += stride)
2858 uchar* row1 = dst->ptr<uchar>(j);
2859 uchar* row2 = dst->ptr<uchar>(j + 1);
2860 const uchar* y2 = y1 + stride;
2862 for (int i = 0; i < width; i += 2, row1 += 8, row2 += 8)
2864 int u = int(uv[i + 0 + uIdx]) - 128;
2865 int v = int(uv[i + 1 - uIdx]) - 128;
2867 int ruv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVR * v;
2868 int guv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVG * v + ITUR_BT_601_CUG * u;
2869 int buv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CUB * u;
2871 int y00 = std::max(0, int(y1[i]) - 16) * ITUR_BT_601_CY;
2872 row1[2-bIdx] = saturate_cast<uchar>((y00 + ruv) >> ITUR_BT_601_SHIFT);
2873 row1[1] = saturate_cast<uchar>((y00 + guv) >> ITUR_BT_601_SHIFT);
2874 row1[bIdx] = saturate_cast<uchar>((y00 + buv) >> ITUR_BT_601_SHIFT);
2875 row1[3] = uchar(0xff);
2877 int y01 = std::max(0, int(y1[i + 1]) - 16) * ITUR_BT_601_CY;
2878 row1[6-bIdx] = saturate_cast<uchar>((y01 + ruv) >> ITUR_BT_601_SHIFT);
2879 row1[5] = saturate_cast<uchar>((y01 + guv) >> ITUR_BT_601_SHIFT);
2880 row1[4+bIdx] = saturate_cast<uchar>((y01 + buv) >> ITUR_BT_601_SHIFT);
2881 row1[7] = uchar(0xff);
2883 int y10 = std::max(0, int(y2[i]) - 16) * ITUR_BT_601_CY;
2884 row2[2-bIdx] = saturate_cast<uchar>((y10 + ruv) >> ITUR_BT_601_SHIFT);
2885 row2[1] = saturate_cast<uchar>((y10 + guv) >> ITUR_BT_601_SHIFT);
2886 row2[bIdx] = saturate_cast<uchar>((y10 + buv) >> ITUR_BT_601_SHIFT);
2887 row2[3] = uchar(0xff);
2889 int y11 = std::max(0, int(y2[i + 1]) - 16) * ITUR_BT_601_CY;
2890 row2[6-bIdx] = saturate_cast<uchar>((y11 + ruv) >> ITUR_BT_601_SHIFT);
2891 row2[5] = saturate_cast<uchar>((y11 + guv) >> ITUR_BT_601_SHIFT);
2892 row2[4+bIdx] = saturate_cast<uchar>((y11 + buv) >> ITUR_BT_601_SHIFT);
2893 row2[7] = uchar(0xff);
2900 struct YUV420p2RGB888Invoker : ParallelLoopBody
2903 const uchar* my1, *mu, *mv;
2905 int ustepIdx, vstepIdx;
2907 YUV420p2RGB888Invoker(Mat* _dst, int _stride, const uchar* _y1, const uchar* _u, const uchar* _v, int _ustepIdx, int _vstepIdx)
2908 : dst(_dst), my1(_y1), mu(_u), mv(_v), width(_dst->cols), stride(_stride), ustepIdx(_ustepIdx), vstepIdx(_vstepIdx) {}
2910 void operator()(const Range& range) const
2912 const int rangeBegin = range.start * 2;
2913 const int rangeEnd = range.end * 2;
2915 size_t uvsteps[2] = {width/2, stride - width/2};
2916 int usIdx = ustepIdx, vsIdx = vstepIdx;
2918 const uchar* y1 = my1 + rangeBegin * stride;
2919 const uchar* u1 = mu + (range.start / 2) * stride;
2920 const uchar* v1 = mv + (range.start / 2) * stride;
2922 if(range.start % 2 == 1)
2924 u1 += uvsteps[(usIdx++) & 1];
2925 v1 += uvsteps[(vsIdx++) & 1];
2928 for (int j = rangeBegin; j < rangeEnd; j += 2, y1 += stride * 2, u1 += uvsteps[(usIdx++) & 1], v1 += uvsteps[(vsIdx++) & 1])
2930 uchar* row1 = dst->ptr<uchar>(j);
2931 uchar* row2 = dst->ptr<uchar>(j + 1);
2932 const uchar* y2 = y1 + stride;
2934 for (int i = 0; i < width / 2; i += 1, row1 += 6, row2 += 6)
2936 int u = int(u1[i]) - 128;
2937 int v = int(v1[i]) - 128;
2939 int ruv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVR * v;
2940 int guv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVG * v + ITUR_BT_601_CUG * u;
2941 int buv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CUB * u;
2943 int y00 = std::max(0, int(y1[2 * i]) - 16) * ITUR_BT_601_CY;
2944 row1[2-bIdx] = saturate_cast<uchar>((y00 + ruv) >> ITUR_BT_601_SHIFT);
2945 row1[1] = saturate_cast<uchar>((y00 + guv) >> ITUR_BT_601_SHIFT);
2946 row1[bIdx] = saturate_cast<uchar>((y00 + buv) >> ITUR_BT_601_SHIFT);
2948 int y01 = std::max(0, int(y1[2 * i + 1]) - 16) * ITUR_BT_601_CY;
2949 row1[5-bIdx] = saturate_cast<uchar>((y01 + ruv) >> ITUR_BT_601_SHIFT);
2950 row1[4] = saturate_cast<uchar>((y01 + guv) >> ITUR_BT_601_SHIFT);
2951 row1[3+bIdx] = saturate_cast<uchar>((y01 + buv) >> ITUR_BT_601_SHIFT);
2953 int y10 = std::max(0, int(y2[2 * i]) - 16) * ITUR_BT_601_CY;
2954 row2[2-bIdx] = saturate_cast<uchar>((y10 + ruv) >> ITUR_BT_601_SHIFT);
2955 row2[1] = saturate_cast<uchar>((y10 + guv) >> ITUR_BT_601_SHIFT);
2956 row2[bIdx] = saturate_cast<uchar>((y10 + buv) >> ITUR_BT_601_SHIFT);
2958 int y11 = std::max(0, int(y2[2 * i + 1]) - 16) * ITUR_BT_601_CY;
2959 row2[5-bIdx] = saturate_cast<uchar>((y11 + ruv) >> ITUR_BT_601_SHIFT);
2960 row2[4] = saturate_cast<uchar>((y11 + guv) >> ITUR_BT_601_SHIFT);
2961 row2[3+bIdx] = saturate_cast<uchar>((y11 + buv) >> ITUR_BT_601_SHIFT);
2968 struct YUV420p2RGBA8888Invoker : ParallelLoopBody
2971 const uchar* my1, *mu, *mv;
2973 int ustepIdx, vstepIdx;
2975 YUV420p2RGBA8888Invoker(Mat* _dst, int _stride, const uchar* _y1, const uchar* _u, const uchar* _v, int _ustepIdx, int _vstepIdx)
2976 : dst(_dst), my1(_y1), mu(_u), mv(_v), width(_dst->cols), stride(_stride), ustepIdx(_ustepIdx), vstepIdx(_vstepIdx) {}
2978 void operator()(const Range& range) const
2980 int rangeBegin = range.start * 2;
2981 int rangeEnd = range.end * 2;
2983 size_t uvsteps[2] = {width/2, stride - width/2};
2984 int usIdx = ustepIdx, vsIdx = vstepIdx;
2986 const uchar* y1 = my1 + rangeBegin * stride;
2987 const uchar* u1 = mu + (range.start / 2) * stride;
2988 const uchar* v1 = mv + (range.start / 2) * stride;
2990 if(range.start % 2 == 1)
2992 u1 += uvsteps[(usIdx++) & 1];
2993 v1 += uvsteps[(vsIdx++) & 1];
2996 for (int j = rangeBegin; j < rangeEnd; j += 2, y1 += stride * 2, u1 += uvsteps[(usIdx++) & 1], v1 += uvsteps[(vsIdx++) & 1])
2998 uchar* row1 = dst->ptr<uchar>(j);
2999 uchar* row2 = dst->ptr<uchar>(j + 1);
3000 const uchar* y2 = y1 + stride;
3002 for (int i = 0; i < width / 2; i += 1, row1 += 8, row2 += 8)
3004 int u = int(u1[i]) - 128;
3005 int v = int(v1[i]) - 128;
3007 int ruv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVR * v;
3008 int guv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVG * v + ITUR_BT_601_CUG * u;
3009 int buv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CUB * u;
3011 int y00 = std::max(0, int(y1[2 * i]) - 16) * ITUR_BT_601_CY;
3012 row1[2-bIdx] = saturate_cast<uchar>((y00 + ruv) >> ITUR_BT_601_SHIFT);
3013 row1[1] = saturate_cast<uchar>((y00 + guv) >> ITUR_BT_601_SHIFT);
3014 row1[bIdx] = saturate_cast<uchar>((y00 + buv) >> ITUR_BT_601_SHIFT);
3015 row1[3] = uchar(0xff);
3017 int y01 = std::max(0, int(y1[2 * i + 1]) - 16) * ITUR_BT_601_CY;
3018 row1[6-bIdx] = saturate_cast<uchar>((y01 + ruv) >> ITUR_BT_601_SHIFT);
3019 row1[5] = saturate_cast<uchar>((y01 + guv) >> ITUR_BT_601_SHIFT);
3020 row1[4+bIdx] = saturate_cast<uchar>((y01 + buv) >> ITUR_BT_601_SHIFT);
3021 row1[7] = uchar(0xff);
3023 int y10 = std::max(0, int(y2[2 * i]) - 16) * ITUR_BT_601_CY;
3024 row2[2-bIdx] = saturate_cast<uchar>((y10 + ruv) >> ITUR_BT_601_SHIFT);
3025 row2[1] = saturate_cast<uchar>((y10 + guv) >> ITUR_BT_601_SHIFT);
3026 row2[bIdx] = saturate_cast<uchar>((y10 + buv) >> ITUR_BT_601_SHIFT);
3027 row2[3] = uchar(0xff);
3029 int y11 = std::max(0, int(y2[2 * i + 1]) - 16) * ITUR_BT_601_CY;
3030 row2[6-bIdx] = saturate_cast<uchar>((y11 + ruv) >> ITUR_BT_601_SHIFT);
3031 row2[5] = saturate_cast<uchar>((y11 + guv) >> ITUR_BT_601_SHIFT);
3032 row2[4+bIdx] = saturate_cast<uchar>((y11 + buv) >> ITUR_BT_601_SHIFT);
3033 row2[7] = uchar(0xff);
3039 #define MIN_SIZE_FOR_PARALLEL_YUV420_CONVERSION (320*240)
3041 template<int bIdx, int uIdx>
3042 inline void cvtYUV420sp2RGB(Mat& _dst, int _stride, const uchar* _y1, const uchar* _uv)
3044 YUV420sp2RGB888Invoker<bIdx, uIdx> converter(&_dst, _stride, _y1, _uv);
3045 if (_dst.total() >= MIN_SIZE_FOR_PARALLEL_YUV420_CONVERSION)
3046 parallel_for_(Range(0, _dst.rows/2), converter);
3048 converter(Range(0, _dst.rows/2));
3051 template<int bIdx, int uIdx>
3052 inline void cvtYUV420sp2RGBA(Mat& _dst, int _stride, const uchar* _y1, const uchar* _uv)
3054 YUV420sp2RGBA8888Invoker<bIdx, uIdx> converter(&_dst, _stride, _y1, _uv);
3055 if (_dst.total() >= MIN_SIZE_FOR_PARALLEL_YUV420_CONVERSION)
3056 parallel_for_(Range(0, _dst.rows/2), converter);
3058 converter(Range(0, _dst.rows/2));
3062 inline void cvtYUV420p2RGB(Mat& _dst, int _stride, const uchar* _y1, const uchar* _u, const uchar* _v, int ustepIdx, int vstepIdx)
3064 YUV420p2RGB888Invoker<bIdx> converter(&_dst, _stride, _y1, _u, _v, ustepIdx, vstepIdx);
3065 if (_dst.total() >= MIN_SIZE_FOR_PARALLEL_YUV420_CONVERSION)
3066 parallel_for_(Range(0, _dst.rows/2), converter);
3068 converter(Range(0, _dst.rows/2));
3072 inline void cvtYUV420p2RGBA(Mat& _dst, int _stride, const uchar* _y1, const uchar* _u, const uchar* _v, int ustepIdx, int vstepIdx)
3074 YUV420p2RGBA8888Invoker<bIdx> converter(&_dst, _stride, _y1, _u, _v, ustepIdx, vstepIdx);
3075 if (_dst.total() >= MIN_SIZE_FOR_PARALLEL_YUV420_CONVERSION)
3076 parallel_for_(Range(0, _dst.rows/2), converter);
3078 converter(Range(0, _dst.rows/2));
3081 ///////////////////////////////////// RGB -> YUV420p /////////////////////////////////////
3084 struct RGB888toYUV420pInvoker: public ParallelLoopBody
3086 RGB888toYUV420pInvoker( const Mat& src, Mat* dst, const int uIdx )
3091 void operator()(const Range& rowRange) const
3093 const int w = src_.cols;
3094 const int h = src_.rows;
3096 const int cn = src_.channels();
3097 for( int i = rowRange.start; i < rowRange.end; i++ )
3099 const uchar* row0 = src_.ptr<uchar>(2 * i);
3100 const uchar* row1 = src_.ptr<uchar>(2 * i + 1);
3102 uchar* y = dst_->ptr<uchar>(2*i);
3103 uchar* u = dst_->ptr<uchar>(h + i/2) + (i % 2) * (w/2);
3104 uchar* v = dst_->ptr<uchar>(h + (i + h/2)/2) + ((i + h/2) % 2) * (w/2);
3105 if( uIdx_ == 2 ) std::swap(u, v);
3107 for( int j = 0, k = 0; j < w * cn; j += 2 * cn, k++ )
3109 int r00 = row0[2-bIdx + j]; int g00 = row0[1 + j]; int b00 = row0[bIdx + j];
3110 int r01 = row0[2-bIdx + cn + j]; int g01 = row0[1 + cn + j]; int b01 = row0[bIdx + cn + j];
3111 int r10 = row1[2-bIdx + j]; int g10 = row1[1 + j]; int b10 = row1[bIdx + j];
3112 int r11 = row1[2-bIdx + cn + j]; int g11 = row1[1 + cn + j]; int b11 = row1[bIdx + cn + j];
3114 const int shifted16 = (16 << ITUR_BT_601_SHIFT);
3115 const int halfShift = (1 << (ITUR_BT_601_SHIFT - 1));
3116 int y00 = ITUR_BT_601_CRY * r00 + ITUR_BT_601_CGY * g00 + ITUR_BT_601_CBY * b00 + halfShift + shifted16;
3117 int y01 = ITUR_BT_601_CRY * r01 + ITUR_BT_601_CGY * g01 + ITUR_BT_601_CBY * b01 + halfShift + shifted16;
3118 int y10 = ITUR_BT_601_CRY * r10 + ITUR_BT_601_CGY * g10 + ITUR_BT_601_CBY * b10 + halfShift + shifted16;
3119 int y11 = ITUR_BT_601_CRY * r11 + ITUR_BT_601_CGY * g11 + ITUR_BT_601_CBY * b11 + halfShift + shifted16;
3121 y[2*k + 0] = saturate_cast<uchar>(y00 >> ITUR_BT_601_SHIFT);
3122 y[2*k + 1] = saturate_cast<uchar>(y01 >> ITUR_BT_601_SHIFT);
3123 y[2*k + dst_->step + 0] = saturate_cast<uchar>(y10 >> ITUR_BT_601_SHIFT);
3124 y[2*k + dst_->step + 1] = saturate_cast<uchar>(y11 >> ITUR_BT_601_SHIFT);
3126 const int shifted128 = (128 << ITUR_BT_601_SHIFT);
3127 int u00 = ITUR_BT_601_CRU * r00 + ITUR_BT_601_CGU * g00 + ITUR_BT_601_CBU * b00 + halfShift + shifted128;
3128 int v00 = ITUR_BT_601_CBU * r00 + ITUR_BT_601_CGV * g00 + ITUR_BT_601_CBV * b00 + halfShift + shifted128;
3130 u[k] = saturate_cast<uchar>(u00 >> ITUR_BT_601_SHIFT);
3131 v[k] = saturate_cast<uchar>(v00 >> ITUR_BT_601_SHIFT);
3136 static bool isFit( const Mat& src )
3138 return (src.total() >= 320*240);
3142 RGB888toYUV420pInvoker& operator=(const RGB888toYUV420pInvoker&);
3149 template<int bIdx, int uIdx>
3150 static void cvtRGBtoYUV420p(const Mat& src, Mat& dst)
3152 RGB888toYUV420pInvoker<bIdx> colorConverter(src, &dst, uIdx);
3153 if( RGB888toYUV420pInvoker<bIdx>::isFit(src) )
3154 parallel_for_(Range(0, src.rows/2), colorConverter);
3156 colorConverter(Range(0, src.rows/2));
3159 ///////////////////////////////////// YUV422 -> RGB /////////////////////////////////////
3161 template<int bIdx, int uIdx, int yIdx>
3162 struct YUV422toRGB888Invoker : ParallelLoopBody
3168 YUV422toRGB888Invoker(Mat* _dst, int _stride, const uchar* _yuv)
3169 : dst(_dst), src(_yuv), width(_dst->cols), stride(_stride) {}
3171 void operator()(const Range& range) const
3173 int rangeBegin = range.start;
3174 int rangeEnd = range.end;
3176 const int uidx = 1 - yIdx + uIdx * 2;
3177 const int vidx = (2 + uidx) % 4;
3178 const uchar* yuv_src = src + rangeBegin * stride;
3180 for (int j = rangeBegin; j < rangeEnd; j++, yuv_src += stride)
3182 uchar* row = dst->ptr<uchar>(j);
3184 for (int i = 0; i < 2 * width; i += 4, row += 6)
3186 int u = int(yuv_src[i + uidx]) - 128;
3187 int v = int(yuv_src[i + vidx]) - 128;
3189 int ruv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVR * v;
3190 int guv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVG * v + ITUR_BT_601_CUG * u;
3191 int buv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CUB * u;
3193 int y00 = std::max(0, int(yuv_src[i + yIdx]) - 16) * ITUR_BT_601_CY;
3194 row[2-bIdx] = saturate_cast<uchar>((y00 + ruv) >> ITUR_BT_601_SHIFT);
3195 row[1] = saturate_cast<uchar>((y00 + guv) >> ITUR_BT_601_SHIFT);
3196 row[bIdx] = saturate_cast<uchar>((y00 + buv) >> ITUR_BT_601_SHIFT);
3198 int y01 = std::max(0, int(yuv_src[i + yIdx + 2]) - 16) * ITUR_BT_601_CY;
3199 row[5-bIdx] = saturate_cast<uchar>((y01 + ruv) >> ITUR_BT_601_SHIFT);
3200 row[4] = saturate_cast<uchar>((y01 + guv) >> ITUR_BT_601_SHIFT);
3201 row[3+bIdx] = saturate_cast<uchar>((y01 + buv) >> ITUR_BT_601_SHIFT);
3207 template<int bIdx, int uIdx, int yIdx>
3208 struct YUV422toRGBA8888Invoker : ParallelLoopBody
3214 YUV422toRGBA8888Invoker(Mat* _dst, int _stride, const uchar* _yuv)
3215 : dst(_dst), src(_yuv), width(_dst->cols), stride(_stride) {}
3217 void operator()(const Range& range) const
3219 int rangeBegin = range.start;
3220 int rangeEnd = range.end;
3222 const int uidx = 1 - yIdx + uIdx * 2;
3223 const int vidx = (2 + uidx) % 4;
3224 const uchar* yuv_src = src + rangeBegin * stride;
3226 for (int j = rangeBegin; j < rangeEnd; j++, yuv_src += stride)
3228 uchar* row = dst->ptr<uchar>(j);
3230 for (int i = 0; i < 2 * width; i += 4, row += 8)
3232 int u = int(yuv_src[i + uidx]) - 128;
3233 int v = int(yuv_src[i + vidx]) - 128;
3235 int ruv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVR * v;
3236 int guv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVG * v + ITUR_BT_601_CUG * u;
3237 int buv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CUB * u;
3239 int y00 = std::max(0, int(yuv_src[i + yIdx]) - 16) * ITUR_BT_601_CY;
3240 row[2-bIdx] = saturate_cast<uchar>((y00 + ruv) >> ITUR_BT_601_SHIFT);
3241 row[1] = saturate_cast<uchar>((y00 + guv) >> ITUR_BT_601_SHIFT);
3242 row[bIdx] = saturate_cast<uchar>((y00 + buv) >> ITUR_BT_601_SHIFT);
3243 row[3] = uchar(0xff);
3245 int y01 = std::max(0, int(yuv_src[i + yIdx + 2]) - 16) * ITUR_BT_601_CY;
3246 row[6-bIdx] = saturate_cast<uchar>((y01 + ruv) >> ITUR_BT_601_SHIFT);
3247 row[5] = saturate_cast<uchar>((y01 + guv) >> ITUR_BT_601_SHIFT);
3248 row[4+bIdx] = saturate_cast<uchar>((y01 + buv) >> ITUR_BT_601_SHIFT);
3249 row[7] = uchar(0xff);
3255 #define MIN_SIZE_FOR_PARALLEL_YUV422_CONVERSION (320*240)
3257 template<int bIdx, int uIdx, int yIdx>
3258 inline void cvtYUV422toRGB(Mat& _dst, int _stride, const uchar* _yuv)
3260 YUV422toRGB888Invoker<bIdx, uIdx, yIdx> converter(&_dst, _stride, _yuv);
3261 if (_dst.total() >= MIN_SIZE_FOR_PARALLEL_YUV422_CONVERSION)
3262 parallel_for_(Range(0, _dst.rows), converter);
3264 converter(Range(0, _dst.rows));
3267 template<int bIdx, int uIdx, int yIdx>
3268 inline void cvtYUV422toRGBA(Mat& _dst, int _stride, const uchar* _yuv)
3270 YUV422toRGBA8888Invoker<bIdx, uIdx, yIdx> converter(&_dst, _stride, _yuv);
3271 if (_dst.total() >= MIN_SIZE_FOR_PARALLEL_YUV422_CONVERSION)
3272 parallel_for_(Range(0, _dst.rows), converter);
3274 converter(Range(0, _dst.rows));
3277 /////////////////////////// RGBA <-> mRGBA (alpha premultiplied) //////////////
3279 template<typename _Tp>
3282 typedef _Tp channel_type;
3284 void operator()(const _Tp* src, _Tp* dst, int n) const
3286 _Tp max_val = ColorChannel<_Tp>::max();
3287 _Tp half_val = ColorChannel<_Tp>::half();
3288 for( int i = 0; i < n; i++ )
3295 *dst++ = (v0 * v3 + half_val) / max_val;
3296 *dst++ = (v1 * v3 + half_val) / max_val;
3297 *dst++ = (v2 * v3 + half_val) / max_val;
3304 template<typename _Tp>
3307 typedef _Tp channel_type;
3309 void operator()(const _Tp* src, _Tp* dst, int n) const
3311 _Tp max_val = ColorChannel<_Tp>::max();
3312 for( int i = 0; i < n; i++ )
3318 _Tp v3_half = v3 / 2;
3320 *dst++ = (v3==0)? 0 : (v0 * max_val + v3_half) / v3;
3321 *dst++ = (v3==0)? 0 : (v1 * max_val + v3_half) / v3;
3322 *dst++ = (v3==0)? 0 : (v2 * max_val + v3_half) / v3;
3330 //////////////////////////////////////////////////////////////////////////////////////////
3331 // The main function //
3332 //////////////////////////////////////////////////////////////////////////////////////////
3334 void cv::cvtColor( InputArray _src, OutputArray _dst, int code, int dcn )
3336 Mat src = _src.getMat(), dst;
3337 Size sz = src.size();
3338 int scn = src.channels(), depth = src.depth(), bidx;
3340 CV_Assert( depth == CV_8U || depth == CV_16U || depth == CV_32F );
3344 case CV_BGR2BGRA: case CV_RGB2BGRA: case CV_BGRA2BGR:
3345 case CV_RGBA2BGR: case CV_RGB2BGR: case CV_BGRA2RGBA:
3346 CV_Assert( scn == 3 || scn == 4 );
3347 dcn = code == CV_BGR2BGRA || code == CV_RGB2BGRA || code == CV_BGRA2RGBA ? 4 : 3;
3348 bidx = code == CV_BGR2BGRA || code == CV_BGRA2BGR ? 0 : 2;
3350 _dst.create( sz, CV_MAKETYPE(depth, dcn));
3351 dst = _dst.getMat();
3353 if( depth == CV_8U )
3355 #ifdef HAVE_TEGRA_OPTIMIZATION
3356 if(!tegra::cvtBGR2RGB(src, dst, bidx))
3358 CvtColorLoop(src, dst, RGB2RGB<uchar>(scn, dcn, bidx));
3360 else if( depth == CV_16U )
3361 CvtColorLoop(src, dst, RGB2RGB<ushort>(scn, dcn, bidx));
3363 CvtColorLoop(src, dst, RGB2RGB<float>(scn, dcn, bidx));
3366 case CV_BGR2BGR565: case CV_BGR2BGR555: case CV_RGB2BGR565: case CV_RGB2BGR555:
3367 case CV_BGRA2BGR565: case CV_BGRA2BGR555: case CV_RGBA2BGR565: case CV_RGBA2BGR555:
3368 CV_Assert( (scn == 3 || scn == 4) && depth == CV_8U );
3369 _dst.create(sz, CV_8UC2);
3370 dst = _dst.getMat();
3372 #ifdef HAVE_TEGRA_OPTIMIZATION
3373 if(code == CV_BGR2BGR565 || code == CV_BGRA2BGR565 || code == CV_RGB2BGR565 || code == CV_RGBA2BGR565)
3374 if(tegra::cvtRGB2RGB565(src, dst, code == CV_RGB2BGR565 || code == CV_RGBA2BGR565 ? 0 : 2))
3378 CvtColorLoop(src, dst, RGB2RGB5x5(scn,
3379 code == CV_BGR2BGR565 || code == CV_BGR2BGR555 ||
3380 code == CV_BGRA2BGR565 || code == CV_BGRA2BGR555 ? 0 : 2,
3381 code == CV_BGR2BGR565 || code == CV_RGB2BGR565 ||
3382 code == CV_BGRA2BGR565 || code == CV_RGBA2BGR565 ? 6 : 5 // green bits
3386 case CV_BGR5652BGR: case CV_BGR5552BGR: case CV_BGR5652RGB: case CV_BGR5552RGB:
3387 case CV_BGR5652BGRA: case CV_BGR5552BGRA: case CV_BGR5652RGBA: case CV_BGR5552RGBA:
3388 if(dcn <= 0) dcn = (code==CV_BGR5652BGRA || code==CV_BGR5552BGRA || code==CV_BGR5652RGBA || code==CV_BGR5552RGBA) ? 4 : 3;
3389 CV_Assert( (dcn == 3 || dcn == 4) && scn == 2 && depth == CV_8U );
3390 _dst.create(sz, CV_MAKETYPE(depth, dcn));
3391 dst = _dst.getMat();
3393 CvtColorLoop(src, dst, RGB5x52RGB(dcn,
3394 code == CV_BGR5652BGR || code == CV_BGR5552BGR ||
3395 code == CV_BGR5652BGRA || code == CV_BGR5552BGRA ? 0 : 2, // blue idx
3396 code == CV_BGR5652BGR || code == CV_BGR5652RGB ||
3397 code == CV_BGR5652BGRA || code == CV_BGR5652RGBA ? 6 : 5 // green bits
3401 case CV_BGR2GRAY: case CV_BGRA2GRAY: case CV_RGB2GRAY: case CV_RGBA2GRAY:
3402 CV_Assert( scn == 3 || scn == 4 );
3403 _dst.create(sz, CV_MAKETYPE(depth, 1));
3404 dst = _dst.getMat();
3406 bidx = code == CV_BGR2GRAY || code == CV_BGRA2GRAY ? 0 : 2;
3408 if( depth == CV_8U )
3410 #ifdef HAVE_TEGRA_OPTIMIZATION
3411 if(!tegra::cvtRGB2Gray(src, dst, bidx))
3413 CvtColorLoop(src, dst, RGB2Gray<uchar>(scn, bidx, 0));
3415 else if( depth == CV_16U )
3416 CvtColorLoop(src, dst, RGB2Gray<ushort>(scn, bidx, 0));
3418 CvtColorLoop(src, dst, RGB2Gray<float>(scn, bidx, 0));
3421 case CV_BGR5652GRAY: case CV_BGR5552GRAY:
3422 CV_Assert( scn == 2 && depth == CV_8U );
3423 _dst.create(sz, CV_8UC1);
3424 dst = _dst.getMat();
3426 CvtColorLoop(src, dst, RGB5x52Gray(code == CV_BGR5652GRAY ? 6 : 5));
3429 case CV_GRAY2BGR: case CV_GRAY2BGRA:
3430 if( dcn <= 0 ) dcn = (code==CV_GRAY2BGRA) ? 4 : 3;
3431 CV_Assert( scn == 1 && (dcn == 3 || dcn == 4));
3432 _dst.create(sz, CV_MAKETYPE(depth, dcn));
3433 dst = _dst.getMat();
3435 if( depth == CV_8U )
3437 #ifdef HAVE_TEGRA_OPTIMIZATION
3438 if(!tegra::cvtGray2RGB(src, dst))
3440 CvtColorLoop(src, dst, Gray2RGB<uchar>(dcn));
3442 else if( depth == CV_16U )
3443 CvtColorLoop(src, dst, Gray2RGB<ushort>(dcn));
3445 CvtColorLoop(src, dst, Gray2RGB<float>(dcn));
3448 case CV_GRAY2BGR565: case CV_GRAY2BGR555:
3449 CV_Assert( scn == 1 && depth == CV_8U );
3450 _dst.create(sz, CV_8UC2);
3451 dst = _dst.getMat();
3453 CvtColorLoop(src, dst, Gray2RGB5x5(code == CV_GRAY2BGR565 ? 6 : 5));
3456 case CV_BGR2YCrCb: case CV_RGB2YCrCb:
3457 case CV_BGR2YUV: case CV_RGB2YUV:
3459 CV_Assert( scn == 3 || scn == 4 );
3460 bidx = code == CV_BGR2YCrCb || code == CV_RGB2YUV ? 0 : 2;
3461 static const float yuv_f[] = { 0.114f, 0.587f, 0.299f, 0.492f, 0.877f };
3462 static const int yuv_i[] = { B2Y, G2Y, R2Y, 8061, 14369 };
3463 const float* coeffs_f = code == CV_BGR2YCrCb || code == CV_RGB2YCrCb ? 0 : yuv_f;
3464 const int* coeffs_i = code == CV_BGR2YCrCb || code == CV_RGB2YCrCb ? 0 : yuv_i;
3466 _dst.create(sz, CV_MAKETYPE(depth, 3));
3467 dst = _dst.getMat();
3469 if( depth == CV_8U )
3471 #ifdef HAVE_TEGRA_OPTIMIZATION
3472 if((code == CV_RGB2YCrCb || code == CV_BGR2YCrCb) && tegra::cvtRGB2YCrCb(src, dst, bidx))
3475 CvtColorLoop(src, dst, RGB2YCrCb_i<uchar>(scn, bidx, coeffs_i));
3477 else if( depth == CV_16U )
3478 CvtColorLoop(src, dst, RGB2YCrCb_i<ushort>(scn, bidx, coeffs_i));
3480 CvtColorLoop(src, dst, RGB2YCrCb_f<float>(scn, bidx, coeffs_f));
3484 case CV_YCrCb2BGR: case CV_YCrCb2RGB:
3485 case CV_YUV2BGR: case CV_YUV2RGB:
3487 if( dcn <= 0 ) dcn = 3;
3488 CV_Assert( scn == 3 && (dcn == 3 || dcn == 4) );
3489 bidx = code == CV_YCrCb2BGR || code == CV_YUV2RGB ? 0 : 2;
3490 static const float yuv_f[] = { 2.032f, -0.395f, -0.581f, 1.140f };
3491 static const int yuv_i[] = { 33292, -6472, -9519, 18678 };
3492 const float* coeffs_f = code == CV_YCrCb2BGR || code == CV_YCrCb2RGB ? 0 : yuv_f;
3493 const int* coeffs_i = code == CV_YCrCb2BGR || code == CV_YCrCb2RGB ? 0 : yuv_i;
3495 _dst.create(sz, CV_MAKETYPE(depth, dcn));
3496 dst = _dst.getMat();
3498 if( depth == CV_8U )
3499 CvtColorLoop(src, dst, YCrCb2RGB_i<uchar>(dcn, bidx, coeffs_i));
3500 else if( depth == CV_16U )
3501 CvtColorLoop(src, dst, YCrCb2RGB_i<ushort>(dcn, bidx, coeffs_i));
3503 CvtColorLoop(src, dst, YCrCb2RGB_f<float>(dcn, bidx, coeffs_f));
3507 case CV_BGR2XYZ: case CV_RGB2XYZ:
3508 CV_Assert( scn == 3 || scn == 4 );
3509 bidx = code == CV_BGR2XYZ ? 0 : 2;
3511 _dst.create(sz, CV_MAKETYPE(depth, 3));
3512 dst = _dst.getMat();
3514 if( depth == CV_8U )
3515 CvtColorLoop(src, dst, RGB2XYZ_i<uchar>(scn, bidx, 0));
3516 else if( depth == CV_16U )
3517 CvtColorLoop(src, dst, RGB2XYZ_i<ushort>(scn, bidx, 0));
3519 CvtColorLoop(src, dst, RGB2XYZ_f<float>(scn, bidx, 0));
3522 case CV_XYZ2BGR: case CV_XYZ2RGB:
3523 if( dcn <= 0 ) dcn = 3;
3524 CV_Assert( scn == 3 && (dcn == 3 || dcn == 4) );
3525 bidx = code == CV_XYZ2BGR ? 0 : 2;
3527 _dst.create(sz, CV_MAKETYPE(depth, dcn));
3528 dst = _dst.getMat();
3530 if( depth == CV_8U )
3531 CvtColorLoop(src, dst, XYZ2RGB_i<uchar>(dcn, bidx, 0));
3532 else if( depth == CV_16U )
3533 CvtColorLoop(src, dst, XYZ2RGB_i<ushort>(dcn, bidx, 0));
3535 CvtColorLoop(src, dst, XYZ2RGB_f<float>(dcn, bidx, 0));
3538 case CV_BGR2HSV: case CV_RGB2HSV: case CV_BGR2HSV_FULL: case CV_RGB2HSV_FULL:
3539 case CV_BGR2HLS: case CV_RGB2HLS: case CV_BGR2HLS_FULL: case CV_RGB2HLS_FULL:
3541 CV_Assert( (scn == 3 || scn == 4) && (depth == CV_8U || depth == CV_32F) );
3542 bidx = code == CV_BGR2HSV || code == CV_BGR2HLS ||
3543 code == CV_BGR2HSV_FULL || code == CV_BGR2HLS_FULL ? 0 : 2;
3544 int hrange = depth == CV_32F ? 360 : code == CV_BGR2HSV || code == CV_RGB2HSV ||
3545 code == CV_BGR2HLS || code == CV_RGB2HLS ? 180 : 256;
3547 _dst.create(sz, CV_MAKETYPE(depth, 3));
3548 dst = _dst.getMat();
3550 if( code == CV_BGR2HSV || code == CV_RGB2HSV ||
3551 code == CV_BGR2HSV_FULL || code == CV_RGB2HSV_FULL )
3553 #ifdef HAVE_TEGRA_OPTIMIZATION
3554 if(tegra::cvtRGB2HSV(src, dst, bidx, hrange))
3557 if( depth == CV_8U )
3558 CvtColorLoop(src, dst, RGB2HSV_b(scn, bidx, hrange));
3560 CvtColorLoop(src, dst, RGB2HSV_f(scn, bidx, (float)hrange));
3564 if( depth == CV_8U )
3565 CvtColorLoop(src, dst, RGB2HLS_b(scn, bidx, hrange));
3567 CvtColorLoop(src, dst, RGB2HLS_f(scn, bidx, (float)hrange));
3572 case CV_HSV2BGR: case CV_HSV2RGB: case CV_HSV2BGR_FULL: case CV_HSV2RGB_FULL:
3573 case CV_HLS2BGR: case CV_HLS2RGB: case CV_HLS2BGR_FULL: case CV_HLS2RGB_FULL:
3575 if( dcn <= 0 ) dcn = 3;
3576 CV_Assert( scn == 3 && (dcn == 3 || dcn == 4) && (depth == CV_8U || depth == CV_32F) );
3577 bidx = code == CV_HSV2BGR || code == CV_HLS2BGR ||
3578 code == CV_HSV2BGR_FULL || code == CV_HLS2BGR_FULL ? 0 : 2;
3579 int hrange = depth == CV_32F ? 360 : code == CV_HSV2BGR || code == CV_HSV2RGB ||
3580 code == CV_HLS2BGR || code == CV_HLS2RGB ? 180 : 255;
3582 _dst.create(sz, CV_MAKETYPE(depth, dcn));
3583 dst = _dst.getMat();
3585 if( code == CV_HSV2BGR || code == CV_HSV2RGB ||
3586 code == CV_HSV2BGR_FULL || code == CV_HSV2RGB_FULL )
3588 if( depth == CV_8U )
3589 CvtColorLoop(src, dst, HSV2RGB_b(dcn, bidx, hrange));
3591 CvtColorLoop(src, dst, HSV2RGB_f(dcn, bidx, (float)hrange));
3595 if( depth == CV_8U )
3596 CvtColorLoop(src, dst, HLS2RGB_b(dcn, bidx, hrange));
3598 CvtColorLoop(src, dst, HLS2RGB_f(dcn, bidx, (float)hrange));
3603 case CV_BGR2Lab: case CV_RGB2Lab: case CV_LBGR2Lab: case CV_LRGB2Lab:
3604 case CV_BGR2Luv: case CV_RGB2Luv: case CV_LBGR2Luv: case CV_LRGB2Luv:
3606 CV_Assert( (scn == 3 || scn == 4) && (depth == CV_8U || depth == CV_32F) );
3607 bidx = code == CV_BGR2Lab || code == CV_BGR2Luv ||
3608 code == CV_LBGR2Lab || code == CV_LBGR2Luv ? 0 : 2;
3609 bool srgb = code == CV_BGR2Lab || code == CV_RGB2Lab ||
3610 code == CV_BGR2Luv || code == CV_RGB2Luv;
3612 _dst.create(sz, CV_MAKETYPE(depth, 3));
3613 dst = _dst.getMat();
3615 if( code == CV_BGR2Lab || code == CV_RGB2Lab ||
3616 code == CV_LBGR2Lab || code == CV_LRGB2Lab )
3618 if( depth == CV_8U )
3619 CvtColorLoop(src, dst, RGB2Lab_b(scn, bidx, 0, 0, srgb));
3621 CvtColorLoop(src, dst, RGB2Lab_f(scn, bidx, 0, 0, srgb));
3625 if( depth == CV_8U )
3626 CvtColorLoop(src, dst, RGB2Luv_b(scn, bidx, 0, 0, srgb));
3628 CvtColorLoop(src, dst, RGB2Luv_f(scn, bidx, 0, 0, srgb));
3633 case CV_Lab2BGR: case CV_Lab2RGB: case CV_Lab2LBGR: case CV_Lab2LRGB:
3634 case CV_Luv2BGR: case CV_Luv2RGB: case CV_Luv2LBGR: case CV_Luv2LRGB:
3636 if( dcn <= 0 ) dcn = 3;
3637 CV_Assert( scn == 3 && (dcn == 3 || dcn == 4) && (depth == CV_8U || depth == CV_32F) );
3638 bidx = code == CV_Lab2BGR || code == CV_Luv2BGR ||
3639 code == CV_Lab2LBGR || code == CV_Luv2LBGR ? 0 : 2;
3640 bool srgb = code == CV_Lab2BGR || code == CV_Lab2RGB ||
3641 code == CV_Luv2BGR || code == CV_Luv2RGB;
3643 _dst.create(sz, CV_MAKETYPE(depth, dcn));
3644 dst = _dst.getMat();
3646 if( code == CV_Lab2BGR || code == CV_Lab2RGB ||
3647 code == CV_Lab2LBGR || code == CV_Lab2LRGB )
3649 if( depth == CV_8U )
3650 CvtColorLoop(src, dst, Lab2RGB_b(dcn, bidx, 0, 0, srgb));
3652 CvtColorLoop(src, dst, Lab2RGB_f(dcn, bidx, 0, 0, srgb));
3656 if( depth == CV_8U )
3657 CvtColorLoop(src, dst, Luv2RGB_b(dcn, bidx, 0, 0, srgb));
3659 CvtColorLoop(src, dst, Luv2RGB_f(dcn, bidx, 0, 0, srgb));
3664 case CV_BayerBG2GRAY: case CV_BayerGB2GRAY: case CV_BayerRG2GRAY: case CV_BayerGR2GRAY:
3665 if(dcn <= 0) dcn = 1;
3666 CV_Assert( scn == 1 && dcn == 1 );
3668 _dst.create(sz, CV_MAKETYPE(depth, dcn));
3669 dst = _dst.getMat();
3671 if( depth == CV_8U )
3672 Bayer2Gray_<uchar, SIMDBayerInterpolator_8u>(src, dst, code);
3673 else if( depth == CV_16U )
3674 Bayer2Gray_<ushort, SIMDBayerStubInterpolator_<ushort> >(src, dst, code);
3676 CV_Error(CV_StsUnsupportedFormat, "Bayer->Gray demosaicing only supports 8u and 16u types");
3679 case CV_BayerBG2BGR: case CV_BayerGB2BGR: case CV_BayerRG2BGR: case CV_BayerGR2BGR:
3680 case CV_BayerBG2BGR_VNG: case CV_BayerGB2BGR_VNG: case CV_BayerRG2BGR_VNG: case CV_BayerGR2BGR_VNG:
3684 CV_Assert( scn == 1 && dcn == 3 );
3686 _dst.create(sz, CV_MAKE_TYPE(depth, dcn));
3687 Mat dst_ = _dst.getMat();
3689 if( code == CV_BayerBG2BGR || code == CV_BayerGB2BGR ||
3690 code == CV_BayerRG2BGR || code == CV_BayerGR2BGR )
3692 if( depth == CV_8U )
3693 Bayer2RGB_<uchar, SIMDBayerInterpolator_8u>(src, dst_, code);
3694 else if( depth == CV_16U )
3695 Bayer2RGB_<ushort, SIMDBayerStubInterpolator_<ushort> >(src, dst_, code);
3697 CV_Error(CV_StsUnsupportedFormat, "Bayer->RGB demosaicing only supports 8u and 16u types");
3701 CV_Assert( depth == CV_8U );
3702 Bayer2RGB_VNG_8u(src, dst_, code);
3706 case CV_YUV2BGR_NV21: case CV_YUV2RGB_NV21: case CV_YUV2BGR_NV12: case CV_YUV2RGB_NV12:
3707 case CV_YUV2BGRA_NV21: case CV_YUV2RGBA_NV21: case CV_YUV2BGRA_NV12: case CV_YUV2RGBA_NV12:
3709 // 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
3710 // 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
3712 if (dcn <= 0) dcn = (code==CV_YUV420sp2BGRA || code==CV_YUV420sp2RGBA || code==CV_YUV2BGRA_NV12 || code==CV_YUV2RGBA_NV12) ? 4 : 3;
3713 const int bIdx = (code==CV_YUV2BGR_NV21 || code==CV_YUV2BGRA_NV21 || code==CV_YUV2BGR_NV12 || code==CV_YUV2BGRA_NV12) ? 0 : 2;
3714 const int uIdx = (code==CV_YUV2BGR_NV21 || code==CV_YUV2BGRA_NV21 || code==CV_YUV2RGB_NV21 || code==CV_YUV2RGBA_NV21) ? 1 : 0;
3716 CV_Assert( dcn == 3 || dcn == 4 );
3717 CV_Assert( sz.width % 2 == 0 && sz.height % 3 == 0 && depth == CV_8U );
3719 Size dstSz(sz.width, sz.height * 2 / 3);
3720 _dst.create(dstSz, CV_MAKETYPE(depth, dcn));
3721 dst = _dst.getMat();
3723 int srcstep = (int)src.step;
3724 const uchar* y = src.ptr();
3725 const uchar* uv = y + srcstep * dstSz.height;
3727 switch(dcn*100 + bIdx * 10 + uIdx)
3729 case 300: cvtYUV420sp2RGB<0, 0> (dst, srcstep, y, uv); break;
3730 case 301: cvtYUV420sp2RGB<0, 1> (dst, srcstep, y, uv); break;
3731 case 320: cvtYUV420sp2RGB<2, 0> (dst, srcstep, y, uv); break;
3732 case 321: cvtYUV420sp2RGB<2, 1> (dst, srcstep, y, uv); break;
3733 case 400: cvtYUV420sp2RGBA<0, 0>(dst, srcstep, y, uv); break;
3734 case 401: cvtYUV420sp2RGBA<0, 1>(dst, srcstep, y, uv); break;
3735 case 420: cvtYUV420sp2RGBA<2, 0>(dst, srcstep, y, uv); break;
3736 case 421: cvtYUV420sp2RGBA<2, 1>(dst, srcstep, y, uv); break;
3737 default: CV_Error( CV_StsBadFlag, "Unknown/unsupported color conversion code" ); break;
3741 case CV_YUV2BGR_YV12: case CV_YUV2RGB_YV12: case CV_YUV2BGRA_YV12: case CV_YUV2RGBA_YV12:
3742 case CV_YUV2BGR_IYUV: case CV_YUV2RGB_IYUV: case CV_YUV2BGRA_IYUV: case CV_YUV2RGBA_IYUV:
3744 //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.
3745 //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
3747 if (dcn <= 0) dcn = (code==CV_YUV2BGRA_YV12 || code==CV_YUV2RGBA_YV12 || code==CV_YUV2RGBA_IYUV || code==CV_YUV2BGRA_IYUV) ? 4 : 3;
3748 const int bIdx = (code==CV_YUV2BGR_YV12 || code==CV_YUV2BGRA_YV12 || code==CV_YUV2BGR_IYUV || code==CV_YUV2BGRA_IYUV) ? 0 : 2;
3749 const int uIdx = (code==CV_YUV2BGR_YV12 || code==CV_YUV2RGB_YV12 || code==CV_YUV2BGRA_YV12 || code==CV_YUV2RGBA_YV12) ? 1 : 0;
3751 CV_Assert( dcn == 3 || dcn == 4 );
3752 CV_Assert( sz.width % 2 == 0 && sz.height % 3 == 0 && depth == CV_8U );
3754 Size dstSz(sz.width, sz.height * 2 / 3);
3755 _dst.create(dstSz, CV_MAKETYPE(depth, dcn));
3756 dst = _dst.getMat();
3758 int srcstep = (int)src.step;
3759 const uchar* y = src.ptr();
3760 const uchar* u = y + srcstep * dstSz.height;
3761 const uchar* v = y + srcstep * (dstSz.height + dstSz.height/4) + (dstSz.width/2) * ((dstSz.height % 4)/2);
3764 int vstepIdx = dstSz.height % 4 == 2 ? 1 : 0;
3766 if(uIdx == 1) { std::swap(u ,v), std::swap(ustepIdx, vstepIdx); };
3768 switch(dcn*10 + bIdx)
3770 case 30: cvtYUV420p2RGB<0>(dst, srcstep, y, u, v, ustepIdx, vstepIdx); break;
3771 case 32: cvtYUV420p2RGB<2>(dst, srcstep, y, u, v, ustepIdx, vstepIdx); break;
3772 case 40: cvtYUV420p2RGBA<0>(dst, srcstep, y, u, v, ustepIdx, vstepIdx); break;
3773 case 42: cvtYUV420p2RGBA<2>(dst, srcstep, y, u, v, ustepIdx, vstepIdx); break;
3774 default: CV_Error( CV_StsBadFlag, "Unknown/unsupported color conversion code" ); break;
3778 case CV_YUV2GRAY_420:
3780 if (dcn <= 0) dcn = 1;
3782 CV_Assert( dcn == 1 );
3783 CV_Assert( sz.width % 2 == 0 && sz.height % 3 == 0 && depth == CV_8U );
3785 Size dstSz(sz.width, sz.height * 2 / 3);
3786 _dst.create(dstSz, CV_MAKETYPE(depth, dcn));
3787 dst = _dst.getMat();
3789 src(Range(0, dstSz.height), Range::all()).copyTo(dst);
3792 case CV_RGB2YUV_YV12: case CV_BGR2YUV_YV12: case CV_RGBA2YUV_YV12: case CV_BGRA2YUV_YV12:
3793 case CV_RGB2YUV_IYUV: case CV_BGR2YUV_IYUV: case CV_RGBA2YUV_IYUV: case CV_BGRA2YUV_IYUV:
3795 if (dcn <= 0) dcn = 1;
3796 const int bIdx = (code == CV_BGR2YUV_IYUV || code == CV_BGRA2YUV_IYUV || code == CV_BGR2YUV_YV12 || code == CV_BGRA2YUV_YV12) ? 0 : 2;
3797 const int uIdx = (code == CV_BGR2YUV_IYUV || code == CV_BGRA2YUV_IYUV || code == CV_RGB2YUV_IYUV || code == CV_RGBA2YUV_IYUV) ? 1 : 2;
3799 CV_Assert( (scn == 3 || scn == 4) && depth == CV_8U );
3800 CV_Assert( dcn == 1 );
3801 CV_Assert( sz.width % 2 == 0 && sz.height % 2 == 0 );
3803 Size dstSz(sz.width, sz.height / 2 * 3);
3804 _dst.create(dstSz, CV_MAKETYPE(depth, dcn));
3805 dst = _dst.getMat();
3807 switch(bIdx + uIdx*10)
3809 case 10: cvtRGBtoYUV420p<0, 1>(src, dst); break;
3810 case 12: cvtRGBtoYUV420p<2, 1>(src, dst); break;
3811 case 20: cvtRGBtoYUV420p<0, 2>(src, dst); break;
3812 case 22: cvtRGBtoYUV420p<2, 2>(src, dst); break;
3813 default: CV_Error( CV_StsBadFlag, "Unknown/unsupported color conversion code" ); break;
3817 case CV_YUV2RGB_UYVY: case CV_YUV2BGR_UYVY: case CV_YUV2RGBA_UYVY: case CV_YUV2BGRA_UYVY:
3818 case CV_YUV2RGB_YUY2: case CV_YUV2BGR_YUY2: case CV_YUV2RGB_YVYU: case CV_YUV2BGR_YVYU:
3819 case CV_YUV2RGBA_YUY2: case CV_YUV2BGRA_YUY2: case CV_YUV2RGBA_YVYU: case CV_YUV2BGRA_YVYU:
3821 //http://www.fourcc.org/yuv.php#UYVY
3822 //http://www.fourcc.org/yuv.php#YUY2
3823 //http://www.fourcc.org/yuv.php#YVYU
3825 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;
3826 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;
3827 const int ycn = (code==CV_YUV2RGB_UYVY || code==CV_YUV2BGR_UYVY || code==CV_YUV2RGBA_UYVY || code==CV_YUV2BGRA_UYVY) ? 1 : 0;
3828 const int uIdx = (code==CV_YUV2RGB_YVYU || code==CV_YUV2BGR_YVYU || code==CV_YUV2RGBA_YVYU || code==CV_YUV2BGRA_YVYU) ? 1 : 0;
3830 CV_Assert( dcn == 3 || dcn == 4 );
3831 CV_Assert( scn == 2 && depth == CV_8U );
3833 _dst.create(sz, CV_8UC(dcn));
3834 dst = _dst.getMat();
3836 switch(dcn*1000 + bIdx*100 + uIdx*10 + ycn)
3838 case 3000: cvtYUV422toRGB<0,0,0>(dst, (int)src.step, src.ptr<uchar>()); break;
3839 case 3001: cvtYUV422toRGB<0,0,1>(dst, (int)src.step, src.ptr<uchar>()); break;
3840 case 3010: cvtYUV422toRGB<0,1,0>(dst, (int)src.step, src.ptr<uchar>()); break;
3841 case 3011: cvtYUV422toRGB<0,1,1>(dst, (int)src.step, src.ptr<uchar>()); break;
3842 case 3200: cvtYUV422toRGB<2,0,0>(dst, (int)src.step, src.ptr<uchar>()); break;
3843 case 3201: cvtYUV422toRGB<2,0,1>(dst, (int)src.step, src.ptr<uchar>()); break;
3844 case 3210: cvtYUV422toRGB<2,1,0>(dst, (int)src.step, src.ptr<uchar>()); break;
3845 case 3211: cvtYUV422toRGB<2,1,1>(dst, (int)src.step, src.ptr<uchar>()); break;
3846 case 4000: cvtYUV422toRGBA<0,0,0>(dst, (int)src.step, src.ptr<uchar>()); break;
3847 case 4001: cvtYUV422toRGBA<0,0,1>(dst, (int)src.step, src.ptr<uchar>()); break;
3848 case 4010: cvtYUV422toRGBA<0,1,0>(dst, (int)src.step, src.ptr<uchar>()); break;
3849 case 4011: cvtYUV422toRGBA<0,1,1>(dst, (int)src.step, src.ptr<uchar>()); break;
3850 case 4200: cvtYUV422toRGBA<2,0,0>(dst, (int)src.step, src.ptr<uchar>()); break;
3851 case 4201: cvtYUV422toRGBA<2,0,1>(dst, (int)src.step, src.ptr<uchar>()); break;
3852 case 4210: cvtYUV422toRGBA<2,1,0>(dst, (int)src.step, src.ptr<uchar>()); break;
3853 case 4211: cvtYUV422toRGBA<2,1,1>(dst, (int)src.step, src.ptr<uchar>()); break;
3854 default: CV_Error( CV_StsBadFlag, "Unknown/unsupported color conversion code" ); break;
3858 case CV_YUV2GRAY_UYVY: case CV_YUV2GRAY_YUY2:
3860 if (dcn <= 0) dcn = 1;
3862 CV_Assert( dcn == 1 );
3863 CV_Assert( scn == 2 && depth == CV_8U );
3865 extractChannel(_src, _dst, code == CV_YUV2GRAY_UYVY ? 1 : 0);
3870 if (dcn <= 0) dcn = 4;
3871 CV_Assert( scn == 4 && dcn == 4 );
3873 _dst.create(sz, CV_MAKETYPE(depth, dcn));
3874 dst = _dst.getMat();
3876 if( depth == CV_8U )
3878 CvtColorLoop(src, dst, RGBA2mRGBA<uchar>());
3880 CV_Error( CV_StsBadArg, "Unsupported image depth" );
3886 if (dcn <= 0) dcn = 4;
3887 CV_Assert( scn == 4 && dcn == 4 );
3889 _dst.create(sz, CV_MAKETYPE(depth, dcn));
3890 dst = _dst.getMat();
3892 if( depth == CV_8U )
3894 CvtColorLoop(src, dst, mRGBA2RGBA<uchar>());
3896 CV_Error( CV_StsBadArg, "Unsupported image depth" );
3901 CV_Error( CV_StsBadFlag, "Unknown/unsupported color conversion code" );
3906 cvCvtColor( const CvArr* srcarr, CvArr* dstarr, int code )
3908 cv::Mat src = cv::cvarrToMat(srcarr), dst0 = cv::cvarrToMat(dstarr), dst = dst0;
3909 CV_Assert( src.depth() == dst.depth() );
3911 cv::cvtColor(src, dst, code, dst.channels());
3912 CV_Assert( dst.data == dst0.data );