imagecore 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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. */