Home | History | Annotate | Download | only in src
      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. */
   1558