imagecore 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. data/.gitignore +24 -0
  2. data/Gemfile +4 -0
  3. data/Rakefile +2 -0
  4. data/ext/imagecore/analyze_image.cxx +58 -0
  5. data/ext/imagecore/analyze_image.h +6 -0
  6. data/ext/imagecore/extconf.rb +9 -0
  7. data/ext/imagecore/imagecore.cxx +34 -0
  8. data/ext/opencv/core/___.c +3 -0
  9. data/ext/opencv/core/alloc.cpp +697 -0
  10. data/ext/opencv/core/array.cpp +3206 -0
  11. data/ext/opencv/core/datastructs.cpp +4064 -0
  12. data/ext/opencv/core/extconf.rb +22 -0
  13. data/ext/opencv/core/matrix.cpp +3777 -0
  14. data/ext/opencv/core/precomp.hpp +216 -0
  15. data/ext/opencv/core/system.cpp +832 -0
  16. data/ext/opencv/core/tables.cpp +3512 -0
  17. data/ext/opencv/highgui/___.c +3 -0
  18. data/ext/opencv/highgui/bitstrm.cpp +582 -0
  19. data/ext/opencv/highgui/bitstrm.hpp +182 -0
  20. data/ext/opencv/highgui/extconf.rb +28 -0
  21. data/ext/opencv/highgui/grfmt_base.cpp +128 -0
  22. data/ext/opencv/highgui/grfmt_base.hpp +113 -0
  23. data/ext/opencv/highgui/grfmt_bmp.cpp +564 -0
  24. data/ext/opencv/highgui/grfmt_bmp.hpp +99 -0
  25. data/ext/opencv/highgui/grfmt_exr.hpp +113 -0
  26. data/ext/opencv/highgui/grfmt_imageio.hpp +56 -0
  27. data/ext/opencv/highgui/grfmt_jpeg.cpp +622 -0
  28. data/ext/opencv/highgui/grfmt_jpeg.hpp +90 -0
  29. data/ext/opencv/highgui/grfmt_jpeg2000.cpp +529 -0
  30. data/ext/opencv/highgui/grfmt_jpeg2000.hpp +95 -0
  31. data/ext/opencv/highgui/grfmt_png.cpp +406 -0
  32. data/ext/opencv/highgui/grfmt_png.hpp +101 -0
  33. data/ext/opencv/highgui/grfmt_pxm.cpp +513 -0
  34. data/ext/opencv/highgui/grfmt_pxm.hpp +92 -0
  35. data/ext/opencv/highgui/grfmt_sunras.cpp +425 -0
  36. data/ext/opencv/highgui/grfmt_sunras.hpp +105 -0
  37. data/ext/opencv/highgui/grfmt_tiff.cpp +718 -0
  38. data/ext/opencv/highgui/grfmt_tiff.hpp +136 -0
  39. data/ext/opencv/highgui/grfmts.hpp +56 -0
  40. data/ext/opencv/highgui/loadsave.cpp +535 -0
  41. data/ext/opencv/highgui/precomp.hpp +223 -0
  42. data/ext/opencv/highgui/utils.cpp +689 -0
  43. data/ext/opencv/highgui/utils.hpp +128 -0
  44. data/ext/opencv/imgproc/___.c +3 -0
  45. data/ext/opencv/imgproc/_geom.h +72 -0
  46. data/ext/opencv/imgproc/color.cpp +3179 -0
  47. data/ext/opencv/imgproc/contours.cpp +1780 -0
  48. data/ext/opencv/imgproc/extconf.rb +11 -0
  49. data/ext/opencv/imgproc/filter.cpp +3063 -0
  50. data/ext/opencv/imgproc/precomp.hpp +159 -0
  51. data/ext/opencv/imgproc/shapedescr.cpp +1306 -0
  52. data/ext/opencv/imgproc/smooth.cpp +1566 -0
  53. data/ext/opencv/imgproc/tables.cpp +214 -0
  54. data/ext/opencv/imgproc/thresh.cpp +636 -0
  55. data/ext/opencv/imgproc/utils.cpp +242 -0
  56. data/ext/opencv/include/opencv2/core/core.hpp +4344 -0
  57. data/ext/opencv/include/opencv2/core/core_c.h +1885 -0
  58. data/ext/opencv/include/opencv2/core/internal.hpp +710 -0
  59. data/ext/opencv/include/opencv2/core/mat.hpp +2557 -0
  60. data/ext/opencv/include/opencv2/core/operations.hpp +3623 -0
  61. data/ext/opencv/include/opencv2/core/types_c.h +1875 -0
  62. data/ext/opencv/include/opencv2/core/version.hpp +58 -0
  63. data/ext/opencv/include/opencv2/highgui/highgui.hpp +198 -0
  64. data/ext/opencv/include/opencv2/highgui/highgui_c.h +506 -0
  65. data/ext/opencv/include/opencv2/imgproc/imgproc.hpp +1139 -0
  66. data/ext/opencv/include/opencv2/imgproc/imgproc_c.h +783 -0
  67. data/ext/opencv/include/opencv2/imgproc/types_c.h +538 -0
  68. data/imagecore.gemspec +20 -0
  69. data/lib/imagecore.rb +16 -0
  70. data/lib/imagecore/version.rb +3 -0
  71. metadata +119 -0
