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
cvSplit(const void * srcarr,void * dstarr0,void * dstarr1,void * dstarr2,void * dstarr3)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
cvMerge(const void * srcarr0,const void * srcarr1,const void * srcarr2,const void * srcarr3,void * dstarr)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
icvInitMixChannelsTab(CvFuncTable * tab)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
cvMixChannels(const CvArr ** src,int src_count,CvArr ** dst,int dst_count,const int * from_to,int pair_count)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
icvCvtScaleAbsTo_8u_C1R(const uchar * src,int srcstep,uchar * dst,int dststep,CvSize size,double scale,double shift,int param)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
cvConvertScaleAbs(const void * srcarr,void * dstarr,double scale,double shift)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
cvConvertScale(const void * srcarr,void * dstarr,double scale,double shift)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
icvScale_32f(const float * src,float * dst,int len,float a,float b)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
icvScale_64f(const double * src,double * dst,int len,double a,double b)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. */
1789