Update the changelog
[opencv] / cxcore / src / cxconvert.cpp
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 #include "_cxcore.h"
43
44 /****************************************************************************************\
45 *                            Splitting/extracting array channels                         *
46 \****************************************************************************************/
47
48 #define  ICV_DEF_PX2PL2PX_ENTRY_C2( arrtype_ptr, ptr )  \
49     arrtype_ptr plane0 = ptr[0];                        \
50     arrtype_ptr plane1 = ptr[1];
51
52 #define  ICV_DEF_PX2PL2PX_ENTRY_C3( arrtype_ptr, ptr )  \
53     arrtype_ptr plane0 = ptr[0];                        \
54     arrtype_ptr plane1 = ptr[1];                        \
55     arrtype_ptr plane2 = ptr[2];
56
57 #define  ICV_DEF_PX2PL2PX_ENTRY_C4( arrtype_ptr, ptr )  \
58     arrtype_ptr plane0 = ptr[0];                        \
59     arrtype_ptr plane1 = ptr[1];                        \
60     arrtype_ptr plane2 = ptr[2];                        \
61     arrtype_ptr plane3 = ptr[3];
62
63
64 #define  ICV_DEF_PX2PL_C2( arrtype, len )           \
65 {                                                   \
66     int j;                                          \
67                                                     \
68     for( j = 0; j < (len); j++, (src) += 2 )        \
69     {                                               \
70         arrtype t0 = (src)[0];                      \
71         arrtype t1 = (src)[1];                      \
72                                                     \
73         plane0[j] = t0;                             \
74         plane1[j] = t1;                             \
75     }                                               \
76     plane0 += dststep;                              \
77     plane1 += dststep;                              \
78 }
79
80
81 #define  ICV_DEF_PX2PL_C3( arrtype, len )           \
82 {                                                   \
83     int j;                                          \
84                                                     \
85     for( j = 0; j < (len); j++, (src) += 3 )        \
86     {                                               \
87         arrtype t0 = (src)[0];                      \
88         arrtype t1 = (src)[1];                      \
89         arrtype t2 = (src)[2];                      \
90                                                     \
91         plane0[j] = t0;                             \
92         plane1[j] = t1;                             \
93         plane2[j] = t2;                             \
94     }                                               \
95     plane0 += dststep;                              \
96     plane1 += dststep;                              \
97     plane2 += dststep;                              \
98 }
99
100
101 #define  ICV_DEF_PX2PL_C4( arrtype, len )           \
102 {                                                   \
103     int j;                                          \
104                                                     \
105     for( j = 0; j < (len); j++, (src) += 4 )        \
106     {                                               \
107         arrtype t0 = (src)[0];                      \
108         arrtype t1 = (src)[1];                      \
109                                                     \
110         plane0[j] = t0;                             \
111         plane1[j] = t1;                             \
112                                                     \
113         t0 = (src)[2];                              \
114         t1 = (src)[3];                              \
115                                                     \
116         plane2[j] = t0;                             \
117         plane3[j] = t1;                             \
118     }                                               \
119     plane0 += dststep;                              \
120     plane1 += dststep;                              \
121     plane2 += dststep;                              \
122     plane3 += dststep;                              \
123 }
124
125
126 #define  ICV_DEF_PX2PL_COI( arrtype, len, cn )      \
127 {                                                   \
128     int j;                                          \
129                                                     \
130     for( j = 0; j <= (len) - 4; j += 4, (src) += 4*(cn))\
131     {                                               \
132         arrtype t0 = (src)[0];                      \
133         arrtype t1 = (src)[(cn)];                   \
134                                                     \
135         (dst)[j] = t0;                              \
136         (dst)[j+1] = t1;                            \
137                                                     \
138         t0 = (src)[(cn)*2];                         \
139         t1 = (src)[(cn)*3];                         \
140                                                     \
141         (dst)[j+2] = t0;                            \
142         (dst)[j+3] = t1;                            \
143     }                                               \
144                                                     \
145     for( ; j < (len); j++, (src) += (cn))           \
146     {                                               \
147         (dst)[j] = (src)[0];                        \
148     }                                               \
149 }
150
151
152 #define  ICV_DEF_COPY_PX2PL_FUNC_2D( arrtype, flavor,   \
153                                      cn, entry_macro )  \
154 IPCVAPI_IMPL( CvStatus, icvCopy_##flavor##_C##cn##P##cn##R,\
155 ( const arrtype* src, int srcstep,                      \
156   arrtype** dst, int dststep, CvSize size ),            \
157   (src, srcstep, dst, dststep, size))                   \
158 {                                                       \
159     entry_macro(arrtype*, dst);                         \
160     srcstep /= sizeof(src[0]);                          \
161     dststep /= sizeof(dst[0][0]);                       \
162                                                         \
163     for( ; size.height--; src += srcstep )              \
164     {                                                   \
165         ICV_DEF_PX2PL_C##cn( arrtype, size.width );     \
166         src -= size.width*(cn);                         \
167     }                                                   \
168                                                         \
169     return CV_OK;                                       \
170 }
171
172
173 #define  ICV_DEF_COPY_PX2PL_FUNC_2D_COI( arrtype, flavor )\
174 IPCVAPI_IMPL( CvStatus, icvCopy_##flavor##_CnC1CR,      \
175 ( const arrtype* src, int srcstep, arrtype* dst, int dststep,\
176   CvSize size, int cn, int coi ),                       \
177   (src, srcstep, dst, dststep, size, cn, coi))          \
178 {                                                       \
179     src += coi - 1;                                     \
180     srcstep /= sizeof(src[0]);                          \
181     dststep /= sizeof(dst[0]);                          \
182                                                         \
183     for( ; size.height--; src += srcstep, dst += dststep )\
184     {                                                   \
185         ICV_DEF_PX2PL_COI( arrtype, size.width, cn );   \
186         src -= size.width*(cn);                         \
187     }                                                   \
188                                                         \
189     return CV_OK;                                       \
190 }
191
192
193 ICV_DEF_COPY_PX2PL_FUNC_2D( uchar, 8u, 2, ICV_DEF_PX2PL2PX_ENTRY_C2 )
194 ICV_DEF_COPY_PX2PL_FUNC_2D( uchar, 8u, 3, ICV_DEF_PX2PL2PX_ENTRY_C3 )
195 ICV_DEF_COPY_PX2PL_FUNC_2D( uchar, 8u, 4, ICV_DEF_PX2PL2PX_ENTRY_C4 )
196 ICV_DEF_COPY_PX2PL_FUNC_2D( ushort, 16s, 2, ICV_DEF_PX2PL2PX_ENTRY_C2 )
197 ICV_DEF_COPY_PX2PL_FUNC_2D( ushort, 16s, 3, ICV_DEF_PX2PL2PX_ENTRY_C3 )
198 ICV_DEF_COPY_PX2PL_FUNC_2D( ushort, 16s, 4, ICV_DEF_PX2PL2PX_ENTRY_C4 )
199 ICV_DEF_COPY_PX2PL_FUNC_2D( int, 32f, 2, ICV_DEF_PX2PL2PX_ENTRY_C2 )
200 ICV_DEF_COPY_PX2PL_FUNC_2D( int, 32f, 3, ICV_DEF_PX2PL2PX_ENTRY_C3 )
201 ICV_DEF_COPY_PX2PL_FUNC_2D( int, 32f, 4, ICV_DEF_PX2PL2PX_ENTRY_C4 )
202 ICV_DEF_COPY_PX2PL_FUNC_2D( int64, 64f, 2, ICV_DEF_PX2PL2PX_ENTRY_C2 )
203 ICV_DEF_COPY_PX2PL_FUNC_2D( int64, 64f, 3, ICV_DEF_PX2PL2PX_ENTRY_C3 )
204 ICV_DEF_COPY_PX2PL_FUNC_2D( int64, 64f, 4, ICV_DEF_PX2PL2PX_ENTRY_C4 )
205
206
207 ICV_DEF_COPY_PX2PL_FUNC_2D_COI( uchar, 8u )
208 ICV_DEF_COPY_PX2PL_FUNC_2D_COI( ushort, 16s )
209 ICV_DEF_COPY_PX2PL_FUNC_2D_COI( int, 32f )
210 ICV_DEF_COPY_PX2PL_FUNC_2D_COI( int64, 64f )
211
212
213 /****************************************************************************************\
214 *                            Merging/inserting array channels                            *
215 \****************************************************************************************/
216
217
218 #define  ICV_DEF_PL2PX_C2( arrtype, len )   \
219 {                                           \
220     int j;                                  \
221                                             \
222     for( j = 0; j < (len); j++, (dst) += 2 )\
223     {                                       \
224         arrtype t0 = plane0[j];             \
225         arrtype t1 = plane1[j];             \
226                                             \
227         dst[0] = t0;                        \
228         dst[1] = t1;                        \
229     }                                       \
230     plane0 += srcstep;                      \
231     plane1 += srcstep;                      \
232 }
233
234
235 #define  ICV_DEF_PL2PX_C3( arrtype, len )   \
236 {                                           \
237     int j;                                  \
238                                             \
239     for( j = 0; j < (len); j++, (dst) += 3 )\
240     {                                       \
241         arrtype t0 = plane0[j];             \
242         arrtype t1 = plane1[j];             \
243         arrtype t2 = plane2[j];             \
244                                             \
245         dst[0] = t0;                        \
246         dst[1] = t1;                        \
247         dst[2] = t2;                        \
248     }                                       \
249     plane0 += srcstep;                      \
250     plane1 += srcstep;                      \
251     plane2 += srcstep;                      \
252 }
253
254
255 #define  ICV_DEF_PL2PX_C4( arrtype, len )   \
256 {                                           \
257     int j;                                  \
258                                             \
259     for( j = 0; j < (len); j++, (dst) += 4 )\
260     {                                       \
261         arrtype t0 = plane0[j];             \
262         arrtype t1 = plane1[j];             \
263                                             \
264         dst[0] = t0;                        \
265         dst[1] = t1;                        \
266                                             \
267         t0 = plane2[j];                     \
268         t1 = plane3[j];                     \
269                                             \
270         dst[2] = t0;                        \
271         dst[3] = t1;                        \
272     }                                       \
273     plane0 += srcstep;                      \
274     plane1 += srcstep;                      \
275     plane2 += srcstep;                      \
276     plane3 += srcstep;                      \
277 }
278
279
280 #define  ICV_DEF_PL2PX_COI( arrtype, len, cn )          \
281 {                                                       \
282     int j;                                              \
283                                                         \
284     for( j = 0; j <= (len) - 4; j += 4, (dst) += 4*(cn))\
285     {                                                   \
286         arrtype t0 = (src)[j];                          \
287         arrtype t1 = (src)[j+1];                        \
288                                                         \
289         (dst)[0] = t0;                                  \
290         (dst)[(cn)] = t1;                               \
291                                                         \
292         t0 = (src)[j+2];                                \
293         t1 = (src)[j+3];                                \
294                                                         \
295         (dst)[(cn)*2] = t0;                             \
296         (dst)[(cn)*3] = t1;                             \
297     }                                                   \
298                                                         \
299     for( ; j < (len); j++, (dst) += (cn))               \
300     {                                                   \
301         (dst)[0] = (src)[j];                            \
302     }                                                   \
303 }
304
305
306 #define  ICV_DEF_COPY_PL2PX_FUNC_2D( arrtype, flavor, cn, entry_macro ) \
307 IPCVAPI_IMPL( CvStatus, icvCopy_##flavor##_P##cn##C##cn##R, \
308 ( const arrtype** src, int srcstep,                         \
309   arrtype* dst, int dststep, CvSize size ),                 \
310   (src, srcstep, dst, dststep, size))                       \
311 {                                                           \
312     entry_macro(const arrtype*, src);                       \
313     srcstep /= sizeof(src[0][0]);                           \
314     dststep /= sizeof(dst[0]);                              \
315                                                             \
316     for( ; size.height--; dst += dststep )                  \
317     {                                                       \
318         ICV_DEF_PL2PX_C##cn( arrtype, size.width );         \
319         dst -= size.width*(cn);                             \
320     }                                                       \
321                                                             \
322     return CV_OK;                                           \
323 }
324
325
326 #define  ICV_DEF_COPY_PL2PX_FUNC_2D_COI( arrtype, flavor )  \
327 IPCVAPI_IMPL( CvStatus, icvCopy_##flavor##_C1CnCR,          \
328 ( const arrtype* src, int srcstep,                          \
329   arrtype* dst, int dststep,                                \
330   CvSize size, int cn, int coi ),                           \
331   (src, srcstep, dst, dststep, size, cn, coi))              \
332 {                                                           \
333     dst += coi - 1;                                         \
334     srcstep /= sizeof(src[0]); dststep /= sizeof(dst[0]);   \
335                                                             \
336     for( ; size.height--; src += srcstep, dst += dststep )  \
337     {                                                       \
338         ICV_DEF_PL2PX_COI( arrtype, size.width, cn );       \
339         dst -= size.width*(cn);                             \
340     }                                                       \
341                                                             \
342     return CV_OK;                                           \
343 }
344
345
346 ICV_DEF_COPY_PL2PX_FUNC_2D( uchar, 8u, 2, ICV_DEF_PX2PL2PX_ENTRY_C2 )
347 ICV_DEF_COPY_PL2PX_FUNC_2D( uchar, 8u, 3, ICV_DEF_PX2PL2PX_ENTRY_C3 )
348 ICV_DEF_COPY_PL2PX_FUNC_2D( uchar, 8u, 4, ICV_DEF_PX2PL2PX_ENTRY_C4 )
349 ICV_DEF_COPY_PL2PX_FUNC_2D( ushort, 16s, 2, ICV_DEF_PX2PL2PX_ENTRY_C2 )
350 ICV_DEF_COPY_PL2PX_FUNC_2D( ushort, 16s, 3, ICV_DEF_PX2PL2PX_ENTRY_C3 )
351 ICV_DEF_COPY_PL2PX_FUNC_2D( ushort, 16s, 4, ICV_DEF_PX2PL2PX_ENTRY_C4 )
352 ICV_DEF_COPY_PL2PX_FUNC_2D( int, 32f, 2, ICV_DEF_PX2PL2PX_ENTRY_C2 )
353 ICV_DEF_COPY_PL2PX_FUNC_2D( int, 32f, 3, ICV_DEF_PX2PL2PX_ENTRY_C3 )
354 ICV_DEF_COPY_PL2PX_FUNC_2D( int, 32f, 4, ICV_DEF_PX2PL2PX_ENTRY_C4 )
355 ICV_DEF_COPY_PL2PX_FUNC_2D( int64, 64f, 2, ICV_DEF_PX2PL2PX_ENTRY_C2 )
356 ICV_DEF_COPY_PL2PX_FUNC_2D( int64, 64f, 3, ICV_DEF_PX2PL2PX_ENTRY_C3 )
357 ICV_DEF_COPY_PL2PX_FUNC_2D( int64, 64f, 4, ICV_DEF_PX2PL2PX_ENTRY_C4 )
358
359 ICV_DEF_COPY_PL2PX_FUNC_2D_COI( uchar, 8u )
360 ICV_DEF_COPY_PL2PX_FUNC_2D_COI( ushort, 16s )
361 ICV_DEF_COPY_PL2PX_FUNC_2D_COI( int, 32f )
362 ICV_DEF_COPY_PL2PX_FUNC_2D_COI( int64, 64f )
363
364
365 #define  ICV_DEF_PXPLPX_TAB( name, FROM, TO )                           \
366 static void                                                             \
367 name( CvBigFuncTable* tab )                                             \
368 {                                                                       \
369     tab->fn_2d[CV_8UC2] = (void*)icvCopy##_8u_##FROM##2##TO##2R;        \
370     tab->fn_2d[CV_8UC3] = (void*)icvCopy##_8u_##FROM##3##TO##3R;        \
371     tab->fn_2d[CV_8UC4] = (void*)icvCopy##_8u_##FROM##4##TO##4R;        \
372                                                                         \
373     tab->fn_2d[CV_8SC2] = (void*)icvCopy##_8u_##FROM##2##TO##2R;        \
374     tab->fn_2d[CV_8SC3] = (void*)icvCopy##_8u_##FROM##3##TO##3R;        \
375     tab->fn_2d[CV_8SC4] = (void*)icvCopy##_8u_##FROM##4##TO##4R;        \
376                                                                         \
377     tab->fn_2d[CV_16UC2] = (void*)icvCopy##_16s_##FROM##2##TO##2R;      \
378     tab->fn_2d[CV_16UC3] = (void*)icvCopy##_16s_##FROM##3##TO##3R;      \
379     tab->fn_2d[CV_16UC4] = (void*)icvCopy##_16s_##FROM##4##TO##4R;      \
380                                                                         \
381     tab->fn_2d[CV_16SC2] = (void*)icvCopy##_16s_##FROM##2##TO##2R;      \
382     tab->fn_2d[CV_16SC3] = (void*)icvCopy##_16s_##FROM##3##TO##3R;      \
383     tab->fn_2d[CV_16SC4] = (void*)icvCopy##_16s_##FROM##4##TO##4R;      \
384                                                                         \
385     tab->fn_2d[CV_32SC2] = (void*)icvCopy##_32f_##FROM##2##TO##2R;      \
386     tab->fn_2d[CV_32SC3] = (void*)icvCopy##_32f_##FROM##3##TO##3R;      \
387     tab->fn_2d[CV_32SC4] = (void*)icvCopy##_32f_##FROM##4##TO##4R;      \
388                                                                         \
389     tab->fn_2d[CV_32FC2] = (void*)icvCopy##_32f_##FROM##2##TO##2R;      \
390     tab->fn_2d[CV_32FC3] = (void*)icvCopy##_32f_##FROM##3##TO##3R;      \
391     tab->fn_2d[CV_32FC4] = (void*)icvCopy##_32f_##FROM##4##TO##4R;      \
392                                                                         \
393     tab->fn_2d[CV_64FC2] = (void*)icvCopy##_64f_##FROM##2##TO##2R;      \
394     tab->fn_2d[CV_64FC3] = (void*)icvCopy##_64f_##FROM##3##TO##3R;      \
395     tab->fn_2d[CV_64FC4] = (void*)icvCopy##_64f_##FROM##4##TO##4R;      \
396 }
397
398
399
400 #define  ICV_DEF_PXPLCOI_TAB( name, FROM, TO )                          \
401 static void                                                             \
402 name( CvFuncTable* tab )                                                \
403 {                                                                       \
404     tab->fn_2d[CV_8U] = (void*)icvCopy##_8u_##FROM##TO##CR;             \
405     tab->fn_2d[CV_8S] = (void*)icvCopy##_8u_##FROM##TO##CR;             \
406     tab->fn_2d[CV_16U] = (void*)icvCopy##_16s_##FROM##TO##CR;           \
407     tab->fn_2d[CV_16S] = (void*)icvCopy##_16s_##FROM##TO##CR;           \
408     tab->fn_2d[CV_32S] = (void*)icvCopy##_32f_##FROM##TO##CR;           \
409     tab->fn_2d[CV_32F] = (void*)icvCopy##_32f_##FROM##TO##CR;           \
410     tab->fn_2d[CV_64F] = (void*)icvCopy##_64f_##FROM##TO##CR;           \
411 }
412
413
414 ICV_DEF_PXPLPX_TAB( icvInitSplitRTable, C, P )
415 ICV_DEF_PXPLCOI_TAB( icvInitSplitRCoiTable, Cn, C1 )
416 ICV_DEF_PXPLPX_TAB( icvInitCvtPlaneToPixRTable, P, C )
417 ICV_DEF_PXPLCOI_TAB( icvInitCvtPlaneToPixRCoiTable, C1, Cn )
418
419 typedef CvStatus (CV_STDCALL *CvSplitFunc)( const void* src, int srcstep,
420                                                     void** dst, int dststep, CvSize size);
421
422 typedef CvStatus (CV_STDCALL *CvExtractPlaneFunc)( const void* src, int srcstep,
423                                                    void* dst, int dststep,
424                                                    CvSize size, int cn, int coi );
425
426 typedef CvStatus (CV_STDCALL *CvMergeFunc)( const void** src, int srcstep,
427                                                     void* dst, int dststep, CvSize size);
428
429 typedef CvStatus (CV_STDCALL *CvInsertPlaneFunc)( const void* src, int srcstep,
430                                                   void* dst, int dststep,
431                                                   CvSize size, int cn, int coi );
432
433 CV_IMPL void
434 cvSplit( const void* srcarr, void* dstarr0, void* dstarr1, void* dstarr2, void* dstarr3 )
435 {
436     static CvBigFuncTable  pxpl_tab;
437     static CvFuncTable  pxplcoi_tab;
438     static int inittab = 0;
439
440     CV_FUNCNAME( "cvSplit" );
441
442     __BEGIN__;
443
444     CvMat stub[5], *dst[4], *src = (CvMat*)srcarr;
445     CvSize size;
446     void* dstptr[4] = { 0, 0, 0, 0 };
447     int type, cn, coi = 0;
448     int i, nzplanes = 0, nzidx = -1;
449     int cont_flag;
450     int src_step, dst_step = 0;
451
452     if( !inittab )
453     {
454         icvInitSplitRTable( &pxpl_tab );
455         icvInitSplitRCoiTable( &pxplcoi_tab );
456         inittab = 1;
457     }
458
459     dst[0] = (CvMat*)dstarr0;
460     dst[1] = (CvMat*)dstarr1;
461     dst[2] = (CvMat*)dstarr2;
462     dst[3] = (CvMat*)dstarr3;
463
464     CV_CALL( src = cvGetMat( src, stub + 4, &coi ));
465
466     //if( coi != 0 )
467     //    CV_ERROR( CV_BadCOI, "" );
468
469     type = CV_MAT_TYPE( src->type );
470     cn = CV_MAT_CN( type );
471
472     cont_flag = src->type;
473
474     if( cn == 1 )
475         CV_ERROR( CV_BadNumChannels, "" );
476
477     for( i = 0; i < 4; i++ )
478     {
479         if( dst[i] )
480         {
481             nzplanes++;
482             nzidx = i;
483             CV_CALL( dst[i] = cvGetMat( dst[i], stub + i ));
484             if( CV_MAT_CN( dst[i]->type ) != 1 )
485                 CV_ERROR( CV_BadNumChannels, "" );
486             if( !CV_ARE_DEPTHS_EQ( dst[i], src ))
487                 CV_ERROR( CV_StsUnmatchedFormats, "" );
488             if( !CV_ARE_SIZES_EQ( dst[i], src ))
489                 CV_ERROR( CV_StsUnmatchedSizes, "" );
490             if( nzplanes > i && i > 0 && dst[i]->step != dst[i-1]->step )
491                 CV_ERROR( CV_BadStep, "" );
492             dst_step = dst[i]->step;
493             dstptr[nzplanes-1] = dst[i]->data.ptr;
494
495             cont_flag &= dst[i]->type;
496         }
497     }
498
499     src_step = src->step;
500     size = cvGetMatSize( src );
501
502     if( CV_IS_MAT_CONT( cont_flag ))
503     {
504         size.width *= size.height;
505         src_step = dst_step = CV_STUB_STEP;
506
507         size.height = 1;
508     }
509
510     if( nzplanes == cn )
511     {
512         CvSplitFunc func = (CvSplitFunc)pxpl_tab.fn_2d[type];
513
514         if( !func )
515             CV_ERROR( CV_StsUnsupportedFormat, "" );
516
517         IPPI_CALL( func( src->data.ptr, src_step, dstptr, dst_step, size ));
518     }
519     else if( nzplanes == 1 )
520     {
521         CvExtractPlaneFunc func = (CvExtractPlaneFunc)pxplcoi_tab.fn_2d[CV_MAT_DEPTH(type)];
522
523         if( !func )
524             CV_ERROR( CV_StsUnsupportedFormat, "" );
525
526         IPPI_CALL( func( src->data.ptr, src_step,
527                          dst[nzidx]->data.ptr, dst_step,
528                          size, cn, nzidx + 1 ));
529     }
530     else
531     {
532         CV_ERROR( CV_StsBadArg,
533             "Either all output planes or only one output plane should be non zero" );
534     }
535
536     __END__;
537 }
538
539
540
541 CV_IMPL void
542 cvMerge( const void* srcarr0, const void* srcarr1, const void* srcarr2,
543          const void* srcarr3, void* dstarr )
544 {
545     static CvBigFuncTable plpx_tab;
546     static CvFuncTable plpxcoi_tab;
547     static int inittab = 0;
548
549     CV_FUNCNAME( "cvMerge" );
550
551     __BEGIN__;
552
553     int src_step = 0, dst_step;
554     CvMat stub[5], *src[4], *dst = (CvMat*)dstarr;
555     CvSize size;
556     const void* srcptr[4] = { 0, 0, 0, 0 };
557     int type, cn, coi = 0;
558     int i, nzplanes = 0, nzidx = -1;
559     int cont_flag;
560
561     if( !inittab )
562     {
563         icvInitCvtPlaneToPixRTable( &plpx_tab );
564         icvInitCvtPlaneToPixRCoiTable( &plpxcoi_tab );
565         inittab = 1;
566     }
567
568     src[0] = (CvMat*)srcarr0;
569     src[1] = (CvMat*)srcarr1;
570     src[2] = (CvMat*)srcarr2;
571     src[3] = (CvMat*)srcarr3;
572
573     CV_CALL( dst = cvGetMat( dst, stub + 4, &coi ));
574
575     type = CV_MAT_TYPE( dst->type );
576     cn = CV_MAT_CN( type );
577
578     cont_flag = dst->type;
579
580     if( cn == 1 )
581         CV_ERROR( CV_BadNumChannels, "" );
582
583     for( i = 0; i < 4; i++ )
584     {
585         if( src[i] )
586         {
587             nzplanes++;
588             nzidx = i;
589             CV_CALL( src[i] = cvGetMat( src[i], stub + i ));
590             if( CV_MAT_CN( src[i]->type ) != 1 )
591                 CV_ERROR( CV_BadNumChannels, "" );
592             if( !CV_ARE_DEPTHS_EQ( src[i], dst ))
593                 CV_ERROR( CV_StsUnmatchedFormats, "" );
594             if( !CV_ARE_SIZES_EQ( src[i], dst ))
595                 CV_ERROR( CV_StsUnmatchedSizes, "" );
596             if( nzplanes > i && i > 0 && src[i]->step != src[i-1]->step )
597                 CV_ERROR( CV_BadStep, "" );
598             src_step = src[i]->step;
599             srcptr[nzplanes-1] = (const void*)(src[i]->data.ptr);
600
601             cont_flag &= src[i]->type;
602         }
603     }
604
605     size = cvGetMatSize( dst );
606     dst_step = dst->step;
607
608     if( CV_IS_MAT_CONT( cont_flag ))
609     {
610         size.width *= size.height;
611         src_step = dst_step = CV_STUB_STEP;
612         size.height = 1;
613     }
614
615     if( nzplanes == cn )
616     {
617         CvMergeFunc func = (CvMergeFunc)plpx_tab.fn_2d[type];
618
619         if( !func )
620             CV_ERROR( CV_StsUnsupportedFormat, "" );
621
622         IPPI_CALL( func( srcptr, src_step, dst->data.ptr, dst_step, size ));
623     }
624     else if( nzplanes == 1 )
625     {
626         CvInsertPlaneFunc func = (CvInsertPlaneFunc)plpxcoi_tab.fn_2d[CV_MAT_DEPTH(type)];
627
628         if( !func )
629             CV_ERROR( CV_StsUnsupportedFormat, "" );
630
631         IPPI_CALL( func( src[nzidx]->data.ptr, src_step,
632                          dst->data.ptr, dst_step,
633                          size, cn, nzidx + 1 ));
634     }
635     else
636     {
637         CV_ERROR( CV_StsBadArg,
638             "Either all input planes or only one input plane should be non zero" );
639     }
640
641     __END__;
642 }
643
644
645 /****************************************************************************************\
646 *                       Generalized split/merge: mixing channels                         *
647 \****************************************************************************************/
648
649 #define  ICV_DEF_MIX_CH_FUNC_2D( arrtype, flavor )              \
650 static CvStatus CV_STDCALL                                      \
651 icvMixChannels_##flavor( const arrtype** src, int* sdelta0,     \
652                          int* sdelta1, arrtype** dst,           \
653                          int* ddelta0, int* ddelta1,            \
654                          int n, CvSize size )                   \
655 {                                                               \
656     int i, k;                                                   \
657     int block_size0 = n == 1 ? size.width : 1024;               \
658                                                                 \
659     for( ; size.height--; )                                     \
660     {                                                           \
661         int remaining = size.width;                             \
662         for( ; remaining > 0; )                                 \
663         {                                                       \
664             int block_size = MIN( remaining, block_size0 );     \
665             for( k = 0; k < n; k++ )                            \
666             {                                                   \
667                 const arrtype* s = src[k];                      \
668                 arrtype* d = dst[k];                            \
669                 int ds = sdelta1[k], dd = ddelta1[k];           \
670                 if( s )                                         \
671                 {                                               \
672                     for( i = 0; i <= block_size - 2; i += 2,    \
673                                         s += ds*2, d += dd*2 )  \
674                     {                                           \
675                         arrtype t0 = s[0], t1 = s[ds];          \
676                         d[0] = t0; d[dd] = t1;                  \
677                     }                                           \
678                     if( i < block_size )                        \
679                         d[0] = s[0], s += ds, d += dd;          \
680                     src[k] = s;                                 \
681                 }                                               \
682                 else                                            \
683                 {                                               \
684                     for( i=0; i <= block_size-2; i+=2, d+=dd*2 )\
685                         d[0] = d[dd] = 0;                       \
686                     if( i < block_size )                        \
687                         d[0] = 0, d += dd;                      \
688                 }                                               \
689                 dst[k] = d;                                     \
690             }                                                   \
691             remaining -= block_size;                            \
692         }                                                       \
693         for( k = 0; k < n; k++ )                                \
694             src[k] += sdelta0[k], dst[k] += ddelta0[k];         \
695     }                                                           \
696                                                                 \
697     return CV_OK;                                               \
698 }
699
700
701 ICV_DEF_MIX_CH_FUNC_2D( uchar, 8u )
702 ICV_DEF_MIX_CH_FUNC_2D( ushort, 16u )
703 ICV_DEF_MIX_CH_FUNC_2D( int, 32s )
704 ICV_DEF_MIX_CH_FUNC_2D( int64, 64s )
705
706 static void
707 icvInitMixChannelsTab( CvFuncTable* tab )
708 {
709     tab->fn_2d[CV_8U] = (void*)icvMixChannels_8u;
710     tab->fn_2d[CV_8S] = (void*)icvMixChannels_8u;
711     tab->fn_2d[CV_16U] = (void*)icvMixChannels_16u;
712     tab->fn_2d[CV_16S] = (void*)icvMixChannels_16u;
713     tab->fn_2d[CV_32S] = (void*)icvMixChannels_32s;
714     tab->fn_2d[CV_32F] = (void*)icvMixChannels_32s;
715     tab->fn_2d[CV_64F] = (void*)icvMixChannels_64s;
716 }
717
718 typedef CvStatus (CV_STDCALL * CvMixChannelsFunc)( const void** src, int* sdelta0,
719         int* sdelta1, void** dst, int* ddelta0, int* ddelta1, int n, CvSize size );
720
721 CV_IMPL void
722 cvMixChannels( const CvArr** src, int src_count,
723                CvArr** dst, int dst_count,
724                const int* from_to, int pair_count )
725 {
726     static CvFuncTable mixcn_tab;
727     static int inittab = 0;
728     uchar* buffer = 0;
729     int heap_alloc = 0;
730
731     CV_FUNCNAME( "cvMixChannels" );
732
733     __BEGIN__;
734
735     CvSize size = {0,0};
736     int depth = -1, elem_size = 1;
737     int *sdelta0 = 0, *sdelta1 = 0, *ddelta0 = 0, *ddelta1 = 0;
738     uchar **sptr = 0, **dptr = 0;
739     uchar **src0 = 0, **dst0 = 0;
740     int* src_cn = 0, *dst_cn = 0;
741     int* src_step = 0, *dst_step = 0;
742     int buf_size, i, k;
743     int cont_flag = CV_MAT_CONT_FLAG;
744     CvMixChannelsFunc func;
745
746     if( !inittab )
747     {
748         icvInitMixChannelsTab( &mixcn_tab );
749         inittab = 1;
750     }
751
752     src_count = MAX( src_count, 0 );
753
754     if( !src && src_count > 0 )
755         CV_ERROR( CV_StsNullPtr, "The input array of arrays is NULL" );
756
757     if( !dst )
758         CV_ERROR( CV_StsNullPtr, "The output array of arrays is NULL" );
759
760     if( dst_count <= 0 || pair_count <= 0 )
761         CV_ERROR( CV_StsOutOfRange,
762         "The number of output arrays and the number of copied channels must be positive" );
763
764     if( !from_to )
765         CV_ERROR( CV_StsNullPtr, "The array of copied channel indices is NULL" );
766
767     buf_size = (src_count + dst_count + 2)*
768         (sizeof(src0[0]) + sizeof(src_cn[0]) + sizeof(src_step[0])) +
769         pair_count*2*(sizeof(sptr[0]) + sizeof(sdelta0[0]) + sizeof(sdelta1[0]));
770
771     if( buf_size > CV_MAX_LOCAL_SIZE )
772     {
773         CV_CALL( buffer = (uchar*)cvAlloc( buf_size ) );
774         heap_alloc = 1;
775     }
776     else
777         buffer = (uchar*)cvStackAlloc( buf_size );
778
779     src0 = (uchar**)buffer;
780     dst0 = src0 + src_count;
781     src_cn = (int*)(dst0 + dst_count);
782     dst_cn = src_cn + src_count + 1;
783     src_step = dst_cn + dst_count + 1;
784     dst_step = src_step + src_count;
785
786     sptr = (uchar**)cvAlignPtr( dst_step + dst_count, (int)sizeof(void*) );
787     dptr = sptr + pair_count;
788     sdelta0 = (int*)(dptr + pair_count);
789     sdelta1 = sdelta0 + pair_count;
790     ddelta0 = sdelta1 + pair_count;
791     ddelta1 = ddelta0 + pair_count;
792
793     src_cn[0] = dst_cn[0] = 0;
794
795     for( k = 0; k < 2; k++ )
796     {
797         for( i = 0; i < (k == 0 ? src_count : dst_count); i++ )
798         {
799             CvMat stub, *mat = (CvMat*)(k == 0 ? src[i] : dst[i]);
800             int cn;
801
802             if( !CV_IS_MAT(mat) )
803                 CV_CALL( mat = cvGetMat( mat, &stub ));
804
805             if( depth < 0 )
806             {
807                 depth = CV_MAT_DEPTH(mat->type);
808                 elem_size = CV_ELEM_SIZE1(depth);
809                 size = cvGetMatSize(mat);
810             }
811
812             if( CV_MAT_DEPTH(mat->type) != depth )
813                 CV_ERROR( CV_StsUnmatchedFormats, "All the arrays must have the same bit depth" );
814
815             if( mat->cols != size.width || mat->rows != size.height )
816                 CV_ERROR( CV_StsUnmatchedSizes, "All the arrays must have the same size" );
817
818             if( k == 0 )
819             {
820                 src0[i] = mat->data.ptr;
821                 cn = CV_MAT_CN(mat->type);
822                 src_cn[i+1] = src_cn[i] + cn;
823                 src_step[i] = mat->step / elem_size - size.width * cn;
824             }
825             else
826             {
827                 dst0[i] = mat->data.ptr;
828                 cn = CV_MAT_CN(mat->type);
829                 dst_cn[i+1] = dst_cn[i] + cn;
830                 dst_step[i] = mat->step / elem_size - size.width * cn;
831             }
832
833             cont_flag &= mat->type;
834         }
835     }
836
837     if( cont_flag )
838     {
839         size.width *= size.height;
840         size.height = 1;
841     }
842
843     for( i = 0; i < pair_count; i++ )
844     {
845         for( k = 0; k < 2; k++ )
846         {
847             int cn = from_to[i*2 + k];
848             const int* cn_arr = k == 0 ? src_cn : dst_cn;
849             int a = 0, b = k == 0 ? src_count-1 : dst_count-1;
850
851             if( cn < 0 || cn >= cn_arr[b+1] )
852             {
853                 if( k == 0 && cn < 0 )
854                 {
855                     sptr[i] = 0;
856                     sdelta0[i] = sdelta1[i] = 0;
857                     continue;
858                 }
859                 else
860                 {
861                     char err_str[100];
862                     sprintf( err_str, "channel index #%d in the array of pairs is negative "
863                         "or exceeds the total number of channels in all the %s arrays", i*2+k,
864                         k == 0 ? "input" : "output" );
865                     CV_ERROR( CV_StsOutOfRange, err_str );
866                 }
867             }
868
869             for( ; cn >= cn_arr[a+1]; a++ )
870                 ;
871
872             if( k == 0 )
873             {
874                 sptr[i] = src0[a] + (cn - cn_arr[a])*elem_size;
875                 sdelta1[i] = cn_arr[a+1] - cn_arr[a];
876                 sdelta0[i] = src_step[a];
877             }
878             else
879             {
880                 dptr[i] = dst0[a] + (cn - cn_arr[a])*elem_size;
881                 ddelta1[i] = cn_arr[a+1] - cn_arr[a];
882                 ddelta0[i] = dst_step[a];
883             }
884         }
885     }
886
887     func = (CvMixChannelsFunc)mixcn_tab.fn_2d[depth];
888     if( !func )
889         CV_ERROR( CV_StsUnsupportedFormat, "The data type is not supported by the function" );
890
891     IPPI_CALL( func( (const void**)sptr, sdelta0, sdelta1, (void**)dptr,
892                      ddelta0, ddelta1, pair_count, size ));
893
894     __END__;
895
896     if( buffer && heap_alloc )
897         cvFree( &buffer );
898 }
899
900
901 /****************************************************************************************\
902 *                                   cvConvertScaleAbs                                    *
903 \****************************************************************************************/
904
905 #define ICV_DEF_CVT_SCALE_ABS_CASE( srctype, worktype,                  \
906             scale_macro, abs_macro, cast_macro, a, b )                  \
907                                                                         \
908 {                                                                       \
909     const srctype* _src = (const srctype*)src;                          \
910     srcstep /= sizeof(_src[0]); /*dststep /= sizeof(_dst[0]);*/         \
911                                                                         \
912     for( ; size.height--; _src += srcstep, dst += dststep )             \
913     {                                                                   \
914         int i;                                                          \
915                                                                         \
916         for( i = 0; i <= size.width - 4; i += 4 )                       \
917         {                                                               \
918             worktype t0 = scale_macro((a)*_src[i] + (b));               \
919             worktype t1 = scale_macro((a)*_src[i+1] + (b));             \
920                                                                         \
921             t0 = (worktype)abs_macro(t0);                               \
922             t1 = (worktype)abs_macro(t1);                               \
923                                                                         \
924             dst[i] = cast_macro(t0);                                    \
925             dst[i+1] = cast_macro(t1);                                  \
926                                                                         \
927             t0 = scale_macro((a)*_src[i+2] + (b));                      \
928             t1 = scale_macro((a)*_src[i+3] + (b));                      \
929                                                                         \
930             t0 = (worktype)abs_macro(t0);                               \
931             t1 = (worktype)abs_macro(t1);                               \
932                                                                         \
933             dst[i+2] = cast_macro(t0);                                  \
934             dst[i+3] = cast_macro(t1);                                  \
935         }                                                               \
936                                                                         \
937         for( ; i < size.width; i++ )                                    \
938         {                                                               \
939             worktype t0 = scale_macro((a)*_src[i] + (b));               \
940             t0 = (worktype)abs_macro(t0);                               \
941             dst[i] = cast_macro(t0);                                    \
942         }                                                               \
943     }                                                                   \
944 }
945
946
947 #define ICV_FIX_SHIFT  15
948 #define ICV_SCALE(x)   (((x) + (1 << (ICV_FIX_SHIFT-1))) >> ICV_FIX_SHIFT)
949
950 static CvStatus CV_STDCALL
951 icvCvtScaleAbsTo_8u_C1R( const uchar* src, int srcstep,
952                          uchar* dst, int dststep,
953                          CvSize size, double scale, double shift,
954                          int param )
955 {
956     int srctype = param;
957     int srcdepth = CV_MAT_DEPTH(srctype);
958
959     size.width *= CV_MAT_CN(srctype);
960
961     switch( srcdepth )
962     {
963     case  CV_8S:
964     case  CV_8U:
965         {
966         uchar lut[256];
967         int i;
968         double val = shift;
969
970         for( i = 0; i < 128; i++, val += scale )
971         {
972             int t = cvRound(fabs(val));
973             lut[i] = CV_CAST_8U(t);
974         }
975
976         if( srcdepth == CV_8S )
977             val = -val;
978
979         for( ; i < 256; i++, val += scale )
980         {
981             int t = cvRound(fabs(val));
982             lut[i] = CV_CAST_8U(t);
983         }
984
985         icvLUT_Transform8u_8u_C1R( src, srcstep, dst,
986                                    dststep, size, lut );
987         }
988         break;
989     case  CV_16U:
990         if( fabs( scale ) <= 1. && fabs(shift) < DBL_EPSILON )
991         {
992             int iscale = cvRound(scale*(1 << ICV_FIX_SHIFT));
993
994             if( iscale == ICV_FIX_SHIFT )
995             {
996                 ICV_DEF_CVT_SCALE_ABS_CASE( ushort, int, CV_NOP, CV_IABS,
997                                             CV_CAST_8U, 1, 0 );
998             }
999             else
1000             {
1001                 ICV_DEF_CVT_SCALE_ABS_CASE( ushort, int, ICV_SCALE, CV_IABS,
1002                                             CV_CAST_8U, iscale, 0 );
1003             }
1004         }
1005         else
1006         {
1007             ICV_DEF_CVT_SCALE_ABS_CASE( ushort, int, cvRound, CV_IABS,
1008                                         CV_CAST_8U, scale, shift );
1009         }
1010         break;
1011     case  CV_16S:
1012         if( fabs( scale ) <= 1. &&
1013             fabs( shift ) <= (INT_MAX*0.5)/(1 << ICV_FIX_SHIFT))
1014         {
1015             int iscale = cvRound(scale*(1 << ICV_FIX_SHIFT));
1016             int ishift = cvRound(shift*(1 << ICV_FIX_SHIFT));
1017
1018             if( iscale == ICV_FIX_SHIFT && ishift == 0 )
1019             {
1020                 ICV_DEF_CVT_SCALE_ABS_CASE( short, int, CV_NOP, CV_IABS,
1021                                             CV_CAST_8U, 1, 0 );
1022             }
1023             else
1024             {
1025                 ICV_DEF_CVT_SCALE_ABS_CASE( short, int, ICV_SCALE, CV_IABS,
1026                                             CV_CAST_8U, iscale, ishift );
1027             }
1028         }
1029         else
1030         {
1031             ICV_DEF_CVT_SCALE_ABS_CASE( short, int, cvRound, CV_IABS,
1032                                         CV_CAST_8U, scale, shift );
1033         }
1034         break;
1035     case  CV_32S:
1036         ICV_DEF_CVT_SCALE_ABS_CASE( int, int, cvRound, CV_IABS,
1037                                     CV_CAST_8U, scale, shift );
1038         break;
1039     case  CV_32F:
1040         ICV_DEF_CVT_SCALE_ABS_CASE( float, int, cvRound, CV_IABS,
1041                                     CV_CAST_8U, scale, shift );
1042         break;
1043     case  CV_64F:
1044         ICV_DEF_CVT_SCALE_ABS_CASE( double, int, cvRound, CV_IABS,
1045                                     CV_CAST_8U, scale, shift );
1046         break;
1047     default:
1048         assert(0);
1049         return CV_BADFLAG_ERR;
1050     }
1051
1052     return  CV_OK;
1053 }
1054
1055
1056 CV_IMPL void
1057 cvConvertScaleAbs( const void* srcarr, void* dstarr,
1058                    double scale, double shift )
1059 {
1060     CV_FUNCNAME( "cvConvertScaleAbs" );
1061
1062     __BEGIN__;
1063
1064     int coi1 = 0, coi2 = 0;
1065     CvMat  srcstub, *src = (CvMat*)srcarr;
1066     CvMat  dststub, *dst = (CvMat*)dstarr;
1067     CvSize size;
1068     int src_step, dst_step;
1069
1070     CV_CALL( src = cvGetMat( src, &srcstub, &coi1 ));
1071     CV_CALL( dst = cvGetMat( dst, &dststub, &coi2 ));
1072
1073     if( coi1 != 0 || coi2 != 0 )
1074         CV_ERROR( CV_BadCOI, "" );
1075
1076     if( !CV_ARE_SIZES_EQ( src, dst ))
1077         CV_ERROR( CV_StsUnmatchedSizes, "" );
1078
1079     if( !CV_ARE_CNS_EQ( src, dst ))
1080         CV_ERROR( CV_StsUnmatchedFormats, "" );
1081
1082     if( CV_MAT_DEPTH( dst->type ) != CV_8U )
1083         CV_ERROR( CV_StsUnsupportedFormat, "" );
1084
1085     size = cvGetMatSize( src );
1086     src_step = src->step;
1087     dst_step = dst->step;
1088
1089     if( CV_IS_MAT_CONT( src->type & dst->type ))
1090     {
1091         size.width *= size.height;
1092         src_step = dst_step = CV_STUB_STEP;
1093         size.height = 1;
1094     }
1095
1096     IPPI_CALL( icvCvtScaleAbsTo_8u_C1R( src->data.ptr, src_step,
1097                              (uchar*)(dst->data.ptr), dst_step,
1098                              size, scale, shift, CV_MAT_TYPE(src->type)));
1099     __END__;
1100 }
1101
1102 /****************************************************************************************\
1103 *                                      cvConvertScale                                    *
1104 \****************************************************************************************/
1105
1106 #define ICV_DEF_CVT_SCALE_CASE( srctype, worktype,          \
1107                             scale_macro, cast_macro, a, b ) \
1108                                                             \
1109 {                                                           \
1110     const srctype* _src = (const srctype*)src;              \
1111     srcstep /= sizeof(_src[0]);                             \
1112                                                             \
1113     for( ; size.height--; _src += srcstep, dst += dststep ) \
1114     {                                                       \
1115         for( i = 0; i <= size.width - 4; i += 4 )           \
1116         {                                                   \
1117             worktype t0 = scale_macro((a)*_src[i]+(b));     \
1118             worktype t1 = scale_macro((a)*_src[i+1]+(b));   \
1119                                                             \
1120             dst[i] = cast_macro(t0);                        \
1121             dst[i+1] = cast_macro(t1);                      \
1122                                                             \
1123             t0 = scale_macro((a)*_src[i+2] + (b));          \
1124             t1 = scale_macro((a)*_src[i+3] + (b));          \
1125                                                             \
1126             dst[i+2] = cast_macro(t0);                      \
1127             dst[i+3] = cast_macro(t1);                      \
1128         }                                                   \
1129                                                             \
1130         for( ; i < size.width; i++ )                        \
1131         {                                                   \
1132             worktype t0 = scale_macro((a)*_src[i] + (b));   \
1133             dst[i] = cast_macro(t0);                        \
1134         }                                                   \
1135     }                                                       \
1136 }
1137
1138
1139 #define  ICV_DEF_CVT_SCALE_FUNC_INT( flavor, dsttype, cast_macro )      \
1140 static  CvStatus  CV_STDCALL                                            \
1141 icvCvtScaleTo_##flavor##_C1R( const uchar* src, int srcstep,            \
1142                               dsttype* dst, int dststep, CvSize size,   \
1143                               double scale, double shift, int param )   \
1144 {                                                                       \
1145     int i, srctype = param;                                             \
1146     dsttype lut[256];                                                   \
1147     dststep /= sizeof(dst[0]);                                          \
1148                                                                         \
1149     switch( CV_MAT_DEPTH(srctype) )                                     \
1150     {                                                                   \
1151     case  CV_8U:                                                        \
1152         if( size.width*size.height >= 256 )                             \
1153         {                                                               \
1154             double val = shift;                                         \
1155             for( i = 0; i < 256; i++, val += scale )                    \
1156             {                                                           \
1157                 int t = cvRound(val);                                   \
1158                 lut[i] = cast_macro(t);                                 \
1159             }                                                           \
1160                                                                         \
1161             icvLUT_Transform8u_##flavor##_C1R( src, srcstep, dst,       \
1162                                 dststep*sizeof(dst[0]), size, lut );    \
1163         }                                                               \
1164         else if( fabs( scale ) <= 128. &&                               \
1165                  fabs( shift ) <= (INT_MAX*0.5)/(1 << ICV_FIX_SHIFT))   \
1166         {                                                               \
1167             int iscale = cvRound(scale*(1 << ICV_FIX_SHIFT));           \
1168             int ishift = cvRound(shift*(1 << ICV_FIX_SHIFT));           \
1169                                                                         \
1170             ICV_DEF_CVT_SCALE_CASE( uchar, int, ICV_SCALE,              \
1171                                     cast_macro, iscale, ishift );       \
1172         }                                                               \
1173         else                                                            \
1174         {                                                               \
1175             ICV_DEF_CVT_SCALE_CASE( uchar, int, cvRound,                \
1176                                     cast_macro, scale, shift );         \
1177         }                                                               \
1178         break;                                                          \
1179     case  CV_8S:                                                        \
1180         if( size.width*size.height >= 256 )                             \
1181         {                                                               \
1182             for( i = 0; i < 256; i++ )                                  \
1183             {                                                           \
1184                 int t = cvRound( (schar)i*scale + shift );              \
1185                 lut[i] = cast_macro(t);                                 \
1186             }                                                           \
1187                                                                         \
1188             icvLUT_Transform8u_##flavor##_C1R( src, srcstep, dst,       \
1189                                 dststep*sizeof(dst[0]), size, lut );    \
1190         }                                                               \
1191         else if( fabs( scale ) <= 128. &&                               \
1192                  fabs( shift ) <= (INT_MAX*0.5)/(1 << ICV_FIX_SHIFT))   \
1193         {                                                               \
1194             int iscale = cvRound(scale*(1 << ICV_FIX_SHIFT));           \
1195             int ishift = cvRound(shift*(1 << ICV_FIX_SHIFT));           \
1196                                                                         \
1197             ICV_DEF_CVT_SCALE_CASE( schar, int, ICV_SCALE,              \
1198                                     cast_macro, iscale, ishift );       \
1199         }                                                               \
1200         else                                                            \
1201         {                                                               \
1202             ICV_DEF_CVT_SCALE_CASE( schar, int, cvRound,                \
1203                                     cast_macro, scale, shift );         \
1204         }                                                               \
1205         break;                                                          \
1206     case  CV_16U:                                                       \
1207         if( fabs( scale ) <= 1. && fabs(shift) < DBL_EPSILON )          \
1208         {                                                               \
1209             int iscale = cvRound(scale*(1 << ICV_FIX_SHIFT));           \
1210                                                                         \
1211             ICV_DEF_CVT_SCALE_CASE( ushort, int, ICV_SCALE,             \
1212                                     cast_macro, iscale, 0 );            \
1213         }                                                               \
1214         else                                                            \
1215         {                                                               \
1216             ICV_DEF_CVT_SCALE_CASE( ushort, int, cvRound,               \
1217                                     cast_macro, scale, shift );         \
1218         }                                                               \
1219         break;                                                          \
1220     case  CV_16S:                                                       \
1221         if( fabs( scale ) <= 1. &&                                      \
1222             fabs( shift ) <= (INT_MAX*0.5)/(1 << ICV_FIX_SHIFT))        \
1223         {                                                               \
1224             int iscale = cvRound(scale*(1 << ICV_FIX_SHIFT));           \
1225             int ishift = cvRound(shift*(1 << ICV_FIX_SHIFT));           \
1226                                                                         \
1227             ICV_DEF_CVT_SCALE_CASE( short, int, ICV_SCALE,              \
1228                                     cast_macro, iscale, ishift );       \
1229         }                                                               \
1230         else                                                            \
1231         {                                                               \
1232             ICV_DEF_CVT_SCALE_CASE( short, int, cvRound,                \
1233                                     cast_macro, scale, shift );         \
1234         }                                                               \
1235         break;                                                          \
1236     case  CV_32S:                                                       \
1237         ICV_DEF_CVT_SCALE_CASE( int, int, cvRound,                      \
1238                                 cast_macro, scale, shift );             \
1239         break;                                                          \
1240     case  CV_32F:                                                       \
1241         ICV_DEF_CVT_SCALE_CASE( float, int, cvRound,                    \
1242                                 cast_macro, scale, shift );             \
1243         break;                                                          \
1244     case  CV_64F:                                                       \
1245         ICV_DEF_CVT_SCALE_CASE( double, int, cvRound,                   \
1246                                 cast_macro, scale, shift );             \
1247         break;                                                          \
1248     default:                                                            \
1249         assert(0);                                                      \
1250         return CV_BADFLAG_ERR;                                          \
1251     }                                                                   \
1252                                                                         \
1253     return  CV_OK;                                                      \
1254 }
1255
1256
1257 #define  ICV_DEF_CVT_SCALE_FUNC_FLT( flavor, dsttype, cast_macro )      \
1258 static  CvStatus  CV_STDCALL                                            \
1259 icvCvtScaleTo_##flavor##_C1R( const uchar* src, int srcstep,            \
1260                               dsttype* dst, int dststep, CvSize size,   \
1261                               double scale, double shift, int param )   \
1262 {                                                                       \
1263     int i, srctype = param;                                             \
1264     dsttype lut[256];                                                   \
1265     dststep /= sizeof(dst[0]);                                          \
1266                                                                         \
1267     switch( CV_MAT_DEPTH(srctype) )                                     \
1268     {                                                                   \
1269     case  CV_8U:                                                        \
1270         if( size.width*size.height >= 256 )                             \
1271         {                                                               \
1272             double val = shift;                                         \
1273             for( i = 0; i < 256; i++, val += scale )                    \
1274                 lut[i] = (dsttype)val;                                  \
1275                                                                         \
1276             icvLUT_Transform8u_##flavor##_C1R( src, srcstep, dst,       \
1277                                 dststep*sizeof(dst[0]), size, lut );    \
1278         }                                                               \
1279         else                                                            \
1280         {                                                               \
1281             ICV_DEF_CVT_SCALE_CASE( uchar, double, CV_NOP,              \
1282                                     cast_macro, scale, shift );         \
1283         }                                                               \
1284         break;                                                          \
1285     case  CV_8S:                                                        \
1286         if( size.width*size.height >= 256 )                             \
1287         {                                                               \
1288             for( i = 0; i < 256; i++ )                                  \
1289                 lut[i] = (dsttype)((schar)i*scale + shift);             \
1290                                                                         \
1291             icvLUT_Transform8u_##flavor##_C1R( src, srcstep, dst,       \
1292                                 dststep*sizeof(dst[0]), size, lut );    \
1293         }                                                               \
1294         else                                                            \
1295         {                                                               \
1296             ICV_DEF_CVT_SCALE_CASE( schar, double, CV_NOP,              \
1297                                     cast_macro, scale, shift );         \
1298         }                                                               \
1299         break;                                                          \
1300     case  CV_16U:                                                       \
1301         ICV_DEF_CVT_SCALE_CASE( ushort, double, CV_NOP,                 \
1302                                 cast_macro, scale, shift );             \
1303         break;                                                          \
1304     case  CV_16S:                                                       \
1305         ICV_DEF_CVT_SCALE_CASE( short, double, CV_NOP,                  \
1306                                 cast_macro, scale, shift );             \
1307         break;                                                          \
1308     case  CV_32S:                                                       \
1309         ICV_DEF_CVT_SCALE_CASE( int, double, CV_NOP,                    \
1310                                 cast_macro, scale, shift );             \
1311         break;                                                          \
1312     case  CV_32F:                                                       \
1313         ICV_DEF_CVT_SCALE_CASE( float, double, CV_NOP,                  \
1314                                 cast_macro, scale, shift );             \
1315         break;                                                          \
1316     case  CV_64F:                                                       \
1317         ICV_DEF_CVT_SCALE_CASE( double, double, CV_NOP,                 \
1318                                 cast_macro, scale, shift );             \
1319         break;                                                          \
1320     default:                                                            \
1321         assert(0);                                                      \
1322         return CV_BADFLAG_ERR;                                          \
1323     }                                                                   \
1324                                                                         \
1325     return  CV_OK;                                                      \
1326 }
1327
1328
1329 ICV_DEF_CVT_SCALE_FUNC_INT( 8u, uchar, CV_CAST_8U )
1330 ICV_DEF_CVT_SCALE_FUNC_INT( 8s, schar, CV_CAST_8S )
1331 ICV_DEF_CVT_SCALE_FUNC_INT( 16s, short, CV_CAST_16S )
1332 ICV_DEF_CVT_SCALE_FUNC_INT( 16u, ushort, CV_CAST_16U )
1333 ICV_DEF_CVT_SCALE_FUNC_INT( 32s, int, CV_CAST_32S )
1334
1335 ICV_DEF_CVT_SCALE_FUNC_FLT( 32f, float, CV_CAST_32F )
1336 ICV_DEF_CVT_SCALE_FUNC_FLT( 64f, double, CV_CAST_64F )
1337
1338 CV_DEF_INIT_FUNC_TAB_2D( CvtScaleTo, C1R )
1339
1340
1341 /****************************************************************************************\
1342 *                             Conversion w/o scaling macros                              *
1343 \****************************************************************************************/
1344
1345 #define ICV_DEF_CVT_CASE_2D( srctype, worktype,             \
1346                              cast_macro1, cast_macro2 )     \
1347 {                                                           \
1348     const srctype* _src = (const srctype*)src;              \
1349     srcstep /= sizeof(_src[0]);                             \
1350                                                             \
1351     for( ; size.height--; _src += srcstep, dst += dststep ) \
1352     {                                                       \
1353         int i;                                              \
1354                                                             \
1355         for( i = 0; i <= size.width - 4; i += 4 )           \
1356         {                                                   \
1357             worktype t0 = cast_macro1(_src[i]);             \
1358             worktype t1 = cast_macro1(_src[i+1]);           \
1359                                                             \
1360             dst[i] = cast_macro2(t0);                       \
1361             dst[i+1] = cast_macro2(t1);                     \
1362                                                             \
1363             t0 = cast_macro1(_src[i+2]);                    \
1364             t1 = cast_macro1(_src[i+3]);                    \
1365                                                             \
1366             dst[i+2] = cast_macro2(t0);                     \
1367             dst[i+3] = cast_macro2(t1);                     \
1368         }                                                   \
1369                                                             \
1370         for( ; i < size.width; i++ )                        \
1371         {                                                   \
1372             worktype t0 = cast_macro1(_src[i]);             \
1373             dst[i] = cast_macro2(t0);                       \
1374         }                                                   \
1375     }                                                       \
1376 }
1377
1378
1379 #define ICV_DEF_CVT_FUNC_2D( flavor, dsttype, worktype, cast_macro2,    \
1380                              srcdepth1, srctype1, cast_macro11,         \
1381                              srcdepth2, srctype2, cast_macro12,         \
1382                              srcdepth3, srctype3, cast_macro13,         \
1383                              srcdepth4, srctype4, cast_macro14,         \
1384                              srcdepth5, srctype5, cast_macro15,         \
1385                              srcdepth6, srctype6, cast_macro16 )        \
1386 static CvStatus CV_STDCALL                                              \
1387 icvCvtTo_##flavor##_C1R( const uchar* src, int srcstep,                 \
1388                          dsttype* dst, int dststep,                     \
1389                          CvSize size, int param )                       \
1390 {                                                                       \
1391     int srctype = param;                                                \
1392     dststep /= sizeof(dst[0]);                                          \
1393                                                                         \
1394     switch( CV_MAT_DEPTH(srctype) )                                     \
1395     {                                                                   \
1396     case srcdepth1:                                                     \
1397         ICV_DEF_CVT_CASE_2D( srctype1, worktype,                        \
1398                              cast_macro11, cast_macro2 );               \
1399         break;                                                          \
1400     case srcdepth2:                                                     \
1401         ICV_DEF_CVT_CASE_2D( srctype2, worktype,                        \
1402                              cast_macro12, cast_macro2 );               \
1403         break;                                                          \
1404     case srcdepth3:                                                     \
1405         ICV_DEF_CVT_CASE_2D( srctype3, worktype,                        \
1406                              cast_macro13, cast_macro2 );               \
1407         break;                                                          \
1408     case srcdepth4:                                                     \
1409         ICV_DEF_CVT_CASE_2D( srctype4, worktype,                        \
1410                              cast_macro14, cast_macro2 );               \
1411         break;                                                          \
1412     case srcdepth5:                                                     \
1413         ICV_DEF_CVT_CASE_2D( srctype5, worktype,                        \
1414                              cast_macro15, cast_macro2 );               \
1415         break;                                                          \
1416     case srcdepth6:                                                     \
1417         ICV_DEF_CVT_CASE_2D( srctype6, worktype,                        \
1418                              cast_macro16, cast_macro2 );               \
1419         break;                                                          \
1420     }                                                                   \
1421                                                                         \
1422     return  CV_OK;                                                      \
1423 }
1424
1425
1426 ICV_DEF_CVT_FUNC_2D( 8u, uchar, int, CV_CAST_8U,
1427                      CV_8S,  schar,  CV_NOP,
1428                      CV_16U, ushort, CV_NOP,
1429                      CV_16S, short,  CV_NOP,
1430                      CV_32S, int,    CV_NOP,
1431                      CV_32F, float,  cvRound,
1432                      CV_64F, double, cvRound )
1433
1434 ICV_DEF_CVT_FUNC_2D( 8s, schar, int, CV_CAST_8S,
1435                      CV_8U,  uchar,  CV_NOP,
1436                      CV_16U, ushort, CV_NOP,
1437                      CV_16S, short,  CV_NOP,
1438                      CV_32S, int,    CV_NOP,
1439                      CV_32F, float,  cvRound,
1440                      CV_64F, double, cvRound )
1441
1442 ICV_DEF_CVT_FUNC_2D( 16u, ushort, int, CV_CAST_16U,
1443                      CV_8U,  uchar,  CV_NOP,
1444                      CV_8S,  schar,  CV_NOP,
1445                      CV_16S, short,  CV_NOP,
1446                      CV_32S, int,    CV_NOP,
1447                      CV_32F, float,  cvRound,
1448                      CV_64F, double, cvRound )
1449
1450 ICV_DEF_CVT_FUNC_2D( 16s, short, int, CV_CAST_16S,
1451                      CV_8U,  uchar,  CV_NOP,
1452                      CV_8S,  schar,  CV_NOP,
1453                      CV_16U, ushort, CV_NOP,
1454                      CV_32S, int,    CV_NOP,
1455                      CV_32F, float,  cvRound,
1456                      CV_64F, double, cvRound )
1457
1458 ICV_DEF_CVT_FUNC_2D( 32s, int, int, CV_NOP,
1459                      CV_8U,  uchar,  CV_NOP,
1460                      CV_8S,  schar,  CV_NOP,
1461                      CV_16U, ushort, CV_NOP,
1462                      CV_16S, short,  CV_NOP,
1463                      CV_32F, float,  cvRound,
1464                      CV_64F, double, cvRound )
1465
1466 ICV_DEF_CVT_FUNC_2D( 32f, float, float, CV_NOP,
1467                      CV_8U,  uchar,  CV_8TO32F,
1468                      CV_8S,  schar,  CV_8TO32F,
1469                      CV_16U, ushort, CV_NOP,
1470                      CV_16S, short,  CV_NOP,
1471                      CV_32S, int,    CV_CAST_32F,
1472                      CV_64F, double, CV_CAST_32F )
1473
1474 ICV_DEF_CVT_FUNC_2D( 64f, double, double, CV_NOP,
1475                      CV_8U,  uchar,  CV_8TO32F,
1476                      CV_8S,  schar,  CV_8TO32F,
1477                      CV_16U, ushort, CV_NOP,
1478                      CV_16S, short,  CV_NOP,
1479                      CV_32S, int,    CV_NOP,
1480                      CV_32F, float,  CV_NOP )
1481
1482 CV_DEF_INIT_FUNC_TAB_2D( CvtTo, C1R )
1483
1484
1485 typedef  CvStatus (CV_STDCALL *CvCvtFunc)( const void* src, int srcstep,
1486                                            void* dst, int dststep, CvSize size,
1487                                            int param );
1488
1489 typedef  CvStatus (CV_STDCALL *CvCvtScaleFunc)( const void* src, int srcstep,
1490                                              void* dst, int dststep, CvSize size,
1491                                              double scale, double shift,
1492                                              int param );
1493
1494 CV_IMPL void
1495 cvConvertScale( const void* srcarr, void* dstarr,
1496                 double scale, double shift )
1497 {
1498     static CvFuncTable cvt_tab, cvtscale_tab;
1499     static int inittab = 0;
1500
1501     CV_FUNCNAME( "cvConvertScale" );
1502
1503     __BEGIN__;
1504
1505     int type;
1506     int is_nd = 0;
1507     CvMat  srcstub, *src = (CvMat*)srcarr;
1508     CvMat  dststub, *dst = (CvMat*)dstarr;
1509     CvSize size;
1510     int src_step, dst_step;
1511     int no_scale = scale == 1 && shift == 0;
1512
1513     if( !CV_IS_MAT(src) )
1514     {
1515         if( CV_IS_MATND(src) )
1516             is_nd = 1;
1517         else
1518         {
1519             int coi = 0;
1520             CV_CALL( src = cvGetMat( src, &srcstub, &coi ));
1521
1522             if( coi != 0 )
1523                 CV_ERROR( CV_BadCOI, "" );
1524         }
1525     }
1526
1527     if( !CV_IS_MAT(dst) )
1528     {
1529         if( CV_IS_MATND(dst) )
1530             is_nd = 1;
1531         else
1532         {
1533             int coi = 0;
1534             CV_CALL( dst = cvGetMat( dst, &dststub, &coi ));
1535
1536             if( coi != 0 )
1537                 CV_ERROR( CV_BadCOI, "" );
1538         }
1539     }
1540
1541     if( is_nd )
1542     {
1543         CvArr* arrs[] = { src, dst };
1544         CvMatND stubs[2];
1545         CvNArrayIterator iterator;
1546         int dsttype;
1547
1548         CV_CALL( cvInitNArrayIterator( 2, arrs, 0, stubs, &iterator, CV_NO_DEPTH_CHECK ));
1549
1550         type = iterator.hdr[0]->type;
1551         dsttype = iterator.hdr[1]->type;
1552         iterator.size.width *= CV_MAT_CN(type);
1553
1554         if( !inittab )
1555         {
1556             icvInitCvtToC1RTable( &cvt_tab );
1557             icvInitCvtScaleToC1RTable( &cvtscale_tab );
1558             inittab = 1;
1559         }
1560
1561         if( no_scale )
1562         {
1563             CvCvtFunc func = (CvCvtFunc)(cvt_tab.fn_2d[CV_MAT_DEPTH(dsttype)]);
1564             if( !func )
1565                 CV_ERROR( CV_StsUnsupportedFormat, "" );
1566
1567             do
1568             {
1569                 IPPI_CALL( func( iterator.ptr[0], CV_STUB_STEP,
1570                                  iterator.ptr[1], CV_STUB_STEP,
1571                                  iterator.size, type ));
1572             }
1573             while( cvNextNArraySlice( &iterator ));
1574         }
1575         else
1576         {
1577             CvCvtScaleFunc func =
1578                 (CvCvtScaleFunc)(cvtscale_tab.fn_2d[CV_MAT_DEPTH(dsttype)]);
1579             if( !func )
1580                 CV_ERROR( CV_StsUnsupportedFormat, "" );
1581
1582             do
1583             {
1584                 IPPI_CALL( func( iterator.ptr[0], CV_STUB_STEP,
1585                                  iterator.ptr[1], CV_STUB_STEP,
1586                                  iterator.size, scale, shift, type ));
1587             }
1588             while( cvNextNArraySlice( &iterator ));
1589         }
1590         EXIT;
1591     }
1592
1593     if( no_scale && CV_ARE_TYPES_EQ( src, dst ) )
1594     {
1595         if( src != dst )
1596           cvCopy( src, dst );
1597         EXIT;
1598     }
1599
1600     if( !CV_ARE_SIZES_EQ( src, dst ))
1601         CV_ERROR( CV_StsUnmatchedSizes, "" );
1602
1603     size = cvGetMatSize( src );
1604     type = CV_MAT_TYPE(src->type);
1605     src_step = src->step;
1606     dst_step = dst->step;
1607
1608     if( CV_IS_MAT_CONT( src->type & dst->type ))
1609     {
1610         size.width *= size.height;
1611         src_step = dst_step = CV_STUB_STEP;
1612         size.height = 1;
1613     }
1614
1615     size.width *= CV_MAT_CN( type );
1616
1617     if( CV_ARE_TYPES_EQ( src, dst ) && size.height == 1 &&
1618         size.width <= CV_MAX_INLINE_MAT_OP_SIZE )
1619     {
1620         if( CV_MAT_DEPTH(type) == CV_32F )
1621         {
1622             const float* srcdata = (const float*)(src->data.ptr);
1623             float* dstdata = (float*)(dst->data.ptr);
1624
1625             do
1626             {
1627                 dstdata[size.width - 1] = (float)(srcdata[size.width-1]*scale + shift);
1628             }
1629             while( --size.width );
1630
1631             EXIT;
1632         }
1633
1634         if( CV_MAT_DEPTH(type) == CV_64F )
1635         {
1636             const double* srcdata = (const double*)(src->data.ptr);
1637             double* dstdata = (double*)(dst->data.ptr);
1638
1639             do
1640             {
1641                 dstdata[size.width - 1] = srcdata[size.width-1]*scale + shift;
1642             }
1643             while( --size.width );
1644
1645             EXIT;
1646         }
1647     }
1648
1649     if( !inittab )
1650     {
1651         icvInitCvtToC1RTable( &cvt_tab );
1652         icvInitCvtScaleToC1RTable( &cvtscale_tab );
1653         inittab = 1;
1654     }
1655
1656     if( !CV_ARE_CNS_EQ( src, dst ))
1657         CV_ERROR( CV_StsUnmatchedFormats, "" );
1658
1659     if( no_scale )
1660     {
1661         CvCvtFunc func = (CvCvtFunc)(cvt_tab.fn_2d[CV_MAT_DEPTH(dst->type)]);
1662
1663         if( !func )
1664             CV_ERROR( CV_StsUnsupportedFormat, "" );
1665
1666         IPPI_CALL( func( src->data.ptr, src_step,
1667                    dst->data.ptr, dst_step, size, type ));
1668     }
1669     else
1670     {
1671         CvCvtScaleFunc func = (CvCvtScaleFunc)
1672             (cvtscale_tab.fn_2d[CV_MAT_DEPTH(dst->type)]);
1673
1674         if( !func )
1675             CV_ERROR( CV_StsUnsupportedFormat, "" );
1676
1677         IPPI_CALL( func( src->data.ptr, src_step,
1678                    dst->data.ptr, dst_step, size,
1679                    scale, shift, type ));
1680     }
1681
1682     __END__;
1683 }
1684
1685 /********************* helper functions for converting 32f<->64f ************************/
1686
1687 IPCVAPI_IMPL( CvStatus, icvCvt_32f64f,
1688     ( const float* src, double* dst, int len ), (src, dst, len) )
1689 {
1690     int i;
1691     for( i = 0; i <= len - 4; i += 4 )
1692     {
1693         double t0 = src[i];
1694         double t1 = src[i+1];
1695
1696         dst[i] = t0;
1697         dst[i+1] = t1;
1698
1699         t0 = src[i+2];
1700         t1 = src[i+3];
1701
1702         dst[i+2] = t0;
1703         dst[i+3] = t1;
1704     }
1705
1706     for( ; i < len; i++ )
1707         dst[i] = src[i];
1708
1709     return CV_OK;
1710 }
1711
1712
1713 IPCVAPI_IMPL( CvStatus, icvCvt_64f32f,
1714     ( const double* src, float* dst, int len ), (src, dst, len) )
1715 {
1716     int i = 0;
1717     for( ; i <= len - 4; i += 4 )
1718     {
1719         double t0 = src[i];
1720         double t1 = src[i+1];
1721
1722         dst[i] = (float)t0;
1723         dst[i+1] = (float)t1;
1724
1725         t0 = src[i+2];
1726         t1 = src[i+3];
1727
1728         dst[i+2] = (float)t0;
1729         dst[i+3] = (float)t1;
1730     }
1731
1732     for( ; i < len; i++ )
1733         dst[i] = (float)src[i];
1734
1735     return CV_OK;
1736 }
1737
1738
1739 CvStatus CV_STDCALL icvScale_32f( const float* src, float* dst, int len, float a, float b )
1740 {
1741     int i;
1742     for( i = 0; i <= len - 4; i += 4 )
1743     {
1744         double t0 = src[i]*a + b;
1745         double t1 = src[i+1]*a + b;
1746
1747         dst[i] = (float)t0;
1748         dst[i+1] = (float)t1;
1749
1750         t0 = src[i+2]*a + b;
1751         t1 = src[i+3]*a + b;
1752
1753         dst[i+2] = (float)t0;
1754         dst[i+3] = (float)t1;
1755     }
1756
1757     for( ; i < len; i++ )
1758         dst[i] = (float)(src[i]*a + b);
1759
1760     return CV_OK;
1761 }
1762
1763
1764 CvStatus CV_STDCALL icvScale_64f( const double* src, double* dst, int len, double a, double b )
1765 {
1766     int i;
1767     for( i = 0; i <= len - 4; i += 4 )
1768     {
1769         double t0 = src[i]*a + b;
1770         double t1 = src[i+1]*a + b;
1771
1772         dst[i] = t0;
1773         dst[i+1] = t1;
1774
1775         t0 = src[i+2]*a + b;
1776         t1 = src[i+3]*a + b;
1777
1778         dst[i+2] = t0;
1779         dst[i+3] = t1;
1780     }
1781
1782     for( ; i < len; i++ )
1783         dst[i] = src[i]*a + b;
1784
1785     return CV_OK;
1786 }
1787
1788 /* End of file. */