@@ -0,0 +1,128 @@
1
+ /*M///////////////////////////////////////////////////////////////////////////////////////
2
+ //
3
+ // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4
+ //
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.
8
+ //
9
+ //
10
+ // Intel License Agreement
11
+ // For Open Source Computer Vision Library
12
+ //
13
+ // Copyright (C) 2000, Intel Corporation, all rights reserved.
14
+ // Third party copyrights are property of their respective owners.
15
+ //
16
+ // Redistribution and use in source and binary forms, with or without modification,
17
+ // are permitted provided that the following conditions are met:
18
+ //
19
+ // * Redistribution's of source code must retain the above copyright notice,
20
+ // this list of conditions and the following disclaimer.
21
+ //
22
+ // * Redistribution's in binary form must reproduce the above copyright notice,
23
+ // this list of conditions and the following disclaimer in the documentation
24
+ // and/or other materials provided with the distribution.
25
+ //
26
+ // * The name of Intel Corporation may not be used to endorse or promote products
27
+ // derived from this software without specific prior written permission.
28
+ //
29
+ // This software is provided by the copyright holders and contributors "as is" and
30
+ // any express or implied warranties, including, but not limited to, the implied
31
+ // warranties of merchantability and fitness for a particular purpose are disclaimed.
32
+ // In no event shall the Intel Corporation or contributors be liable for any direct,
33
+ // indirect, incidental, special, exemplary, or consequential damages
34
+ // (including, but not limited to, procurement of substitute goods or services;
35
+ // loss of use, data, or profits; or business interruption) however caused
36
+ // and on any theory of liability, whether in contract, strict liability,
37
+ // or tort (including negligence or otherwise) arising in any way out of
38
+ // the use of this software, even if advised of the possibility of such damage.
39
+ //
40
+ //M*/
41
+
42
+ #ifndef _UTILS_H_
43
+ #define _UTILS_H_
44
+
45
+ struct PaletteEntry
46
+ {
47
+ unsigned char b, g, r, a;
48
+ };
49
+
50
+ #define WRITE_PIX( ptr, clr ) \
51
+ (((uchar*)(ptr))[0] = (clr).b, \
52
+ ((uchar*)(ptr))[1] = (clr).g, \
53
+ ((uchar*)(ptr))[2] = (clr).r)
54
+
55
+ #define descale(x,n) (((x) + (1 << ((n)-1))) >> (n))
56
+ #define saturate(x) (uchar)(((x) & ~255) == 0 ? (x) : ~((x)>>31))
57
+
58
+ void icvCvt_BGR2Gray_8u_C3C1R( const uchar* bgr, int bgr_step,
59
+ uchar* gray, int gray_step,
60
+ CvSize size, int swap_rb=0 );
61
+ void icvCvt_BGRA2Gray_8u_C4C1R( const uchar* bgra, int bgra_step,
62
+ uchar* gray, int gray_step,
63
+ CvSize size, int swap_rb=0 );
64
+ void icvCvt_BGRA2Gray_16u_CnC1R( const ushort* bgra, int bgra_step,
65
+ ushort* gray, int gray_step,
66
+ CvSize size, int ncn, int swap_rb=0 );
67
+
68
+ void icvCvt_Gray2BGR_8u_C1C3R( const uchar* gray, int gray_step,
69
+ uchar* bgr, int bgr_step, CvSize size );
70
+ void icvCvt_Gray2BGR_16u_C1C3R( const ushort* gray, int gray_step,
71
+ ushort* bgr, int bgr_step, CvSize size );
72
+
73
+ void icvCvt_BGRA2BGR_8u_C4C3R( const uchar* bgra, int bgra_step,
74
+ uchar* bgr, int bgr_step,
75
+ CvSize size, int swap_rb=0 );
76
+ void icvCvt_BGRA2BGR_16u_C4C3R( const ushort* bgra, int bgra_step,
77
+ ushort* bgr, int bgr_step,
78
+ CvSize size, int _swap_rb );
79
+
80
+ void icvCvt_BGR2RGB_8u_C3R( const uchar* bgr, int bgr_step,
81
+ uchar* rgb, int rgb_step, CvSize size );
82
+ #define icvCvt_RGB2BGR_8u_C3R icvCvt_BGR2RGB_8u_C3R
83
+ void icvCvt_BGR2RGB_16u_C3R( const ushort* bgr, int bgr_step,
84
+ ushort* rgb, int rgb_step, CvSize size );
85
+ #define icvCvt_RGB2BGR_16u_C3R icvCvt_BGR2RGB_16u_C3R
86
+
87
+ void icvCvt_BGRA2RGBA_8u_C4R( const uchar* bgra, int bgra_step,
88
+ uchar* rgba, int rgba_step, CvSize size );
89
+ #define icvCvt_RGBA2BGRA_8u_C4R icvCvt_BGRA2RGBA_8u_C4R
90
+
91
+ void icvCvt_BGRA2RGBA_16u_C4R( const ushort* bgra, int bgra_step,
92
+ ushort* rgba, int rgba_step, CvSize size );
93
+ #define icvCvt_RGBA2BGRA_16u_C4R icvCvt_BGRA2RGBA_16u_C4R
94
+
95
+ void icvCvt_BGR5552Gray_8u_C2C1R( const uchar* bgr555, int bgr555_step,
96
+ uchar* gray, int gray_step, CvSize size );
97
+ void icvCvt_BGR5652Gray_8u_C2C1R( const uchar* bgr565, int bgr565_step,
98
+ uchar* gray, int gray_step, CvSize size );
99
+ void icvCvt_BGR5552BGR_8u_C2C3R( const uchar* bgr555, int bgr555_step,
100
+ uchar* bgr, int bgr_step, CvSize size );
101
+ void icvCvt_BGR5652BGR_8u_C2C3R( const uchar* bgr565, int bgr565_step,
102
+ uchar* bgr, int bgr_step, CvSize size );
103
+ void icvCvt_CMYK2BGR_8u_C4C3R( const uchar* cmyk, int cmyk_step,
104
+ uchar* bgr, int bgr_step, CvSize size );
105
+ void icvCvt_CMYK2Gray_8u_C4C1R( const uchar* ycck, int ycck_step,
106
+ uchar* gray, int gray_step, CvSize size );
107
+
108
+ void FillGrayPalette( PaletteEntry* palette, int bpp, bool negative = false );
109
+ bool IsColorPalette( PaletteEntry* palette, int bpp );
110
+ void CvtPaletteToGray( const PaletteEntry* palette, uchar* grayPalette, int entries );
111
+ uchar* FillUniColor( uchar* data, uchar*& line_end, int step, int width3,
112
+ int& y, int height, int count3, PaletteEntry clr );
113
+ uchar* FillUniGray( uchar* data, uchar*& line_end, int step, int width3,
114
+ int& y, int height, int count3, uchar clr );
115
+
116
+ uchar* FillColorRow8( uchar* data, uchar* indices, int len, PaletteEntry* palette );
117
+ uchar* FillGrayRow8( uchar* data, uchar* indices, int len, uchar* palette );
118
+ uchar* FillColorRow4( uchar* data, uchar* indices, int len, PaletteEntry* palette );
119
+ uchar* FillGrayRow4( uchar* data, uchar* indices, int len, uchar* palette );
120
+ uchar* FillColorRow1( uchar* data, uchar* indices, int len, PaletteEntry* palette );
121
+ uchar* FillGrayRow1( uchar* data, uchar* indices, int len, uchar* palette );
122
+
123
+ CV_INLINE bool isBigEndian( void )
124
+ {
125
+ return (((const int*)"\0\x1\x2\x3\x4\x5\x6\x7")[0] & 255) != 0;
126
+ }
127
+
128
+ #endif/*_UTILS_H_*/
@@ -0,0 +1,3 @@
1
+ void Init_opencv_imgproc()
2
+ {
3
+ }
@@ -0,0 +1,72 @@
1
+ /*M///////////////////////////////////////////////////////////////////////////////////////
2
+ //
3
+ // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4
+ //
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.
8
+ //
9
+ //
10
+ // Intel License Agreement
11
+ // For Open Source Computer Vision Library
12
+ //
13
+ // Copyright (C) 2000, Intel Corporation, all rights reserved.
14
+ // Third party copyrights are property of their respective owners.
15
+ //
16
+ // Redistribution and use in source and binary forms, with or without modification,
17
+ // are permitted provided that the following conditions are met:
18
+ //
19
+ // * Redistribution's of source code must retain the above copyright notice,
20
+ // this list of conditions and the following disclaimer.
21
+ //
22
+ // * Redistribution's in binary form must reproduce the above copyright notice,
23
+ // this list of conditions and the following disclaimer in the documentation
24
+ // and/or other materials provided with the distribution.
25
+ //
26
+ // * The name of Intel Corporation may not be used to endorse or promote products
27
+ // derived from this software without specific prior written permission.
28
+ //
29
+ // This software is provided by the copyright holders and contributors "as is" and
30
+ // any express or implied warranties, including, but not limited to, the implied
31
+ // warranties of merchantability and fitness for a particular purpose are disclaimed.
32
+ // In no event shall the Intel Corporation or contributors be liable for any direct,
33
+ // indirect, incidental, special, exemplary, or consequential damages
34
+ // (including, but not limited to, procurement of substitute goods or services;
35
+ // loss of use, data, or profits; or business interruption) however caused
36
+ // and on any theory of liability, whether in contract, strict liability,
37
+ // or tort (including negligence or otherwise) arising in any way out of
38
+ // the use of this software, even if advised of the possibility of such damage.
39
+ //
40
+ //M*/
41
+
42
+ #ifndef _CV_GEOM_H_
43
+ #define _CV_GEOM_H_
44
+
45
+ /* Finds distance between two points */
46
+ CV_INLINE float icvDistanceL2_32f( CvPoint2D32f pt1, CvPoint2D32f pt2 )
47
+ {
48
+ float dx = pt2.x - pt1.x;
49
+ float dy = pt2.y - pt1.y;
50
+
51
+ return std::sqrt( dx*dx + dy*dy );
52
+ }
53
+
54
+
55
+ int icvIntersectLines( double x1, double dx1, double y1, double dy1,
56
+ double x2, double dx2, double y2, double dy2,
57
+ double* t2 );
58
+
59
+
60
+ void icvCreateCenterNormalLine( CvSubdiv2DEdge edge, double* a, double* b, double* c );
61
+
62
+ void icvIntersectLines3( double* a0, double* b0, double* c0,
63
+ double* a1, double* b1, double* c1,
64
+ CvPoint2D32f* point );
65
+
66
+
67
+ /* curvature: 0 - 1-curvature, 1 - k-cosine curvature. */
68
+ CvSeq* icvApproximateChainTC89( CvChain* chain, int header_size, CvMemStorage* storage, int method );
69
+
70
+ #endif /*_IPCVGEOM_H_*/
71
+
72
+ /* End of file. */
@@ -0,0 +1,3179 @@
1
+ /*M///////////////////////////////////////////////////////////////////////////////////////
2
+ //
3
+ // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4
+ //
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.
8
+ //
9
+ //
10
+ // License Agreement
11
+ // For Open Source Computer Vision Library
12
+ //
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.
16
+ //
17
+ // Redistribution and use in source and binary forms, with or without modification,
18
+ // are permitted provided that the following conditions are met:
19
+ //
20
+ // * Redistribution's of source code must retain the above copyright notice,
21
+ // this list of conditions and the following disclaimer.
22
+ //
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.
26
+ //
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.
29
+ //
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.
40
+ //
41
+ //M*/
42
+
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
+ \**********************************************************************************/
48
+
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:
52
+
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.
57
+
58
+ Contributors License Agreement:
59
+
60
+ Copyright (c) 2002,
61
+ MD-Mathematische Dienste GmbH
62
+ Im Defdahl 5-10
63
+ 44141 Dortmund
64
+ Germany
65
+ www.md-it.de
66
+
67
+ Redistribution and use in source and binary forms,
68
+ with or without modification, are permitted provided
69
+ that the following conditions are met:
70
+
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.
78
+
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
+ \**********************************************************************************/
91
+
92
+ #include "precomp.hpp"
93
+ #include <limits>
94
+
95
+ namespace cv
96
+ {
97
+
98
+ // computes cubic spline coefficients for a function: (xi=i, yi=f[i]), i=0..n
99
+ template<typename _Tp> static void splineBuild(const _Tp* f, int n, _Tp* tab)
100
+ {
101
+ _Tp cn = 0;
102
+ int i;
103
+ tab[0] = tab[1] = (_Tp)0;
104
+
105
+ for(i = 1; i < n-1; i++)
106
+ {
107
+ _Tp t = 3*(f[i+1] - 2*f[i] + f[i-1]);
108
+ _Tp l = 1/(4 - tab[(i-1)*4]);
109
+ tab[i*4] = l; tab[i*4+1] = (t - tab[(i-1)*4+1])*l;
110
+ }
111
+
112
+ for(i = n-1; i >= 0; i--)
113
+ {
114
+ _Tp c = tab[i*4+1] - tab[i*4]*cn;
115
+ _Tp b = f[i+1] - f[i] - (cn + c*2)*(_Tp)0.3333333333333333;
116
+ _Tp d = (cn - c)*(_Tp)0.3333333333333333;
117
+ tab[i*4] = f[i]; tab[i*4+1] = b;
118
+ tab[i*4+2] = c; tab[i*4+3] = d;
119
+ cn = c;
120
+ }
121
+ }
122
+
123
+ // interpolates value of a function at x, 0 <= x <= n using a cubic spline.
124
+ template<typename _Tp> static inline _Tp splineInterpolate(_Tp x, const _Tp* tab, int n)
125
+ {
126
+ int ix = cvFloor(x);
127
+ ix = std::min(std::max(ix, 0), n-1);
128
+ x -= ix;
129
+ tab += ix*4;
130
+ return ((tab[3]*x + tab[2])*x + tab[1])*x + tab[0];
131
+ }
132
+
133
+
134
+ template<typename _Tp> struct ColorChannel
135
+ {
136
+ typedef float worktype_f;
137
+ static _Tp max() { return std::numeric_limits<_Tp>::max(); }
138
+ static _Tp half() { return (_Tp)(max()/2 + 1); }
139
+ };
140
+
141
+ template<> struct ColorChannel<float>
142
+ {
143
+ typedef float worktype_f;
144
+ static float max() { return 1.f; }
145
+ static float half() { return 0.5f; }
146
+ };
147
+
148
+ /*template<> struct ColorChannel<double>
149
+ {
150
+ typedef double worktype_f;
151
+ static double max() { return 1.; }
152
+ static double half() { return 0.5; }
153
+ };*/
154
+
155
+
156
+ ///////////////////////////// Top-level template function ////////////////////////////////
157
+
158
+ template<class Cvt> void CvtColorLoop(const Mat& srcmat, Mat& dstmat, const Cvt& cvt)
159
+ {
160
+ typedef typename Cvt::channel_type _Tp;
161
+ Size sz = srcmat.size();
162
+ const uchar* src = srcmat.data;
163
+ uchar* dst = dstmat.data;
164
+ size_t srcstep = srcmat.step, dststep = dstmat.step;
165
+
166
+ if( srcmat.isContinuous() && dstmat.isContinuous() )
167
+ {
168
+ sz.width *= sz.height;
169
+ sz.height = 1;
170
+ }
171
+
172
+ for( ; sz.height--; src += srcstep, dst += dststep )
173
+ cvt((const _Tp*)src, (_Tp*)dst, sz.width);
174
+ }
175
+
176
+
177
+ ////////////////// Various 3/4-channel to 3/4-channel RGB transformations /////////////////
178
+
179
+ template<typename _Tp> struct RGB2RGB
180
+ {
181
+ typedef _Tp channel_type;
182
+
183
+ RGB2RGB(int _srccn, int _dstcn, int _blueIdx) : srccn(_srccn), dstcn(_dstcn), blueIdx(_blueIdx) {}
184
+ void operator()(const _Tp* src, _Tp* dst, int n) const
185
+ {
186
+ int scn = srccn, dcn = dstcn, bidx = blueIdx;
187
+ if( dcn == 3 )
188
+ {
189
+ n *= 3;
190
+ for( int i = 0; i < n; i += 3, src += scn )
191
+ {
192
+ _Tp t0 = src[bidx], t1 = src[1], t2 = src[bidx ^ 2];
193
+ dst[i] = t0; dst[i+1] = t1; dst[i+2] = t2;
194
+ }
195
+ }
196
+ else if( scn == 3 )
197
+ {
198
+ n *= 3;
199
+ _Tp alpha = ColorChannel<_Tp>::max();
200
+ for( int i = 0; i < n; i += 3, dst += 4 )
201
+ {
202
+ _Tp t0 = src[i], t1 = src[i+1], t2 = src[i+2];
203
+ dst[bidx] = t0; dst[1] = t1; dst[bidx^2] = t2; dst[3] = alpha;
204
+ }
205
+ }
206
+ else
207
+ {
208
+ n *= 4;
209
+ for( int i = 0; i < n; i += 4 )
210
+ {
211
+ _Tp t0 = src[i], t1 = src[i+1], t2 = src[i+2], t3 = src[i+3];
212
+ dst[i] = t2; dst[i+1] = t1; dst[i+2] = t0; dst[i+3] = t3;
213
+ }
214
+ }
215
+ }
216
+
217
+ int srccn, dstcn, blueIdx;
218
+ };
219
+
220
+ /////////// Transforming 16-bit (565 or 555) RGB to/from 24/32-bit (888[8]) RGB //////////
221
+
222
+ struct RGB5x52RGB
223
+ {
224
+ typedef uchar channel_type;
225
+
226
+ RGB5x52RGB(int _dstcn, int _blueIdx, int _greenBits)
227
+ : dstcn(_dstcn), blueIdx(_blueIdx), greenBits(_greenBits) {}
228
+
229
+ void operator()(const uchar* src, uchar* dst, int n) const
230
+ {
231
+ int dcn = dstcn, bidx = blueIdx;
232
+ if( greenBits == 6 )
233
+ for( int i = 0; i < n; i++, dst += dcn )
234
+ {
235
+ unsigned t = ((const ushort*)src)[i];
236
+ dst[bidx] = (uchar)(t << 3);
237
+ dst[1] = (uchar)((t >> 3) & ~3);
238
+ dst[bidx ^ 2] = (uchar)((t >> 8) & ~7);
239
+ if( dcn == 4 )
240
+ dst[3] = 255;
241
+ }
242
+ else
243
+ for( int i = 0; i < n; i++, dst += dcn )
244
+ {
245
+ unsigned t = ((const ushort*)src)[i];
246
+ dst[bidx] = (uchar)(t << 3);
247
+ dst[1] = (uchar)((t >> 2) & ~7);
248
+ dst[bidx ^ 2] = (uchar)((t >> 7) & ~7);
249
+ if( dcn == 4 )
250
+ dst[3] = t & 0x8000 ? 255 : 0;
251
+ }
252
+ }
253
+
254
+ int dstcn, blueIdx, greenBits;
255
+ };
256
+
257
+
258
+ struct RGB2RGB5x5
259
+ {
260
+ typedef uchar channel_type;
261
+
262
+ RGB2RGB5x5(int _srccn, int _blueIdx, int _greenBits)
263
+ : srccn(_srccn), blueIdx(_blueIdx), greenBits(_greenBits) {}
264
+
265
+ void operator()(const uchar* src, uchar* dst, int n) const
266
+ {
267
+ int scn = srccn, bidx = blueIdx;
268
+ if( greenBits == 6 )
269
+ for( int i = 0; i < n; i++, src += scn )
270
+ {
271
+ ((ushort*)dst)[i] = (ushort)((src[bidx] >> 3)|((src[1]&~3) << 3)|((src[bidx^2]&~7) << 8));
272
+ }
273
+ else if( scn == 3 )
274
+ for( int i = 0; i < n; i++, src += 3 )
275
+ {
276
+ ((ushort*)dst)[i] = (ushort)((src[bidx] >> 3)|((src[1]&~7) << 2)|((src[bidx^2]&~7) << 7));
277
+ }
278
+ else
279
+ for( int i = 0; i < n; i++, src += 4 )
280
+ {
281
+ ((ushort*)dst)[i] = (ushort)((src[bidx] >> 3)|((src[1]&~7) << 2)|
282
+ ((src[bidx^2]&~7) << 7)|(src[3] ? 0x8000 : 0));
283
+ }
284
+ }
285
+
286
+ int srccn, blueIdx, greenBits;
287
+ };
288
+
289
+ ///////////////////////////////// Color to/from Grayscale ////////////////////////////////
290
+
291
+ template<typename _Tp>
292
+ struct Gray2RGB
293
+ {
294
+ typedef _Tp channel_type;
295
+
296
+ Gray2RGB(int _dstcn) : dstcn(_dstcn) {}
297
+ void operator()(const _Tp* src, _Tp* dst, int n) const
298
+ {
299
+ if( dstcn == 3 )
300
+ for( int i = 0; i < n; i++, dst += 3 )
301
+ {
302
+ dst[0] = dst[1] = dst[2] = src[i];
303
+ }
304
+ else
305
+ {
306
+ _Tp alpha = ColorChannel<_Tp>::max();
307
+ for( int i = 0; i < n; i++, dst += 4 )
308
+ {
309
+ dst[0] = dst[1] = dst[2] = src[i];
310
+ dst[3] = alpha;
311
+ }
312
+ }
313
+ }
314
+
315
+ int dstcn;
316
+ };
317
+
318
+
319
+ struct Gray2RGB5x5
320
+ {
321
+ typedef uchar channel_type;
322
+
323
+ Gray2RGB5x5(int _greenBits) : greenBits(_greenBits) {}
324
+ void operator()(const uchar* src, uchar* dst, int n) const
325
+ {
326
+ if( greenBits == 6 )
327
+ for( int i = 0; i < n; i++ )
328
+ {
329
+ int t = src[i];
330
+ ((ushort*)dst)[i] = (ushort)((t >> 3)|((t & ~3) << 3)|((t & ~7) << 8));
331
+ }
332
+ else
333
+ for( int i = 0; i < n; i++ )
334
+ {
335
+ int t = src[i] >> 3;
336
+ ((ushort*)dst)[i] = (ushort)(t|(t << 5)|(t << 10));
337
+ }
338
+ }
339
+ int greenBits;
340
+ };
341
+
342
+
343
+ #undef R2Y
344
+ #undef G2Y
345
+ #undef B2Y
346
+
347
+ enum
348
+ {
349
+ yuv_shift = 14,
350
+ xyz_shift = 12,
351
+ R2Y = 4899,
352
+ G2Y = 9617,
353
+ B2Y = 1868,
354
+ BLOCK_SIZE = 256
355
+ };
356
+
357
+
358
+ struct RGB5x52Gray
359
+ {
360
+ typedef uchar channel_type;
361
+
362
+ RGB5x52Gray(int _greenBits) : greenBits(_greenBits) {}
363
+ void operator()(const uchar* src, uchar* dst, int n) const
364
+ {
365
+ if( greenBits == 6 )
366
+ for( int i = 0; i < n; i++ )
367
+ {
368
+ int t = ((ushort*)src)[i];
369
+ dst[i] = (uchar)CV_DESCALE(((t << 3) & 0xf8)*B2Y +
370
+ ((t >> 3) & 0xfc)*G2Y +
371
+ ((t >> 8) & 0xf8)*R2Y, yuv_shift);
372
+ }
373
+ else
374
+ for( int i = 0; i < n; i++ )
375
+ {
376
+ int t = ((ushort*)src)[i];
377
+ dst[i] = (uchar)CV_DESCALE(((t << 3) & 0xf8)*B2Y +
378
+ ((t >> 2) & 0xf8)*G2Y +
379
+ ((t >> 7) & 0xf8)*R2Y, yuv_shift);
380
+ }
381
+ }
382
+ int greenBits;
383
+ };
384
+
385
+
386
+ template<typename _Tp> struct RGB2Gray
387
+ {
388
+ typedef _Tp channel_type;
389
+
390
+ RGB2Gray(int _srccn, int blueIdx, const float* _coeffs) : srccn(_srccn)
391
+ {
392
+ static const float coeffs0[] = { 0.299f, 0.587f, 0.114f };
393
+ memcpy( coeffs, _coeffs ? _coeffs : coeffs0, 3*sizeof(coeffs[0]) );
394
+ if(blueIdx == 0)
395
+ std::swap(coeffs[0], coeffs[2]);
396
+ }
397
+
398
+ void operator()(const _Tp* src, _Tp* dst, int n) const
399
+ {
400
+ int scn = srccn;
401
+ float cb = coeffs[0], cg = coeffs[1], cr = coeffs[2];
402
+ for(int i = 0; i < n; i++, src += scn)
403
+ dst[i] = saturate_cast<_Tp>(src[0]*cb + src[1]*cg + src[2]*cr);
404
+ }
405
+ int srccn;
406
+ float coeffs[3];
407
+ };
408
+
409
+
410
+ template<> struct RGB2Gray<uchar>
411
+ {
412
+ typedef uchar channel_type;
413
+
414
+ RGB2Gray<uchar>(int _srccn, int blueIdx, const int* coeffs) : srccn(_srccn)
415
+ {
416
+ const int coeffs0[] = { R2Y, G2Y, B2Y };
417
+ if(!coeffs) coeffs = coeffs0;
418
+
419
+ int b = 0, g = 0, r = (1 << (yuv_shift-1));
420
+ int db = coeffs[blueIdx^2], dg = coeffs[1], dr = coeffs[blueIdx];
421
+
422
+ for( int i = 0; i < 256; i++, b += db, g += dg, r += dr )
423
+ {
424
+ tab[i] = b;
425
+ tab[i+256] = g;
426
+ tab[i+512] = r;
427
+ }
428
+ }
429
+ void operator()(const uchar* src, uchar* dst, int n) const
430
+ {
431
+ int scn = srccn;
432
+ const int* _tab = tab;
433
+ for(int i = 0; i < n; i++, src += scn)
434
+ dst[i] = (uchar)((_tab[src[0]] + _tab[src[1]+256] + _tab[src[2]+512]) >> yuv_shift);
435
+ }
436
+ int srccn, blueIdx;
437
+ int tab[256*3];
438
+ };
439
+
440
+
441
+ template<> struct RGB2Gray<ushort>
442
+ {
443
+ typedef ushort channel_type;
444
+
445
+ RGB2Gray<ushort>(int _srccn, int blueIdx, const int* _coeffs) : srccn(_srccn)
446
+ {
447
+ static const int coeffs0[] = { R2Y, G2Y, B2Y };
448
+ memcpy(coeffs, _coeffs ? _coeffs : coeffs0, 3*sizeof(coeffs[0]));
449
+ if( blueIdx == 0 )
450
+ std::swap(coeffs[0], coeffs[2]);
451
+ }
452
+
453
+ void operator()(const ushort* src, ushort* dst, int n) const
454
+ {
455
+ int scn = srccn, cb = coeffs[0], cg = coeffs[1], cr = coeffs[2];
456
+ for(int i = 0; i < n; i++, src += scn)
457
+ dst[i] = (ushort)CV_DESCALE((unsigned)(src[0]*cb + src[1]*cg + src[2]*cr), yuv_shift);
458
+ }
459
+ int srccn;
460
+ int coeffs[3];
461
+ };
462
+
463
+
464
+ ///////////////////////////////////// RGB <-> YCrCb //////////////////////////////////////
465
+
466
+ template<typename _Tp> struct RGB2YCrCb_f
467
+ {
468
+ typedef _Tp channel_type;
469
+
470
+ RGB2YCrCb_f(int _srccn, int _blueIdx, const float* _coeffs) : srccn(_srccn), blueIdx(_blueIdx)
471
+ {
472
+ static const float coeffs0[] = {0.299f, 0.587f, 0.114f, 0.713f, 0.564f};
473
+ memcpy(coeffs, _coeffs ? _coeffs : coeffs0, 5*sizeof(coeffs[0]));
474
+ if(blueIdx==0) std::swap(coeffs[0], coeffs[2]);
475
+ }
476
+
477
+ void operator()(const _Tp* src, _Tp* dst, int n) const
478
+ {
479
+ int scn = srccn, bidx = blueIdx;
480
+ const _Tp delta = ColorChannel<_Tp>::half();
481
+ float C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2], C3 = coeffs[3], C4 = coeffs[4];
482
+ n *= 3;
483
+ for(int i = 0; i < n; i += 3, src += scn)
484
+ {
485
+ _Tp Y = saturate_cast<_Tp>(src[0]*C0 + src[1]*C1 + src[2]*C2);
486
+ _Tp Cr = saturate_cast<_Tp>((src[bidx^2] - Y)*C3 + delta);
487
+ _Tp Cb = saturate_cast<_Tp>((src[bidx] - Y)*C4 + delta);
488
+ dst[i] = Y; dst[i+1] = Cr; dst[i+2] = Cb;
489
+ }
490
+ }
491
+ int srccn, blueIdx;
492
+ float coeffs[5];
493
+ };
494
+
495
+
496
+ template<typename _Tp> struct RGB2YCrCb_i
497
+ {
498
+ typedef _Tp channel_type;
499
+
500
+ RGB2YCrCb_i(int _srccn, int _blueIdx, const int* _coeffs)
501
+ : srccn(_srccn), blueIdx(_blueIdx)
502
+ {
503
+ static const int coeffs0[] = {R2Y, G2Y, B2Y, 11682, 9241};
504
+ memcpy(coeffs, _coeffs ? _coeffs : coeffs0, 5*sizeof(coeffs[0]));
505
+ if(blueIdx==0) std::swap(coeffs[0], coeffs[2]);
506
+ }
507
+ void operator()(const _Tp* src, _Tp* dst, int n) const
508
+ {
509
+ int scn = srccn, bidx = blueIdx;
510
+ int C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2], C3 = coeffs[3], C4 = coeffs[4];
511
+ int delta = ColorChannel<_Tp>::half()*(1 << yuv_shift);
512
+ n *= 3;
513
+ for(int i = 0; i < n; i += 3, src += scn)
514
+ {
515
+ int Y = CV_DESCALE(src[0]*C0 + src[1]*C1 + src[2]*C2, yuv_shift);
516
+ int Cr = CV_DESCALE((src[bidx^2] - Y)*C3 + delta, yuv_shift);
517
+ int Cb = CV_DESCALE((src[bidx] - Y)*C4 + delta, yuv_shift);
518
+ dst[i] = saturate_cast<_Tp>(Y);
519
+ dst[i+1] = saturate_cast<_Tp>(Cr);
520
+ dst[i+2] = saturate_cast<_Tp>(Cb);
521
+ }
522
+ }
523
+ int srccn, blueIdx;
524
+ int coeffs[5];
525
+ };
526
+
527
+
528
+ template<typename _Tp> struct YCrCb2RGB_f
529
+ {
530
+ typedef _Tp channel_type;
531
+
532
+ YCrCb2RGB_f(int _dstcn, int _blueIdx, const float* _coeffs)
533
+ : dstcn(_dstcn), blueIdx(_blueIdx)
534
+ {
535
+ static const float coeffs0[] = {1.403f, -0.714f, -0.344f, 1.773f};
536
+ memcpy(coeffs, _coeffs ? _coeffs : coeffs0, 4*sizeof(coeffs[0]));
537
+ }
538
+ void operator()(const _Tp* src, _Tp* dst, int n) const
539
+ {
540
+ int dcn = dstcn, bidx = blueIdx;
541
+ const _Tp delta = ColorChannel<_Tp>::half(), alpha = ColorChannel<_Tp>::max();
542
+ float C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2], C3 = coeffs[3];
543
+ n *= 3;
544
+ for(int i = 0; i < n; i += 3, dst += dcn)
545
+ {
546
+ _Tp Y = src[i];
547
+ _Tp Cr = src[i+1];
548
+ _Tp Cb = src[i+2];
549
+
550
+ _Tp b = saturate_cast<_Tp>(Y + (Cb - delta)*C3);
551
+ _Tp g = saturate_cast<_Tp>(Y + (Cb - delta)*C2 + (Cr - delta)*C1);
552
+ _Tp r = saturate_cast<_Tp>(Y + (Cr - delta)*C0);
553
+
554
+ dst[bidx] = b; dst[1] = g; dst[bidx^2] = r;
555
+ if( dcn == 4 )
556
+ dst[3] = alpha;
557
+ }
558
+ }
559
+ int dstcn, blueIdx;
560
+ float coeffs[4];
561
+ };
562
+
563
+
564
+ template<typename _Tp> struct YCrCb2RGB_i
565
+ {
566
+ typedef _Tp channel_type;
567
+
568
+ YCrCb2RGB_i(int _dstcn, int _blueIdx, const int* _coeffs)
569
+ : dstcn(_dstcn), blueIdx(_blueIdx)
570
+ {
571
+ static const int coeffs0[] = {22987, -11698, -5636, 29049};
572
+ memcpy(coeffs, _coeffs ? _coeffs : coeffs0, 4*sizeof(coeffs[0]));
573
+ }
574
+
575
+ void operator()(const _Tp* src, _Tp* dst, int n) const
576
+ {
577
+ int dcn = dstcn, bidx = blueIdx;
578
+ const _Tp delta = ColorChannel<_Tp>::half(), alpha = ColorChannel<_Tp>::max();
579
+ int C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2], C3 = coeffs[3];
580
+ n *= 3;
581
+ for(int i = 0; i < n; i += 3, dst += dcn)
582
+ {
583
+ _Tp Y = src[i];
584
+ _Tp Cr = src[i+1];
585
+ _Tp Cb = src[i+2];
586
+
587
+ int b = Y + CV_DESCALE((Cb - delta)*C3, yuv_shift);
588
+ int g = Y + CV_DESCALE((Cb - delta)*C2 + (Cr - delta)*C1, yuv_shift);
589
+ int r = Y + CV_DESCALE((Cr - delta)*C0, yuv_shift);
590
+
591
+ dst[bidx] = saturate_cast<_Tp>(b);
592
+ dst[1] = saturate_cast<_Tp>(g);
593
+ dst[bidx^2] = saturate_cast<_Tp>(r);
594
+ if( dcn == 4 )
595
+ dst[3] = alpha;
596
+ }
597
+ }
598
+ int dstcn, blueIdx;
599
+ int coeffs[4];
600
+ };
601
+
602
+
603
+ ////////////////////////////////////// RGB <-> XYZ ///////////////////////////////////////
604
+
605
+ static const float sRGB2XYZ_D65[] =
606
+ {
607
+ 0.412453f, 0.357580f, 0.180423f,
608
+ 0.212671f, 0.715160f, 0.072169f,
609
+ 0.019334f, 0.119193f, 0.950227f
610
+ };
611
+
612
+ static const float XYZ2sRGB_D65[] =
613
+ {
614
+ 3.240479f, -1.53715f, -0.498535f,
615
+ -0.969256f, 1.875991f, 0.041556f,
616
+ 0.055648f, -0.204043f, 1.057311f
617
+ };
618
+
619
+ template<typename _Tp> struct RGB2XYZ_f
620
+ {
621
+ typedef _Tp channel_type;
622
+
623
+ RGB2XYZ_f(int _srccn, int blueIdx, const float* _coeffs) : srccn(_srccn)
624
+ {
625
+ memcpy(coeffs, _coeffs ? _coeffs : sRGB2XYZ_D65, 9*sizeof(coeffs[0]));
626
+ if(blueIdx == 0)
627
+ {
628
+ std::swap(coeffs[0], coeffs[2]);
629
+ std::swap(coeffs[3], coeffs[5]);
630
+ std::swap(coeffs[6], coeffs[8]);
631
+ }
632
+ }
633
+ void operator()(const _Tp* src, _Tp* dst, int n) const
634
+ {
635
+ int scn = srccn;
636
+ float C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2],
637
+ C3 = coeffs[3], C4 = coeffs[4], C5 = coeffs[5],
638
+ C6 = coeffs[6], C7 = coeffs[7], C8 = coeffs[8];
639
+
640
+ n *= 3;
641
+ for(int i = 0; i < n; i += 3, src += scn)
642
+ {
643
+ _Tp X = saturate_cast<_Tp>(src[0]*C0 + src[1]*C1 + src[2]*C2);
644
+ _Tp Y = saturate_cast<_Tp>(src[0]*C3 + src[1]*C4 + src[2]*C5);
645
+ _Tp Z = saturate_cast<_Tp>(src[0]*C6 + src[1]*C7 + src[2]*C8);
646
+ dst[i] = X; dst[i+1] = Y; dst[i+2] = Z;
647
+ }
648
+ }
649
+ int srccn;
650
+ float coeffs[9];
651
+ };
652
+
653
+
654
+ template<typename _Tp> struct RGB2XYZ_i
655
+ {
656
+ typedef _Tp channel_type;
657
+
658
+ RGB2XYZ_i(int _srccn, int blueIdx, const float* _coeffs) : srccn(_srccn)
659
+ {
660
+ static const int coeffs0[] =
661
+ {
662
+ 1689, 1465, 739,
663
+ 871, 2929, 296,
664
+ 79, 488, 3892
665
+ };
666
+ for( int i = 0; i < 9; i++ )
667
+ coeffs[i] = _coeffs ? cvRound(_coeffs[i]*(1 << xyz_shift)) : coeffs0[i];
668
+ if(blueIdx == 0)
669
+ {
670
+ std::swap(coeffs[0], coeffs[2]);
671
+ std::swap(coeffs[3], coeffs[5]);
672
+ std::swap(coeffs[6], coeffs[8]);
673
+ }
674
+ }
675
+ void operator()(const _Tp* src, _Tp* dst, int n) const
676
+ {
677
+ int scn = srccn;
678
+ int C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2],
679
+ C3 = coeffs[3], C4 = coeffs[4], C5 = coeffs[5],
680
+ C6 = coeffs[6], C7 = coeffs[7], C8 = coeffs[8];
681
+ n *= 3;
682
+ for(int i = 0; i < n; i += 3, src += scn)
683
+ {
684
+ int X = CV_DESCALE(src[0]*C0 + src[1]*C1 + src[2]*C2, xyz_shift);
685
+ int Y = CV_DESCALE(src[0]*C3 + src[1]*C4 + src[2]*C5, xyz_shift);
686
+ int Z = CV_DESCALE(src[0]*C6 + src[1]*C7 + src[2]*C8, xyz_shift);
687
+ dst[i] = saturate_cast<_Tp>(X); dst[i+1] = saturate_cast<_Tp>(Y);
688
+ dst[i+2] = saturate_cast<_Tp>(Z);
689
+ }
690
+ }
691
+ int srccn;
692
+ int coeffs[9];
693
+ };
694
+
695
+
696
+ template<typename _Tp> struct XYZ2RGB_f
697
+ {
698
+ typedef _Tp channel_type;
699
+
700
+ XYZ2RGB_f(int _dstcn, int _blueIdx, const float* _coeffs)
701
+ : dstcn(_dstcn), blueIdx(_blueIdx)
702
+ {
703
+ memcpy(coeffs, _coeffs ? _coeffs : XYZ2sRGB_D65, 9*sizeof(coeffs[0]));
704
+ if(blueIdx == 0)
705
+ {
706
+ std::swap(coeffs[0], coeffs[6]);
707
+ std::swap(coeffs[1], coeffs[7]);
708
+ std::swap(coeffs[2], coeffs[8]);
709
+ }
710
+ }
711
+
712
+ void operator()(const _Tp* src, _Tp* dst, int n) const
713
+ {
714
+ int dcn = dstcn;
715
+ _Tp alpha = ColorChannel<_Tp>::max();
716
+ float C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2],
717
+ C3 = coeffs[3], C4 = coeffs[4], C5 = coeffs[5],
718
+ C6 = coeffs[6], C7 = coeffs[7], C8 = coeffs[8];
719
+ n *= 3;
720
+ for(int i = 0; i < n; i += 3, dst += dcn)
721
+ {
722
+ _Tp B = saturate_cast<_Tp>(src[i]*C0 + src[i+1]*C1 + src[i+2]*C2);
723
+ _Tp G = saturate_cast<_Tp>(src[i]*C3 + src[i+1]*C4 + src[i+2]*C5);
724
+ _Tp R = saturate_cast<_Tp>(src[i]*C6 + src[i+1]*C7 + src[i+2]*C8);
725
+ dst[0] = B; dst[1] = G; dst[2] = R;
726
+ if( dcn == 4 )
727
+ dst[3] = alpha;
728
+ }
729
+ }
730
+ int dstcn, blueIdx;
731
+ float coeffs[9];
732
+ };
733
+
734
+
735
+ template<typename _Tp> struct XYZ2RGB_i
736
+ {
737
+ typedef _Tp channel_type;
738
+
739
+ XYZ2RGB_i(int _dstcn, int _blueIdx, const int* _coeffs)
740
+ : dstcn(_dstcn), blueIdx(_blueIdx)
741
+ {
742
+ static const int coeffs0[] =
743
+ {
744
+ 13273, -6296, -2042,
745
+ -3970, 7684, 170,
746
+ 228, -836, 4331
747
+ };
748
+ for(int i = 0; i < 9; i++)
749
+ coeffs[i] = _coeffs ? cvRound(_coeffs[i]*(1 << xyz_shift)) : coeffs0[i];
750
+
751
+ if(blueIdx == 0)
752
+ {
753
+ std::swap(coeffs[0], coeffs[6]);
754
+ std::swap(coeffs[1], coeffs[7]);
755
+ std::swap(coeffs[2], coeffs[8]);
756
+ }
757
+ }
758
+ void operator()(const _Tp* src, _Tp* dst, int n) const
759
+ {
760
+ int dcn = dstcn;
761
+ _Tp alpha = ColorChannel<_Tp>::max();
762
+ int C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2],
763
+ C3 = coeffs[3], C4 = coeffs[4], C5 = coeffs[5],
764
+ C6 = coeffs[6], C7 = coeffs[7], C8 = coeffs[8];
765
+ n *= 3;
766
+ for(int i = 0; i < n; i += 3, dst += dcn)
767
+ {
768
+ int B = CV_DESCALE(src[i]*C0 + src[i+1]*C1 + src[i+2]*C2, xyz_shift);
769
+ int G = CV_DESCALE(src[i]*C3 + src[i+1]*C4 + src[i+2]*C5, xyz_shift);
770
+ int R = CV_DESCALE(src[i]*C6 + src[i+1]*C7 + src[i+2]*C8, xyz_shift);
771
+ dst[0] = saturate_cast<_Tp>(B); dst[1] = saturate_cast<_Tp>(G);
772
+ dst[2] = saturate_cast<_Tp>(R);
773
+ if( dcn == 4 )
774
+ dst[3] = alpha;
775
+ }
776
+ }
777
+ int dstcn, blueIdx;
778
+ int coeffs[9];
779
+ };
780
+
781
+
782
+ ////////////////////////////////////// RGB <-> HSV ///////////////////////////////////////
783
+
784
+
785
+ struct RGB2HSV_b
786
+ {
787
+ typedef uchar channel_type;
788
+
789
+ RGB2HSV_b(int _srccn, int _blueIdx, int _hrange)
790
+ : srccn(_srccn), blueIdx(_blueIdx), hrange(_hrange)
791
+ {
792
+ CV_Assert( hrange == 180 || hrange == 256 );
793
+ }
794
+
795
+ void operator()(const uchar* src, uchar* dst, int n) const
796
+ {
797
+ int i, bidx = blueIdx, scn = srccn;
798
+ const int hsv_shift = 12;
799
+
800
+ static int sdiv_table[256];
801
+ static int hdiv_table180[256];
802
+ static int hdiv_table256[256];
803
+ static volatile bool initialized = false;
804
+
805
+ int hr = hrange;
806
+ const int* hdiv_table = hr == 180 ? hdiv_table180 : hdiv_table256;
807
+ n *= 3;
808
+
809
+ if( !initialized )
810
+ {
811
+ sdiv_table[0] = hdiv_table180[0] = hdiv_table256[0] = 0;
812
+ for( i = 1; i < 256; i++ )
813
+ {
814
+ sdiv_table[i] = saturate_cast<int>((255 << hsv_shift)/(1.*i));
815
+ hdiv_table180[i] = saturate_cast<int>((180 << hsv_shift)/(6.*i));
816
+ hdiv_table256[i] = saturate_cast<int>((256 << hsv_shift)/(6.*i));
817
+ }
818
+ initialized = true;
819
+ }
820
+
821
+ for( i = 0; i < n; i += 3, src += scn )
822
+ {
823
+ int b = src[bidx], g = src[1], r = src[bidx^2];
824
+ int h, s, v = b;
825
+ int vmin = b, diff;
826
+ int vr, vg;
827
+
828
+ CV_CALC_MAX_8U( v, g );
829
+ CV_CALC_MAX_8U( v, r );
830
+ CV_CALC_MIN_8U( vmin, g );
831
+ CV_CALC_MIN_8U( vmin, r );
832
+
833
+ diff = v - vmin;
834
+ vr = v == r ? -1 : 0;
835
+ vg = v == g ? -1 : 0;
836
+
837
+ s = (diff * sdiv_table[v] + (1 << (hsv_shift-1))) >> hsv_shift;
838
+ h = (vr & (g - b)) +
839
+ (~vr & ((vg & (b - r + 2 * diff)) + ((~vg) & (r - g + 4 * diff))));
840
+ h = (h * hdiv_table[diff] + (1 << (hsv_shift-1))) >> hsv_shift;
841
+ h += h < 0 ? hr : 0;
842
+
843
+ dst[i] = saturate_cast<uchar>(h);
844
+ dst[i+1] = (uchar)s;
845
+ dst[i+2] = (uchar)v;
846
+ }
847
+ }
848
+
849
+ int srccn, blueIdx, hrange;
850
+ };
851
+
852
+
853
+ struct RGB2HSV_f
854
+ {
855
+ typedef float channel_type;
856
+
857
+ RGB2HSV_f(int _srccn, int _blueIdx, float _hrange)
858
+ : srccn(_srccn), blueIdx(_blueIdx), hrange(_hrange) {}
859
+
860
+ void operator()(const float* src, float* dst, int n) const
861
+ {
862
+ int i, bidx = blueIdx, scn = srccn;
863
+ float hscale = hrange*(1.f/360.f);
864
+ n *= 3;
865
+
866
+ for( i = 0; i < n; i += 3, src += scn )
867
+ {
868
+ float b = src[bidx], g = src[1], r = src[bidx^2];
869
+ float h, s, v;
870
+
871
+ float vmin, diff;
872
+
873
+ v = vmin = r;
874
+ if( v < g ) v = g;
875
+ if( v < b ) v = b;
876
+ if( vmin > g ) vmin = g;
877
+ if( vmin > b ) vmin = b;
878
+
879
+ diff = v - vmin;
880
+ s = diff/(float)(fabs(v) + FLT_EPSILON);
881
+ diff = (float)(60./(diff + FLT_EPSILON));
882
+ if( v == r )
883
+ h = (g - b)*diff;
884
+ else if( v == g )
885
+ h = (b - r)*diff + 120.f;
886
+ else
887
+ h = (r - g)*diff + 240.f;
888
+
889
+ if( h < 0 ) h += 360.f;
890
+
891
+ dst[i] = h*hscale;
892
+ dst[i+1] = s;
893
+ dst[i+2] = v;
894
+ }
895
+ }
896
+
897
+ int srccn, blueIdx;
898
+ float hrange;
899
+ };
900
+
901
+
902
+ struct HSV2RGB_f
903
+ {
904
+ typedef float channel_type;
905
+
906
+ HSV2RGB_f(int _dstcn, int _blueIdx, float _hrange)
907
+ : dstcn(_dstcn), blueIdx(_blueIdx), hscale(6.f/_hrange) {}
908
+
909
+ void operator()(const float* src, float* dst, int n) const
910
+ {
911
+ int i, bidx = blueIdx, dcn = dstcn;
912
+ float _hscale = hscale;
913
+ float alpha = ColorChannel<float>::max();
914
+ n *= 3;
915
+
916
+ for( i = 0; i < n; i += 3, dst += dcn )
917
+ {
918
+ float h = src[i], s = src[i+1], v = src[i+2];
919
+ float b, g, r;
920
+
921
+ if( s == 0 )
922
+ b = g = r = v;
923
+ else
924
+ {
925
+ static const int sector_data[][3]=
926
+ {{1,3,0}, {1,0,2}, {3,0,1}, {0,2,1}, {0,1,3}, {2,1,0}};
927
+ float tab[4];
928
+ int sector;
929
+ h *= _hscale;
930
+ if( h < 0 )
931
+ do h += 6; while( h < 0 );
932
+ else if( h >= 6 )
933
+ do h -= 6; while( h >= 6 );
934
+ sector = cvFloor(h);
935
+ h -= sector;
936
+
937
+ tab[0] = v;
938
+ tab[1] = v*(1.f - s);
939
+ tab[2] = v*(1.f - s*h);
940
+ tab[3] = v*(1.f - s*(1.f - h));
941
+
942
+ b = tab[sector_data[sector][0]];
943
+ g = tab[sector_data[sector][1]];
944
+ r = tab[sector_data[sector][2]];
945
+ }
946
+
947
+ dst[bidx] = b;
948
+ dst[1] = g;
949
+ dst[bidx^2] = r;
950
+ if( dcn == 4 )
951
+ dst[3] = alpha;
952
+ }
953
+ }
954
+
955
+ int dstcn, blueIdx;
956
+ float hscale;
957
+ };
958
+
959
+
960
+ struct HSV2RGB_b
961
+ {
962
+ typedef uchar channel_type;
963
+
964
+ HSV2RGB_b(int _dstcn, int _blueIdx, int _hrange)
965
+ : dstcn(_dstcn), cvt(3, _blueIdx, (float)_hrange)
966
+ {}
967
+
968
+ void operator()(const uchar* src, uchar* dst, int n) const
969
+ {
970
+ int i, j, dcn = dstcn;
971
+ uchar alpha = ColorChannel<uchar>::max();
972
+ float buf[3*BLOCK_SIZE];
973
+
974
+ for( i = 0; i < n; i += BLOCK_SIZE, src += BLOCK_SIZE*3 )
975
+ {
976
+ int dn = std::min(n - i, (int)BLOCK_SIZE);
977
+
978
+ for( j = 0; j < dn*3; j += 3 )
979
+ {
980
+ buf[j] = src[j];
981
+ buf[j+1] = src[j+1]*(1.f/255.f);
982
+ buf[j+2] = src[j+2]*(1.f/255.f);
983
+ }
984
+ cvt(buf, buf, dn);
985
+
986
+ for( j = 0; j < dn*3; j += 3, dst += dcn )
987
+ {
988
+ dst[0] = saturate_cast<uchar>(buf[j]*255.f);
989
+ dst[1] = saturate_cast<uchar>(buf[j+1]*255.f);
990
+ dst[2] = saturate_cast<uchar>(buf[j+2]*255.f);
991
+ if( dcn == 4 )
992
+ dst[3] = alpha;
993
+ }
994
+ }
995
+ }
996
+
997
+ int dstcn;
998
+ HSV2RGB_f cvt;
999
+ };
1000
+
1001
+
1002
+ ///////////////////////////////////// RGB <-> HLS ////////////////////////////////////////
1003
+
1004
+ struct RGB2HLS_f
1005
+ {
1006
+ typedef float channel_type;
1007
+
1008
+ RGB2HLS_f(int _srccn, int _blueIdx, float _hrange)
1009
+ : srccn(_srccn), blueIdx(_blueIdx), hrange(_hrange) {}
1010
+
1011
+ void operator()(const float* src, float* dst, int n) const
1012
+ {
1013
+ int i, bidx = blueIdx, scn = srccn;
1014
+ float hscale = hrange*(1.f/360.f);
1015
+ n *= 3;
1016
+
1017
+ for( i = 0; i < n; i += 3, src += scn )
1018
+ {
1019
+ float b = src[bidx], g = src[1], r = src[bidx^2];
1020
+ float h = 0.f, s = 0.f, l;
1021
+ float vmin, vmax, diff;
1022
+
1023
+ vmax = vmin = r;
1024
+ if( vmax < g ) vmax = g;
1025
+ if( vmax < b ) vmax = b;
1026
+ if( vmin > g ) vmin = g;
1027
+ if( vmin > b ) vmin = b;
1028
+
1029
+ diff = vmax - vmin;
1030
+ l = (vmax + vmin)*0.5f;
1031
+
1032
+ if( diff > FLT_EPSILON )
1033
+ {
1034
+ s = l < 0.5f ? diff/(vmax + vmin) : diff/(2 - vmax - vmin);
1035
+ diff = 60.f/diff;
1036
+
1037
+ if( vmax == r )
1038
+ h = (g - b)*diff;
1039
+ else if( vmax == g )
1040
+ h = (b - r)*diff + 120.f;
1041
+ else
1042
+ h = (r - g)*diff + 240.f;
1043
+
1044
+ if( h < 0.f ) h += 360.f;
1045
+ }
1046
+
1047
+ dst[i] = h*hscale;
1048
+ dst[i+1] = l;
1049
+ dst[i+2] = s;
1050
+ }
1051
+ }
1052
+
1053
+ int srccn, blueIdx;
1054
+ float hrange;
1055
+ };
1056
+
1057
+
1058
+ struct RGB2HLS_b
1059
+ {
1060
+ typedef uchar channel_type;
1061
+
1062
+ RGB2HLS_b(int _srccn, int _blueIdx, int _hrange)
1063
+ : srccn(_srccn), cvt(3, _blueIdx, (float)_hrange) {}
1064
+
1065
+ void operator()(const uchar* src, uchar* dst, int n) const
1066
+ {
1067
+ int i, j, scn = srccn;
1068
+ float buf[3*BLOCK_SIZE];
1069
+
1070
+ for( i = 0; i < n; i += BLOCK_SIZE, dst += BLOCK_SIZE*3 )
1071
+ {
1072
+ int dn = std::min(n - i, (int)BLOCK_SIZE);
1073
+
1074
+ for( j = 0; j < dn*3; j += 3, src += scn )
1075
+ {
1076
+ buf[j] = src[0]*(1.f/255.f);
1077
+ buf[j+1] = src[1]*(1.f/255.f);
1078
+ buf[j+2] = src[2]*(1.f/255.f);
1079
+ }
1080
+ cvt(buf, buf, dn);
1081
+
1082
+ for( j = 0; j < dn*3; j += 3 )
1083
+ {
1084
+ dst[j] = saturate_cast<uchar>(buf[j]);
1085
+ dst[j+1] = saturate_cast<uchar>(buf[j+1]*255.f);
1086
+ dst[j+2] = saturate_cast<uchar>(buf[j+2]*255.f);
1087
+ }
1088
+ }
1089
+ }
1090
+
1091
+ int srccn;
1092
+ RGB2HLS_f cvt;
1093
+ };
1094
+
1095
+
1096
+ struct HLS2RGB_f
1097
+ {
1098
+ typedef float channel_type;
1099
+
1100
+ HLS2RGB_f(int _dstcn, int _blueIdx, float _hrange)
1101
+ : dstcn(_dstcn), blueIdx(_blueIdx), hscale(6.f/_hrange) {}
1102
+
1103
+ void operator()(const float* src, float* dst, int n) const
1104
+ {
1105
+ int i, bidx = blueIdx, dcn = dstcn;
1106
+ float _hscale = hscale;
1107
+ float alpha = ColorChannel<float>::max();
1108
+ n *= 3;
1109
+
1110
+ for( i = 0; i < n; i += 3, dst += dcn )
1111
+ {
1112
+ float h = src[i], l = src[i+1], s = src[i+2];
1113
+ float b, g, r;
1114
+
1115
+ if( s == 0 )
1116
+ b = g = r = l;
1117
+ else
1118
+ {
1119
+ static const int sector_data[][3]=
1120
+ {{1,3,0}, {1,0,2}, {3,0,1}, {0,2,1}, {0,1,3}, {2,1,0}};
1121
+ float tab[4];
1122
+ int sector;
1123
+
1124
+ float p2 = l <= 0.5f ? l*(1 + s) : l + s - l*s;
1125
+ float p1 = 2*l - p2;
1126
+
1127
+ h *= _hscale;
1128
+ if( h < 0 )
1129
+ do h += 6; while( h < 0 );
1130
+ else if( h >= 6 )
1131
+ do h -= 6; while( h >= 6 );
1132
+
1133
+ assert( 0 <= h && h < 6 );
1134
+ sector = cvFloor(h);
1135
+ h -= sector;
1136
+
1137
+ tab[0] = p2;
1138
+ tab[1] = p1;
1139
+ tab[2] = p1 + (p2 - p1)*(1-h);
1140
+ tab[3] = p1 + (p2 - p1)*h;
1141
+
1142
+ b = tab[sector_data[sector][0]];
1143
+ g = tab[sector_data[sector][1]];
1144
+ r = tab[sector_data[sector][2]];
1145
+ }
1146
+
1147
+ dst[bidx] = b;
1148
+ dst[1] = g;
1149
+ dst[bidx^2] = r;
1150
+ if( dcn == 4 )
1151
+ dst[3] = alpha;
1152
+ }
1153
+ }
1154
+
1155
+ int dstcn, blueIdx;
1156
+ float hscale;
1157
+ };
1158
+
1159
+
1160
+ struct HLS2RGB_b
1161
+ {
1162
+ typedef uchar channel_type;
1163
+
1164
+ HLS2RGB_b(int _dstcn, int _blueIdx, int _hrange)
1165
+ : dstcn(_dstcn), cvt(3, _blueIdx, (float)_hrange)
1166
+ {}
1167
+
1168
+ void operator()(const uchar* src, uchar* dst, int n) const
1169
+ {
1170
+ int i, j, dcn = dstcn;
1171
+ uchar alpha = ColorChannel<uchar>::max();
1172
+ float buf[3*BLOCK_SIZE];
1173
+
1174
+ for( i = 0; i < n; i += BLOCK_SIZE, src += BLOCK_SIZE*3 )
1175
+ {
1176
+ int dn = std::min(n - i, (int)BLOCK_SIZE);
1177
+
1178
+ for( j = 0; j < dn*3; j += 3 )
1179
+ {
1180
+ buf[j] = src[j];
1181
+ buf[j+1] = src[j+1]*(1.f/255.f);
1182
+ buf[j+2] = src[j+2]*(1.f/255.f);
1183
+ }
1184
+ cvt(buf, buf, dn);
1185
+
1186
+ for( j = 0; j < dn*3; j += 3, dst += dcn )
1187
+ {
1188
+ dst[0] = saturate_cast<uchar>(buf[j]*255.f);
1189
+ dst[1] = saturate_cast<uchar>(buf[j+1]*255.f);
1190
+ dst[2] = saturate_cast<uchar>(buf[j+2]*255.f);
1191
+ if( dcn == 4 )
1192
+ dst[3] = alpha;
1193
+ }
1194
+ }
1195
+ }
1196
+
1197
+ int dstcn;
1198
+ HLS2RGB_f cvt;
1199
+ };
1200
+
1201
+
1202
+ ///////////////////////////////////// RGB <-> L*a*b* /////////////////////////////////////
1203
+
1204
+ static const float D65[] = { 0.950456f, 1.f, 1.088754f };
1205
+
1206
+ enum { LAB_CBRT_TAB_SIZE = 1024, GAMMA_TAB_SIZE = 1024 };
1207
+ static float LabCbrtTab[LAB_CBRT_TAB_SIZE*4];
1208
+ static const float LabCbrtTabScale = LAB_CBRT_TAB_SIZE/1.5f;
1209
+
1210
+ static float sRGBGammaTab[GAMMA_TAB_SIZE*4], sRGBInvGammaTab[GAMMA_TAB_SIZE*4];
1211
+ static const float GammaTabScale = (float)GAMMA_TAB_SIZE;
1212
+
1213
+ static ushort sRGBGammaTab_b[256], linearGammaTab_b[256];
1214
+ #undef lab_shift
1215
+ #define lab_shift xyz_shift
1216
+ #define gamma_shift 3
1217
+ #define lab_shift2 (lab_shift + gamma_shift)
1218
+ #define LAB_CBRT_TAB_SIZE_B (256*3/2*(1<<gamma_shift))
1219
+ static ushort LabCbrtTab_b[LAB_CBRT_TAB_SIZE_B];
1220
+
1221
+ static void initLabTabs()
1222
+ {
1223
+ static bool initialized = false;
1224
+ if(!initialized)
1225
+ {
1226
+ float f[LAB_CBRT_TAB_SIZE+1], g[GAMMA_TAB_SIZE+1], ig[GAMMA_TAB_SIZE+1], scale = 1.f/LabCbrtTabScale;
1227
+ int i;
1228
+ for(i = 0; i <= LAB_CBRT_TAB_SIZE; i++)
1229
+ {
1230
+ float x = i*scale;
1231
+ f[i] = x < 0.008856f ? x*7.787f + 0.13793103448275862f : cvCbrt(x);
1232
+ }
1233
+ splineBuild(f, LAB_CBRT_TAB_SIZE, LabCbrtTab);
1234
+
1235
+ scale = 1.f/GammaTabScale;
1236
+ for(i = 0; i <= GAMMA_TAB_SIZE; i++)
1237
+ {
1238
+ float x = i*scale;
1239
+ g[i] = x <= 0.04045f ? x*(1.f/12.92f) : (float)pow((double)(x + 0.055)*(1./1.055), 2.4);
1240
+ ig[i] = x <= 0.0031308 ? x*12.92f : (float)(1.055*pow((double)x, 1./2.4) - 0.055);
1241
+ }
1242
+ splineBuild(g, GAMMA_TAB_SIZE, sRGBGammaTab);
1243
+ splineBuild(ig, GAMMA_TAB_SIZE, sRGBInvGammaTab);
1244
+
1245
+ for(i = 0; i < 256; i++)
1246
+ {
1247
+ float x = i*(1.f/255.f);
1248
+ 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)));
1249
+ linearGammaTab_b[i] = (ushort)(i*(1 << gamma_shift));
1250
+ }
1251
+
1252
+ for(i = 0; i < LAB_CBRT_TAB_SIZE_B; i++)
1253
+ {
1254
+ float x = i*(1.f/(255.f*(1 << gamma_shift)));
1255
+ LabCbrtTab_b[i] = saturate_cast<ushort>((1 << lab_shift2)*(x < 0.008856f ? x*7.787f + 0.13793103448275862f : cvCbrt(x)));
1256
+ }
1257
+ initialized = true;
1258
+ }
1259
+ }
1260
+
1261
+ struct RGB2Lab_b
1262
+ {
1263
+ typedef uchar channel_type;
1264
+
1265
+ RGB2Lab_b(int _srccn, int blueIdx, const float* _coeffs,
1266
+ const float* _whitept, bool _srgb)
1267
+ : srccn(_srccn), srgb(_srgb)
1268
+ {
1269
+ static volatile int _3 = 3;
1270
+ initLabTabs();
1271
+
1272
+ if(!_coeffs) _coeffs = sRGB2XYZ_D65;
1273
+ if(!_whitept) _whitept = D65;
1274
+ float scale[] =
1275
+ {
1276
+ (1 << lab_shift)/_whitept[0],
1277
+ (float)(1 << lab_shift),
1278
+ (1 << lab_shift)/_whitept[2]
1279
+ };
1280
+
1281
+ for( int i = 0; i < _3; i++ )
1282
+ {
1283
+ coeffs[i*3+(blueIdx^2)] = cvRound(_coeffs[i*3]*scale[i]);
1284
+ coeffs[i*3+1] = cvRound(_coeffs[i*3+1]*scale[i]);
1285
+ coeffs[i*3+blueIdx] = cvRound(_coeffs[i*3+2]*scale[i]);
1286
+
1287
+ CV_Assert( coeffs[i] >= 0 && coeffs[i*3+1] >= 0 && coeffs[i*3+2] >= 0 &&
1288
+ coeffs[i*3] + coeffs[i*3+1] + coeffs[i*3+2] < 2*(1 << lab_shift) );
1289
+ }
1290
+ }
1291
+
1292
+ void operator()(const uchar* src, uchar* dst, int n) const
1293
+ {
1294
+ const int Lscale = (116*255+50)/100;
1295
+ const int Lshift = -((16*255*(1 << lab_shift2) + 50)/100);
1296
+ const ushort* tab = srgb ? sRGBGammaTab_b : linearGammaTab_b;
1297
+ int i, scn = srccn;
1298
+ int C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2],
1299
+ C3 = coeffs[3], C4 = coeffs[4], C5 = coeffs[5],
1300
+ C6 = coeffs[6], C7 = coeffs[7], C8 = coeffs[8];
1301
+ n *= 3;
1302
+
1303
+ for( i = 0; i < n; i += 3, src += scn )
1304
+ {
1305
+ int R = tab[src[0]], G = tab[src[1]], B = tab[src[2]];
1306
+ int fX = LabCbrtTab_b[CV_DESCALE(R*C0 + G*C1 + B*C2, lab_shift)];
1307
+ int fY = LabCbrtTab_b[CV_DESCALE(R*C3 + G*C4 + B*C5, lab_shift)];
1308
+ int fZ = LabCbrtTab_b[CV_DESCALE(R*C6 + G*C7 + B*C8, lab_shift)];
1309
+
1310
+ int L = CV_DESCALE( Lscale*fY + Lshift, lab_shift2 );
1311
+ int a = CV_DESCALE( 500*(fX - fY) + 128*(1 << lab_shift2), lab_shift2 );
1312
+ int b = CV_DESCALE( 200*(fY - fZ) + 128*(1 << lab_shift2), lab_shift2 );
1313
+
1314
+ dst[i] = saturate_cast<uchar>(L);
1315
+ dst[i+1] = saturate_cast<uchar>(a);
1316
+ dst[i+2] = saturate_cast<uchar>(b);
1317
+ }
1318
+ }
1319
+
1320
+ int srccn;
1321
+ int coeffs[9];
1322
+ bool srgb;
1323
+ };
1324
+
1325
+
1326
+ struct RGB2Lab_f
1327
+ {
1328
+ typedef float channel_type;
1329
+
1330
+ RGB2Lab_f(int _srccn, int blueIdx, const float* _coeffs,
1331
+ const float* _whitept, bool _srgb)
1332
+ : srccn(_srccn), srgb(_srgb)
1333
+ {
1334
+ volatile int _3 = 3;
1335
+ initLabTabs();
1336
+
1337
+ if(!_coeffs) _coeffs = sRGB2XYZ_D65;
1338
+ if(!_whitept) _whitept = D65;
1339
+ float scale[] = { LabCbrtTabScale/_whitept[0], LabCbrtTabScale, LabCbrtTabScale/_whitept[2] };
1340
+
1341
+ for( int i = 0; i < _3; i++ )
1342
+ {
1343
+ coeffs[i*3+(blueIdx^2)] = _coeffs[i*3]*scale[i];
1344
+ coeffs[i*3+1] = _coeffs[i*3+1]*scale[i];
1345
+ coeffs[i*3+blueIdx] = _coeffs[i*3+2]*scale[i];
1346
+ CV_Assert( coeffs[i*3] >= 0 && coeffs[i*3+1] >= 0 && coeffs[i*3+2] >= 0 &&
1347
+ coeffs[i*3] + coeffs[i*3+1] + coeffs[i*3+2] < 1.5f*LabCbrtTabScale );
1348
+ }
1349
+ }
1350
+
1351
+ void operator()(const float* src, float* dst, int n) const
1352
+ {
1353
+ int i, scn = srccn;
1354
+ float gscale = GammaTabScale;
1355
+ const float* gammaTab = srgb ? sRGBGammaTab : 0;
1356
+ float C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2],
1357
+ C3 = coeffs[3], C4 = coeffs[4], C5 = coeffs[5],
1358
+ C6 = coeffs[6], C7 = coeffs[7], C8 = coeffs[8];
1359
+ n *= 3;
1360
+
1361
+ for( i = 0; i < n; i += 3, src += scn )
1362
+ {
1363
+ float R = src[0], G = src[1], B = src[2];
1364
+ if( gammaTab )
1365
+ {
1366
+ R = splineInterpolate(R*gscale, gammaTab, GAMMA_TAB_SIZE);
1367
+ G = splineInterpolate(G*gscale, gammaTab, GAMMA_TAB_SIZE);
1368
+ B = splineInterpolate(B*gscale, gammaTab, GAMMA_TAB_SIZE);
1369
+ }
1370
+ float fX = splineInterpolate(R*C0 + G*C1 + B*C2, LabCbrtTab, LAB_CBRT_TAB_SIZE);
1371
+ float fY = splineInterpolate(R*C3 + G*C4 + B*C5, LabCbrtTab, LAB_CBRT_TAB_SIZE);
1372
+ float fZ = splineInterpolate(R*C6 + G*C7 + B*C8, LabCbrtTab, LAB_CBRT_TAB_SIZE);
1373
+
1374
+ float L = 116.f*fY - 16.f;
1375
+ float a = 500.f*(fX - fY);
1376
+ float b = 200.f*(fY - fZ);
1377
+
1378
+ dst[i] = L; dst[i+1] = a; dst[i+2] = b;
1379
+ }
1380
+ }
1381
+
1382
+ int srccn;
1383
+ float coeffs[9];
1384
+ bool srgb;
1385
+ };
1386
+
1387
+
1388
+ struct Lab2RGB_f
1389
+ {
1390
+ typedef float channel_type;
1391
+
1392
+ Lab2RGB_f( int _dstcn, int blueIdx, const float* _coeffs,
1393
+ const float* _whitept, bool _srgb )
1394
+ : dstcn(_dstcn), srgb(_srgb)
1395
+ {
1396
+ initLabTabs();
1397
+
1398
+ if(!_coeffs) _coeffs = XYZ2sRGB_D65;
1399
+ if(!_whitept) _whitept = D65;
1400
+
1401
+ for( int i = 0; i < 3; i++ )
1402
+ {
1403
+ coeffs[i+(blueIdx^2)*3] = _coeffs[i]*_whitept[i];
1404
+ coeffs[i+3] = _coeffs[i+3]*_whitept[i];
1405
+ coeffs[i+blueIdx*3] = _coeffs[i+6]*_whitept[i];
1406
+ }
1407
+ }
1408
+
1409
+ void operator()(const float* src, float* dst, int n) const
1410
+ {
1411
+ int i, dcn = dstcn;
1412
+ const float* gammaTab = srgb ? sRGBInvGammaTab : 0;
1413
+ float gscale = GammaTabScale;
1414
+ float C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2],
1415
+ C3 = coeffs[3], C4 = coeffs[4], C5 = coeffs[5],
1416
+ C6 = coeffs[6], C7 = coeffs[7], C8 = coeffs[8];
1417
+ float alpha = ColorChannel<float>::max();
1418
+ n *= 3;
1419
+
1420
+ for( i = 0; i < n; i += 3, dst += dcn )
1421
+ {
1422
+ float L = src[i], a = src[i+1], b = src[i+2];
1423
+ float Y = (L + 16.f)*(1.f/116.f);
1424
+ float X = (Y + a*0.002f);
1425
+ float Z = (Y - b*0.005f);
1426
+ Y = Y*Y*Y;
1427
+ X = X*X*X;
1428
+ Z = Z*Z*Z;
1429
+
1430
+ float R = X*C0 + Y*C1 + Z*C2;
1431
+ float G = X*C3 + Y*C4 + Z*C5;
1432
+ float B = X*C6 + Y*C7 + Z*C8;
1433
+
1434
+ if( gammaTab )
1435
+ {
1436
+ R = splineInterpolate(R*gscale, gammaTab, GAMMA_TAB_SIZE);
1437
+ G = splineInterpolate(G*gscale, gammaTab, GAMMA_TAB_SIZE);
1438
+ B = splineInterpolate(B*gscale, gammaTab, GAMMA_TAB_SIZE);
1439
+ }
1440
+
1441
+ dst[0] = R; dst[1] = G; dst[2] = B;
1442
+ if( dcn == 4 )
1443
+ dst[3] = alpha;
1444
+ }
1445
+ }
1446
+
1447
+ int dstcn;
1448
+ float coeffs[9];
1449
+ bool srgb;
1450
+ };
1451
+
1452
+
1453
+ struct Lab2RGB_b
1454
+ {
1455
+ typedef uchar channel_type;
1456
+
1457
+ Lab2RGB_b( int _dstcn, int blueIdx, const float* _coeffs,
1458
+ const float* _whitept, bool _srgb )
1459
+ : dstcn(_dstcn), cvt(3, blueIdx, _coeffs, _whitept, _srgb ) {}
1460
+
1461
+ void operator()(const uchar* src, uchar* dst, int n) const
1462
+ {
1463
+ int i, j, dcn = dstcn;
1464
+ uchar alpha = ColorChannel<uchar>::max();
1465
+ float buf[3*BLOCK_SIZE];
1466
+
1467
+ for( i = 0; i < n; i += BLOCK_SIZE, src += BLOCK_SIZE*3 )
1468
+ {
1469
+ int dn = std::min(n - i, (int)BLOCK_SIZE);
1470
+
1471
+ for( j = 0; j < dn*3; j += 3 )
1472
+ {
1473
+ buf[j] = src[j]*(100.f/255.f);
1474
+ buf[j+1] = (float)(src[j+1] - 128);
1475
+ buf[j+2] = (float)(src[j+2] - 128);
1476
+ }
1477
+ cvt(buf, buf, dn);
1478
+
1479
+ for( j = 0; j < dn*3; j += 3, dst += dcn )
1480
+ {
1481
+ dst[0] = saturate_cast<uchar>(buf[j]*255.f);
1482
+ dst[1] = saturate_cast<uchar>(buf[j+1]*255.f);
1483
+ dst[2] = saturate_cast<uchar>(buf[j+2]*255.f);
1484
+ if( dcn == 4 )
1485
+ dst[3] = alpha;
1486
+ }
1487
+ }
1488
+ }
1489
+
1490
+ int dstcn;
1491
+ Lab2RGB_f cvt;
1492
+ };
1493
+
1494
+
1495
+ ///////////////////////////////////// RGB <-> L*u*v* /////////////////////////////////////
1496
+
1497
+ struct RGB2Luv_f
1498
+ {
1499
+ typedef float channel_type;
1500
+
1501
+ RGB2Luv_f( int _srccn, int blueIdx, const float* _coeffs,
1502
+ const float* whitept, bool _srgb )
1503
+ : srccn(_srccn), srgb(_srgb)
1504
+ {
1505
+ volatile int i;
1506
+ initLabTabs();
1507
+
1508
+ if(!_coeffs) _coeffs = sRGB2XYZ_D65;
1509
+ if(!whitept) whitept = D65;
1510
+
1511
+ for( i = 0; i < 3; i++ )
1512
+ {
1513
+ coeffs[i*3] = _coeffs[i*3];
1514
+ coeffs[i*3+1] = _coeffs[i*3+1];
1515
+ coeffs[i*3+2] = _coeffs[i*3+2];
1516
+ if( blueIdx == 0 )
1517
+ std::swap(coeffs[i*3], coeffs[i*3+2]);
1518
+ CV_Assert( coeffs[i*3] >= 0 && coeffs[i*3+1] >= 0 && coeffs[i*3+2] >= 0 &&
1519
+ coeffs[i*3] + coeffs[i*3+1] + coeffs[i*3+2] < 1.5f );
1520
+ }
1521
+
1522
+ float d = 1.f/(whitept[0] + whitept[1]*15 + whitept[2]*3);
1523
+ un = 4*whitept[0]*d;
1524
+ vn = 9*whitept[1]*d;
1525
+
1526
+ CV_Assert(whitept[1] == 1.f);
1527
+ }
1528
+
1529
+ void operator()(const float* src, float* dst, int n) const
1530
+ {
1531
+ int i, scn = srccn;
1532
+ float gscale = GammaTabScale;
1533
+ const float* gammaTab = srgb ? sRGBGammaTab : 0;
1534
+ float C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2],
1535
+ C3 = coeffs[3], C4 = coeffs[4], C5 = coeffs[5],
1536
+ C6 = coeffs[6], C7 = coeffs[7], C8 = coeffs[8];
1537
+ float _un = 13*un, _vn = 13*vn;
1538
+ n *= 3;
1539
+
1540
+ for( i = 0; i < n; i += 3, src += scn )
1541
+ {
1542
+ float R = src[0], G = src[1], B = src[2];
1543
+ if( gammaTab )
1544
+ {
1545
+ R = splineInterpolate(R*gscale, gammaTab, GAMMA_TAB_SIZE);
1546
+ G = splineInterpolate(G*gscale, gammaTab, GAMMA_TAB_SIZE);
1547
+ B = splineInterpolate(B*gscale, gammaTab, GAMMA_TAB_SIZE);
1548
+ }
1549
+
1550
+ float X = R*C0 + G*C1 + B*C2;
1551
+ float Y = R*C3 + G*C4 + B*C5;
1552
+ float Z = R*C6 + G*C7 + B*C8;
1553
+
1554
+ float L = splineInterpolate(Y*LabCbrtTabScale, LabCbrtTab, LAB_CBRT_TAB_SIZE);
1555
+ L = 116.f*L - 16.f;
1556
+
1557
+ float d = (4*13) / std::max(X + 15 * Y + 3 * Z, FLT_EPSILON);
1558
+ float u = L*(X*d - _un);
1559
+ float v = L*((9*0.25f)*Y*d - _vn);
1560
+
1561
+ dst[i] = L; dst[i+1] = u; dst[i+2] = v;
1562
+ }
1563
+ }
1564
+
1565
+ int srccn;
1566
+ float coeffs[9], un, vn;
1567
+ bool srgb;
1568
+ };
1569
+
1570
+
1571
+ struct Luv2RGB_f
1572
+ {
1573
+ typedef float channel_type;
1574
+
1575
+ Luv2RGB_f( int _dstcn, int blueIdx, const float* _coeffs,
1576
+ const float* whitept, bool _srgb )
1577
+ : dstcn(_dstcn), srgb(_srgb)
1578
+ {
1579
+ initLabTabs();
1580
+
1581
+ if(!_coeffs) _coeffs = XYZ2sRGB_D65;
1582
+ if(!whitept) whitept = D65;
1583
+
1584
+ for( int i = 0; i < 3; i++ )
1585
+ {
1586
+ coeffs[i+(blueIdx^2)*3] = _coeffs[i];
1587
+ coeffs[i+3] = _coeffs[i+3];
1588
+ coeffs[i+blueIdx*3] = _coeffs[i+6];
1589
+ }
1590
+
1591
+ float d = 1.f/(whitept[0] + whitept[1]*15 + whitept[2]*3);
1592
+ un = 4*whitept[0]*d;
1593
+ vn = 9*whitept[1]*d;
1594
+
1595
+ CV_Assert(whitept[1] == 1.f);
1596
+ }
1597
+
1598
+ void operator()(const float* src, float* dst, int n) const
1599
+ {
1600
+ int i, dcn = dstcn;
1601
+ const float* gammaTab = srgb ? sRGBInvGammaTab : 0;
1602
+ float gscale = GammaTabScale;
1603
+ float C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2],
1604
+ C3 = coeffs[3], C4 = coeffs[4], C5 = coeffs[5],
1605
+ C6 = coeffs[6], C7 = coeffs[7], C8 = coeffs[8];
1606
+ float alpha = ColorChannel<float>::max();
1607
+ float _un = un, _vn = vn;
1608
+ n *= 3;
1609
+
1610
+ for( i = 0; i < n; i += 3, dst += dcn )
1611
+ {
1612
+ float L = src[i], u = src[i+1], v = src[i+2], d, X, Y, Z;
1613
+ Y = (L + 16.f) * (1.f/116.f);
1614
+ Y = Y*Y*Y;
1615
+ d = (1.f/13.f)/L;
1616
+ u = u*d + _un;
1617
+ v = v*d + _vn;
1618
+ float iv = 1.f/v;
1619
+ X = 2.25f * u * Y * iv ;
1620
+ Z = (12 - 3 * u - 20 * v) * Y * 0.25f * iv;
1621
+
1622
+ float R = X*C0 + Y*C1 + Z*C2;
1623
+ float G = X*C3 + Y*C4 + Z*C5;
1624
+ float B = X*C6 + Y*C7 + Z*C8;
1625
+
1626
+ if( gammaTab )
1627
+ {
1628
+ R = splineInterpolate(R*gscale, gammaTab, GAMMA_TAB_SIZE);
1629
+ G = splineInterpolate(G*gscale, gammaTab, GAMMA_TAB_SIZE);
1630
+ B = splineInterpolate(B*gscale, gammaTab, GAMMA_TAB_SIZE);
1631
+ }
1632
+
1633
+ dst[0] = R; dst[1] = G; dst[2] = B;
1634
+ if( dcn == 4 )
1635
+ dst[3] = alpha;
1636
+ }
1637
+ }
1638
+
1639
+ int dstcn;
1640
+ float coeffs[9], un, vn;
1641
+ bool srgb;
1642
+ };
1643
+
1644
+
1645
+ struct RGB2Luv_b
1646
+ {
1647
+ typedef uchar channel_type;
1648
+
1649
+ RGB2Luv_b( int _srccn, int blueIdx, const float* _coeffs,
1650
+ const float* _whitept, bool _srgb )
1651
+ : srccn(_srccn), cvt(3, blueIdx, _coeffs, _whitept, _srgb) {}
1652
+
1653
+ void operator()(const uchar* src, uchar* dst, int n) const
1654
+ {
1655
+ int i, j, scn = srccn;
1656
+ float buf[3*BLOCK_SIZE];
1657
+
1658
+ for( i = 0; i < n; i += BLOCK_SIZE, dst += BLOCK_SIZE*3 )
1659
+ {
1660
+ int dn = std::min(n - i, (int)BLOCK_SIZE);
1661
+
1662
+ for( j = 0; j < dn*3; j += 3, src += scn )
1663
+ {
1664
+ buf[j] = src[0]*(1.f/255.f);
1665
+ buf[j+1] = (float)(src[1]*(1.f/255.f));
1666
+ buf[j+2] = (float)(src[2]*(1.f/255.f));
1667
+ }
1668
+ cvt(buf, buf, dn);
1669
+
1670
+ for( j = 0; j < dn*3; j += 3 )
1671
+ {
1672
+ dst[j] = saturate_cast<uchar>(buf[j]*2.55f);
1673
+ dst[j+1] = saturate_cast<uchar>(buf[j+1]*0.72033898305084743f + 96.525423728813564f);
1674
+ dst[j+2] = saturate_cast<uchar>(buf[j+2]*0.99609375f + 139.453125f);
1675
+ }
1676
+ }
1677
+ }
1678
+
1679
+ int srccn;
1680
+ RGB2Luv_f cvt;
1681
+ };
1682
+
1683
+
1684
+ struct Luv2RGB_b
1685
+ {
1686
+ typedef uchar channel_type;
1687
+
1688
+ Luv2RGB_b( int _dstcn, int blueIdx, const float* _coeffs,
1689
+ const float* _whitept, bool _srgb )
1690
+ : dstcn(_dstcn), cvt(3, blueIdx, _coeffs, _whitept, _srgb ) {}
1691
+
1692
+ void operator()(const uchar* src, uchar* dst, int n) const
1693
+ {
1694
+ int i, j, dcn = dstcn;
1695
+ uchar alpha = ColorChannel<uchar>::max();
1696
+ float buf[3*BLOCK_SIZE];
1697
+
1698
+ for( i = 0; i < n; i += BLOCK_SIZE, src += BLOCK_SIZE*3 )
1699
+ {
1700
+ int dn = std::min(n - i, (int)BLOCK_SIZE);
1701
+
1702
+ for( j = 0; j < dn*3; j += 3 )
1703
+ {
1704
+ buf[j] = src[j]*(100.f/255.f);
1705
+ buf[j+1] = (float)(src[j+1]*1.388235294117647f - 134.f);
1706
+ buf[j+2] = (float)(src[j+2]*1.003921568627451f - 140.f);
1707
+ }
1708
+ cvt(buf, buf, dn);
1709
+
1710
+ for( j = 0; j < dn*3; j += 3, dst += dcn )
1711
+ {
1712
+ dst[0] = saturate_cast<uchar>(buf[j]*255.f);
1713
+ dst[1] = saturate_cast<uchar>(buf[j+1]*255.f);
1714
+ dst[2] = saturate_cast<uchar>(buf[j+2]*255.f);
1715
+ if( dcn == 4 )
1716
+ dst[3] = alpha;
1717
+ }
1718
+ }
1719
+ }
1720
+
1721
+ int dstcn;
1722
+ Luv2RGB_f cvt;
1723
+ };
1724
+
1725
+
1726
+ //////////////////////////// Bayer Pattern -> RGB conversion /////////////////////////////
1727
+
1728
+ template<typename T>
1729
+ class SIMDBayerStubInterpolator_
1730
+ {
1731
+ public:
1732
+ int bayer2Gray(const T*, int, T*, int, int, int, int) const
1733
+ {
1734
+ return 0;
1735
+ }
1736
+
1737
+ int bayer2RGB(const T*, int, T*, int, int) const
1738
+ {
1739
+ return 0;
1740
+ }
1741
+ };
1742
+
1743
+ #if CV_SSE2
1744
+ class SIMDBayerInterpolator_8u
1745
+ {
1746
+ public:
1747
+ SIMDBayerInterpolator_8u()
1748
+ {
1749
+ use_simd = checkHardwareSupport(CV_CPU_SSE2);
1750
+ }
1751
+
1752
+ int bayer2Gray(const uchar* bayer, int bayer_step, uchar* dst,
1753
+ int width, int bcoeff, int gcoeff, int rcoeff) const
1754
+ {
1755
+ if( !use_simd )
1756
+ return 0;
1757
+
1758
+ __m128i _b2y = _mm_set1_epi16((short)(rcoeff*2));
1759
+ __m128i _g2y = _mm_set1_epi16((short)(gcoeff*2));
1760
+ __m128i _r2y = _mm_set1_epi16((short)(bcoeff*2));
1761
+ const uchar* bayer_end = bayer + width;
1762
+
1763
+ for( ; bayer <= bayer_end - 18; bayer += 14, dst += 14 )
1764
+ {
1765
+ __m128i r0 = _mm_loadu_si128((const __m128i*)bayer);
1766
+ __m128i r1 = _mm_loadu_si128((const __m128i*)(bayer+bayer_step));
1767
+ __m128i r2 = _mm_loadu_si128((const __m128i*)(bayer+bayer_step*2));
1768
+
1769
+ __m128i b1 = _mm_add_epi16(_mm_srli_epi16(_mm_slli_epi16(r0, 8), 8),
1770
+ _mm_srli_epi16(_mm_slli_epi16(r2, 8), 8));
1771
+ __m128i b0 = _mm_add_epi16(b1, _mm_srli_si128(b1, 2));
1772
+ b1 = _mm_slli_epi16(_mm_srli_si128(b1, 2), 1);
1773
+
1774
+ __m128i g0 = _mm_add_epi16(_mm_srli_epi16(r0, 8), _mm_srli_epi16(r2, 8));
1775
+ __m128i g1 = _mm_srli_epi16(_mm_slli_epi16(r1, 8), 8);
1776
+ g0 = _mm_add_epi16(g0, _mm_add_epi16(g1, _mm_srli_si128(g1, 2)));
1777
+ g1 = _mm_slli_epi16(_mm_srli_si128(g1, 2), 2);
1778
+
1779
+ r0 = _mm_srli_epi16(r1, 8);
1780
+ r1 = _mm_slli_epi16(_mm_add_epi16(r0, _mm_srli_si128(r0, 2)), 1);
1781
+ r0 = _mm_slli_epi16(r0, 2);
1782
+
1783
+ g0 = _mm_add_epi16(_mm_mulhi_epi16(b0, _b2y), _mm_mulhi_epi16(g0, _g2y));
1784
+ g1 = _mm_add_epi16(_mm_mulhi_epi16(b1, _b2y), _mm_mulhi_epi16(g1, _g2y));
1785
+ g0 = _mm_add_epi16(g0, _mm_mulhi_epi16(r0, _r2y));
1786
+ g1 = _mm_add_epi16(g1, _mm_mulhi_epi16(r1, _r2y));
1787
+ g0 = _mm_srli_epi16(g0, 1);
1788
+ g1 = _mm_srli_epi16(g1, 1);
1789
+ g0 = _mm_packus_epi16(g0, g0);
1790
+ g1 = _mm_packus_epi16(g1, g1);
1791
+ g0 = _mm_unpacklo_epi8(g0, g1);
1792
+ _mm_storeu_si128((__m128i*)dst, g0);
1793
+ }
1794
+
1795
+ return (int)(bayer - (bayer_end - width));
1796
+ }
1797
+
1798
+ int bayer2RGB(const uchar* bayer, int bayer_step, uchar* dst, int width, int blue) const
1799
+ {
1800
+ if( !use_simd )
1801
+ return 0;
1802
+ /*
1803
+ B G B G | B G B G | B G B G | B G B G
1804
+ G R G R | G R G R | G R G R | G R G R
1805
+ B G B G | B G B G | B G B G | B G B G
1806
+ */
1807
+ __m128i delta1 = _mm_set1_epi16(1), delta2 = _mm_set1_epi16(2);
1808
+ __m128i mask = _mm_set1_epi16(blue < 0 ? -1 : 0), z = _mm_setzero_si128();
1809
+ __m128i masklo = _mm_set1_epi16(0x00ff);
1810
+ const uchar* bayer_end = bayer + width;
1811
+
1812
+ for( ; bayer <= bayer_end - 18; bayer += 14, dst += 42 )
1813
+ {
1814
+ __m128i r0 = _mm_loadu_si128((const __m128i*)bayer);
1815
+ __m128i r1 = _mm_loadu_si128((const __m128i*)(bayer+bayer_step));
1816
+ __m128i r2 = _mm_loadu_si128((const __m128i*)(bayer+bayer_step*2));
1817
+
1818
+ __m128i b1 = _mm_add_epi16(_mm_and_si128(r0, masklo), _mm_and_si128(r2, masklo));
1819
+ __m128i b0 = _mm_add_epi16(b1, _mm_srli_si128(b1, 2));
1820
+ b1 = _mm_srli_si128(b1, 2);
1821
+ b1 = _mm_srli_epi16(_mm_add_epi16(b1, delta1), 1);
1822
+ b0 = _mm_srli_epi16(_mm_add_epi16(b0, delta2), 2);
1823
+ b0 = _mm_packus_epi16(b0, b1);
1824
+
1825
+ __m128i g0 = _mm_add_epi16(_mm_srli_epi16(r0, 8), _mm_srli_epi16(r2, 8));
1826
+ __m128i g1 = _mm_and_si128(r1, masklo);
1827
+ g0 = _mm_add_epi16(g0, _mm_add_epi16(g1, _mm_srli_si128(g1, 2)));
1828
+ g1 = _mm_srli_si128(g1, 2);
1829
+ g0 = _mm_srli_epi16(_mm_add_epi16(g0, delta2), 2);
1830
+ g0 = _mm_packus_epi16(g0, g1);
1831
+
1832
+ r0 = _mm_srli_epi16(r1, 8);
1833
+ r1 = _mm_add_epi16(r0, _mm_srli_si128(r0, 2));
1834
+ r1 = _mm_srli_epi16(_mm_add_epi16(r1, delta1), 1);
1835
+ r0 = _mm_packus_epi16(r0, r1);
1836
+
1837
+ b1 = _mm_and_si128(_mm_xor_si128(b0, r0), mask);
1838
+ b0 = _mm_xor_si128(b0, b1);
1839
+ r0 = _mm_xor_si128(r0, b1);
1840
+
1841
+ // b1 g1 b1 g1 ...
1842
+ b1 = _mm_unpackhi_epi8(b0, g0);
1843
+ // b0 g0 b2 g2 b4 g4 ....
1844
+ b0 = _mm_unpacklo_epi8(b0, g0);
1845
+
1846
+ // r1 0 r3 0 ...
1847
+ r1 = _mm_unpackhi_epi8(r0, z);
1848
+ // r0 0 r2 0 r4 0 ...
1849
+ r0 = _mm_unpacklo_epi8(r0, z);
1850
+
1851
+ // 0 b0 g0 r0 0 b2 g2 r2 0 ...
1852
+ g0 = _mm_slli_si128(_mm_unpacklo_epi16(b0, r0), 1);
1853
+ // 0 b8 g8 r8 0 b10 g10 r10 0 ...
1854
+ g1 = _mm_slli_si128(_mm_unpackhi_epi16(b0, r0), 1);
1855
+
1856
+ // b1 g1 r1 0 b3 g3 r3 ....
1857
+ r0 = _mm_unpacklo_epi16(b1, r1);
1858
+ // b9 g9 r9 0 ...
1859
+ r1 = _mm_unpackhi_epi16(b1, r1);
1860
+
1861
+ b0 = _mm_srli_si128(_mm_unpacklo_epi32(g0, r0), 1);
1862
+ b1 = _mm_srli_si128(_mm_unpackhi_epi32(g0, r0), 1);
1863
+
1864
+ _mm_storel_epi64((__m128i*)(dst-1+0), b0);
1865
+ _mm_storel_epi64((__m128i*)(dst-1+6*1), _mm_srli_si128(b0, 8));
1866
+ _mm_storel_epi64((__m128i*)(dst-1+6*2), b1);
1867
+ _mm_storel_epi64((__m128i*)(dst-1+6*3), _mm_srli_si128(b1, 8));
1868
+
1869
+ g0 = _mm_srli_si128(_mm_unpacklo_epi32(g1, r1), 1);
1870
+ g1 = _mm_srli_si128(_mm_unpackhi_epi32(g1, r1), 1);
1871
+
1872
+ _mm_storel_epi64((__m128i*)(dst-1+6*4), g0);
1873
+ _mm_storel_epi64((__m128i*)(dst-1+6*5), _mm_srli_si128(g0, 8));
1874
+
1875
+ _mm_storel_epi64((__m128i*)(dst-1+6*6), g1);
1876
+ }
1877
+
1878
+ return (int)(bayer - (bayer_end - width));
1879
+ }
1880
+
1881
+ bool use_simd;
1882
+ };
1883
+ #else
1884
+ typedef SIMDBayerStubInterpolator_<uchar> SIMDBayerInterpolator_8u;
1885
+ #endif
1886
+
1887
+ template<typename T, class SIMDInterpolator>
1888
+ static void Bayer2Gray_( const Mat& srcmat, Mat& dstmat, int code )
1889
+ {
1890
+ SIMDInterpolator vecOp;
1891
+ const int R2Y = 4899;
1892
+ const int G2Y = 9617;
1893
+ const int B2Y = 1868;
1894
+ const int SHIFT = 14;
1895
+
1896
+ const T* bayer0 = (const T*)srcmat.data;
1897
+ int bayer_step = (int)(srcmat.step/sizeof(T));
1898
+ T* dst0 = (T*)dstmat.data;
1899
+ int dst_step = (int)(dstmat.step/sizeof(T));
1900
+ Size size = srcmat.size();
1901
+ int bcoeff = B2Y, rcoeff = R2Y;
1902
+ int start_with_green = code == CV_BayerGB2GRAY || code == CV_BayerGR2GRAY;
1903
+ bool brow = true;
1904
+
1905
+ if( code != CV_BayerBG2GRAY && code != CV_BayerGB2GRAY )
1906
+ {
1907
+ brow = false;
1908
+ std::swap(bcoeff, rcoeff);
1909
+ }
1910
+
1911
+ dst0 += dst_step + 1;
1912
+ size.height -= 2;
1913
+ size.width -= 2;
1914
+
1915
+ for( ; size.height-- > 0; bayer0 += bayer_step, dst0 += dst_step )
1916
+ {
1917
+ unsigned t0, t1, t2;
1918
+ const T* bayer = bayer0;
1919
+ T* dst = dst0;
1920
+ const T* bayer_end = bayer + size.width;
1921
+
1922
+ if( size.width <= 0 )
1923
+ {
1924
+ dst[-1] = dst[size.width] = 0;
1925
+ continue;
1926
+ }
1927
+
1928
+ if( start_with_green )
1929
+ {
1930
+ t0 = (bayer[1] + bayer[bayer_step*2+1])*rcoeff;
1931
+ t1 = (bayer[bayer_step] + bayer[bayer_step+2])*bcoeff;
1932
+ t2 = bayer[bayer_step+1]*(2*G2Y);
1933
+
1934
+ dst[0] = (T)CV_DESCALE(t0 + t1 + t2, SHIFT+1);
1935
+ bayer++;
1936
+ dst++;
1937
+ }
1938
+
1939
+ int delta = vecOp.bayer2Gray(bayer, bayer_step, dst, size.width, bcoeff, G2Y, rcoeff);
1940
+ bayer += delta;
1941
+ dst += delta;
1942
+
1943
+ for( ; bayer <= bayer_end - 2; bayer += 2, dst += 2 )
1944
+ {
1945
+ t0 = (bayer[0] + bayer[2] + bayer[bayer_step*2] + bayer[bayer_step*2+2])*rcoeff;
1946
+ t1 = (bayer[1] + bayer[bayer_step] + bayer[bayer_step+2] + bayer[bayer_step*2+1])*G2Y;
1947
+ t2 = bayer[bayer_step+1]*(4*bcoeff);
1948
+ dst[0] = (T)CV_DESCALE(t0 + t1 + t2, SHIFT+2);
1949
+
1950
+ t0 = (bayer[2] + bayer[bayer_step*2+2])*rcoeff;
1951
+ t1 = (bayer[bayer_step+1] + bayer[bayer_step+3])*bcoeff;
1952
+ t2 = bayer[bayer_step+2]*(2*G2Y);
1953
+ dst[1] = (T)CV_DESCALE(t0 + t1 + t2, SHIFT+1);
1954
+ }
1955
+
1956
+ if( bayer < bayer_end )
1957
+ {
1958
+ t0 = (bayer[0] + bayer[2] + bayer[bayer_step*2] + bayer[bayer_step*2+2])*rcoeff;
1959
+ t1 = (bayer[1] + bayer[bayer_step] + bayer[bayer_step+2] + bayer[bayer_step*2+1])*G2Y;
1960
+ t2 = bayer[bayer_step+1]*(4*bcoeff);
1961
+ dst[0] = (T)CV_DESCALE(t0 + t1 + t2, SHIFT+2);
1962
+ bayer++;
1963
+ dst++;
1964
+ }
1965
+
1966
+ dst0[-1] = dst0[0];
1967
+ dst0[size.width] = dst0[size.width-1];
1968
+
1969
+ brow = !brow;
1970
+ std::swap(bcoeff, rcoeff);
1971
+ start_with_green = !start_with_green;
1972
+ }
1973
+
1974
+ size = dstmat.size();
1975
+ dst0 = (T*)dstmat.data;
1976
+ if( size.height > 2 )
1977
+ for( int i = 0; i < size.width; i++ )
1978
+ {
1979
+ dst0[i] = dst0[i + dst_step];
1980
+ dst0[i + (size.height-1)*dst_step] = dst0[i + (size.height-2)*dst_step];
1981
+ }
1982
+ else
1983
+ for( int i = 0; i < size.width; i++ )
1984
+ {
1985
+ dst0[i] = dst0[i + (size.height-1)*dst_step] = 0;
1986
+ }
1987
+ }
1988
+
1989
+ template<typename T, class SIMDInterpolator>
1990
+ static void Bayer2RGB_( const Mat& srcmat, Mat& dstmat, int code )
1991
+ {
1992
+ SIMDInterpolator vecOp;
1993
+ const T* bayer0 = (const T*)srcmat.data;
1994
+ int bayer_step = (int)(srcmat.step/sizeof(T));
1995
+ T* dst0 = (T*)dstmat.data;
1996
+ int dst_step = (int)(dstmat.step/sizeof(T));
1997
+ Size size = srcmat.size();
1998
+ int blue = code == CV_BayerBG2BGR || code == CV_BayerGB2BGR ? -1 : 1;
1999
+ int start_with_green = code == CV_BayerGB2BGR || code == CV_BayerGR2BGR;
2000
+
2001
+ dst0 += dst_step + 3 + 1;
2002
+ size.height -= 2;
2003
+ size.width -= 2;
2004
+
2005
+ for( ; size.height-- > 0; bayer0 += bayer_step, dst0 += dst_step )
2006
+ {
2007
+ int t0, t1;
2008
+ const T* bayer = bayer0;
2009
+ T* dst = dst0;
2010
+ const T* bayer_end = bayer + size.width;
2011
+
2012
+ if( size.width <= 0 )
2013
+ {
2014
+ dst[-4] = dst[-3] = dst[-2] = dst[size.width*3-1] =
2015
+ dst[size.width*3] = dst[size.width*3+1] = 0;
2016
+ continue;
2017
+ }
2018
+
2019
+ if( start_with_green )
2020
+ {
2021
+ t0 = (bayer[1] + bayer[bayer_step*2+1] + 1) >> 1;
2022
+ t1 = (bayer[bayer_step] + bayer[bayer_step+2] + 1) >> 1;
2023
+ dst[-blue] = (T)t0;
2024
+ dst[0] = bayer[bayer_step+1];
2025
+ dst[blue] = (T)t1;
2026
+ bayer++;
2027
+ dst += 3;
2028
+ }
2029
+
2030
+ int delta = vecOp.bayer2RGB(bayer, bayer_step, dst, size.width, blue);
2031
+ bayer += delta;
2032
+ dst += delta*3;
2033
+
2034
+ if( blue > 0 )
2035
+ {
2036
+ for( ; bayer <= bayer_end - 2; bayer += 2, dst += 6 )
2037
+ {
2038
+ t0 = (bayer[0] + bayer[2] + bayer[bayer_step*2] +
2039
+ bayer[bayer_step*2+2] + 2) >> 2;
2040
+ t1 = (bayer[1] + bayer[bayer_step] +
2041
+ bayer[bayer_step+2] + bayer[bayer_step*2+1]+2) >> 2;
2042
+ dst[-1] = (T)t0;
2043
+ dst[0] = (T)t1;
2044
+ dst[1] = bayer[bayer_step+1];
2045
+
2046
+ t0 = (bayer[2] + bayer[bayer_step*2+2] + 1) >> 1;
2047
+ t1 = (bayer[bayer_step+1] + bayer[bayer_step+3] + 1) >> 1;
2048
+ dst[2] = (T)t0;
2049
+ dst[3] = bayer[bayer_step+2];
2050
+ dst[4] = (T)t1;
2051
+ }
2052
+ }
2053
+ else
2054
+ {
2055
+ for( ; bayer <= bayer_end - 2; bayer += 2, dst += 6 )
2056
+ {
2057
+ t0 = (bayer[0] + bayer[2] + bayer[bayer_step*2] +
2058
+ bayer[bayer_step*2+2] + 2) >> 2;
2059
+ t1 = (bayer[1] + bayer[bayer_step] +
2060
+ bayer[bayer_step+2] + bayer[bayer_step*2+1]+2) >> 2;
2061
+ dst[1] = (T)t0;
2062
+ dst[0] = (T)t1;
2063
+ dst[-1] = bayer[bayer_step+1];
2064
+
2065
+ t0 = (bayer[2] + bayer[bayer_step*2+2] + 1) >> 1;
2066
+ t1 = (bayer[bayer_step+1] + bayer[bayer_step+3] + 1) >> 1;
2067
+ dst[4] = (T)t0;
2068
+ dst[3] = bayer[bayer_step+2];
2069
+ dst[2] = (T)t1;
2070
+ }
2071
+ }
2072
+
2073
+ if( bayer < bayer_end )
2074
+ {
2075
+ t0 = (bayer[0] + bayer[2] + bayer[bayer_step*2] +
2076
+ bayer[bayer_step*2+2] + 2) >> 2;
2077
+ t1 = (bayer[1] + bayer[bayer_step] +
2078
+ bayer[bayer_step+2] + bayer[bayer_step*2+1]+2) >> 2;
2079
+ dst[-blue] = (T)t0;
2080
+ dst[0] = (T)t1;
2081
+ dst[blue] = bayer[bayer_step+1];
2082
+ bayer++;
2083
+ dst += 3;
2084
+ }
2085
+
2086
+ dst0[-4] = dst0[-1];
2087
+ dst0[-3] = dst0[0];
2088
+ dst0[-2] = dst0[1];
2089
+ dst0[size.width*3-1] = dst0[size.width*3-4];
2090
+ dst0[size.width*3] = dst0[size.width*3-3];
2091
+ dst0[size.width*3+1] = dst0[size.width*3-2];
2092
+
2093
+ blue = -blue;
2094
+ start_with_green = !start_with_green;
2095
+ }
2096
+
2097
+ size = dstmat.size();
2098
+ dst0 = (T*)dstmat.data;
2099
+ if( size.height > 2 )
2100
+ for( int i = 0; i < size.width*3; i++ )
2101
+ {
2102
+ dst0[i] = dst0[i + dst_step];
2103
+ dst0[i + (size.height-1)*dst_step] = dst0[i + (size.height-2)*dst_step];
2104
+ }
2105
+ else
2106
+ for( int i = 0; i < size.width*3; i++ )
2107
+ {
2108
+ dst0[i] = dst0[i + (size.height-1)*dst_step] = 0;
2109
+ }
2110
+ }
2111
+
2112
+
2113
+ /////////////////// Demosaicing using Variable Number of Gradients ///////////////////////
2114
+
2115
+ static void Bayer2RGB_VNG_8u( const Mat& srcmat, Mat& dstmat, int code )
2116
+ {
2117
+ const uchar* bayer = srcmat.data;
2118
+ int bstep = (int)srcmat.step;
2119
+ uchar* dst = dstmat.data;
2120
+ int dststep = (int)dstmat.step;
2121
+ Size size = srcmat.size();
2122
+
2123
+ int blueIdx = code == CV_BayerBG2BGR_VNG || code == CV_BayerGB2BGR_VNG ? 0 : 2;
2124
+ bool greenCell0 = code != CV_BayerBG2BGR_VNG && code != CV_BayerRG2BGR_VNG;
2125
+
2126
+ // for too small images use the simple interpolation algorithm
2127
+ if( MIN(size.width, size.height) < 8 )
2128
+ {
2129
+ Bayer2RGB_<uchar, SIMDBayerInterpolator_8u>( srcmat, dstmat, code );
2130
+ return;
2131
+ }
2132
+
2133
+ const int brows = 3, bcn = 7;
2134
+ int N = size.width, N2 = N*2, N3 = N*3, N4 = N*4, N5 = N*5, N6 = N*6, N7 = N*7;
2135
+ int i, bufstep = N7*bcn;
2136
+ cv::AutoBuffer<ushort> _buf(bufstep*brows);
2137
+ ushort* buf = (ushort*)_buf;
2138
+
2139
+ bayer += bstep*2;
2140
+
2141
+ #if CV_SSE2
2142
+ bool haveSSE = cv::checkHardwareSupport(CV_CPU_SSE2);
2143
+ #define _mm_absdiff_epu16(a,b) _mm_adds_epu16(_mm_subs_epu16(a, b), _mm_subs_epu16(b, a))
2144
+ #endif
2145
+
2146
+ for( int y = 2; y < size.height - 4; y++ )
2147
+ {
2148
+ uchar* dstrow = dst + dststep*y + 6;
2149
+ const uchar* srow;
2150
+
2151
+ for( int dy = (y == 2 ? -1 : 1); dy <= 1; dy++ )
2152
+ {
2153
+ ushort* brow = buf + ((y + dy - 1)%brows)*bufstep + 1;
2154
+ srow = bayer + (y+dy)*bstep + 1;
2155
+
2156
+ for( i = 0; i < bcn; i++ )
2157
+ brow[N*i-1] = brow[(N-2) + N*i] = 0;
2158
+
2159
+ i = 1;
2160
+
2161
+ #if CV_SSE2
2162
+ if( haveSSE )
2163
+ {
2164
+ __m128i z = _mm_setzero_si128();
2165
+ for( ; i <= N-9; i += 8, srow += 8, brow += 8 )
2166
+ {
2167
+ __m128i s1, s2, s3, s4, s6, s7, s8, s9;
2168
+
2169
+ s1 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow-1-bstep)),z);
2170
+ s2 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow-bstep)),z);
2171
+ s3 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow+1-bstep)),z);
2172
+
2173
+ s4 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow-1)),z);
2174
+ s6 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow+1)),z);
2175
+
2176
+ s7 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow-1+bstep)),z);
2177
+ s8 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow+bstep)),z);
2178
+ s9 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow+1+bstep)),z);
2179
+
2180
+ __m128i b0, b1, b2, b3, b4, b5, b6;
2181
+
2182
+ b0 = _mm_adds_epu16(_mm_slli_epi16(_mm_absdiff_epu16(s2,s8),1),
2183
+ _mm_adds_epu16(_mm_absdiff_epu16(s1, s7),
2184
+ _mm_absdiff_epu16(s3, s9)));
2185
+ b1 = _mm_adds_epu16(_mm_slli_epi16(_mm_absdiff_epu16(s4,s6),1),
2186
+ _mm_adds_epu16(_mm_absdiff_epu16(s1, s3),
2187
+ _mm_absdiff_epu16(s7, s9)));
2188
+ b2 = _mm_slli_epi16(_mm_absdiff_epu16(s3,s7),1);
2189
+ b3 = _mm_slli_epi16(_mm_absdiff_epu16(s1,s9),1);
2190
+
2191
+ _mm_storeu_si128((__m128i*)brow, b0);
2192
+ _mm_storeu_si128((__m128i*)(brow + N), b1);
2193
+ _mm_storeu_si128((__m128i*)(brow + N2), b2);
2194
+ _mm_storeu_si128((__m128i*)(brow + N3), b3);
2195
+
2196
+ b4 = _mm_adds_epu16(b2,_mm_adds_epu16(_mm_absdiff_epu16(s2, s4),
2197
+ _mm_absdiff_epu16(s6, s8)));
2198
+ b5 = _mm_adds_epu16(b3,_mm_adds_epu16(_mm_absdiff_epu16(s2, s6),
2199
+ _mm_absdiff_epu16(s4, s8)));
2200
+ b6 = _mm_adds_epu16(_mm_adds_epu16(s2, s4), _mm_adds_epu16(s6, s8));
2201
+ b6 = _mm_srli_epi16(b6, 1);
2202
+
2203
+ _mm_storeu_si128((__m128i*)(brow + N4), b4);
2204
+ _mm_storeu_si128((__m128i*)(brow + N5), b5);
2205
+ _mm_storeu_si128((__m128i*)(brow + N6), b6);
2206
+ }
2207
+ }
2208
+ #endif
2209
+
2210
+ for( ; i < N-1; i++, srow++, brow++ )
2211
+ {
2212
+ brow[0] = (ushort)(std::abs(srow[-1-bstep] - srow[-1+bstep]) +
2213
+ std::abs(srow[-bstep] - srow[+bstep])*2 +
2214
+ std::abs(srow[1-bstep] - srow[1+bstep]));
2215
+ brow[N] = (ushort)(std::abs(srow[-1-bstep] - srow[1-bstep]) +
2216
+ std::abs(srow[-1] - srow[1])*2 +
2217
+ std::abs(srow[-1+bstep] - srow[1+bstep]));
2218
+ brow[N2] = (ushort)(std::abs(srow[+1-bstep] - srow[-1+bstep])*2);
2219
+ brow[N3] = (ushort)(std::abs(srow[-1-bstep] - srow[1+bstep])*2);
2220
+ brow[N4] = (ushort)(brow[N2] + std::abs(srow[-bstep] - srow[-1]) +
2221
+ std::abs(srow[+bstep] - srow[1]));
2222
+ brow[N5] = (ushort)(brow[N3] + std::abs(srow[-bstep] - srow[1]) +
2223
+ std::abs(srow[+bstep] - srow[-1]));
2224
+ brow[N6] = (ushort)((srow[-bstep] + srow[-1] + srow[1] + srow[+bstep])>>1);
2225
+ }
2226
+ }
2227
+
2228
+ const ushort* brow0 = buf + ((y - 2) % brows)*bufstep + 2;
2229
+ const ushort* brow1 = buf + ((y - 1) % brows)*bufstep + 2;
2230
+ const ushort* brow2 = buf + (y % brows)*bufstep + 2;
2231
+ static const float scale[] = { 0.f, 0.5f, 0.25f, 0.1666666666667f, 0.125f, 0.1f, 0.08333333333f, 0.0714286f, 0.0625f };
2232
+ srow = bayer + y*bstep + 2;
2233
+ bool greenCell = greenCell0;
2234
+
2235
+ i = 2;
2236
+ #if CV_SSE2
2237
+ int limit = !haveSSE ? N-2 : greenCell ? std::min(3, N-2) : 2;
2238
+ #else
2239
+ int limit = N - 2;
2240
+ #endif
2241
+
2242
+ do
2243
+ {
2244
+ for( ; i < limit; i++, srow++, brow0++, brow1++, brow2++, dstrow += 3 )
2245
+ {
2246
+ int gradN = brow0[0] + brow1[0];
2247
+ int gradS = brow1[0] + brow2[0];
2248
+ int gradW = brow1[N-1] + brow1[N];
2249
+ int gradE = brow1[N] + brow1[N+1];
2250
+ int minGrad = std::min(std::min(std::min(gradN, gradS), gradW), gradE);
2251
+ int maxGrad = std::max(std::max(std::max(gradN, gradS), gradW), gradE);
2252
+ int R, G, B;
2253
+
2254
+ if( !greenCell )
2255
+ {
2256
+ int gradNE = brow0[N4+1] + brow1[N4];
2257
+ int gradSW = brow1[N4] + brow2[N4-1];
2258
+ int gradNW = brow0[N5-1] + brow1[N5];
2259
+ int gradSE = brow1[N5] + brow2[N5+1];
2260
+
2261
+ minGrad = std::min(std::min(std::min(std::min(minGrad, gradNE), gradSW), gradNW), gradSE);
2262
+ maxGrad = std::max(std::max(std::max(std::max(maxGrad, gradNE), gradSW), gradNW), gradSE);
2263
+ int T = minGrad + maxGrad/2;
2264
+
2265
+ int Rs = 0, Gs = 0, Bs = 0, ng = 0;
2266
+ if( gradN < T )
2267
+ {
2268
+ Rs += srow[-bstep*2] + srow[0];
2269
+ Gs += srow[-bstep]*2;
2270
+ Bs += srow[-bstep-1] + srow[-bstep+1];
2271
+ ng++;
2272
+ }
2273
+ if( gradS < T )
2274
+ {
2275
+ Rs += srow[bstep*2] + srow[0];
2276
+ Gs += srow[bstep]*2;
2277
+ Bs += srow[bstep-1] + srow[bstep+1];
2278
+ ng++;
2279
+ }
2280
+ if( gradW < T )
2281
+ {
2282
+ Rs += srow[-2] + srow[0];
2283
+ Gs += srow[-1]*2;
2284
+ Bs += srow[-bstep-1] + srow[bstep-1];
2285
+ ng++;
2286
+ }
2287
+ if( gradE < T )
2288
+ {
2289
+ Rs += srow[2] + srow[0];
2290
+ Gs += srow[1]*2;
2291
+ Bs += srow[-bstep+1] + srow[bstep+1];
2292
+ ng++;
2293
+ }
2294
+ if( gradNE < T )
2295
+ {
2296
+ Rs += srow[-bstep*2+2] + srow[0];
2297
+ Gs += brow0[N6+1];
2298
+ Bs += srow[-bstep+1]*2;
2299
+ ng++;
2300
+ }
2301
+ if( gradSW < T )
2302
+ {
2303
+ Rs += srow[bstep*2-2] + srow[0];
2304
+ Gs += brow2[N6-1];
2305
+ Bs += srow[bstep-1]*2;
2306
+ ng++;
2307
+ }
2308
+ if( gradNW < T )
2309
+ {
2310
+ Rs += srow[-bstep*2-2] + srow[0];
2311
+ Gs += brow0[N6-1];
2312
+ Bs += srow[-bstep+1]*2;
2313
+ ng++;
2314
+ }
2315
+ if( gradSE < T )
2316
+ {
2317
+ Rs += srow[bstep*2+2] + srow[0];
2318
+ Gs += brow2[N6+1];
2319
+ Bs += srow[-bstep+1]*2;
2320
+ ng++;
2321
+ }
2322
+ R = srow[0];
2323
+ G = R + cvRound((Gs - Rs)*scale[ng]);
2324
+ B = R + cvRound((Bs - Rs)*scale[ng]);
2325
+ }
2326
+ else
2327
+ {
2328
+ int gradNE = brow0[N2] + brow0[N2+1] + brow1[N2] + brow1[N2+1];
2329
+ int gradSW = brow1[N2] + brow1[N2-1] + brow2[N2] + brow2[N2-1];
2330
+ int gradNW = brow0[N3] + brow0[N3-1] + brow1[N3] + brow1[N3-1];
2331
+ int gradSE = brow1[N3] + brow1[N3+1] + brow2[N3] + brow2[N3+1];
2332
+
2333
+ minGrad = std::min(std::min(std::min(std::min(minGrad, gradNE), gradSW), gradNW), gradSE);
2334
+ maxGrad = std::max(std::max(std::max(std::max(maxGrad, gradNE), gradSW), gradNW), gradSE);
2335
+ int T = minGrad + maxGrad/2;
2336
+
2337
+ int Rs = 0, Gs = 0, Bs = 0, ng = 0;
2338
+ if( gradN < T )
2339
+ {
2340
+ Rs += srow[-bstep*2-1] + srow[-bstep*2+1];
2341
+ Gs += srow[-bstep*2] + srow[0];
2342
+ Bs += srow[-bstep]*2;
2343
+ ng++;
2344
+ }
2345
+ if( gradS < T )
2346
+ {
2347
+ Rs += srow[bstep*2-1] + srow[bstep*2+1];
2348
+ Gs += srow[bstep*2] + srow[0];
2349
+ Bs += srow[bstep]*2;
2350
+ ng++;
2351
+ }
2352
+ if( gradW < T )
2353
+ {
2354
+ Rs += srow[-1]*2;
2355
+ Gs += srow[-2] + srow[0];
2356
+ Bs += srow[-bstep-2]+srow[bstep-2];
2357
+ ng++;
2358
+ }
2359
+ if( gradE < T )
2360
+ {
2361
+ Rs += srow[1]*2;
2362
+ Gs += srow[2] + srow[0];
2363
+ Bs += srow[-bstep+2]+srow[bstep+2];
2364
+ ng++;
2365
+ }
2366
+ if( gradNE < T )
2367
+ {
2368
+ Rs += srow[-bstep*2+1] + srow[1];
2369
+ Gs += srow[-bstep+1]*2;
2370
+ Bs += srow[-bstep] + srow[-bstep+2];
2371
+ ng++;
2372
+ }
2373
+ if( gradSW < T )
2374
+ {
2375
+ Rs += srow[bstep*2-1] + srow[-1];
2376
+ Gs += srow[bstep-1]*2;
2377
+ Bs += srow[bstep] + srow[bstep-2];
2378
+ ng++;
2379
+ }
2380
+ if( gradNW < T )
2381
+ {
2382
+ Rs += srow[-bstep*2-1] + srow[-1];
2383
+ Gs += srow[-bstep-1]*2;
2384
+ Bs += srow[-bstep-2]+srow[-bstep];
2385
+ ng++;
2386
+ }
2387
+ if( gradSE < T )
2388
+ {
2389
+ Rs += srow[bstep*2+1] + srow[1];
2390
+ Gs += srow[bstep+1]*2;
2391
+ Bs += srow[bstep+2]+srow[bstep];
2392
+ ng++;
2393
+ }
2394
+ G = srow[0];
2395
+ R = G + cvRound((Rs - Gs)*scale[ng]);
2396
+ B = G + cvRound((Bs - Gs)*scale[ng]);
2397
+ }
2398
+ dstrow[blueIdx] = CV_CAST_8U(B);
2399
+ dstrow[1] = CV_CAST_8U(G);
2400
+ dstrow[blueIdx^2] = CV_CAST_8U(R);
2401
+ greenCell = !greenCell;
2402
+ }
2403
+
2404
+ #if CV_SSE2
2405
+ if( !haveSSE )
2406
+ break;
2407
+
2408
+ __m128i emask = _mm_set1_epi32(0x0000ffff),
2409
+ omask = _mm_set1_epi32(0xffff0000),
2410
+ all_ones = _mm_set1_epi16(1),
2411
+ z = _mm_setzero_si128();
2412
+ __m128 _0_5 = _mm_set1_ps(0.5f);
2413
+
2414
+ #define _mm_merge_epi16(a, b) \
2415
+ _mm_or_si128(_mm_and_si128(a, emask), _mm_and_si128(b, omask))
2416
+ #define _mm_cvtloepi16_ps(a) _mm_cvtepi32_ps(_mm_srai_epi32(_mm_unpacklo_epi16(a,a), 16))
2417
+ #define _mm_cvthiepi16_ps(a) _mm_cvtepi32_ps(_mm_srai_epi32(_mm_unpackhi_epi16(a,a), 16))
2418
+
2419
+ // process 8 pixels at once
2420
+ for( ; i <= N - 10; i += 8, srow += 8, brow0 += 8, brow1 += 8, brow2 += 8 )
2421
+ {
2422
+ __m128i gradN, gradS, gradW, gradE, gradNE, gradSW, gradNW, gradSE;
2423
+ gradN = _mm_adds_epu16(_mm_loadu_si128((__m128i*)brow0),
2424
+ _mm_loadu_si128((__m128i*)brow1));
2425
+ gradS = _mm_adds_epu16(_mm_loadu_si128((__m128i*)brow1),
2426
+ _mm_loadu_si128((__m128i*)brow2));
2427
+ gradW = _mm_adds_epu16(_mm_loadu_si128((__m128i*)(brow1+N-1)),
2428
+ _mm_loadu_si128((__m128i*)(brow1+N)));
2429
+ gradE = _mm_adds_epu16(_mm_loadu_si128((__m128i*)(brow1+N+1)),
2430
+ _mm_loadu_si128((__m128i*)(brow1+N)));
2431
+
2432
+ __m128i minGrad, maxGrad, T;
2433
+ minGrad = _mm_min_epi16(_mm_min_epi16(_mm_min_epi16(gradN, gradS), gradW), gradE);
2434
+ maxGrad = _mm_max_epi16(_mm_max_epi16(_mm_max_epi16(gradN, gradS), gradW), gradE);
2435
+
2436
+ __m128i grad0, grad1;
2437
+
2438
+ grad0 = _mm_adds_epu16(_mm_loadu_si128((__m128i*)(brow0+N4+1)),
2439
+ _mm_loadu_si128((__m128i*)(brow1+N4)));
2440
+ grad1 = _mm_adds_epu16(_mm_adds_epu16(_mm_loadu_si128((__m128i*)(brow0+N2)),
2441
+ _mm_loadu_si128((__m128i*)(brow0+N2+1))),
2442
+ _mm_adds_epu16(_mm_loadu_si128((__m128i*)(brow1+N2)),
2443
+ _mm_loadu_si128((__m128i*)(brow1+N2+1))));
2444
+ gradNE = _mm_srli_epi16(_mm_merge_epi16(grad0, grad1), 1);
2445
+
2446
+ grad0 = _mm_adds_epu16(_mm_loadu_si128((__m128i*)(brow2+N4-1)),
2447
+ _mm_loadu_si128((__m128i*)(brow1+N4)));
2448
+ grad1 = _mm_adds_epu16(_mm_adds_epu16(_mm_loadu_si128((__m128i*)(brow2+N2)),
2449
+ _mm_loadu_si128((__m128i*)(brow2+N2-1))),
2450
+ _mm_adds_epu16(_mm_loadu_si128((__m128i*)(brow1+N2)),
2451
+ _mm_loadu_si128((__m128i*)(brow1+N2-1))));
2452
+ gradSW = _mm_srli_epi16(_mm_merge_epi16(grad0, grad1), 1);
2453
+
2454
+ minGrad = _mm_min_epi16(_mm_min_epi16(minGrad, gradNE), gradSW);
2455
+ maxGrad = _mm_max_epi16(_mm_max_epi16(maxGrad, gradNE), gradSW);
2456
+
2457
+ grad0 = _mm_adds_epu16(_mm_loadu_si128((__m128i*)(brow0+N5-1)),
2458
+ _mm_loadu_si128((__m128i*)(brow1+N5)));
2459
+ grad1 = _mm_adds_epu16(_mm_adds_epu16(_mm_loadu_si128((__m128i*)(brow0+N3)),
2460
+ _mm_loadu_si128((__m128i*)(brow0+N3-1))),
2461
+ _mm_adds_epu16(_mm_loadu_si128((__m128i*)(brow1+N3)),
2462
+ _mm_loadu_si128((__m128i*)(brow1+N3-1))));
2463
+ gradNW = _mm_srli_epi16(_mm_merge_epi16(grad0, grad1), 1);
2464
+
2465
+ grad0 = _mm_adds_epu16(_mm_loadu_si128((__m128i*)(brow2+N5+1)),
2466
+ _mm_loadu_si128((__m128i*)(brow1+N5)));
2467
+ grad1 = _mm_adds_epu16(_mm_adds_epu16(_mm_loadu_si128((__m128i*)(brow2+N3)),
2468
+ _mm_loadu_si128((__m128i*)(brow2+N3+1))),
2469
+ _mm_adds_epu16(_mm_loadu_si128((__m128i*)(brow1+N3)),
2470
+ _mm_loadu_si128((__m128i*)(brow1+N3+1))));
2471
+ gradSE = _mm_srli_epi16(_mm_merge_epi16(grad0, grad1), 1);
2472
+
2473
+ minGrad = _mm_min_epi16(_mm_min_epi16(minGrad, gradNW), gradSE);
2474
+ maxGrad = _mm_max_epi16(_mm_max_epi16(maxGrad, gradNW), gradSE);
2475
+
2476
+ T = _mm_add_epi16(_mm_srli_epi16(maxGrad, 1), minGrad);
2477
+ __m128i RGs = z, GRs = z, Bs = z, ng = z, mask;
2478
+
2479
+ __m128i t0, t1, x0, x1, x2, x3, x4, x5, x6, x7, x8,
2480
+ x9, x10, x11, x12, x13, x14, x15, x16;
2481
+
2482
+ x0 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)srow), z);
2483
+
2484
+ x1 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow-bstep-1)), z);
2485
+ x2 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow-bstep*2-1)), z);
2486
+ x3 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow-bstep)), z);
2487
+ x4 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow-bstep*2+1)), z);
2488
+ x5 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow-bstep+1)), z);
2489
+ x6 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow-bstep+2)), z);
2490
+ x7 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow+1)), z);
2491
+ x8 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow+bstep+2)), z);
2492
+ x9 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow+bstep+1)), z);
2493
+ x10 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow+bstep*2+1)), z);
2494
+ x11 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow+bstep)), z);
2495
+ x12 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow+bstep*2-1)), z);
2496
+ x13 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow+bstep-1)), z);
2497
+ x14 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow+bstep-2)), z);
2498
+ x15 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow-1)), z);
2499
+ x16 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow-bstep-2)), z);
2500
+
2501
+ // gradN
2502
+ mask = _mm_cmpgt_epi16(T, gradN);
2503
+ ng = _mm_sub_epi16(ng, mask);
2504
+
2505
+ t0 = _mm_slli_epi16(x3, 1);
2506
+ t1 = _mm_adds_epu16(_mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow-bstep*2)), z), x0);
2507
+
2508
+ RGs = _mm_adds_epu16(RGs, _mm_and_si128(t1, mask));
2509
+ GRs = _mm_adds_epu16(GRs, _mm_and_si128(_mm_merge_epi16(t0, _mm_adds_epu16(x2,x4)), mask));
2510
+ Bs = _mm_adds_epu16(Bs, _mm_and_si128(_mm_merge_epi16(_mm_adds_epu16(x1,x5), t0), mask));
2511
+
2512
+ // gradNE
2513
+ mask = _mm_cmpgt_epi16(T, gradNE);
2514
+ ng = _mm_sub_epi16(ng, mask);
2515
+
2516
+ t0 = _mm_slli_epi16(x5, 1);
2517
+ t1 = _mm_adds_epu16(_mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow-bstep*2+2)), z), x0);
2518
+
2519
+ RGs = _mm_adds_epu16(RGs, _mm_and_si128(_mm_merge_epi16(t1, t0), mask));
2520
+ GRs = _mm_adds_epu16(GRs, _mm_and_si128(_mm_merge_epi16(_mm_loadu_si128((__m128i*)(brow0+N6+1)),
2521
+ _mm_adds_epu16(x4,x7)), mask));
2522
+ Bs = _mm_adds_epu16(Bs, _mm_and_si128(_mm_merge_epi16(t0,_mm_adds_epu16(x3,x6)), mask));
2523
+
2524
+ // gradE
2525
+ mask = _mm_cmpgt_epi16(T, gradE);
2526
+ ng = _mm_sub_epi16(ng, mask);
2527
+
2528
+ t0 = _mm_slli_epi16(x7, 1);
2529
+ t1 = _mm_adds_epu16(_mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow+2)), z), x0);
2530
+
2531
+ RGs = _mm_adds_epu16(RGs, _mm_and_si128(t1, mask));
2532
+ GRs = _mm_adds_epu16(GRs, _mm_and_si128(t0, mask));
2533
+ Bs = _mm_adds_epu16(Bs, _mm_and_si128(_mm_merge_epi16(_mm_adds_epu16(x5,x9),
2534
+ _mm_adds_epu16(x6,x8)), mask));
2535
+
2536
+ // gradSE
2537
+ mask = _mm_cmpgt_epi16(T, gradSE);
2538
+ ng = _mm_sub_epi16(ng, mask);
2539
+
2540
+ t0 = _mm_slli_epi16(x9, 1);
2541
+ t1 = _mm_adds_epu16(_mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow+bstep*2+2)), z), x0);
2542
+
2543
+ RGs = _mm_adds_epu16(RGs, _mm_and_si128(_mm_merge_epi16(t1, t0), mask));
2544
+ GRs = _mm_adds_epu16(GRs, _mm_and_si128(_mm_merge_epi16(_mm_loadu_si128((__m128i*)(brow2+N6+1)),
2545
+ _mm_adds_epu16(x7,x10)), mask));
2546
+ Bs = _mm_adds_epu16(Bs, _mm_and_si128(_mm_merge_epi16(t0, _mm_adds_epu16(x8,x11)), mask));
2547
+
2548
+ // gradS
2549
+ mask = _mm_cmpgt_epi16(T, gradS);
2550
+ ng = _mm_sub_epi16(ng, mask);
2551
+
2552
+ t0 = _mm_slli_epi16(x11, 1);
2553
+ t1 = _mm_adds_epu16(_mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow+bstep*2)), z), x0);
2554
+
2555
+ RGs = _mm_adds_epu16(RGs, _mm_and_si128(t1, mask));
2556
+ GRs = _mm_adds_epu16(GRs, _mm_and_si128(_mm_merge_epi16(t0, _mm_adds_epu16(x10,x12)), mask));
2557
+ Bs = _mm_adds_epu16(Bs, _mm_and_si128(_mm_merge_epi16(_mm_adds_epu16(x9,x13), t0), mask));
2558
+
2559
+ // gradSW
2560
+ mask = _mm_cmpgt_epi16(T, gradSW);
2561
+ ng = _mm_sub_epi16(ng, mask);
2562
+
2563
+ t0 = _mm_slli_epi16(x13, 1);
2564
+ t1 = _mm_adds_epu16(_mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow+bstep*2-2)), z), x0);
2565
+
2566
+ RGs = _mm_adds_epu16(RGs, _mm_and_si128(_mm_merge_epi16(t1, t0), mask));
2567
+ GRs = _mm_adds_epu16(GRs, _mm_and_si128(_mm_merge_epi16(_mm_loadu_si128((__m128i*)(brow2+N6-1)),
2568
+ _mm_adds_epu16(x12,x15)), mask));
2569
+ Bs = _mm_adds_epu16(Bs, _mm_and_si128(_mm_merge_epi16(t0,_mm_adds_epu16(x11,x14)), mask));
2570
+
2571
+ // gradW
2572
+ mask = _mm_cmpgt_epi16(T, gradW);
2573
+ ng = _mm_sub_epi16(ng, mask);
2574
+
2575
+ t0 = _mm_slli_epi16(x15, 1);
2576
+ t1 = _mm_adds_epu16(_mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow-2)), z), x0);
2577
+
2578
+ RGs = _mm_adds_epu16(RGs, _mm_and_si128(t1, mask));
2579
+ GRs = _mm_adds_epu16(GRs, _mm_and_si128(t0, mask));
2580
+ Bs = _mm_adds_epu16(Bs, _mm_and_si128(_mm_merge_epi16(_mm_adds_epu16(x1,x13),
2581
+ _mm_adds_epu16(x14,x16)), mask));
2582
+
2583
+ // gradNW
2584
+ mask = _mm_cmpgt_epi16(T, gradNW);
2585
+ ng = _mm_max_epi16(_mm_sub_epi16(ng, mask), all_ones);
2586
+
2587
+ __m128 ngf0, ngf1;
2588
+ ngf0 = _mm_div_ps(_0_5, _mm_cvtloepi16_ps(ng));
2589
+ ngf1 = _mm_div_ps(_0_5, _mm_cvthiepi16_ps(ng));
2590
+
2591
+ t0 = _mm_slli_epi16(x1, 1);
2592
+ t1 = _mm_adds_epu16(_mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow-bstep*2-2)), z), x0);
2593
+
2594
+ RGs = _mm_adds_epu16(RGs, _mm_and_si128(_mm_merge_epi16(t1, t0), mask));
2595
+ GRs = _mm_adds_epu16(GRs, _mm_and_si128(_mm_merge_epi16(_mm_loadu_si128((__m128i*)(brow0+N6-1)),
2596
+ _mm_adds_epu16(x2,x15)), mask));
2597
+ Bs = _mm_adds_epu16(Bs, _mm_and_si128(_mm_merge_epi16(t0,_mm_adds_epu16(x3,x16)), mask));
2598
+
2599
+ // now interpolate r, g & b
2600
+ t0 = _mm_sub_epi16(GRs, RGs);
2601
+ t1 = _mm_sub_epi16(Bs, RGs);
2602
+
2603
+ t0 = _mm_add_epi16(x0, _mm_packs_epi32(
2604
+ _mm_cvtps_epi32(_mm_mul_ps(_mm_cvtloepi16_ps(t0), ngf0)),
2605
+ _mm_cvtps_epi32(_mm_mul_ps(_mm_cvthiepi16_ps(t0), ngf1))));
2606
+
2607
+ t1 = _mm_add_epi16(x0, _mm_packs_epi32(
2608
+ _mm_cvtps_epi32(_mm_mul_ps(_mm_cvtloepi16_ps(t1), ngf0)),
2609
+ _mm_cvtps_epi32(_mm_mul_ps(_mm_cvthiepi16_ps(t1), ngf1))));
2610
+
2611
+ x1 = _mm_merge_epi16(x0, t0);
2612
+ x2 = _mm_merge_epi16(t0, x0);
2613
+
2614
+ uchar R[8], G[8], B[8];
2615
+
2616
+ _mm_storel_epi64(blueIdx ? (__m128i*)B : (__m128i*)R, _mm_packus_epi16(x1, z));
2617
+ _mm_storel_epi64((__m128i*)G, _mm_packus_epi16(x2, z));
2618
+ _mm_storel_epi64(blueIdx ? (__m128i*)R : (__m128i*)B, _mm_packus_epi16(t1, z));
2619
+
2620
+ for( int j = 0; j < 8; j++, dstrow += 3 )
2621
+ {
2622
+ dstrow[0] = B[j]; dstrow[1] = G[j]; dstrow[2] = R[j];
2623
+ }
2624
+ }
2625
+ #endif
2626
+
2627
+ limit = N - 2;
2628
+ }
2629
+ while( i < N - 2 );
2630
+
2631
+ for( i = 0; i < 6; i++ )
2632
+ {
2633
+ dst[dststep*y + 5 - i] = dst[dststep*y + 8 - i];
2634
+ dst[dststep*y + (N - 2)*3 + i] = dst[dststep*y + (N - 3)*3 + i];
2635
+ }
2636
+
2637
+ greenCell0 = !greenCell0;
2638
+ blueIdx ^= 2;
2639
+ }
2640
+
2641
+ for( i = 0; i < size.width*3; i++ )
2642
+ {
2643
+ dst[i] = dst[i + dststep] = dst[i + dststep*2];
2644
+ dst[i + dststep*(size.height-4)] =
2645
+ dst[i + dststep*(size.height-3)] =
2646
+ dst[i + dststep*(size.height-2)] =
2647
+ dst[i + dststep*(size.height-1)] = dst[i + dststep*(size.height-5)];
2648
+ }
2649
+ }
2650
+
2651
+ ///////////////////////////////////// YUV420 -> RGB /////////////////////////////////////
2652
+
2653
+ template<int R, int SPorI>
2654
+ struct YUV4202BGR888Invoker
2655
+ {
2656
+ Mat* dst;
2657
+ const uchar* my1, *muv;
2658
+ int width;
2659
+
2660
+ YUV4202BGR888Invoker(Mat& _dst, int _width, const uchar* _y1, const uchar* _uv)
2661
+ : dst(&_dst), my1(_y1), muv(_uv), width(_width) {}
2662
+
2663
+ void operator()(const BlockedRange& range) const
2664
+ {
2665
+ //B = 1.164(Y - 16) + 2.018(U - 128)
2666
+ //G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128)
2667
+ //R = 1.164(Y - 16) + 1.596(V - 128)
2668
+
2669
+ const uchar* y1 = my1 + range.begin() * width, *uv = muv + range.begin() * width / 2;
2670
+
2671
+ for (int j = range.begin(); j < range.end(); j+=2, y1+=width*2, uv+=width)
2672
+ {
2673
+ uchar* row1 = dst->ptr<uchar>(j);
2674
+ uchar* row2 = dst->ptr<uchar>(j+1);
2675
+ const uchar* y2 = y1 + width;
2676
+
2677
+ for(int i = 0; i < width; i+=2,row1+=6,row2+=6)
2678
+ {
2679
+ int cr = uv[i + SPorI + 0] - 128;
2680
+ int cb = uv[i - SPorI + 1] - 128;
2681
+
2682
+ int ruv = 409 * cr + 128;
2683
+ int guv = 128 - 100 * cb - 208 * cr;
2684
+ int buv = 516 * cb + 128;
2685
+
2686
+ int y00 = (y1[i] - 16) * 298;
2687
+ row1[0+R] = saturate_cast<uchar>((y00 + buv) >> 8);
2688
+ row1[1] = saturate_cast<uchar>((y00 + guv) >> 8);
2689
+ row1[2-R] = saturate_cast<uchar>((y00 + ruv) >> 8);
2690
+
2691
+ int y01 = (y1[i+1] - 16) * 298;
2692
+ row1[3+R] = saturate_cast<uchar>((y01 + buv) >> 8);
2693
+ row1[4] = saturate_cast<uchar>((y01 + guv) >> 8);
2694
+ row1[5-R] = saturate_cast<uchar>((y01 + ruv) >> 8);
2695
+
2696
+ int y10 = (y2[i] - 16) * 298;
2697
+ row2[0+R] = saturate_cast<uchar>((y10 + buv) >> 8);
2698
+ row2[1] = saturate_cast<uchar>((y10 + guv) >> 8);
2699
+ row2[2-R] = saturate_cast<uchar>((y10 + ruv) >> 8);
2700
+
2701
+ int y11 = (y2[i+1] - 16) * 298;
2702
+ row2[3+R] = saturate_cast<uchar>((y11 + buv) >> 8);
2703
+ row2[4] = saturate_cast<uchar>((y11 + guv) >> 8);
2704
+ row2[5-R] = saturate_cast<uchar>((y11 + ruv) >> 8);
2705
+ }
2706
+ }
2707
+ }
2708
+ };
2709
+
2710
+ template<int R, int SPorI>
2711
+ struct YUV4202BGRA8888Invoker
2712
+ {
2713
+ Mat* dst;
2714
+ const uchar* my1, *muv;
2715
+ int width;
2716
+
2717
+ YUV4202BGRA8888Invoker(Mat& _dst, int _width, const uchar* _y1, const uchar* _uv)
2718
+ : dst(&_dst), my1(_y1), muv(_uv), width(_width) {}
2719
+
2720
+ void operator()(const BlockedRange& range) const
2721
+ {
2722
+ //B = 1.164(Y - 16) + 2.018(U - 128)
2723
+ //G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128)
2724
+ //R = 1.164(Y - 16) + 1.596(V - 128)
2725
+
2726
+ const uchar* y1 = my1 + range.begin() * width, *uv = muv + range.begin() * width / 2;
2727
+
2728
+ for (int j = range.begin(); j < range.end(); j+=2, y1+=width*2, uv+=width)
2729
+ {
2730
+ uchar* row1 = dst->ptr<uchar>(j);
2731
+ uchar* row2 = dst->ptr<uchar>(j+1);
2732
+ const uchar* y2 = y1 + width;
2733
+
2734
+ for(int i = 0; i < width; i+=2,row1+=8,row2+=8)
2735
+ {
2736
+ int cr = uv[i + SPorI + 0] - 128;
2737
+ int cb = uv[i - SPorI + 1] - 128;
2738
+
2739
+ int ruv = 409 * cr + 128;
2740
+ int guv = 128 - 100 * cb - 208 * cr;
2741
+ int buv = 516 * cb + 128;
2742
+
2743
+ int y00 = (y1[i] - 16) * 298;
2744
+ row1[0+R] = saturate_cast<uchar>((y00 + buv) >> 8);
2745
+ row1[1] = saturate_cast<uchar>((y00 + guv) >> 8);
2746
+ row1[2-R] = saturate_cast<uchar>((y00 + ruv) >> 8);
2747
+ row1[3] = (uchar)0xff;
2748
+
2749
+ int y01 = (y1[i+1] - 16) * 298;
2750
+ row1[4+R] = saturate_cast<uchar>((y01 + buv) >> 8);
2751
+ row1[5] = saturate_cast<uchar>((y01 + guv) >> 8);
2752
+ row1[6-R] = saturate_cast<uchar>((y01 + ruv) >> 8);
2753
+ row1[7] = (uchar)0xff;
2754
+
2755
+ int y10 = (y2[i] - 16) * 298;
2756
+ row2[0+R] = saturate_cast<uchar>((y10 + buv) >> 8);
2757
+ row2[1] = saturate_cast<uchar>((y10 + guv) >> 8);
2758
+ row2[2-R] = saturate_cast<uchar>((y10 + ruv) >> 8);
2759
+ row2[3] = (uchar)0xff;
2760
+
2761
+ int y11 = (y2[i+1] - 16) * 298;
2762
+ row2[4+R] = saturate_cast<uchar>((y11 + buv) >> 8);
2763
+ row2[5] = saturate_cast<uchar>((y11 + guv) >> 8);
2764
+ row2[6-R] = saturate_cast<uchar>((y11 + ruv) >> 8);
2765
+ row2[7] = (uchar)0xff;
2766
+ }
2767
+ }
2768
+ }
2769
+ };
2770
+
2771
+ }//namespace cv
2772
+
2773
+ //////////////////////////////////////////////////////////////////////////////////////////
2774
+ // The main function //
2775
+ //////////////////////////////////////////////////////////////////////////////////////////
2776
+
2777
+ void cv::cvtColor( InputArray _src, OutputArray _dst, int code, int dcn )
2778
+ {
2779
+ Mat src = _src.getMat(), dst;
2780
+ Size sz = src.size();
2781
+ int scn = src.channels(), depth = src.depth(), bidx;
2782
+
2783
+ CV_Assert( depth == CV_8U || depth == CV_16U || depth == CV_32F );
2784
+
2785
+ switch( code )
2786
+ {
2787
+ case CV_BGR2BGRA: case CV_RGB2BGRA: case CV_BGRA2BGR:
2788
+ case CV_RGBA2BGR: case CV_RGB2BGR: case CV_BGRA2RGBA:
2789
+ CV_Assert( scn == 3 || scn == 4 );
2790
+ dcn = code == CV_BGR2BGRA || code == CV_RGB2BGRA || code == CV_BGRA2RGBA ? 4 : 3;
2791
+ bidx = code == CV_BGR2BGRA || code == CV_BGRA2BGR ? 0 : 2;
2792
+
2793
+ _dst.create( sz, CV_MAKETYPE(depth, dcn));
2794
+ dst = _dst.getMat();
2795
+
2796
+ if( depth == CV_8U )
2797
+ CvtColorLoop(src, dst, RGB2RGB<uchar>(scn, dcn, bidx));
2798
+ else if( depth == CV_16U )
2799
+ CvtColorLoop(src, dst, RGB2RGB<ushort>(scn, dcn, bidx));
2800
+ else
2801
+ CvtColorLoop(src, dst, RGB2RGB<float>(scn, dcn, bidx));
2802
+ break;
2803
+
2804
+ case CV_BGR2BGR565: case CV_BGR2BGR555: case CV_RGB2BGR565: case CV_RGB2BGR555:
2805
+ case CV_BGRA2BGR565: case CV_BGRA2BGR555: case CV_RGBA2BGR565: case CV_RGBA2BGR555:
2806
+ CV_Assert( (scn == 3 || scn == 4) && depth == CV_8U );
2807
+ _dst.create(sz, CV_8UC2);
2808
+ dst = _dst.getMat();
2809
+
2810
+ CvtColorLoop(src, dst, RGB2RGB5x5(scn,
2811
+ code == CV_BGR2BGR565 || code == CV_BGR2BGR555 ||
2812
+ code == CV_BGRA2BGR565 || code == CV_BGRA2BGR555 ? 0 : 2,
2813
+ code == CV_BGR2BGR565 || code == CV_RGB2BGR565 ||
2814
+ code == CV_BGRA2BGR565 || code == CV_RGBA2BGR565 ? 6 : 5 // green bits
2815
+ ));
2816
+ break;
2817
+
2818
+ case CV_BGR5652BGR: case CV_BGR5552BGR: case CV_BGR5652RGB: case CV_BGR5552RGB:
2819
+ case CV_BGR5652BGRA: case CV_BGR5552BGRA: case CV_BGR5652RGBA: case CV_BGR5552RGBA:
2820
+ if(dcn <= 0) dcn = 3;
2821
+ CV_Assert( (dcn == 3 || dcn == 4) && scn == 2 && depth == CV_8U );
2822
+ _dst.create(sz, CV_MAKETYPE(depth, dcn));
2823
+ dst = _dst.getMat();
2824
+
2825
+ CvtColorLoop(src, dst, RGB5x52RGB(dcn,
2826
+ code == CV_BGR5652BGR || code == CV_BGR5552BGR ||
2827
+ code == CV_BGR5652BGRA || code == CV_BGR5552BGRA ? 0 : 2, // blue idx
2828
+ code == CV_BGR5652BGR || code == CV_BGR5652RGB ||
2829
+ code == CV_BGR5652BGRA || code == CV_BGR5652RGBA ? 6 : 5 // green bits
2830
+ ));
2831
+ break;
2832
+
2833
+ case CV_BGR2GRAY: case CV_BGRA2GRAY: case CV_RGB2GRAY: case CV_RGBA2GRAY:
2834
+ CV_Assert( scn == 3 || scn == 4 );
2835
+ _dst.create(sz, CV_MAKETYPE(depth, 1));
2836
+ dst = _dst.getMat();
2837
+
2838
+ bidx = code == CV_BGR2GRAY || code == CV_BGRA2GRAY ? 0 : 2;
2839
+
2840
+ if( depth == CV_8U )
2841
+ CvtColorLoop(src, dst, RGB2Gray<uchar>(scn, bidx, 0));
2842
+ else if( depth == CV_16U )
2843
+ CvtColorLoop(src, dst, RGB2Gray<ushort>(scn, bidx, 0));
2844
+ else
2845
+ CvtColorLoop(src, dst, RGB2Gray<float>(scn, bidx, 0));
2846
+ break;
2847
+
2848
+ case CV_BGR5652GRAY: case CV_BGR5552GRAY:
2849
+ CV_Assert( scn == 2 && depth == CV_8U );
2850
+ _dst.create(sz, CV_8UC1);
2851
+ dst = _dst.getMat();
2852
+
2853
+ CvtColorLoop(src, dst, RGB5x52Gray(code == CV_BGR5652GRAY ? 6 : 5));
2854
+ break;
2855
+
2856
+ case CV_GRAY2BGR: case CV_GRAY2BGRA:
2857
+ if( dcn <= 0 ) dcn = 3;
2858
+ CV_Assert( scn == 1 && (dcn == 3 || dcn == 4));
2859
+ _dst.create(sz, CV_MAKETYPE(depth, dcn));
2860
+ dst = _dst.getMat();
2861
+
2862
+ if( depth == CV_8U )
2863
+ CvtColorLoop(src, dst, Gray2RGB<uchar>(dcn));
2864
+ else if( depth == CV_16U )
2865
+ CvtColorLoop(src, dst, Gray2RGB<ushort>(dcn));
2866
+ else
2867
+ CvtColorLoop(src, dst, Gray2RGB<float>(dcn));
2868
+ break;
2869
+
2870
+ case CV_GRAY2BGR565: case CV_GRAY2BGR555:
2871
+ CV_Assert( scn == 1 && depth == CV_8U );
2872
+ _dst.create(sz, CV_8UC2);
2873
+ dst = _dst.getMat();
2874
+
2875
+ CvtColorLoop(src, dst, Gray2RGB5x5(code == CV_GRAY2BGR565 ? 6 : 5));
2876
+ break;
2877
+
2878
+ case CV_BGR2YCrCb: case CV_RGB2YCrCb:
2879
+ case CV_BGR2YUV: case CV_RGB2YUV:
2880
+ {
2881
+ CV_Assert( scn == 3 || scn == 4 );
2882
+ bidx = code == CV_BGR2YCrCb || code == CV_RGB2YUV ? 0 : 2;
2883
+ static const float yuv_f[] = { 0.114f, 0.587f, 0.299f, 0.492f, 0.877f };
2884
+ static const int yuv_i[] = { B2Y, G2Y, R2Y, 8061, 14369 };
2885
+ const float* coeffs_f = code == CV_BGR2YCrCb || code == CV_RGB2YCrCb ? 0 : yuv_f;
2886
+ const int* coeffs_i = code == CV_BGR2YCrCb || code == CV_RGB2YCrCb ? 0 : yuv_i;
2887
+
2888
+ _dst.create(sz, CV_MAKETYPE(depth, 3));
2889
+ dst = _dst.getMat();
2890
+
2891
+ if( depth == CV_8U )
2892
+ CvtColorLoop(src, dst, RGB2YCrCb_i<uchar>(scn, bidx, coeffs_i));
2893
+ else if( depth == CV_16U )
2894
+ CvtColorLoop(src, dst, RGB2YCrCb_i<ushort>(scn, bidx, coeffs_i));
2895
+ else
2896
+ CvtColorLoop(src, dst, RGB2YCrCb_f<float>(scn, bidx, coeffs_f));
2897
+ }
2898
+ break;
2899
+
2900
+ case CV_YCrCb2BGR: case CV_YCrCb2RGB:
2901
+ case CV_YUV2BGR: case CV_YUV2RGB:
2902
+ {
2903
+ if( dcn <= 0 ) dcn = 3;
2904
+ CV_Assert( scn == 3 && (dcn == 3 || dcn == 4) );
2905
+ bidx = code == CV_YCrCb2BGR || code == CV_YUV2RGB ? 0 : 2;
2906
+ static const float yuv_f[] = { 2.032f, -0.395f, -0.581f, 1.140f };
2907
+ static const int yuv_i[] = { 33292, -6472, -9519, 18678 };
2908
+ const float* coeffs_f = code == CV_YCrCb2BGR || code == CV_YCrCb2RGB ? 0 : yuv_f;
2909
+ const int* coeffs_i = code == CV_YCrCb2BGR || code == CV_YCrCb2RGB ? 0 : yuv_i;
2910
+
2911
+ _dst.create(sz, CV_MAKETYPE(depth, dcn));
2912
+ dst = _dst.getMat();
2913
+
2914
+ if( depth == CV_8U )
2915
+ CvtColorLoop(src, dst, YCrCb2RGB_i<uchar>(dcn, bidx, coeffs_i));
2916
+ else if( depth == CV_16U )
2917
+ CvtColorLoop(src, dst, YCrCb2RGB_i<ushort>(dcn, bidx, coeffs_i));
2918
+ else
2919
+ CvtColorLoop(src, dst, YCrCb2RGB_f<float>(dcn, bidx, coeffs_f));
2920
+ }
2921
+ break;
2922
+
2923
+ case CV_BGR2XYZ: case CV_RGB2XYZ:
2924
+ CV_Assert( scn == 3 || scn == 4 );
2925
+ bidx = code == CV_BGR2XYZ ? 0 : 2;
2926
+
2927
+ _dst.create(sz, CV_MAKETYPE(depth, 3));
2928
+ dst = _dst.getMat();
2929
+
2930
+ if( depth == CV_8U )
2931
+ CvtColorLoop(src, dst, RGB2XYZ_i<uchar>(scn, bidx, 0));
2932
+ else if( depth == CV_16U )
2933
+ CvtColorLoop(src, dst, RGB2XYZ_i<ushort>(scn, bidx, 0));
2934
+ else
2935
+ CvtColorLoop(src, dst, RGB2XYZ_f<float>(scn, bidx, 0));
2936
+ break;
2937
+
2938
+ case CV_XYZ2BGR: case CV_XYZ2RGB:
2939
+ if( dcn <= 0 ) dcn = 3;
2940
+ CV_Assert( scn == 3 && (dcn == 3 || dcn == 4) );
2941
+ bidx = code == CV_XYZ2BGR ? 0 : 2;
2942
+
2943
+ _dst.create(sz, CV_MAKETYPE(depth, dcn));
2944
+ dst = _dst.getMat();
2945
+
2946
+ if( depth == CV_8U )
2947
+ CvtColorLoop(src, dst, XYZ2RGB_i<uchar>(dcn, bidx, 0));
2948
+ else if( depth == CV_16U )
2949
+ CvtColorLoop(src, dst, XYZ2RGB_i<ushort>(dcn, bidx, 0));
2950
+ else
2951
+ CvtColorLoop(src, dst, XYZ2RGB_f<float>(dcn, bidx, 0));
2952
+ break;
2953
+
2954
+ case CV_BGR2HSV: case CV_RGB2HSV: case CV_BGR2HSV_FULL: case CV_RGB2HSV_FULL:
2955
+ case CV_BGR2HLS: case CV_RGB2HLS: case CV_BGR2HLS_FULL: case CV_RGB2HLS_FULL:
2956
+ {
2957
+ CV_Assert( (scn == 3 || scn == 4) && (depth == CV_8U || depth == CV_32F) );
2958
+ bidx = code == CV_BGR2HSV || code == CV_BGR2HLS ||
2959
+ code == CV_BGR2HSV_FULL || code == CV_BGR2HLS_FULL ? 0 : 2;
2960
+ int hrange = depth == CV_32F ? 360 : code == CV_BGR2HSV || code == CV_RGB2HSV ||
2961
+ code == CV_BGR2HLS || code == CV_RGB2HLS ? 180 : 256;
2962
+
2963
+ _dst.create(sz, CV_MAKETYPE(depth, 3));
2964
+ dst = _dst.getMat();
2965
+
2966
+ if( code == CV_BGR2HSV || code == CV_RGB2HSV ||
2967
+ code == CV_BGR2HSV_FULL || code == CV_RGB2HSV_FULL )
2968
+ {
2969
+ if( depth == CV_8U )
2970
+ CvtColorLoop(src, dst, RGB2HSV_b(scn, bidx, hrange));
2971
+ else
2972
+ CvtColorLoop(src, dst, RGB2HSV_f(scn, bidx, (float)hrange));
2973
+ }
2974
+ else
2975
+ {
2976
+ if( depth == CV_8U )
2977
+ CvtColorLoop(src, dst, RGB2HLS_b(scn, bidx, hrange));
2978
+ else
2979
+ CvtColorLoop(src, dst, RGB2HLS_f(scn, bidx, (float)hrange));
2980
+ }
2981
+ }
2982
+ break;
2983
+
2984
+ case CV_HSV2BGR: case CV_HSV2RGB: case CV_HSV2BGR_FULL: case CV_HSV2RGB_FULL:
2985
+ case CV_HLS2BGR: case CV_HLS2RGB: case CV_HLS2BGR_FULL: case CV_HLS2RGB_FULL:
2986
+ {
2987
+ if( dcn <= 0 ) dcn = 3;
2988
+ CV_Assert( scn == 3 && (dcn == 3 || dcn == 4) && (depth == CV_8U || depth == CV_32F) );
2989
+ bidx = code == CV_HSV2BGR || code == CV_HLS2BGR ||
2990
+ code == CV_HSV2BGR_FULL || code == CV_HLS2BGR_FULL ? 0 : 2;
2991
+ int hrange = depth == CV_32F ? 360 : code == CV_HSV2BGR || code == CV_HSV2RGB ||
2992
+ code == CV_HLS2BGR || code == CV_HLS2RGB ? 180 : 255;
2993
+
2994
+ _dst.create(sz, CV_MAKETYPE(depth, dcn));
2995
+ dst = _dst.getMat();
2996
+
2997
+ if( code == CV_HSV2BGR || code == CV_HSV2RGB ||
2998
+ code == CV_HSV2BGR_FULL || code == CV_HSV2RGB_FULL )
2999
+ {
3000
+ if( depth == CV_8U )
3001
+ CvtColorLoop(src, dst, HSV2RGB_b(dcn, bidx, hrange));
3002
+ else
3003
+ CvtColorLoop(src, dst, HSV2RGB_f(dcn, bidx, (float)hrange));
3004
+ }
3005
+ else
3006
+ {
3007
+ if( depth == CV_8U )
3008
+ CvtColorLoop(src, dst, HLS2RGB_b(dcn, bidx, hrange));
3009
+ else
3010
+ CvtColorLoop(src, dst, HLS2RGB_f(dcn, bidx, (float)hrange));
3011
+ }
3012
+ }
3013
+ break;
3014
+
3015
+ case CV_BGR2Lab: case CV_RGB2Lab: case CV_LBGR2Lab: case CV_LRGB2Lab:
3016
+ case CV_BGR2Luv: case CV_RGB2Luv: case CV_LBGR2Luv: case CV_LRGB2Luv:
3017
+ {
3018
+ CV_Assert( (scn == 3 || scn == 4) && (depth == CV_8U || depth == CV_32F) );
3019
+ bidx = code == CV_BGR2Lab || code == CV_BGR2Luv ||
3020
+ code == CV_LBGR2Lab || code == CV_LBGR2Luv ? 0 : 2;
3021
+ bool srgb = code == CV_BGR2Lab || code == CV_RGB2Lab ||
3022
+ code == CV_BGR2Luv || code == CV_RGB2Luv;
3023
+
3024
+ _dst.create(sz, CV_MAKETYPE(depth, 3));
3025
+ dst = _dst.getMat();
3026
+
3027
+ if( code == CV_BGR2Lab || code == CV_RGB2Lab ||
3028
+ code == CV_LBGR2Lab || code == CV_LRGB2Lab )
3029
+ {
3030
+ if( depth == CV_8U )
3031
+ CvtColorLoop(src, dst, RGB2Lab_b(scn, bidx, 0, 0, srgb));
3032
+ else
3033
+ CvtColorLoop(src, dst, RGB2Lab_f(scn, bidx, 0, 0, srgb));
3034
+ }
3035
+ else
3036
+ {
3037
+ if( depth == CV_8U )
3038
+ CvtColorLoop(src, dst, RGB2Luv_b(scn, bidx, 0, 0, srgb));
3039
+ else
3040
+ CvtColorLoop(src, dst, RGB2Luv_f(scn, bidx, 0, 0, srgb));
3041
+ }
3042
+ }
3043
+ break;
3044
+
3045
+ case CV_Lab2BGR: case CV_Lab2RGB: case CV_Lab2LBGR: case CV_Lab2LRGB:
3046
+ case CV_Luv2BGR: case CV_Luv2RGB: case CV_Luv2LBGR: case CV_Luv2LRGB:
3047
+ {
3048
+ if( dcn <= 0 ) dcn = 3;
3049
+ CV_Assert( scn == 3 && (dcn == 3 || dcn == 4) && (depth == CV_8U || depth == CV_32F) );
3050
+ bidx = code == CV_Lab2BGR || code == CV_Luv2BGR ||
3051
+ code == CV_Lab2LBGR || code == CV_Luv2LBGR ? 0 : 2;
3052
+ bool srgb = code == CV_Lab2BGR || code == CV_Lab2RGB ||
3053
+ code == CV_Luv2BGR || code == CV_Luv2RGB;
3054
+
3055
+ _dst.create(sz, CV_MAKETYPE(depth, dcn));
3056
+ dst = _dst.getMat();
3057
+
3058
+ if( code == CV_Lab2BGR || code == CV_Lab2RGB ||
3059
+ code == CV_Lab2LBGR || code == CV_Lab2LRGB )
3060
+ {
3061
+ if( depth == CV_8U )
3062
+ CvtColorLoop(src, dst, Lab2RGB_b(dcn, bidx, 0, 0, srgb));
3063
+ else
3064
+ CvtColorLoop(src, dst, Lab2RGB_f(dcn, bidx, 0, 0, srgb));
3065
+ }
3066
+ else
3067
+ {
3068
+ if( depth == CV_8U )
3069
+ CvtColorLoop(src, dst, Luv2RGB_b(dcn, bidx, 0, 0, srgb));
3070
+ else
3071
+ CvtColorLoop(src, dst, Luv2RGB_f(dcn, bidx, 0, 0, srgb));
3072
+ }
3073
+ }
3074
+ break;
3075
+
3076
+ case CV_BayerBG2GRAY: case CV_BayerGB2GRAY: case CV_BayerRG2GRAY: case CV_BayerGR2GRAY:
3077
+ if(dcn <= 0) dcn = 1;
3078
+ CV_Assert( scn == 1 && dcn == 1 );
3079
+
3080
+ _dst.create(sz, depth);
3081
+ dst = _dst.getMat();
3082
+
3083
+ if( depth == CV_8U )
3084
+ Bayer2Gray_<uchar, SIMDBayerInterpolator_8u>(src, dst, code);
3085
+ else if( depth == CV_16U )
3086
+ Bayer2Gray_<ushort, SIMDBayerStubInterpolator_<ushort> >(src, dst, code);
3087
+ else
3088
+ CV_Error(CV_StsUnsupportedFormat, "Bayer->Gray demosaicing only supports 8u and 16u types");
3089
+ break;
3090
+
3091
+ case CV_BayerBG2BGR: case CV_BayerGB2BGR: case CV_BayerRG2BGR: case CV_BayerGR2BGR:
3092
+ case CV_BayerBG2BGR_VNG: case CV_BayerGB2BGR_VNG: case CV_BayerRG2BGR_VNG: case CV_BayerGR2BGR_VNG:
3093
+ if(dcn <= 0) dcn = 3;
3094
+ CV_Assert( scn == 1 && dcn == 3 );
3095
+
3096
+ _dst.create(sz, CV_MAKETYPE(depth, dcn));
3097
+ dst = _dst.getMat();
3098
+
3099
+ if( code == CV_BayerBG2BGR || code == CV_BayerGB2BGR ||
3100
+ code == CV_BayerRG2BGR || code == CV_BayerGR2BGR )
3101
+ {
3102
+ if( depth == CV_8U )
3103
+ Bayer2RGB_<uchar, SIMDBayerInterpolator_8u>(src, dst, code);
3104
+ else if( depth == CV_16U )
3105
+ Bayer2RGB_<ushort, SIMDBayerStubInterpolator_<ushort> >(src, dst, code);
3106
+ else
3107
+ CV_Error(CV_StsUnsupportedFormat, "Bayer->RGB demosaicing only supports 8u and 16u types");
3108
+ }
3109
+ else
3110
+ {
3111
+ CV_Assert( depth == CV_8U );
3112
+ Bayer2RGB_VNG_8u(src, dst, code);
3113
+ }
3114
+ break;
3115
+ case CV_YUV420sp2BGR: case CV_YUV420sp2RGB: case CV_YUV420i2BGR: case CV_YUV420i2RGB:
3116
+ {
3117
+ if(dcn <= 0) dcn = 3;
3118
+ CV_Assert( dcn == 3 || dcn == 4 );
3119
+ CV_Assert( sz.width % 2 == 0 && sz.height % 3 == 0 && depth == CV_8U && src.isContinuous() );
3120
+
3121
+ Size dstSz(sz.width, sz.height * 2 / 3);
3122
+ _dst.create( dstSz, CV_MAKETYPE(depth, dcn));
3123
+ dst = _dst.getMat();
3124
+
3125
+ const uchar* y = src.ptr();
3126
+ const uchar* uv = y + dstSz.area();
3127
+
3128
+ #ifdef HAVE_TEGRA_OPTIMIZATION
3129
+ if (!tegra::YUV420i2BGR(y, uv, dst, CV_YUV420sp2RGB == code))
3130
+ #endif
3131
+ {
3132
+ if (CV_YUV420sp2RGB == code)
3133
+ {
3134
+ if (dcn == 3)
3135
+ parallel_for(BlockedRange(0, dstSz.height, 2), YUV4202BGR888Invoker<2,0>(dst, dstSz.width, y, uv));
3136
+ else
3137
+ parallel_for(BlockedRange(0, dstSz.height, 2), YUV4202BGRA8888Invoker<2,0>(dst, dstSz.width, y, uv));
3138
+ }
3139
+ else if (CV_YUV420sp2BGR == code)
3140
+ {
3141
+ if (dcn == 3)
3142
+ parallel_for(BlockedRange(0, dstSz.height, 2), YUV4202BGR888Invoker<0,0>(dst, dstSz.width, y, uv));
3143
+ else
3144
+ parallel_for(BlockedRange(0, dstSz.height, 2), YUV4202BGRA8888Invoker<0,0>(dst, dstSz.width, y, uv));
3145
+ }
3146
+ else if (CV_YUV420i2RGB == code)
3147
+ {
3148
+ if (dcn == 3)
3149
+ parallel_for(BlockedRange(0, dstSz.height, 2), YUV4202BGR888Invoker<2,1>(dst, dstSz.width, y, uv));
3150
+ else
3151
+ parallel_for(BlockedRange(0, dstSz.height, 2), YUV4202BGRA8888Invoker<2,1>(dst, dstSz.width, y, uv));
3152
+ }
3153
+ else if (CV_YUV420i2BGR == code)
3154
+ {
3155
+ if (dcn == 3)
3156
+ parallel_for(BlockedRange(0, dstSz.height, 2), YUV4202BGR888Invoker<0,1>(dst, dstSz.width, y, uv));
3157
+ else
3158
+ parallel_for(BlockedRange(0, dstSz.height, 2), YUV4202BGRA8888Invoker<0,1>(dst, dstSz.width, y, uv));
3159
+ }
3160
+ }
3161
+ }
3162
+ break;
3163
+ default:
3164
+ CV_Error( CV_StsBadFlag, "Unknown/unsupported color conversion code" );
3165
+ }
3166
+ }
3167
+
3168
+ CV_IMPL void
3169
+ cvCvtColor( const CvArr* srcarr, CvArr* dstarr, int code )
3170
+ {
3171
+ cv::Mat src = cv::cvarrToMat(srcarr), dst0 = cv::cvarrToMat(dstarr), dst = dst0;
3172
+ CV_Assert( src.depth() == dst.depth() );
3173
+
3174
+ cv::cvtColor(src, dst, code, dst.channels());
3175
+ CV_Assert( dst.data == dst0.data );
3176
+ }
3177
+
3178
+
3179
+ /* End of file. */