Update the changelog
[opencv] / cxcore / src / cxcmp.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 /* ////////////////////////////////////////////////////////////////////
43 //
44 //  CvMat comparison functions: range checking, min, max
45 //
46 // */
47
48 #include "_cxcore.h"
49
50 /****************************************************************************************\
51 *                                      InRange[S]                                        *
52 \****************************************************************************************/
53
54 #define ICV_DEF_IN_RANGE_CASE_C1( worktype, _toggle_macro_ )    \
55 for( x = 0; x < size.width; x++ )                               \
56 {                                                               \
57     worktype a1 = _toggle_macro_(src1[x]),                      \
58              a2 = src2[x], a3 = src3[x];                        \
59     dst[x] = (uchar)-(_toggle_macro_(a2) <= a1 &&               \
60                      a1 < _toggle_macro_(a3));                  \
61 }
62
63
64 #define ICV_DEF_IN_RANGE_CASE_C2( worktype, _toggle_macro_ )        \
65 for( x = 0; x < size.width; x++ )                                   \
66 {                                                                   \
67     worktype a1 = _toggle_macro_(src1[x*2]),                        \
68              a2 = src2[x*2], a3 = src3[x*2];                        \
69     int f = _toggle_macro_(a2) <= a1 && a1 < _toggle_macro_(a3);    \
70     a1 = _toggle_macro_(src1[x*2+1]);                               \
71     a2 = src2[x*2+1];                                               \
72     a3 = src3[x*2+1];                                               \
73     f &= _toggle_macro_(a2) <= a1 && a1 < _toggle_macro_(a3);       \
74     dst[x] = (uchar)-f;                                             \
75 }
76
77
78 #define ICV_DEF_IN_RANGE_CASE_C3( worktype, _toggle_macro_ )        \
79 for( x = 0; x < size.width; x++ )                                   \
80 {                                                                   \
81     worktype a1 = _toggle_macro_(src1[x*3]),                        \
82              a2 = src2[x*3], a3 = src3[x*3];                        \
83     int f = _toggle_macro_(a2) <= a1 && a1 < _toggle_macro_(a3);    \
84     a1 = _toggle_macro_(src1[x*3+1]);                               \
85     a2 = src2[x*3+1];                                               \
86     a3 = src3[x*3+1];                                               \
87     f &= _toggle_macro_(a2) <= a1 && a1 < _toggle_macro_(a3);       \
88     a1 = _toggle_macro_(src1[x*3+2]);                               \
89     a2 = src2[x*3+2];                                               \
90     a3 = src3[x*3+2];                                               \
91     f &= _toggle_macro_(a2) <= a1 && a1 < _toggle_macro_(a3);       \
92     dst[x] = (uchar)-f;                                             \
93 }
94
95
96 #define ICV_DEF_IN_RANGE_CASE_C4( worktype, _toggle_macro_ )        \
97 for( x = 0; x < size.width; x++ )                                   \
98 {                                                                   \
99     worktype a1 = _toggle_macro_(src1[x*4]),                        \
100              a2 = src2[x*4], a3 = src3[x*4];                        \
101     int f = _toggle_macro_(a2) <= a1 && a1 < _toggle_macro_(a3);    \
102     a1 = _toggle_macro_(src1[x*4+1]);                               \
103     a2 = src2[x*4+1];                                               \
104     a3 = src3[x*4+1];                                               \
105     f &= _toggle_macro_(a2) <= a1 && a1 < _toggle_macro_(a3);       \
106     a1 = _toggle_macro_(src1[x*4+2]);                               \
107     a2 = src2[x*4+2];                                               \
108     a3 = src3[x*4+2];                                               \
109     f &= _toggle_macro_(a2) <= a1 && a1 < _toggle_macro_(a3);       \
110     a1 = _toggle_macro_(src1[x*4+3]);                               \
111     a2 = src2[x*4+3];                                               \
112     a3 = src3[x*4+3];                                               \
113     f &= _toggle_macro_(a2) <= a1 && a1 < _toggle_macro_(a3);       \
114     dst[x] = (uchar)-f;                                             \
115 }
116
117
118 #define ICV_DEF_IN_RANGE_FUNC( flavor, arrtype, worktype,           \
119                                _toggle_macro_, cn )                 \
120 static CvStatus CV_STDCALL                                          \
121 icvInRange_##flavor##_C##cn##R( const arrtype* src1, int step1,     \
122                                 const arrtype* src2, int step2,     \
123                                 const arrtype* src3, int step3,     \
124                                 uchar* dst, int step, CvSize size ) \
125 {                                                                   \
126     step1 /= sizeof(src1[0]); step2 /= sizeof(src2[0]);             \
127     step3 /= sizeof(src3[0]); step /= sizeof(dst[0]);               \
128                                                                     \
129     for( ; size.height--; src1 += step1, src2 += step2,             \
130                           src3 += step3, dst += step )              \
131     {                                                               \
132         int x;                                                      \
133         ICV_DEF_IN_RANGE_CASE_C##cn( worktype, _toggle_macro_ )     \
134     }                                                               \
135                                                                     \
136     return CV_OK;                                                   \
137 }
138
139
140 #define ICV_DEF_IN_RANGE_CASE_CONST_C1( worktype, _toggle_macro_ )  \
141 for( x = 0; x < size.width; x++ )                                   \
142 {                                                                   \
143     worktype a1 = _toggle_macro_(src1[x]);                          \
144     dst[x] = (uchar)-(scalar[0] <= a1 && a1 < scalar[1]);           \
145 }
146
147
148 #define ICV_DEF_IN_RANGE_CASE_CONST_C2( worktype, _toggle_macro_ )  \
149 for( x = 0; x < size.width; x++ )                                   \
150 {                                                                   \
151     worktype a1 = _toggle_macro_(src1[x*2]);                        \
152     int f = scalar[0] <= a1 && a1 < scalar[2];                      \
153     a1 = _toggle_macro_(src1[x*2+1]);                               \
154     f &= scalar[1] <= a1 && a1 < scalar[3];                         \
155     dst[x] = (uchar)-f;                                             \
156 }
157
158
159 #define ICV_DEF_IN_RANGE_CASE_CONST_C3( worktype, _toggle_macro_ )  \
160 for( x = 0; x < size.width; x++ )                                   \
161 {                                                                   \
162     worktype a1 = _toggle_macro_(src1[x*3]);                        \
163     int f = scalar[0] <= a1 && a1 < scalar[3];                      \
164     a1 = _toggle_macro_(src1[x*3+1]);                               \
165     f &= scalar[1] <= a1 && a1 < scalar[4];                         \
166     a1 = _toggle_macro_(src1[x*3+2]);                               \
167     f &= scalar[2] <= a1 && a1 < scalar[5];                         \
168     dst[x] = (uchar)-f;                                             \
169 }
170
171
172 #define ICV_DEF_IN_RANGE_CASE_CONST_C4( worktype, _toggle_macro_ )  \
173 for( x = 0; x < size.width; x++ )                                   \
174 {                                                                   \
175     worktype a1 = _toggle_macro_(src1[x*4]);                        \
176     int f = scalar[0] <= a1 && a1 < scalar[4];                      \
177     a1 = _toggle_macro_(src1[x*4+1]);                               \
178     f &= scalar[1] <= a1 && a1 < scalar[5];                         \
179     a1 = _toggle_macro_(src1[x*4+2]);                               \
180     f &= scalar[2] <= a1 && a1 < scalar[6];                         \
181     a1 = _toggle_macro_(src1[x*4+3]);                               \
182     f &= scalar[3] <= a1 && a1 < scalar[7];                         \
183     dst[x] = (uchar)-f;                                             \
184 }
185
186
187 #define ICV_DEF_IN_RANGE_CONST_FUNC( flavor, arrtype, worktype,     \
188                                      _toggle_macro_, cn )           \
189 static CvStatus CV_STDCALL                                          \
190 icvInRangeC_##flavor##_C##cn##R( const arrtype* src1, int step1,    \
191                                  uchar* dst, int step, CvSize size, \
192                                  const worktype* scalar )           \
193 {                                                                   \
194     step1 /= sizeof(src1[0]); step /= sizeof(dst[0]);               \
195                                                                     \
196     for( ; size.height--; src1 += step1, dst += step )              \
197     {                                                               \
198         int x;                                                      \
199         ICV_DEF_IN_RANGE_CASE_CONST_C##cn( worktype, _toggle_macro_)\
200     }                                                               \
201                                                                     \
202     return CV_OK;                                                   \
203 }
204
205
206 #define ICV_DEF_IN_RANGE_ALL( flavor, arrtype, worktype, _toggle_macro_ )   \
207 ICV_DEF_IN_RANGE_FUNC( flavor, arrtype, worktype, _toggle_macro_, 1 )       \
208 ICV_DEF_IN_RANGE_FUNC( flavor, arrtype, worktype, _toggle_macro_, 2 )       \
209 ICV_DEF_IN_RANGE_FUNC( flavor, arrtype, worktype, _toggle_macro_, 3 )       \
210 ICV_DEF_IN_RANGE_FUNC( flavor, arrtype, worktype, _toggle_macro_, 4 )       \
211                                                                             \
212 ICV_DEF_IN_RANGE_CONST_FUNC( flavor, arrtype, worktype, _toggle_macro_, 1 ) \
213 ICV_DEF_IN_RANGE_CONST_FUNC( flavor, arrtype, worktype, _toggle_macro_, 2 ) \
214 ICV_DEF_IN_RANGE_CONST_FUNC( flavor, arrtype, worktype, _toggle_macro_, 3 ) \
215 ICV_DEF_IN_RANGE_CONST_FUNC( flavor, arrtype, worktype, _toggle_macro_, 4 )
216
217 ICV_DEF_IN_RANGE_ALL( 8u, uchar, int, CV_NOP )
218 ICV_DEF_IN_RANGE_ALL( 16u, ushort, int, CV_NOP )
219 ICV_DEF_IN_RANGE_ALL( 16s, short, int, CV_NOP )
220 ICV_DEF_IN_RANGE_ALL( 32s, int, int, CV_NOP )
221 ICV_DEF_IN_RANGE_ALL( 32f, float, float, CV_NOP )
222 ICV_DEF_IN_RANGE_ALL( 64f, double, double, CV_NOP )
223
224 #define icvInRange_8s_C1R 0
225 #define icvInRange_8s_C2R 0
226 #define icvInRange_8s_C3R 0
227 #define icvInRange_8s_C4R 0
228
229 #define icvInRangeC_8s_C1R 0
230 #define icvInRangeC_8s_C2R 0
231 #define icvInRangeC_8s_C3R 0
232 #define icvInRangeC_8s_C4R 0
233
234 CV_DEF_INIT_BIG_FUNC_TAB_2D( InRange, R )
235 CV_DEF_INIT_BIG_FUNC_TAB_2D( InRangeC, R )
236
237 typedef CvStatus (CV_STDCALL * CvInRangeCFunc)( const void* src, int srcstep,
238                                                 uchar* dst, int dststep,
239                                                 CvSize size, const void* scalar );
240
241 /*************************************** InRange ****************************************/
242
243 CV_IMPL void
244 cvInRange( const void* srcarr1, const void* srcarr2,
245            const void* srcarr3, void* dstarr )
246 {
247     static CvBigFuncTable inrange_tab;
248     static int inittab = 0;
249
250     CV_FUNCNAME( "cvInRange" );
251
252     __BEGIN__;
253
254     int type, coi = 0;
255     int src1_step, src2_step, src3_step, dst_step;
256     CvMat srcstub1, *src1 = (CvMat*)srcarr1;
257     CvMat srcstub2, *src2 = (CvMat*)srcarr2;
258     CvMat srcstub3, *src3 = (CvMat*)srcarr3;
259     CvMat dststub,  *dst = (CvMat*)dstarr;
260     CvSize size;
261     CvFunc2D_4A func;
262
263     if( !inittab )
264     {
265         icvInitInRangeRTable( &inrange_tab );
266         inittab = 1;
267     }
268
269     if( !CV_IS_MAT(src1) )
270     {
271         CV_CALL( src1 = cvGetMat( src1, &srcstub1, &coi ));
272         if( coi != 0 )
273             CV_ERROR( CV_BadCOI, "" );
274     }
275
276     if( !CV_IS_MAT(src2) )
277     {
278         CV_CALL( src2 = cvGetMat( src2, &srcstub2, &coi ));
279         if( coi != 0 )
280             CV_ERROR( CV_BadCOI, "" );
281     }
282
283     if( !CV_IS_MAT(src3) )
284     {
285         CV_CALL( src3 = cvGetMat( src3, &srcstub3, &coi ));
286         if( coi != 0 )
287             CV_ERROR( CV_BadCOI, "" );
288     }
289
290     if( !CV_IS_MAT(dst) )
291     {
292         CV_CALL( dst = cvGetMat( dst, &dststub, &coi ));
293         if( coi != 0 )
294             CV_ERROR( CV_BadCOI, "" );
295     }
296
297     if( !CV_ARE_TYPES_EQ( src1, src2 ) ||
298         !CV_ARE_TYPES_EQ( src1, src3 ) )
299         CV_ERROR_FROM_CODE( CV_StsUnmatchedFormats );
300
301     if( !CV_IS_MASK_ARR( dst ))
302         CV_ERROR( CV_StsUnsupportedFormat, "Destination image should be 8uC1 or 8sC1");
303
304     if( !CV_ARE_SIZES_EQ( src1, src2 ) ||
305         !CV_ARE_SIZES_EQ( src1, src3 ) ||
306         !CV_ARE_SIZES_EQ( src1, dst ))
307         CV_ERROR_FROM_CODE( CV_StsUnmatchedSizes );
308
309     type = CV_MAT_TYPE(src1->type);
310     size = cvGetMatSize( src1 );
311
312     if( CV_IS_MAT_CONT( src1->type & src2->type & src3->type & dst->type ))
313     {
314         size.width *= size.height;
315         src1_step = src2_step = src3_step = dst_step = CV_STUB_STEP;
316         size.height = 1;
317     }
318     else
319     {
320         src1_step = src1->step;
321         src2_step = src2->step;
322         src3_step = src3->step;
323         dst_step = dst->step;
324     }
325
326     if( CV_MAT_CN(type) > 4 )
327         CV_ERROR( CV_StsOutOfRange, "The number of channels must be 1, 2, 3 or 4" );
328
329     func = (CvFunc2D_4A)(inrange_tab.fn_2d[type]);
330
331     if( !func )
332         CV_ERROR( CV_StsUnsupportedFormat, "" );
333
334     IPPI_CALL( func( src1->data.ptr, src1_step, src2->data.ptr, src2_step,
335                      src3->data.ptr, src3_step, dst->data.ptr, dst_step, size ));
336
337     __END__;
338 }
339
340
341 /************************************** InRangeS ****************************************/
342
343 CV_IMPL void
344 cvInRangeS( const void* srcarr, CvScalar lower, CvScalar upper, void* dstarr )
345 {
346     static CvBigFuncTable inrange_tab;
347     static int inittab = 0;
348
349     CV_FUNCNAME( "cvInRangeS" );
350
351     __BEGIN__;
352
353     int sctype, type, coi = 0;
354     int src1_step, dst_step;
355     CvMat srcstub1, *src1 = (CvMat*)srcarr;
356     CvMat dststub,  *dst = (CvMat*)dstarr;
357     CvSize size;
358     CvInRangeCFunc func;
359     double buf[8];
360
361     if( !inittab )
362     {
363         icvInitInRangeCRTable( &inrange_tab );
364         inittab = 1;
365     }
366
367     if( !CV_IS_MAT(src1) )
368     {
369         CV_CALL( src1 = cvGetMat( src1, &srcstub1, &coi ));
370         if( coi != 0 )
371             CV_ERROR( CV_BadCOI, "" );
372     }
373
374     if( !CV_IS_MAT(dst) )
375     {
376         CV_CALL( dst = cvGetMat( dst, &dststub, &coi ));
377         if( coi != 0 )
378             CV_ERROR( CV_BadCOI, "" );
379     }
380
381     if( !CV_IS_MASK_ARR( dst ))
382         CV_ERROR( CV_StsUnsupportedFormat, "Destination image should be 8uC1 or 8sC1");
383
384     if( !CV_ARE_SIZES_EQ( src1, dst ))
385         CV_ERROR_FROM_CODE( CV_StsUnmatchedSizes );
386
387     sctype = type = CV_MAT_TYPE(src1->type);
388     if( CV_MAT_DEPTH(sctype) < CV_32S )
389         sctype = (type & CV_MAT_CN_MASK) | CV_32SC1;
390
391     size = cvGetMatSize( src1 );
392
393     if( CV_IS_MAT_CONT( src1->type & dst->type ))
394     {
395         size.width *= size.height;
396         src1_step = dst_step = CV_STUB_STEP;
397         size.height = 1;
398     }
399     else
400     {
401         src1_step = src1->step;
402         dst_step = dst->step;
403     }
404
405     if( CV_MAT_CN(type) > 4 )
406         CV_ERROR( CV_StsOutOfRange, "The number of channels must be 1, 2, 3 or 4" );
407
408     func = (CvInRangeCFunc)(inrange_tab.fn_2d[type]);
409
410     if( !func )
411         CV_ERROR( CV_StsUnsupportedFormat, "" );
412
413     cvScalarToRawData( &lower, buf, sctype, 0 );
414     cvScalarToRawData( &upper, (char*)buf + CV_ELEM_SIZE(sctype), sctype, 0 );
415
416     IPPI_CALL( func( src1->data.ptr, src1_step, dst->data.ptr,
417                      dst_step, size, buf ));
418
419     __END__;
420 }
421
422
423 /****************************************************************************************\
424 *                                         Cmp                                            *
425 \****************************************************************************************/
426
427 #define ICV_DEF_CMP_CASE_C1( __op__, _toggle_macro_ )                   \
428 for( x = 0; x <= size.width - 4; x += 4 )                               \
429 {                                                                       \
430     int f0 = __op__( _toggle_macro_(src1[x]), _toggle_macro_(src2[x])); \
431     int f1 = __op__( _toggle_macro_(src1[x+1]), _toggle_macro_(src2[x+1])); \
432     dst[x] = (uchar)-f0;                                                \
433     dst[x+1] = (uchar)-f1;                                              \
434     f0 = __op__( _toggle_macro_(src1[x+2]), _toggle_macro_(src2[x+2])); \
435     f1 = __op__( _toggle_macro_(src1[x+3]), _toggle_macro_(src2[x+3])); \
436     dst[x+2] = (uchar)-f0;                                              \
437     dst[x+3] = (uchar)-f1;                                              \
438 }                                                                       \
439                                                                         \
440 for( ; x < size.width; x++ )                                            \
441 {                                                                       \
442     int f0 = __op__( _toggle_macro_(src1[x]), _toggle_macro_(src2[x])); \
443     dst[x] = (uchar)-f0;                                                \
444 }
445
446
447 #define ICV_DEF_CMP_FUNC( __op__, name, flavor, arrtype,        \
448                           worktype, _toggle_macro_ )            \
449 static CvStatus CV_STDCALL                                      \
450 icv##name##_##flavor##_C1R( const arrtype* src1, int step1,     \
451                             const arrtype* src2, int step2,     \
452                             uchar* dst, int step, CvSize size ) \
453 {                                                               \
454     step1 /= sizeof(src1[0]); step2 /= sizeof(src2[0]);         \
455     step /= sizeof(dst[0]);                                     \
456                                                                 \
457     for( ; size.height--; src1 += step1, src2 += step2,         \
458                           dst += step )                         \
459     {                                                           \
460         int x;                                                  \
461         ICV_DEF_CMP_CASE_C1( __op__, _toggle_macro_ )           \
462     }                                                           \
463                                                                 \
464     return CV_OK;                                               \
465 }
466
467
468 #define ICV_DEF_CMP_CONST_CASE_C1( __op__, _toggle_macro_ )     \
469 for( x = 0; x <= size.width - 4; x += 4 )                       \
470 {                                                               \
471     int f0 = __op__( _toggle_macro_(src1[x]), scalar );         \
472     int f1 = __op__( _toggle_macro_(src1[x+1]), scalar );       \
473     dst[x] = (uchar)-f0;                                        \
474     dst[x+1] = (uchar)-f1;                                      \
475     f0 = __op__( _toggle_macro_(src1[x+2]), scalar );           \
476     f1 = __op__( _toggle_macro_(src1[x+3]), scalar );           \
477     dst[x+2] = (uchar)-f0;                                      \
478     dst[x+3] = (uchar)-f1;                                      \
479 }                                                               \
480                                                                 \
481 for( ; x < size.width; x++ )                                    \
482 {                                                               \
483     int f0 = __op__( _toggle_macro_(src1[x]), scalar );         \
484     dst[x] = (uchar)-f0;                                        \
485 }
486
487
488 #define ICV_DEF_CMP_CONST_FUNC( __op__, name, flavor, arrtype,  \
489                                 worktype, _toggle_macro_)       \
490 static CvStatus CV_STDCALL                                      \
491 icv##name##C_##flavor##_C1R( const arrtype* src1, int step1,    \
492                              uchar* dst, int step,              \
493                              CvSize size, worktype* pScalar )   \
494 {                                                               \
495     worktype scalar = *pScalar;                                 \
496     step1 /= sizeof(src1[0]); step /= sizeof(dst[0]);           \
497                                                                 \
498     for( ; size.height--; src1 += step1, dst += step )          \
499     {                                                           \
500         int x;                                                  \
501         ICV_DEF_CMP_CONST_CASE_C1( __op__, _toggle_macro_ )     \
502     }                                                           \
503                                                                 \
504     return CV_OK;                                               \
505 }
506
507
508 #define ICV_DEF_CMP_ALL( flavor, arrtype, worktype, _toggle_macro_ )            \
509 ICV_DEF_CMP_FUNC( CV_GT, CmpGT, flavor, arrtype, worktype, _toggle_macro_ )     \
510 ICV_DEF_CMP_FUNC( CV_EQ, CmpEQ, flavor, arrtype, worktype, _toggle_macro_ )     \
511 ICV_DEF_CMP_CONST_FUNC( CV_GT, CmpGT, flavor, arrtype, worktype, _toggle_macro_)\
512 ICV_DEF_CMP_CONST_FUNC( CV_GE, CmpGE, flavor, arrtype, worktype, _toggle_macro_)\
513 ICV_DEF_CMP_CONST_FUNC( CV_EQ, CmpEQ, flavor, arrtype, worktype, _toggle_macro_)
514
515 ICV_DEF_CMP_ALL( 8u, uchar, int, CV_NOP )
516 ICV_DEF_CMP_ALL( 16u, ushort, int, CV_NOP )
517 ICV_DEF_CMP_ALL( 16s, short, int, CV_NOP )
518 ICV_DEF_CMP_ALL( 32s, int, int, CV_NOP )
519 ICV_DEF_CMP_ALL( 32f, float, double, CV_NOP )
520 ICV_DEF_CMP_ALL( 64f, double, double, CV_NOP )
521
522 #define icvCmpGT_8s_C1R     0
523 #define icvCmpEQ_8s_C1R     0
524 #define icvCmpGTC_8s_C1R    0
525 #define icvCmpGEC_8s_C1R    0
526 #define icvCmpEQC_8s_C1R    0
527
528 CV_DEF_INIT_FUNC_TAB_2D( CmpGT, C1R )
529 CV_DEF_INIT_FUNC_TAB_2D( CmpEQ, C1R )
530 CV_DEF_INIT_FUNC_TAB_2D( CmpGTC, C1R )
531 CV_DEF_INIT_FUNC_TAB_2D( CmpGEC, C1R )
532 CV_DEF_INIT_FUNC_TAB_2D( CmpEQC, C1R )
533
534 icvCompare_8u_C1R_t icvCompare_8u_C1R_p = 0;
535 icvCompare_16s_C1R_t icvCompare_16s_C1R_p = 0;
536 icvCompare_32f_C1R_t icvCompare_32f_C1R_p = 0;
537
538 icvCompareC_8u_C1R_t icvCompareC_8u_C1R_p = 0;
539 icvCompareC_16s_C1R_t icvCompareC_16s_C1R_p = 0;
540 icvCompareC_32f_C1R_t icvCompareC_32f_C1R_p = 0;
541
542 icvThreshold_GT_8u_C1R_t icvThreshold_GT_8u_C1R_p = 0;
543 icvThreshold_GT_16s_C1R_t icvThreshold_GT_16s_C1R_p = 0;
544 icvThreshold_GT_32f_C1R_t icvThreshold_GT_32f_C1R_p = 0;
545
546 icvThreshold_LT_8u_C1R_t icvThreshold_LT_8u_C1R_p = 0;
547 icvThreshold_LT_16s_C1R_t icvThreshold_LT_16s_C1R_p = 0;
548 icvThreshold_LT_32f_C1R_t icvThreshold_LT_32f_C1R_p = 0;
549
550 /***************************************** cvCmp ****************************************/
551
552 CV_IMPL void
553 cvCmp( const void* srcarr1, const void* srcarr2,
554        void* dstarr, int cmp_op )
555 {
556     static CvFuncTable cmp_tab[2];
557     static int inittab = 0;
558
559     CV_FUNCNAME( "cvCmp" );
560
561     __BEGIN__;
562
563     int type, coi = 0;
564     int invflag = 0;
565     CvCmpOp ipp_cmp_op;
566     int src1_step, src2_step, dst_step;
567     CvMat srcstub1, *src1 = (CvMat*)srcarr1;
568     CvMat srcstub2, *src2 = (CvMat*)srcarr2;
569     CvMat dststub,  *dst = (CvMat*)dstarr;
570     CvMat *temp;
571     CvSize size;
572     CvFunc2D_3A func;
573
574     if( !inittab )
575     {
576         icvInitCmpGTC1RTable( &cmp_tab[0] );
577         icvInitCmpEQC1RTable( &cmp_tab[1] );
578         inittab = 1;
579     }
580
581     if( !CV_IS_MAT(src1) )
582     {
583         CV_CALL( src1 = cvGetMat( src1, &srcstub1, &coi ));
584         if( coi != 0 )
585             CV_ERROR( CV_BadCOI, "" );
586     }
587
588     if( !CV_IS_MAT(src2) )
589     {
590         CV_CALL( src2 = cvGetMat( src2, &srcstub2, &coi ));
591         if( coi != 0 )
592             CV_ERROR( CV_BadCOI, "" );
593     }
594
595     if( !CV_IS_MAT(dst) )
596     {
597         CV_CALL( dst = cvGetMat( dst, &dststub, &coi ));
598         if( coi != 0 )
599             CV_ERROR( CV_BadCOI, "" );
600     }
601
602     switch( cmp_op )
603     {
604     case CV_CMP_GT:
605     case CV_CMP_EQ:
606         break;
607     case CV_CMP_GE:
608         CV_SWAP( src1, src2, temp );
609         invflag = 1;
610         break;
611     case CV_CMP_LT:
612         CV_SWAP( src1, src2, temp );
613         break;
614     case CV_CMP_LE:
615         invflag = 1;
616         break;
617     case CV_CMP_NE:
618         cmp_op = CV_CMP_EQ;
619         invflag = 1;
620         break;
621     default:
622         CV_ERROR( CV_StsBadArg, "Unknown comparison operation" );
623     }
624
625     if( !CV_ARE_TYPES_EQ( src1, src2 ) )
626         CV_ERROR_FROM_CODE( CV_StsUnmatchedFormats );
627
628     if( CV_MAT_CN( src1->type ) != 1 )
629         CV_ERROR( CV_StsUnsupportedFormat, "Input arrays must be single-channel");
630
631     if( !CV_IS_MASK_ARR( dst ))
632         CV_ERROR( CV_StsUnsupportedFormat, "Destination array should be 8uC1 or 8sC1");
633
634     if( !CV_ARE_SIZES_EQ( src1, src2 ) ||
635         !CV_ARE_SIZES_EQ( src1, dst ))
636         CV_ERROR_FROM_CODE( CV_StsUnmatchedSizes );
637
638     type = CV_MAT_TYPE(src1->type);
639     size = cvGetMatSize( src1 );
640
641     if( CV_IS_MAT_CONT( src1->type & src2->type & dst->type ))
642     {
643         size.width *= size.height;
644         src1_step = src2_step = dst_step = CV_STUB_STEP;
645         size.height = 1;
646     }
647     else
648     {
649         src1_step = src1->step;
650         src2_step = src2->step;
651         dst_step = dst->step;
652     }
653
654     func = (CvFunc2D_3A)(cmp_tab[cmp_op == CV_CMP_EQ].fn_2d[type]);
655
656     if( !func )
657         CV_ERROR( CV_StsUnsupportedFormat, "" );
658
659     ipp_cmp_op = cmp_op == CV_CMP_EQ ? cvCmpEq : cvCmpGreater;
660
661     if( type == CV_8U && icvCompare_8u_C1R_p )
662     {
663         IPPI_CALL( icvCompare_8u_C1R_p( src1->data.ptr, src1_step, src2->data.ptr,
664                             src2_step, dst->data.ptr, dst_step, size, ipp_cmp_op ));
665     }
666     else if( type == CV_16S && icvCompare_16s_C1R_p )
667     {
668         IPPI_CALL( icvCompare_16s_C1R_p( src1->data.s, src1_step, src2->data.s,
669                             src2_step, dst->data.s, dst_step, size, ipp_cmp_op ));
670     }
671     else if( type == CV_32F && icvCompare_32f_C1R_p )
672     {
673         IPPI_CALL( icvCompare_32f_C1R_p( src1->data.fl, src1_step, src2->data.fl,
674                             src2_step, dst->data.fl, dst_step, size, ipp_cmp_op ));
675     }
676     else
677     {
678         IPPI_CALL( func( src1->data.ptr, src1_step, src2->data.ptr, src2_step,
679                          dst->data.ptr, dst_step, size ));
680     }
681
682     if( invflag )
683         IPPI_CALL( icvNot_8u_C1R( dst->data.ptr, dst_step,
684                            dst->data.ptr, dst_step, size ));
685
686     __END__;
687 }
688
689
690 /*************************************** cvCmpS *****************************************/
691
692 CV_IMPL void
693 cvCmpS( const void* srcarr, double value, void* dstarr, int cmp_op )
694 {
695     static CvFuncTable cmps_tab[3];
696     static int inittab = 0;
697
698     CV_FUNCNAME( "cvCmpS" );
699
700     __BEGIN__;
701
702     int y, type, coi = 0;
703     int invflag = 0, ipp_cmp_op;
704     int src1_step, dst_step;
705     CvMat srcstub1, *src1 = (CvMat*)srcarr;
706     CvMat dststub,  *dst = (CvMat*)dstarr;
707     CvSize size;
708     int ival = 0;
709
710     if( !inittab )
711     {
712         icvInitCmpEQCC1RTable( &cmps_tab[CV_CMP_EQ] );
713         icvInitCmpGTCC1RTable( &cmps_tab[CV_CMP_GT] );
714         icvInitCmpGECC1RTable( &cmps_tab[CV_CMP_GE] );
715         inittab = 1;
716     }
717
718     if( !CV_IS_MAT(src1) )
719     {
720         CV_CALL( src1 = cvGetMat( src1, &srcstub1, &coi ));
721         if( coi != 0 )
722             CV_ERROR( CV_BadCOI, "" );
723     }
724
725     if( !CV_IS_MAT(dst) )
726     {
727         CV_CALL( dst = cvGetMat( dst, &dststub, &coi ));
728         if( coi != 0 )
729             CV_ERROR( CV_BadCOI, "" );
730     }
731
732     switch( cmp_op )
733     {
734     case CV_CMP_GT:
735     case CV_CMP_EQ:
736     case CV_CMP_GE:
737         break;
738     case CV_CMP_LT:
739         invflag = 1;
740         cmp_op = CV_CMP_GE;
741         break;
742     case CV_CMP_LE:
743         invflag = 1;
744         cmp_op = CV_CMP_GT;
745         break;
746     case CV_CMP_NE:
747         invflag = 1;
748         cmp_op = CV_CMP_EQ;
749         break;
750     default:
751         CV_ERROR( CV_StsBadArg, "Unknown comparison operation" );
752     }
753
754     if( !CV_IS_MASK_ARR( dst ))
755         CV_ERROR( CV_StsUnsupportedFormat, "Destination array should be 8uC1 or 8sC1");
756
757     if( CV_MAT_CN( src1->type ) != 1 )
758         CV_ERROR( CV_StsUnsupportedFormat, "Input array must be single-channel");
759
760     if( !CV_ARE_SIZES_EQ( src1, dst ))
761         CV_ERROR_FROM_CODE( CV_StsUnmatchedSizes );
762
763     type = CV_MAT_TYPE(src1->type);
764     size = cvGetMatSize( src1 );
765
766     if( CV_IS_MAT_CONT( src1->type & dst->type ))
767     {
768         size.width *= size.height;
769         src1_step = dst_step = CV_STUB_STEP;
770         size.height = 1;
771     }
772     else
773     {
774         src1_step = src1->step;
775         dst_step = dst->step;
776     }
777
778     if( CV_MAT_DEPTH(type) <= CV_32S )
779     {
780         ival = cvRound(value);
781         if( type == CV_8U || type == CV_16S )
782         {
783             int minval = type == CV_8U ? 0 : -32768;
784             int maxval = type == CV_8U ? 255 : 32767;
785             int fillval = -1;
786             if( ival < minval )
787                 fillval = cmp_op == CV_CMP_NE || cmp_op == CV_CMP_GE || cmp_op == CV_CMP_GT ? 255 : 0;
788             else if( ival > maxval )
789                 fillval = cmp_op == CV_CMP_NE || cmp_op == CV_CMP_LE || cmp_op == CV_CMP_LT ? 255 : 0;
790             if( fillval >= 0 )
791             {
792                 fillval ^= invflag ? 255 : 0;
793                 for( y = 0; y < size.height; y++ )
794                     memset( dst->data.ptr + y*dst_step, fillval, size.width );
795                 EXIT;
796             }
797         }
798     }
799
800     ipp_cmp_op = cmp_op == CV_CMP_EQ ? cvCmpEq :
801                  cmp_op == CV_CMP_GE ? cvCmpGreaterEq : cvCmpGreater;
802     if( type == CV_8U && icvCompare_8u_C1R_p )
803     {
804         IPPI_CALL( icvCompareC_8u_C1R_p( src1->data.ptr, src1_step, (uchar)ival,
805                                          dst->data.ptr, dst_step, size, ipp_cmp_op ));
806     }
807     else if( type == CV_16S && icvCompare_16s_C1R_p )
808     {
809         IPPI_CALL( icvCompareC_16s_C1R_p( src1->data.s, src1_step, (short)ival,
810                                           dst->data.s, dst_step, size, ipp_cmp_op ));
811     }
812     else if( type == CV_32F && icvCompare_32f_C1R_p )
813     {
814         IPPI_CALL( icvCompareC_32f_C1R_p( src1->data.fl, src1_step, (float)value,
815                                           dst->data.fl, dst_step, size, ipp_cmp_op ));
816     }
817     else
818     {
819         CvFunc2D_2A1P func = (CvFunc2D_2A1P)(cmps_tab[cmp_op].fn_2d[type]);
820         if( !func )
821             CV_ERROR( CV_StsUnsupportedFormat, "" );
822
823         if( type <= CV_32S )
824         {
825             IPPI_CALL( func( src1->data.ptr, src1_step, dst->data.ptr,
826                              dst_step, size, &ival ));
827         }
828         else
829         {
830             IPPI_CALL( func( src1->data.ptr, src1_step, dst->data.ptr,
831                              dst_step, size, &value ));
832         }
833     }
834
835     if( invflag )
836         IPPI_CALL( icvNot_8u_C1R( dst->data.ptr, dst_step,
837                            dst->data.ptr, dst_step, size ));
838
839     __END__;
840 }
841
842
843 /****************************************************************************************\
844 *                                       Min/Max                                          *
845 \****************************************************************************************/
846
847
848 #define ICV_DEF_MINMAX_FUNC( __op__, name, flavor, arrtype, \
849                              worktype, _toggle_macro_ )     \
850 static CvStatus CV_STDCALL                                  \
851 icv##name##_##flavor##_C1R( const arrtype* src1, int step1, \
852     const arrtype* src2, int step2,                         \
853     arrtype* dst, int step, CvSize size )                   \
854 {                                                           \
855     step1 /= sizeof(src1[0]); step2 /= sizeof(src2[0]);     \
856     step /= sizeof(dst[0]);                                 \
857                                                             \
858     for( ; size.height--; src1 += step1,                    \
859             src2 += step2, dst += step )                    \
860     {                                                       \
861         int x;                                              \
862         for( x = 0; x <= size.width - 4; x += 4 )           \
863         {                                                   \
864             worktype a0 = _toggle_macro_(src1[x]);          \
865             worktype b0 = _toggle_macro_(src2[x]);          \
866             worktype a1 = _toggle_macro_(src1[x+1]);        \
867             worktype b1 = _toggle_macro_(src2[x+1]);        \
868             a0 = __op__( a0, b0 );                          \
869             a1 = __op__( a1, b1 );                          \
870             dst[x] = (arrtype)_toggle_macro_(a0);           \
871             dst[x+1] = (arrtype)_toggle_macro_(a1);         \
872             a0 = _toggle_macro_(src1[x+2]);                 \
873             b0 = _toggle_macro_(src2[x+2]);                 \
874             a1 = _toggle_macro_(src1[x+3]);                 \
875             b1 = _toggle_macro_(src2[x+3]);                 \
876             a0 = __op__( a0, b0 );                          \
877             a1 = __op__( a1, b1 );                          \
878             dst[x+2] = (arrtype)_toggle_macro_(a0);         \
879             dst[x+3] = (arrtype)_toggle_macro_(a1);         \
880         }                                                   \
881                                                             \
882         for( ; x < size.width; x++ )                        \
883         {                                                   \
884             worktype a0 = _toggle_macro_(src1[x]);          \
885             worktype b0 = _toggle_macro_(src2[x]);          \
886             a0 = __op__( a0, b0 );                          \
887             dst[x] = (arrtype)_toggle_macro_(a0);           \
888         }                                                   \
889     }                                                       \
890                                                             \
891     return CV_OK;                                           \
892 }
893
894
895 #define ICV_DEF_MINMAX_CONST_FUNC( __op__, name,            \
896     flavor, arrtype, worktype, _toggle_macro_)              \
897 static CvStatus CV_STDCALL                                  \
898 icv##name##C_##flavor##_C1R( const arrtype* src1, int step1,\
899                              arrtype* dst, int step,        \
900                              CvSize size, worktype* pScalar)\
901 {                                                           \
902     worktype scalar = _toggle_macro_(*pScalar);             \
903     step1 /= sizeof(src1[0]); step /= sizeof(dst[0]);       \
904                                                             \
905     for( ; size.height--; src1 += step1, dst += step )      \
906     {                                                       \
907         int x;                                              \
908         for( x = 0; x <= size.width - 4; x += 4 )           \
909         {                                                   \
910             worktype a0 = _toggle_macro_(src1[x]);          \
911             worktype a1 = _toggle_macro_(src1[x+1]);        \
912             a0 = __op__( a0, scalar );                      \
913             a1 = __op__( a1, scalar );                      \
914             dst[x] = (arrtype)_toggle_macro_(a0);           \
915             dst[x+1] = (arrtype)_toggle_macro_(a1);         \
916             a0 = _toggle_macro_(src1[x+2]);                 \
917             a1 = _toggle_macro_(src1[x+3]);                 \
918             a0 = __op__( a0, scalar );                      \
919             a1 = __op__( a1, scalar );                      \
920             dst[x+2] = (arrtype)_toggle_macro_(a0);         \
921             dst[x+3] = (arrtype)_toggle_macro_(a1);         \
922         }                                                   \
923                                                             \
924         for( ; x < size.width; x++ )                        \
925         {                                                   \
926             worktype a0 = _toggle_macro_(src1[x]);          \
927             a0 = __op__( a0, scalar );                      \
928             dst[x] = (arrtype)_toggle_macro_(a0);           \
929         }                                                   \
930     }                                                       \
931                                                             \
932     return CV_OK;                                           \
933 }
934
935
936 #define ICV_DEF_MINMAX_ALL( flavor, arrtype, worktype,                             \
937                             _toggle_macro_, _min_op_, _max_op_ )                   \
938 ICV_DEF_MINMAX_FUNC( _min_op_, Min, flavor, arrtype, worktype, _toggle_macro_ )    \
939 ICV_DEF_MINMAX_FUNC( _max_op_, Max, flavor, arrtype, worktype, _toggle_macro_ )    \
940 ICV_DEF_MINMAX_CONST_FUNC(_min_op_, Min, flavor, arrtype, worktype, _toggle_macro_)\
941 ICV_DEF_MINMAX_CONST_FUNC(_max_op_, Max, flavor, arrtype, worktype, _toggle_macro_)
942
943 ICV_DEF_MINMAX_ALL( 8u, uchar, int, CV_NOP, CV_MIN_8U, CV_MAX_8U )
944 ICV_DEF_MINMAX_ALL( 16u, ushort, int, CV_NOP, CV_IMIN, CV_IMAX )
945 ICV_DEF_MINMAX_ALL( 16s, short, int, CV_NOP, CV_IMIN, CV_IMAX )
946 ICV_DEF_MINMAX_ALL( 32s, int, int, CV_NOP, CV_IMIN, CV_IMAX )
947 ICV_DEF_MINMAX_ALL( 32f, int, int, CV_TOGGLE_FLT, CV_IMIN, CV_IMAX )
948 ICV_DEF_MINMAX_ALL( 64f, double, double, CV_NOP, MIN, MAX )
949
950 #define icvMin_8s_C1R     0
951 #define icvMax_8s_C1R     0
952 #define icvMinC_8s_C1R    0
953 #define icvMaxC_8s_C1R    0
954
955 CV_DEF_INIT_FUNC_TAB_2D( Min, C1R )
956 CV_DEF_INIT_FUNC_TAB_2D( Max, C1R )
957 CV_DEF_INIT_FUNC_TAB_2D( MinC, C1R )
958 CV_DEF_INIT_FUNC_TAB_2D( MaxC, C1R )
959
960 /*********************************** cvMin & cvMax **************************************/
961
962 static void
963 icvMinMax( const void* srcarr1, const void* srcarr2,
964            void* dstarr, int is_max )
965 {
966     static CvFuncTable minmax_tab[2];
967     static int inittab = 0;
968
969     CV_FUNCNAME( "icvMinMax" );
970
971     __BEGIN__;
972
973     int type, coi = 0;
974     int src1_step, src2_step, dst_step;
975     CvMat srcstub1, *src1 = (CvMat*)srcarr1;
976     CvMat srcstub2, *src2 = (CvMat*)srcarr2;
977     CvMat dststub,  *dst = (CvMat*)dstarr;
978     CvSize size;
979     CvFunc2D_3A func;
980
981     if( !inittab )
982     {
983         icvInitMinC1RTable( &minmax_tab[0] );
984         icvInitMaxC1RTable( &minmax_tab[1] );
985         inittab = 1;
986     }
987
988     if( !CV_IS_MAT(src1) )
989     {
990         CV_CALL( src1 = cvGetMat( src1, &srcstub1, &coi ));
991         if( coi != 0 )
992             CV_ERROR( CV_BadCOI, "" );
993     }
994
995     if( !CV_IS_MAT(src2) )
996     {
997         CV_CALL( src2 = cvGetMat( src2, &srcstub2, &coi ));
998         if( coi != 0 )
999             CV_ERROR( CV_BadCOI, "" );
1000     }
1001
1002     if( !CV_IS_MAT(dst) )
1003     {
1004         CV_CALL( dst = cvGetMat( dst, &dststub, &coi ));
1005         if( coi != 0 )
1006             CV_ERROR( CV_BadCOI, "" );
1007     }
1008
1009     if( !CV_ARE_TYPES_EQ( src1, src2 ) ||
1010         !CV_ARE_TYPES_EQ( src1, dst ))
1011         CV_ERROR_FROM_CODE( CV_StsUnmatchedFormats );
1012
1013     if( CV_MAT_CN( src1->type ) != 1 )
1014         CV_ERROR( CV_StsUnsupportedFormat, "Input arrays must be single-channel");
1015
1016     if( !CV_ARE_SIZES_EQ( src1, src2 ) ||
1017         !CV_ARE_SIZES_EQ( src1, dst ))
1018         CV_ERROR_FROM_CODE( CV_StsUnmatchedSizes );
1019
1020     type = CV_MAT_TYPE(src1->type);
1021     size = cvGetMatSize( src1 );
1022
1023     if( CV_IS_MAT_CONT( src1->type & src2->type & dst->type ))
1024     {
1025         size.width *= size.height;
1026         src1_step = src2_step = dst_step = CV_STUB_STEP;
1027         size.height = 1;
1028     }
1029     else
1030     {
1031         src1_step = src1->step;
1032         src2_step = src2->step;
1033         dst_step = dst->step;
1034     }
1035
1036     func = (CvFunc2D_3A)(minmax_tab[is_max != 0].fn_2d[type]);
1037
1038     if( !func )
1039         CV_ERROR( CV_StsUnsupportedFormat, "" );
1040
1041     IPPI_CALL( func( src1->data.ptr, src1_step, src2->data.ptr, src2_step,
1042                      dst->data.ptr, dst_step, size ));
1043
1044     __END__;
1045 }
1046
1047
1048 CV_IMPL void
1049 cvMin( const void* srcarr1, const void* srcarr2, void* dstarr )
1050 {
1051     icvMinMax( srcarr1, srcarr2, dstarr, 0 );
1052 }
1053
1054
1055 CV_IMPL void
1056 cvMax( const void* srcarr1, const void* srcarr2, void* dstarr )
1057 {
1058     icvMinMax( srcarr1, srcarr2, dstarr, 1 );
1059 }
1060
1061
1062 /********************************* cvMinS / cvMaxS **************************************/
1063
1064 static void
1065 icvMinMaxS( const void* srcarr, double value, void* dstarr, int is_max )
1066 {
1067     static CvFuncTable minmaxs_tab[2];
1068     static int inittab = 0;
1069
1070     CV_FUNCNAME( "icvMinMaxS" );
1071
1072     __BEGIN__;
1073
1074     int type, coi = 0;
1075     int src1_step, dst_step;
1076     CvMat srcstub1, *src1 = (CvMat*)srcarr;
1077     CvMat dststub,  *dst = (CvMat*)dstarr;
1078     CvSize size;
1079     CvFunc2D_2A1P func;
1080     union
1081     {
1082         int i;
1083         float f;
1084         double d;
1085     }
1086     buf;
1087
1088     if( !inittab )
1089     {
1090         icvInitMinCC1RTable( &minmaxs_tab[0] );
1091         icvInitMaxCC1RTable( &minmaxs_tab[1] );
1092         inittab = 1;
1093     }
1094
1095     if( !CV_IS_MAT(src1) )
1096     {
1097         CV_CALL( src1 = cvGetMat( src1, &srcstub1, &coi ));
1098         if( coi != 0 )
1099             CV_ERROR( CV_BadCOI, "" );
1100     }
1101
1102     if( !CV_IS_MAT(dst) )
1103     {
1104         CV_CALL( dst = cvGetMat( dst, &dststub, &coi ));
1105         if( coi != 0 )
1106             CV_ERROR( CV_BadCOI, "" );
1107     }
1108
1109     if( !CV_ARE_TYPES_EQ( src1, dst ))
1110         CV_ERROR_FROM_CODE( CV_StsUnmatchedFormats );
1111
1112     if( CV_MAT_CN( src1->type ) != 1 )
1113         CV_ERROR( CV_StsUnsupportedFormat, "Input array must be single-channel");
1114
1115     if( !CV_ARE_SIZES_EQ( src1, dst ))
1116         CV_ERROR_FROM_CODE( CV_StsUnmatchedSizes );
1117
1118     type = CV_MAT_TYPE(src1->type);
1119
1120     if( CV_MAT_DEPTH(type) <= CV_32S )
1121     {
1122         buf.i = cvRound(value);
1123         if( CV_MAT_DEPTH(type) == CV_8U )
1124             buf.i = CV_CAST_8U(buf.i);
1125         else if( CV_MAT_DEPTH(type) == CV_8S )
1126             buf.i = CV_CAST_8S(buf.i);
1127         else if( CV_MAT_DEPTH(type) == CV_16U )
1128             buf.i = CV_CAST_16U(buf.i);
1129         else if( CV_MAT_DEPTH(type) == CV_16S )
1130             buf.i = CV_CAST_16S(buf.i);
1131     }
1132     else if( CV_MAT_DEPTH(type) == CV_32F )
1133         buf.f = (float)value;
1134     else
1135         buf.d = value;
1136
1137     size = cvGetMatSize( src1 );
1138
1139     if( CV_IS_MAT_CONT( src1->type & dst->type ))
1140     {
1141         size.width *= size.height;
1142         src1_step = dst_step = CV_STUB_STEP;
1143         size.height = 1;
1144     }
1145     else
1146     {
1147         src1_step = src1->step;
1148         dst_step = dst->step;
1149     }
1150
1151     func = (CvFunc2D_2A1P)(minmaxs_tab[is_max].fn_2d[type]);
1152
1153     if( !func )
1154         CV_ERROR( CV_StsUnsupportedFormat, "" );
1155
1156     if( is_max )
1157     {
1158         if( type == CV_8U && icvThreshold_LT_8u_C1R_p )
1159         {
1160             IPPI_CALL( icvThreshold_LT_8u_C1R_p( src1->data.ptr, src1_step, dst->data.ptr,
1161                                                  dst_step, size, (uchar)buf.i ));
1162             EXIT;
1163         }
1164         else if( type == CV_16S && icvThreshold_LT_16s_C1R_p )
1165         {
1166             IPPI_CALL( icvThreshold_LT_16s_C1R_p( src1->data.s, src1_step, dst->data.s,
1167                                                  dst_step, size, (short)buf.i ));
1168             EXIT;
1169         }
1170         else if( type == CV_32F && icvThreshold_LT_32f_C1R_p )
1171         {
1172             IPPI_CALL( icvThreshold_LT_32f_C1R_p( src1->data.fl, src1_step, dst->data.fl,
1173                                                  dst_step, size, buf.f ));
1174             EXIT;
1175         }
1176     }
1177     else
1178     {
1179         if( type == CV_8U && icvThreshold_GT_8u_C1R_p )
1180         {
1181             IPPI_CALL( icvThreshold_GT_8u_C1R_p( src1->data.ptr, src1_step, dst->data.ptr,
1182                                                  dst_step, size, (uchar)buf.i ));
1183             EXIT;
1184         }
1185         else if( type == CV_16S && icvThreshold_GT_16s_C1R_p )
1186         {
1187             IPPI_CALL( icvThreshold_GT_16s_C1R_p( src1->data.s, src1_step, dst->data.s,
1188                                                  dst_step, size, (short)buf.i ));
1189             EXIT;
1190         }
1191         else if( type == CV_32F && icvThreshold_GT_32f_C1R_p )
1192         {
1193             IPPI_CALL( icvThreshold_GT_32f_C1R_p( src1->data.fl, src1_step, dst->data.fl,
1194                                                  dst_step, size, buf.f ));
1195             EXIT;
1196         }
1197     }
1198
1199     if( type == CV_8U && size.width*size.height >= 1024 )
1200     {
1201         int i;
1202         uchar tab[256];
1203         CvMat _tab = cvMat( 1, 256, CV_8U, tab );
1204
1205         if( is_max )
1206         {
1207             for( i = 0; i < buf.i; i++ )
1208                 tab[i] = (uchar)buf.i;
1209             for( ; i < 256; i++ )
1210                 tab[i] = (uchar)i;
1211         }
1212         else
1213         {
1214             for( i = 0; i < buf.i; i++ )
1215                 tab[i] = (uchar)i;
1216             for( ; i < 256; i++ )
1217                 tab[i] = (uchar)buf.i;
1218         }
1219
1220         cvLUT( src1, dst, &_tab );
1221         EXIT;
1222     }
1223
1224     IPPI_CALL( func( src1->data.ptr, src1_step, dst->data.ptr,
1225                      dst_step, size, &buf ));
1226
1227     __END__;
1228 }
1229
1230
1231 CV_IMPL void
1232 cvMinS( const void* srcarr, double value, void* dstarr )
1233 {
1234     icvMinMaxS( srcarr, value, dstarr, 0 );
1235 }
1236
1237
1238 CV_IMPL void
1239 cvMaxS( const void* srcarr, double value, void* dstarr )
1240 {
1241     icvMinMaxS( srcarr, value, dstarr, 1 );
1242 }
1243
1244
1245 /****************************************************************************************\
1246 *                                  Absolute Difference                                   *
1247 \****************************************************************************************/
1248
1249 #define  ICV_DEF_BIN_ABS_DIFF_2D(name, arrtype, temptype, abs_macro, cast_macro)\
1250 IPCVAPI_IMPL( CvStatus,                                 \
1251 name,( const arrtype* src1, int step1,                  \
1252        const arrtype* src2, int step2,                  \
1253        arrtype* dst, int step, CvSize size ),           \
1254        (src1, step1, src2, step2, dst, step, size))     \
1255 {                                                       \
1256     step1 /= sizeof(src1[0]); step2 /= sizeof(src2[0]); \
1257     step /= sizeof(dst[0]);                             \
1258                                                         \
1259     for( ; size.height--; src1 += step1, src2 += step2, \
1260                           dst += step )                 \
1261     {                                                   \
1262         int i;                                          \
1263                                                         \
1264         for( i = 0; i <= size.width - 4; i += 4 )       \
1265         {                                               \
1266             temptype t0 = src1[i] - src2[i];            \
1267             temptype t1 = src1[i+1] - src2[i+1];        \
1268                                                         \
1269             t0 = (temptype)abs_macro(t0);               \
1270             t1 = (temptype)abs_macro(t1);               \
1271                                                         \
1272             dst[i] = cast_macro(t0);                    \
1273             dst[i+1] = cast_macro(t1);                  \
1274                                                         \
1275             t0 = src1[i+2] - src2[i+2];                 \
1276             t1 = src1[i+3] - src2[i+3];                 \
1277                                                         \
1278             t0 = (temptype)abs_macro(t0);               \
1279             t1 = (temptype)abs_macro(t1);               \
1280                                                         \
1281             dst[i+2] = cast_macro(t0);                  \
1282             dst[i+3] = cast_macro(t1);                  \
1283         }                                               \
1284                                                         \
1285         for( ; i < size.width; i++ )                    \
1286         {                                               \
1287             temptype t0 = src1[i] - src2[i];            \
1288             t0 = (temptype)abs_macro(t0);               \
1289             dst[i] = cast_macro(t0);                    \
1290         }                                               \
1291     }                                                   \
1292                                                         \
1293     return CV_OK;                                       \
1294 }
1295
1296
1297 #define  ICV_DEF_UN_ABS_DIFF_2D( name, arrtype, temptype, abs_macro, cast_macro)\
1298 static CvStatus CV_STDCALL                              \
1299 name( const arrtype* src0, int step1,                   \
1300       arrtype* dst0, int step,                          \
1301       CvSize size, const temptype* scalar )             \
1302 {                                                       \
1303     step1 /= sizeof(src0[0]); step /= sizeof(dst0[0]);  \
1304                                                         \
1305     for( ; size.height--; src0 += step1, dst0 += step ) \
1306     {                                                   \
1307         int i, len = size.width;                        \
1308         const arrtype* src = src0;                      \
1309         arrtype* dst = dst0;                            \
1310                                                         \
1311         for( ; (len -= 12) >= 0; dst += 12, src += 12 ) \
1312         {                                               \
1313             temptype t0 = src[0] - scalar[0];           \
1314             temptype t1 = src[1] - scalar[1];           \
1315                                                         \
1316             t0 = (temptype)abs_macro(t0);               \
1317             t1 = (temptype)abs_macro(t1);               \
1318                                                         \
1319             dst[0] = cast_macro( t0 );                  \
1320             dst[1] = cast_macro( t1 );                  \
1321                                                         \
1322             t0 = src[2] - scalar[2];                    \
1323             t1 = src[3] - scalar[3];                    \
1324                                                         \
1325             t0 = (temptype)abs_macro(t0);               \
1326             t1 = (temptype)abs_macro(t1);               \
1327                                                         \
1328             dst[2] = cast_macro( t0 );                  \
1329             dst[3] = cast_macro( t1 );                  \
1330                                                         \
1331             t0 = src[4] - scalar[4];                    \
1332             t1 = src[5] - scalar[5];                    \
1333                                                         \
1334             t0 = (temptype)abs_macro(t0);               \
1335             t1 = (temptype)abs_macro(t1);               \
1336                                                         \
1337             dst[4] = cast_macro( t0 );                  \
1338             dst[5] = cast_macro( t1 );                  \
1339                                                         \
1340             t0 = src[6] - scalar[6];                    \
1341             t1 = src[7] - scalar[7];                    \
1342                                                         \
1343             t0 = (temptype)abs_macro(t0);               \
1344             t1 = (temptype)abs_macro(t1);               \
1345                                                         \
1346             dst[6] = cast_macro( t0 );                  \
1347             dst[7] = cast_macro( t1 );                  \
1348                                                         \
1349             t0 = src[8] - scalar[8];                    \
1350             t1 = src[9] - scalar[9];                    \
1351                                                         \
1352             t0 = (temptype)abs_macro(t0);               \
1353             t1 = (temptype)abs_macro(t1);               \
1354                                                         \
1355             dst[8] = cast_macro( t0 );                  \
1356             dst[9] = cast_macro( t1 );                  \
1357                                                         \
1358             t0 = src[10] - scalar[10];                  \
1359             t1 = src[11] - scalar[11];                  \
1360                                                         \
1361             t0 = (temptype)abs_macro(t0);               \
1362             t1 = (temptype)abs_macro(t1);               \
1363                                                         \
1364             dst[10] = cast_macro( t0 );                 \
1365             dst[11] = cast_macro( t1 );                 \
1366         }                                               \
1367                                                         \
1368         for( (len) += 12, i = 0; i < (len); i++ )       \
1369         {                                               \
1370             temptype t0 = src[i] - scalar[i];           \
1371             t0 = (temptype)abs_macro(t0);               \
1372             dst[i] = cast_macro( t0 );                  \
1373         }                                               \
1374     }                                                   \
1375                                                         \
1376     return CV_OK;                                       \
1377 }
1378
1379
1380 #define  ICV_TO_8U(x)     ((uchar)(x))
1381 #define  ICV_TO_16U(x)    ((ushort)(x))
1382
1383 ICV_DEF_BIN_ABS_DIFF_2D( icvAbsDiff_8u_C1R, uchar, int, CV_IABS, ICV_TO_8U )
1384 ICV_DEF_BIN_ABS_DIFF_2D( icvAbsDiff_16u_C1R, ushort, int, CV_IABS, ICV_TO_16U )
1385 ICV_DEF_BIN_ABS_DIFF_2D( icvAbsDiff_16s_C1R, short, int, CV_IABS, CV_CAST_16S )
1386 ICV_DEF_BIN_ABS_DIFF_2D( icvAbsDiff_32s_C1R, int, int, CV_IABS, CV_CAST_32S )
1387 ICV_DEF_BIN_ABS_DIFF_2D( icvAbsDiff_32f_C1R, float, float, fabs, CV_CAST_32F )
1388 ICV_DEF_BIN_ABS_DIFF_2D( icvAbsDiff_64f_C1R, double, double, fabs, CV_CAST_64F )
1389
1390 ICV_DEF_UN_ABS_DIFF_2D( icvAbsDiffC_8u_CnR, uchar, int, CV_IABS, CV_CAST_8U )
1391 ICV_DEF_UN_ABS_DIFF_2D( icvAbsDiffC_16u_CnR, ushort, int, CV_IABS, CV_CAST_16U )
1392 ICV_DEF_UN_ABS_DIFF_2D( icvAbsDiffC_16s_CnR, short, int, CV_IABS, CV_CAST_16S )
1393 ICV_DEF_UN_ABS_DIFF_2D( icvAbsDiffC_32s_CnR, int, int, CV_IABS, CV_CAST_32S )
1394 ICV_DEF_UN_ABS_DIFF_2D( icvAbsDiffC_32f_CnR, float, float, fabs, CV_CAST_32F )
1395 ICV_DEF_UN_ABS_DIFF_2D( icvAbsDiffC_64f_CnR, double, double, fabs, CV_CAST_64F )
1396
1397
1398 #define  ICV_INIT_MINI_FUNC_TAB_2D( FUNCNAME, suffix )          \
1399 static void icvInit##FUNCNAME##Table( CvFuncTable* tab )        \
1400 {                                                               \
1401     tab->fn_2d[CV_8U] = (void*)icv##FUNCNAME##_8u_##suffix;     \
1402     tab->fn_2d[CV_16U] = (void*)icv##FUNCNAME##_16u_##suffix;   \
1403     tab->fn_2d[CV_16S] = (void*)icv##FUNCNAME##_16s_##suffix;   \
1404     tab->fn_2d[CV_32S] = (void*)icv##FUNCNAME##_32s_##suffix;   \
1405     tab->fn_2d[CV_32F] = (void*)icv##FUNCNAME##_32f_##suffix;   \
1406     tab->fn_2d[CV_64F] = (void*)icv##FUNCNAME##_64f_##suffix;   \
1407 }
1408
1409
1410 ICV_INIT_MINI_FUNC_TAB_2D( AbsDiff, C1R )
1411 ICV_INIT_MINI_FUNC_TAB_2D( AbsDiffC, CnR )
1412
1413
1414 CV_IMPL  void
1415 cvAbsDiff( const void* srcarr1, const void* srcarr2, void* dstarr )
1416 {
1417     static CvFuncTable adiff_tab;
1418     static int inittab = 0;
1419
1420     CV_FUNCNAME( "cvAbsDiff" );
1421
1422     __BEGIN__;
1423
1424     int coi1 = 0, coi2 = 0, coi3 = 0;
1425     CvMat srcstub1, *src1 = (CvMat*)srcarr1;
1426     CvMat srcstub2, *src2 = (CvMat*)srcarr2;
1427     CvMat dststub,  *dst = (CvMat*)dstarr;
1428     int src1_step, src2_step, dst_step;
1429     CvSize size;
1430     int type;
1431
1432     if( !inittab )
1433     {
1434         icvInitAbsDiffTable( &adiff_tab );
1435         inittab = 1;
1436     }
1437
1438     CV_CALL( src1 = cvGetMat( src1, &srcstub1, &coi1 ));
1439     CV_CALL( src2 = cvGetMat( src2, &srcstub2, &coi2 ));
1440     CV_CALL( dst = cvGetMat( dst, &dststub, &coi3 ));
1441
1442     if( coi1 != 0 || coi2 != 0 || coi3 != 0 )
1443         CV_ERROR( CV_BadCOI, "" );
1444
1445     if( !CV_ARE_SIZES_EQ( src1, src2 ) )
1446         CV_ERROR_FROM_CODE( CV_StsUnmatchedSizes );
1447
1448     size = cvGetMatSize( src1 );
1449     type = CV_MAT_TYPE(src1->type);
1450
1451     if( !CV_ARE_SIZES_EQ( src1, dst ))
1452         CV_ERROR_FROM_CODE( CV_StsUnmatchedSizes );
1453
1454     if( !CV_ARE_TYPES_EQ( src1, src2 ))
1455         CV_ERROR_FROM_CODE( CV_StsUnmatchedFormats );
1456
1457     if( !CV_ARE_TYPES_EQ( src1, dst ))
1458         CV_ERROR_FROM_CODE( CV_StsUnmatchedFormats );
1459
1460     size.width *= CV_MAT_CN( type );
1461
1462     src1_step = src1->step;
1463     src2_step = src2->step;
1464     dst_step = dst->step;
1465
1466     if( CV_IS_MAT_CONT( src1->type & src2->type & dst->type ))
1467     {
1468         size.width *= size.height;
1469         size.height = 1;
1470         src1_step = src2_step = dst_step = CV_STUB_STEP;
1471     }
1472
1473     {
1474         CvFunc2D_3A func = (CvFunc2D_3A)
1475             (adiff_tab.fn_2d[CV_MAT_DEPTH(type)]);
1476
1477         if( !func )
1478             CV_ERROR( CV_StsUnsupportedFormat, "" );
1479
1480         IPPI_CALL( func( src1->data.ptr, src1_step, src2->data.ptr, src2_step,
1481                          dst->data.ptr, dst_step, size ));
1482     }
1483
1484     __END__;
1485 }
1486
1487
1488 CV_IMPL void
1489 cvAbsDiffS( const void* srcarr, void* dstarr, CvScalar scalar )
1490 {
1491     static CvFuncTable adiffs_tab;
1492     static int inittab = 0;
1493
1494     CV_FUNCNAME( "cvAbsDiffS" );
1495
1496     __BEGIN__;
1497
1498     int coi1 = 0, coi2 = 0;
1499     int type, sctype;
1500     CvMat srcstub, *src = (CvMat*)srcarr;
1501     CvMat dststub, *dst = (CvMat*)dstarr;
1502     int src_step, dst_step;
1503     double buf[12];
1504     CvSize size;
1505
1506     if( !inittab )
1507     {
1508         icvInitAbsDiffCTable( &adiffs_tab );
1509         inittab = 1;
1510     }
1511
1512     CV_CALL( src = cvGetMat( src, &srcstub, &coi1 ));
1513     CV_CALL( dst = cvGetMat( dst, &dststub, &coi2 ));
1514
1515     if( coi1 != 0 || coi2 != 0 )
1516         CV_ERROR( CV_BadCOI, "" );
1517
1518     if( !CV_ARE_TYPES_EQ(src, dst) )
1519         CV_ERROR_FROM_CODE( CV_StsUnmatchedFormats );
1520
1521     if( !CV_ARE_SIZES_EQ(src, dst) )
1522         CV_ERROR_FROM_CODE( CV_StsUnmatchedSizes );
1523
1524     sctype = type = CV_MAT_TYPE( src->type );
1525     if( CV_MAT_DEPTH(type) < CV_32S )
1526         sctype = (type & CV_MAT_CN_MASK) | CV_32SC1;
1527
1528     size = cvGetMatSize( src );
1529     size.width *= CV_MAT_CN( type );
1530
1531     src_step = src->step;
1532     dst_step = dst->step;
1533
1534     if( CV_IS_MAT_CONT( src->type & dst->type ))
1535     {
1536         size.width *= size.height;
1537         size.height = 1;
1538         src_step = dst_step = CV_STUB_STEP;
1539     }
1540
1541     CV_CALL( cvScalarToRawData( &scalar, buf, sctype, 1 ));
1542
1543     {
1544         CvFunc2D_2A1P func = (CvFunc2D_2A1P)
1545             (adiffs_tab.fn_2d[CV_MAT_DEPTH(type)]);
1546
1547         if( !func )
1548             CV_ERROR( CV_StsUnsupportedFormat, "" );
1549
1550         IPPI_CALL( func( src->data.ptr, src_step, dst->data.ptr,
1551                          dst_step, size, buf ));
1552     }
1553
1554     __END__;
1555 }
1556
1557 /* End of file. */