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 #include "_cv.h"
     43 
     44 /****************************************************************************************\
     45                          Down-sampling pyramids core functions
     46 \****************************************************************************************/
     47 
     48 //////////// Filtering macros /////////////
     49 
     50 /* COMMON CASE */
     51 /* 1/16[1    4    6    4    1]       */
     52 /* ...| x0 | x1 | x2 | x3 | x4 |...  */
     53 #define  PD_FILTER( x0, x1, x2, x3, x4 ) ((x2)*6+((x1)+(x3))*4+(x0)+(x4))
     54 
     55 /* MACROS FOR BORDERS */
     56 
     57 /* | b I a | b | reflection used ("I" denotes the image boundary) */
     58 
     59 /* LEFT/TOP */
     60 /* 1/16[1    4    6    4    1]       */
     61 /*    | x2 | x1 I x0 | x1 | x2 |...  */
     62 #define  PD_LT(x0,x1,x2)                 ((x0)*6 + (x1)*8 + (x2)*2)
     63 
     64 /* RIGHT/BOTTOM */
     65 /* 1/16[1    4    6    4    1]       */
     66 /* ...| x0 | x1 | x2 | x3 I x2 |     */
     67 #define  PD_RB(x0,x1,x2,x3)              ((x0) + ((x1) + (x3))*4 + (x2)*7)
     68 
     69 /* SINGULAR CASE ( width == 2 || height == 2 ) */
     70 /* 1/16[1    4    6    4    1]       */
     71 /*    | x0 | x1 I x0 | x1 I x0 |     */
     72 #define  PD_SINGULAR(x0,x1)    (((x0) + (x1))*8)
     73 
     74 #define  PD_SCALE_INT(x)       (((x) + (1<<7)) >> 8)
     75 #define  PD_SCALE_FLT(x)       ((x)*0.00390625f)
     76 
     77 #define  PD_SZ  5
     78 
     79 ////////// generic macro ////////////
     80 
     81 #define ICV_DEF_PYR_DOWN_FUNC( flavor, type, worktype, _pd_scale_ )                     \
     82 static CvStatus CV_STDCALL                                                              \
     83 icvPyrDownG5x5_##flavor##_CnR( const type* src, int srcstep, type* dst,                 \
     84                                int dststep, CvSize size, void *buf, int Cs )            \
     85 {                                                                                       \
     86     worktype*  buffer = (worktype*)buf;  /* pointer to temporary buffer */              \
     87     worktype*  rows[PD_SZ]; /* array of rows pointers. dim(rows) is PD_SZ */            \
     88     int  y, top_row = 0;                                                                \
     89     int  Wd = size.width/2, Wdn = Wd*Cs;                                                \
     90     int  buffer_step = Wdn;                                                             \
     91     int  pd_sz = (PD_SZ + 1)*buffer_step;                                               \
     92     int  fst = 0, lst = size.height <= PD_SZ/2 ? size.height : PD_SZ/2 + 1;             \
     93                                                                                         \
     94     assert( Cs == 1 || Cs == 3 );                                                       \
     95     srcstep /= sizeof(src[0]); dststep /= sizeof(dst[0]);                               \
     96                                                                                         \
     97     /* main loop */                                                                     \
     98     for( y = 0; y < size.height; y += 2, dst += dststep )                               \
     99     {                                                                                   \
    100         /* set first and last indices of buffer rows which are need to be filled */     \
    101         int x, y1, k = top_row;                                                         \
    102         int x1 = buffer_step;                                                           \
    103         worktype *row01, *row23, *row4;                                                 \
    104                                                                                         \
    105         /* assign rows pointers */                                                      \
    106         for( y1 = 0; y1 < PD_SZ; y1++ )                                                 \
    107         {                                                                               \
    108             rows[y1] = buffer + k;                                                      \
    109             k += buffer_step;                                                           \
    110             k &= k < pd_sz ? -1 : 0;                                                    \
    111         }                                                                               \
    112                                                                                         \
    113         row01 = rows[0];                                                                \
    114         row23 = rows[2];                                                                \
    115         row4  = rows[4];                                                                \
    116                                                                                         \
    117         /* fill new buffer rows with filtered source (horizontal conv) */               \
    118         if( Cs == 1 )                                                                   \
    119         {                                                                               \
    120             if( size.width > PD_SZ/2 )                                                  \
    121                 for( y1 = fst; y1 < lst; y1++, src += srcstep )                         \
    122                 {                                                                       \
    123                     worktype *row = rows[y1];                                           \
    124                                                                                         \
    125                     /* process left & right bounds */                                   \
    126                     row[0]    = PD_LT( src[0], src[1], src[2] );                        \
    127                     row[Wd-1] = PD_RB( src[Wd*2-4], src[Wd*2-3],                        \
    128                                        src[Wd*2-2], src[Wd*2-1]);                       \
    129                     /* other points (even) */                                           \
    130                     for( x = 1; x < Wd - 1; x++ )                                       \
    131                     {                                                                   \
    132                         row[x] = PD_FILTER( src[2*x-2], src[2*x-1], src[2*x],           \
    133                                             src[2*x+1], src[2*x+2] );                   \
    134                     }                                                                   \
    135                 }                                                                       \
    136             else                                                                        \
    137                 for( y1 = fst; y1 < lst; y1++, src += srcstep )                         \
    138                 {                                                                       \
    139                     rows[y1][0] = PD_SINGULAR( src[0], src[1] );                        \
    140                 }                                                                       \
    141         }                                                                               \
    142         else /* Cs == 3 */                                                              \
    143         {                                                                               \
    144             for( y1 = fst; y1 < lst; y1++, src += srcstep )                             \
    145             {                                                                           \
    146                 worktype *row = rows[y1];                                               \
    147                                                                                         \
    148                 if( size.width > PD_SZ/2 )                                              \
    149                 {                                                                       \
    150                     int c;                                                              \
    151                     for( c = 0; c < 3; c++ )                                            \
    152                     {                                                                   \
    153                         /* process left & right bounds  */                              \
    154                         row[c] = PD_LT( src[c], src[3+c], src[6+c] );                   \
    155                         row[Wdn-3+c] = PD_RB( src[Wdn*2-12+c], src[Wdn*2-9+c],          \
    156                                               src[Wdn*2-6+c], src[Wdn*2-3+c] );         \
    157                     }                                                                   \
    158                     /* other points (even) */                                           \
    159                     for( x = 3; x < Wdn - 3; x += 3 )                                   \
    160                     {                                                                   \
    161                         row[x]   = PD_FILTER( src[2*x-6], src[2*x-3], src[2*x],         \
    162                                               src[2*x+3], src[2*x+6] );                 \
    163                         row[x+1] = PD_FILTER( src[2*x-5], src[2*x-2], src[2*x+1],       \
    164                                               src[2*x+4], src[2*x+7] );                 \
    165                         row[x+2] = PD_FILTER( src[2*x-4], src[2*x-1], src[2*x+2],       \
    166                                               src[2*x+5], src[2*x+8] );                 \
    167                     }                                                                   \
    168                 }                                                                       \
    169                 else /* size.width <= PD_SZ/2 */                                        \
    170                 {                                                                       \
    171                     row[0] = PD_SINGULAR( src[0], src[3] );                             \
    172                     row[1] = PD_SINGULAR( src[1], src[4] );                             \
    173                     row[2] = PD_SINGULAR( src[2], src[5] );                             \
    174                 }                                                                       \
    175             }                                                                           \
    176         }                                                                               \
    177                                                                                         \
    178         /* second pass. Do vertical conv and write results do destination image */      \
    179         if( y > 0 )                                                                     \
    180         {                                                                               \
    181             if( y < size.height - PD_SZ/2 )                                             \
    182             {                                                                           \
    183                 for( x = 0; x < Wdn; x++, x1++ )                                        \
    184                 {                                                                       \
    185                     dst[x] = (type)_pd_scale_( PD_FILTER( row01[x],  row01[x1],         \
    186                                                row23[x], row23[x1], row4[x] ));         \
    187                 }                                                                       \
    188                 top_row += 2*buffer_step;                                               \
    189                 top_row &= top_row < pd_sz ? -1 : 0;                                    \
    190             }                                                                           \
    191             else /* bottom */                                                           \
    192                 for( x = 0; x < Wdn; x++, x1++ )                                        \
    193                     dst[x] = (type)_pd_scale_( PD_RB( row01[x], row01[x1],              \
    194                                                       row23[x], row23[x1]));            \
    195         }                                                                               \
    196         else                                                                            \
    197         {                                                                               \
    198             if( size.height > PD_SZ/2 ) /* top */                                       \
    199             {                                                                           \
    200                 for( x = 0; x < Wdn; x++, x1++ )                                        \
    201                     dst[x] = (type)_pd_scale_( PD_LT( row01[x], row01[x1], row23[x] )); \
    202             }                                                                           \
    203             else /* size.height <= PD_SZ/2 */                                           \
    204             {                                                                           \
    205                 for( x = 0; x < Wdn; x++, x1++ )                                        \
    206                     dst[x] = (type)_pd_scale_( PD_SINGULAR( row01[x], row01[x1] ));     \
    207             }                                                                           \
    208             fst = PD_SZ - 2;                                                            \
    209         }                                                                               \
    210                                                                                         \
    211         lst = y + 2 + PD_SZ/2 < size.height ? PD_SZ : size.height - y;                  \
    212     }                                                                                   \
    213                                                                                         \
    214     return CV_OK;                                                                       \
    215 }
    216 
    217 
    218 ICV_DEF_PYR_DOWN_FUNC( 8u, uchar, int, PD_SCALE_INT )
    219 ICV_DEF_PYR_DOWN_FUNC( 16s, short, int, PD_SCALE_INT )
    220 ICV_DEF_PYR_DOWN_FUNC( 16u, ushort, int, PD_SCALE_INT )
    221 ICV_DEF_PYR_DOWN_FUNC( 32f, float, float, PD_SCALE_FLT )
    222 ICV_DEF_PYR_DOWN_FUNC( 64f, double, double, PD_SCALE_FLT )
    223 
    224 
    225 /****************************************************************************************\
    226                            Up-sampling pyramids core functions
    227 \****************************************************************************************/
    228 
    229 /////////// filtering macros //////////////
    230 
    231 /* COMMON CASE: NON ZERO */
    232 /* 1/16[1    4   6    4   1]       */
    233 /* ...| x0 | 0 | x1 | 0 | x2 |...  */
    234 #define  PU_FILTER( x0, x1, x2 )         ((x1)*6 + (x0) + (x2))
    235 
    236 /* ZERO POINT AT CENTER */
    237 /* 1/16[1   4    6   4    1]      */
    238 /* ...| 0 | x0 | 0 | x1 | 0 |...  */
    239 #define  PU_FILTER_ZI( x0, x1 )          (((x0) + (x1))*4)
    240 
    241 /* MACROS FOR BORDERS */
    242 
    243 /* | b I a | b | reflection */
    244 
    245 /* LEFT/TOP */
    246 /* 1/16[1    4   6    4   1]       */
    247 /*    | x1 | 0 I x0 | 0 | x1 |...  */
    248 #define  PU_LT( x0, x1 )                 ((x0)*6 + (x1)*2)
    249 
    250 /* 1/16[1   4    6   4    1]       */
    251 /*    | 0 I x0 | 0 | x1 | 0 |...   */
    252 #define  PU_LT_ZI( x0, x1 )              PU_FILTER_ZI((x0),(x1))
    253 
    254 /* RIGHT/BOTTOM: NON ZERO */
    255 /* 1/16[1    4   6    4   1]       */
    256 /* ...| x0 | 0 | x1 | 0 I x1 |     */
    257 #define  PU_RB( x0, x1 )                 ((x0) + (x1)*7)
    258 
    259 /* RIGHT/BOTTOM: ZERO POINT AT CENTER */
    260 /* 1/16[1   4    6   4    1]       */
    261 /* ...| 0 | x0 | 0 I x0 | 0 |      */
    262 #define  PU_RB_ZI( x0 )                  ((x0)*8)
    263 
    264 /* SINGULAR CASE */
    265 /* 1/16[1    4   6    4   1]       */
    266 /*    | x0 | 0 I x0 | 0 I x0 |     */
    267 #define  PU_SINGULAR( x0 )               PU_RB_ZI((x0)) /* <--| the same formulas */
    268 #define  PU_SINGULAR_ZI( x0 )            PU_RB_ZI((x0)) /* <--| */
    269 
    270 /* x/64  - scaling in up-sampling functions */
    271 #define  PU_SCALE_INT(x)                 (((x) + (1<<5)) >> 6)
    272 #define  PU_SCALE_FLT(x)                 ((x)*0.015625f)
    273 
    274 #define  PU_SZ  3
    275 
    276 //////////// generic macro /////////////
    277 
    278 
    279 #define ICV_DEF_PYR_UP_FUNC( flavor, type, worktype, _pu_scale_ )                       \
    280 static CvStatus CV_STDCALL                                                              \
    281 icvPyrUpG5x5_##flavor##_CnR( const type* src, int srcstep, type* dst,                   \
    282                              int dststep, CvSize size, void *buf, int Cs )              \
    283 {                                                                                       \
    284     worktype *buffer = (worktype*)buf;                                                  \
    285     worktype *rows[PU_SZ];                                                              \
    286     int y, top_row = 0;                                                                 \
    287     int Wd = size.width * 2, Wdn = Wd * Cs, Wn = size.width * Cs;                       \
    288     int buffer_step = Wdn;                                                              \
    289     int pu_sz = PU_SZ*buffer_step;                                                      \
    290     int fst = 0, lst = size.height <= PU_SZ/2 ? size.height : PU_SZ/2 + 1;              \
    291                                                                                         \
    292     assert( Cs == 1 || Cs == 3 );                                                       \
    293     srcstep /= sizeof(src[0]); dststep /= sizeof(dst[0]);                               \
    294                                                                                         \
    295     /* main loop */                                                                     \
    296     for( y = 0; y < size.height; y++, dst += 2 * dststep )                              \
    297     {                                                                                   \
    298         int x, y1, k = top_row;                                                         \
    299         worktype *row0, *row1, *row2;                                                   \
    300         type *dst1;                                                                     \
    301                                                                                         \
    302         /* assign rows pointers */                                                      \
    303         for( y1 = 0; y1 < PU_SZ; y1++ )                                                 \
    304         {                                                                               \
    305             rows[y1] = buffer + k;                                                      \
    306             k += buffer_step;                                                           \
    307             k &= k < pu_sz ? -1 : 0;                                                    \
    308         }                                                                               \
    309                                                                                         \
    310         row0 = rows[0];                                                                 \
    311         row1 = rows[1];                                                                 \
    312         row2 = rows[2];                                                                 \
    313         dst1 = dst + dststep;                                                           \
    314                                                                                         \
    315         /* fill new buffer rows with filtered source (horizontal conv) */               \
    316         if( Cs == 1 )                                                                   \
    317             if( size.width > PU_SZ / 2 )                                                \
    318                 for( y1 = fst; y1 < lst; y1++, src += srcstep )                         \
    319                 {                                                                       \
    320                     worktype *row = rows[y1];                                           \
    321                                                                                         \
    322                     /* process left & right bounds */                                   \
    323                     row[0] = PU_LT( src[0], src[1] );                                   \
    324                     row[1] = PU_LT_ZI( src[0], src[1] );                                \
    325                     row[size.width * 2 - 2] = PU_RB( src[size.width - 2],               \
    326                                                      src[size.width - 1] );             \
    327                     row[size.width * 2 - 1] = PU_RB_ZI( src[size.width - 1] );          \
    328                     /* other points */                                                  \
    329                     for( x = 1; x < size.width - 1; x++ )                               \
    330                     {                                                                   \
    331                         row[2 * x] = PU_FILTER( src[x - 1], src[x], src[x + 1] );       \
    332                         row[2 * x + 1] = PU_FILTER_ZI( src[x], src[x + 1] );            \
    333                     }                                                                   \
    334                 }                                                                       \
    335             else                /* size.width <= PU_SZ/2 */                             \
    336                 for( y1 = fst; y1 < lst; y1++, src += srcstep )                         \
    337                 {                                                                       \
    338                     worktype *row = rows[y1];                                           \
    339                     worktype val = src[0];                                              \
    340                                                                                         \
    341                     row[0] = PU_SINGULAR( val );                                        \
    342                     row[1] = PU_SINGULAR_ZI( val );                                     \
    343                 }                                                                       \
    344         else                    /* Cs == 3 */                                           \
    345             for( y1 = fst; y1 < lst; y1++, src += srcstep )                             \
    346             {                                                                           \
    347                 worktype *row = rows[y1];                                               \
    348                                                                                         \
    349                 if( size.width > PU_SZ / 2 )                                            \
    350                 {                                                                       \
    351                     int c;                                                              \
    352                                                                                         \
    353                     for( c = 0; c < 3; c++ )                                            \
    354                     {                                                                   \
    355                         /* process left & right bounds  */                              \
    356                         row[c] = PU_LT( src[c], src[3 + c] );                           \
    357                         row[3 + c] = PU_LT_ZI( src[c], src[3 + c] );                    \
    358                         row[Wn * 2 - 6 + c] = PU_RB( src[Wn - 6 + c], src[Wn - 3 + c]); \
    359                         row[Wn * 2 - 3 + c] = PU_RB_ZI( src[Wn - 3 + c] );              \
    360                     }                                                                   \
    361                     /* other points */                                                  \
    362                     for( x = 3; x < Wn - 3; x += 3 )                                    \
    363                     {                                                                   \
    364                         row[2 * x] = PU_FILTER( src[x - 3], src[x], src[x + 3] );       \
    365                         row[2 * x + 3] = PU_FILTER_ZI( src[x], src[x + 3] );            \
    366                                                                                         \
    367                         row[2 * x + 1] = PU_FILTER( src[x - 2], src[x + 1], src[x + 4]);\
    368                         row[2 * x + 4] = PU_FILTER_ZI( src[x + 1], src[x + 4] );        \
    369                                                                                         \
    370                         row[2 * x + 2] = PU_FILTER( src[x - 1], src[x + 2], src[x + 5]);\
    371                         row[2 * x + 5] = PU_FILTER_ZI( src[x + 2], src[x + 5] );        \
    372                     }                                                                   \
    373                 }                                                                       \
    374                 else            /* size.width <= PU_SZ/2 */                             \
    375                 {                                                                       \
    376                     int c;                                                              \
    377                                                                                         \
    378                     for( c = 0; c < 3; c++ )                                            \
    379                     {                                                                   \
    380                         row[c] = PU_SINGULAR( src[c] );                                 \
    381                         row[3 + c] = PU_SINGULAR_ZI( src[c] );                          \
    382                     }                                                                   \
    383                 }                                                                       \
    384             }                                                                           \
    385                                                                                         \
    386         /* second pass. Do vertical conv and write results do destination image */      \
    387         if( y > 0 )                                                                     \
    388         {                                                                               \
    389             if( y < size.height - PU_SZ / 2 )                                           \
    390             {                                                                           \
    391                 for( x = 0; x < Wdn; x++ )                                              \
    392                 {                                                                       \
    393                     dst[x] = (type)_pu_scale_( PU_FILTER( row0[x], row1[x], row2[x] )); \
    394                     dst1[x] = (type)_pu_scale_( PU_FILTER_ZI( row1[x], row2[x] ));      \
    395                 }                                                                       \
    396                 top_row += buffer_step;                                                 \
    397                 top_row &= top_row < pu_sz ? -1 : 0;                                    \
    398             }                                                                           \
    399             else                /* bottom */                                            \
    400                 for( x = 0; x < Wdn; x++ )                                              \
    401                 {                                                                       \
    402                     dst[x] = (type)_pu_scale_( PU_RB( row0[x], row1[x] ));              \
    403                     dst1[x] = (type)_pu_scale_( PU_RB_ZI( row1[x] ));                   \
    404                 }                                                                       \
    405         }                                                                               \
    406         else                                                                            \
    407         {                                                                               \
    408             if( size.height > PU_SZ / 2 ) /* top */                                     \
    409                 for( x = 0; x < Wdn; x++ )                                              \
    410                 {                                                                       \
    411                     dst[x] = (type)_pu_scale_( PU_LT( row0[x], row1[x] ));              \
    412                     dst1[x] = (type)_pu_scale_( PU_LT_ZI( row0[x], row1[x] ));          \
    413                 }                                                                       \
    414             else                /* size.height <= PU_SZ/2 */                            \
    415                 for( x = 0; x < Wdn; x++ )                                              \
    416                 {                                                                       \
    417                     dst[x] = (type)_pu_scale_( PU_SINGULAR( row0[x] ));                 \
    418                     dst1[x] = (type)_pu_scale_( PU_SINGULAR_ZI( row0[x] ));             \
    419                 }                                                                       \
    420             fst = PU_SZ - 1;                                                            \
    421         }                                                                               \
    422                                                                                         \
    423         lst = y < size.height - PU_SZ/2 - 1 ? PU_SZ : size.height + PU_SZ/2 - y - 1;    \
    424     }                                                                                   \
    425                                                                                         \
    426     return CV_OK;                                                                       \
    427 }
    428 
    429 
    430 ICV_DEF_PYR_UP_FUNC( 8u, uchar, int, PU_SCALE_INT )
    431 ICV_DEF_PYR_UP_FUNC( 16s, short, int, PU_SCALE_INT )
    432 ICV_DEF_PYR_UP_FUNC( 16u, ushort, int, PU_SCALE_INT )
    433 ICV_DEF_PYR_UP_FUNC( 32f, float, float, PU_SCALE_FLT )
    434 ICV_DEF_PYR_UP_FUNC( 64f, double, double, PU_SCALE_FLT )
    435 
    436 
    437 static CvStatus CV_STDCALL
    438 icvPyrUpG5x5_GetBufSize( int roiWidth, CvDataType dataType,
    439                          int channels, int *bufSize )
    440 {
    441     int bufStep;
    442 
    443     if( !bufSize )
    444         return CV_NULLPTR_ERR;
    445     *bufSize = 0;
    446 
    447     if( roiWidth < 0 )
    448         return CV_BADSIZE_ERR;
    449     if( channels != 1 && channels != 3 )
    450         return CV_UNSUPPORTED_CHANNELS_ERR;
    451 
    452     bufStep = 2*roiWidth*channels;
    453 
    454     if( dataType == cv64f )
    455         bufStep *= sizeof(double);
    456     else
    457         bufStep *= sizeof(int);
    458 
    459     *bufSize = bufStep * PU_SZ;
    460     return CV_OK;
    461 }
    462 
    463 
    464 static CvStatus CV_STDCALL
    465 icvPyrDownG5x5_GetBufSize( int roiWidth, CvDataType dataType,
    466                            int channels, int *bufSize )
    467 {
    468     int bufStep;
    469 
    470     if( !bufSize )
    471         return CV_NULLPTR_ERR;
    472     *bufSize = 0;
    473 
    474     if( roiWidth < 0 || (roiWidth & 1) != 0 )
    475         return CV_BADSIZE_ERR;
    476     if( channels != 1 && channels != 3 )
    477         return CV_UNSUPPORTED_CHANNELS_ERR;
    478 
    479     bufStep = 2*roiWidth*channels;
    480 
    481     if( dataType == cv64f )
    482         bufStep *= sizeof(double);
    483     else
    484         bufStep *= sizeof(int);
    485 
    486     *bufSize = bufStep * (PD_SZ + 1);
    487     return CV_OK;
    488 }
    489 
    490 /****************************************************************************************\
    491                         Downsampled image border completion
    492 \****************************************************************************************/
    493 
    494 #define ICV_DEF_PYR_BORDER_FUNC( flavor, arrtype, worktype, _pd_scale_ )                \
    495 static CvStatus CV_STDCALL                                                              \
    496 icvPyrDownBorder_##flavor##_CnR( const arrtype *src, int src_step, CvSize src_size,     \
    497                           arrtype *dst, int dst_step, CvSize dst_size, int channels )   \
    498 {                                                                                       \
    499     int local_alloc = 0;                                                                \
    500     worktype *buf = 0, *buf0 = 0;                                                       \
    501     const arrtype* src2;                                                                \
    502     arrtype* dst2;                                                                      \
    503     int buf_size;                                                                       \
    504     int i, j;                                                                           \
    505     int W = src_size.width, H = src_size.height;                                        \
    506     int Wd = dst_size.width, Hd = dst_size.height;                                      \
    507     int Wd_, Hd_;                                                                       \
    508     int Wn = W*channels;                                                                \
    509     int bufW;                                                                           \
    510     int cols, rows; /* columns and rows to modify */                                    \
    511                                                                                         \
    512     assert( channels == 1 || channels == 3 );                                           \
    513                                                                                         \
    514     buf_size = MAX(src_size.width,src_size.height) * sizeof(buf[0]) * 2 * channels;     \
    515     if( buf_size > (1 << 14) )                                                          \
    516     {                                                                                   \
    517         buf = (worktype*)cvAlloc( buf_size );                                           \
    518         if( !buf )                                                                      \
    519             return CV_OUTOFMEM_ERR;                                                     \
    520     }                                                                                   \
    521     else                                                                                \
    522     {                                                                                   \
    523         buf = (worktype*)cvAlignPtr(alloca( buf_size+8 ), 8);                           \
    524         local_alloc = 1;                                                                \
    525     }                                                                                   \
    526                                                                                         \
    527     buf0 = buf;                                                                         \
    528                                                                                         \
    529     src_step /= sizeof(src[0]);                                                         \
    530     dst_step /= sizeof(dst[0]);                                                         \
    531                                                                                         \
    532     cols = (W & 1) + (Wd*2 > W);                                                        \
    533     rows = (H & 1) + (Hd*2 > H);                                                        \
    534                                                                                         \
    535     src2 = src + (H-1)*src_step;                                                        \
    536     dst2 = dst + (Hd - rows)*dst_step;                                                  \
    537     src += (W - 1)*channels;                                                            \
    538     dst += (Wd - cols)*channels;                                                        \
    539                                                                                         \
    540     /* part of row(column) from 1 to Wd_(Hd_) is processed using PD_FILTER macro */     \
    541     Wd_ = Wd - 1 + (cols == 1 && (W & 1) != 0);                                         \
    542     Hd_ = Hd - 1 + (rows == 1 && (H & 1) != 0);                                         \
    543                                                                                         \
    544     bufW = channels * cols;                                                             \
    545                                                                                         \
    546     /******************* STAGE 1. ******************/                                   \
    547                                                                                         \
    548     /* do horizontal convolution of the 1-2 right columns and write results to buffer */\
    549     if( cols > 0 )                                                                      \
    550     {                                                                                   \
    551         if( W <= 2 )                                                                    \
    552         {                                                                               \
    553             assert( Wd == 1 );                                                          \
    554             for( i = 0; i < H; i++, src += src_step, buf += channels )                  \
    555             {                                                                           \
    556                 if( channels == 1 )                                                     \
    557                     buf[0] = PD_SINGULAR( src[1-Wn], src[0] );                          \
    558                 else                                                                    \
    559                 {                                                                       \
    560                     buf[0] = PD_SINGULAR( src[3-Wn], src[0] );                          \
    561                     buf[1] = PD_SINGULAR( src[4-Wn], src[1] );                          \
    562                     buf[2] = PD_SINGULAR( src[5-Wn], src[2] );                          \
    563                 }                                                                       \
    564             }                                                                           \
    565         }                                                                               \
    566         else if( (W == 3 && Wd == 1) || (W > 3 && !(Wd & 1)) )                          \
    567         {                                                                               \
    568             for( i = 0; i < H; i++, src += src_step, buf += channels )                  \
    569             {                                                                           \
    570                 if( channels == 1 )                                                     \
    571                     buf[0] = PD_LT( src[-2], src[-1], src[0] );                         \
    572                 else                                                                    \
    573                 {                                                                       \
    574                     buf[0] = PD_LT( src[-6], src[-3], src[0] );                         \
    575                     buf[1] = PD_LT( src[-5], src[-2], src[1] );                         \
    576                     buf[2] = PD_LT( src[-4], src[-1], src[2] );                         \
    577                 }                                                                       \
    578             }                                                                           \
    579         }                                                                               \
    580         else if( W == 3 )                                                               \
    581         {                                                                               \
    582             for( i = 0; i < H; i++, src += src_step, buf += channels*2 )                \
    583             {                                                                           \
    584                 if( channels == 1 )                                                     \
    585                 {                                                                       \
    586                     buf[0] = PD_LT( src[-2], src[-1], src[0] );                         \
    587                     buf[1] = PD_LT( src[0], src[-1], src[-2] );                         \
    588                 }                                                                       \
    589                 else                                                                    \
    590                 {                                                                       \
    591                     buf[0] = PD_LT( src[-6], src[-3], src[0] );                         \
    592                     buf[1] = PD_LT( src[-5], src[-2], src[1] );                         \
    593                     buf[2] = PD_LT( src[-4], src[-1], src[2] );                         \
    594                     buf[3] = PD_LT( src[0], src[-3], src[-6] );                         \
    595                     buf[4] = PD_LT( src[1], src[-2], src[-5] );                         \
    596                     buf[5] = PD_LT( src[2], src[-1], src[-4] );                         \
    597                 }                                                                       \
    598             }                                                                           \
    599         }                                                                               \
    600         else if( cols == 1 )                                                            \
    601         {                                                                               \
    602             for( i = 0; i < H; i++, src += src_step, buf += channels )                  \
    603             {                                                                           \
    604                 if( channels == 1 )                                                     \
    605                     buf[0] = PD_FILTER( src[-4], src[-3], src[-2], src[-1], src[0]);    \
    606                 else                                                                    \
    607                 {                                                                       \
    608                     buf[0] = PD_FILTER( src[-12], src[-9], src[-6], src[-3], src[0]);   \
    609                     buf[1] = PD_FILTER( src[-11], src[-8], src[-5], src[-2], src[1]);   \
    610                     buf[2] = PD_FILTER( src[-10], src[-7], src[-4], src[-1], src[2]);   \
    611                 }                                                                       \
    612             }                                                                           \
    613         }                                                                               \
    614         else                                                                            \
    615         {                                                                               \
    616             for( i = 0; i < H; i++, src += src_step, buf += channels*2 )                \
    617             {                                                                           \
    618                 if( channels == 1 )                                                     \
    619                 {                                                                       \
    620                     buf[0] = PD_FILTER( src[-4], src[-3], src[-2], src[-1], src[0] );   \
    621                     buf[1] = PD_LT( src[0], src[-1], src[-2] );                         \
    622                 }                                                                       \
    623                 else                                                                    \
    624                 {                                                                       \
    625                     buf[0] = PD_FILTER( src[-12], src[-9], src[-6], src[-3], src[0] );  \
    626                     buf[1] = PD_FILTER( src[-11], src[-8], src[-5], src[-2], src[1] );  \
    627                     buf[2] = PD_FILTER( src[-10], src[-7], src[-4], src[-1], src[2] );  \
    628                     buf[3] = PD_LT( src[0], src[-3], src[-6] );                         \
    629                     buf[4] = PD_LT( src[1], src[-2], src[-5] );                         \
    630                     buf[5] = PD_LT( src[2], src[-1], src[-4] );                         \
    631                 }                                                                       \
    632             }                                                                           \
    633         }                                                                               \
    634         buf = buf0;                                                                     \
    635     }                                                                                   \
    636                                                                                         \
    637     src = src2;                                                                         \
    638                                                                                         \
    639     /******************* STAGE 2. ******************/                                   \
    640                                                                                         \
    641     /* do vertical convolution of the pre-processed right columns, */                   \
    642     /* stored in buffer, and write results to the destination */                        \
    643     /* do vertical convolution of the 1-2 bottom rows */                                \
    644     /* and write results to the buffer */                                               \
    645     if( H <= 2 )                                                                        \
    646     {                                                                                   \
    647         if( cols > 0 )                                                                  \
    648         {                                                                               \
    649             assert( Hd == 1 );                                                          \
    650             for( j = 0; j < bufW; j++ )                                                 \
    651                 dst[j] = (arrtype)_pd_scale_( PD_SINGULAR( buf[j], buf[j+(H-1)*bufW] ));\
    652         }                                                                               \
    653                                                                                         \
    654         if( rows > 0 )                                                                  \
    655         {                                                                               \
    656             for( j = 0; j < Wn; j++ )                                                   \
    657                 buf[j] = PD_SINGULAR( src[j-src_step], src[j] );                        \
    658         }                                                                               \
    659     }                                                                                   \
    660     else if( H == 3 )                                                                   \
    661     {                                                                                   \
    662         if( cols > 0 )                                                                  \
    663         {                                                                               \
    664             for( j = 0; j < bufW; j++ )                                                 \
    665             {                                                                           \
    666                 dst[j]= (arrtype)_pd_scale_(PD_LT( buf[j], buf[j+bufW], buf[j+bufW*2]));\
    667             }                                                                           \
    668             if( Hd == 2 )                                                               \
    669             {                                                                           \
    670                 dst += dst_step;                                                        \
    671                 for( j = 0; j < bufW; j++ )                                             \
    672                     dst[j] = (arrtype)_pd_scale_( PD_LT( buf[j+bufW*2],                 \
    673                                                   buf[j+bufW], buf[j] ));               \
    674             }                                                                           \
    675         }                                                                               \
    676                                                                                         \
    677         if( Hd == 1 )                                                                   \
    678         {                                                                               \
    679             for( j = 0; j < Wn; j++ )                                                   \
    680                 buf[j] = PD_LT( src[j-src_step*2], src[j - src_step], src[j] );         \
    681         }                                                                               \
    682         else                                                                            \
    683         {                                                                               \
    684             for( j = 0; j < Wn; j++ )                                                   \
    685             {                                                                           \
    686                 buf[j] = PD_LT( src[j-src_step*2], src[j - src_step], src[j] );         \
    687                 buf[j+Wn] = PD_LT( src[j],src[j-src_step],src[j-src_step*2] );          \
    688             }                                                                           \
    689         }                                                                               \
    690     }                                                                                   \
    691     else                                                                                \
    692     {                                                                                   \
    693         if( cols > 0 )                                                                  \
    694         {                                                                               \
    695             /* top of the right border */                                               \
    696             for( j = 0; j < bufW; j++ )                                                 \
    697                 dst[j]=(arrtype)_pd_scale_( PD_LT( buf[j], buf[j+bufW], buf[j+bufW*2]));\
    698                                                                                         \
    699             /* middle part of the right border */                                       \
    700             buf += bufW*2;                                                              \
    701             dst += dst_step;                                                            \
    702             for( i = 1; i < Hd_; i++, dst += dst_step, buf += bufW*2 )                  \
    703             {                                                                           \
    704                 for( j = 0; j < bufW; j++ )                                             \
    705                     dst[j] = (arrtype)_pd_scale_( PD_FILTER( buf[j-bufW*2], buf[j-bufW],\
    706                                                   buf[j], buf[j+bufW], buf[j+bufW*2] ));\
    707             }                                                                           \
    708                                                                                         \
    709             /* bottom of the right border */                                            \
    710             if( !(H & 1) )                                                              \
    711             {                                                                           \
    712                 for( j = 0; j < bufW; j++ )                                             \
    713                     dst[j] = (arrtype)_pd_scale_( PD_RB( buf[j-bufW*2], buf[j-bufW],    \
    714                                                          buf[j], buf[j+bufW] ));        \
    715             }                                                                           \
    716             else if( rows > 1 )                                                         \
    717             {                                                                           \
    718                 for( j = 0; j < bufW; j++ )                                             \
    719                     dst[j]=(arrtype)_pd_scale_( PD_LT( buf[j-bufW*2],                   \
    720                                                 buf[j-bufW], buf[j]));                  \
    721             }                                                                           \
    722                                                                                         \
    723             buf = buf0;                                                                 \
    724         }                                                                               \
    725                                                                                         \
    726         if( rows > 0 )                                                                  \
    727         {                                                                               \
    728             if( !(H & 1) )                                                              \
    729             {                                                                           \
    730                 for( j = 0; j < Wn; j++ )                                               \
    731                     buf[j] = PD_LT( src[j], src[j-src_step], src[j-src_step*2] );       \
    732             }                                                                           \
    733             else if( cols == 1 )                                                        \
    734             {                                                                           \
    735                 for( j = 0; j < Wn; j++ )                                               \
    736                     buf[j] = PD_FILTER( src[j-src_step*4], src[j-src_step*3],           \
    737                                         src[j-src_step*2], src[j-src_step], src[j] );   \
    738             }                                                                           \
    739             else                                                                        \
    740             {                                                                           \
    741                 for( j = 0; j < Wn; j++ )                                               \
    742                 {                                                                       \
    743                     buf[j] = PD_FILTER( src[j-src_step*4], src[j-src_step*3],           \
    744                                         src[j-src_step*2], src[j-src_step], src[j] );   \
    745                     buf[j+Wn] = PD_LT( src[j], src[j-src_step], src[j-src_step*2] );    \
    746                 }                                                                       \
    747             }                                                                           \
    748         }                                                                               \
    749     }                                                                                   \
    750                                                                                         \
    751                                                                                         \
    752     /******************* STAGE 3. ******************/                                   \
    753                                                                                         \
    754     /* do horizontal convolution of the pre-processed bottom rows,*/                    \
    755     /* stored in buffer, and write results to the destination */                        \
    756     if( rows > 0 )                                                                      \
    757     {                                                                                   \
    758         dst = dst2;                                                                     \
    759                                                                                         \
    760         if( W <= 2 )                                                                    \
    761         {                                                                               \
    762             assert( Wd == 1 );                                                          \
    763             for( ; rows--; dst += dst_step, buf += Wn )                                 \
    764             {                                                                           \
    765                 if( channels == 1 )                                                     \
    766                     dst[0] = (arrtype)_pd_scale_( PD_SINGULAR( buf[0], buf[Wn-1] ));    \
    767                 else                                                                    \
    768                 {                                                                       \
    769                     dst[0] = (arrtype)_pd_scale_( PD_SINGULAR( buf[0], buf[Wn-3] ));    \
    770                     dst[1] = (arrtype)_pd_scale_( PD_SINGULAR( buf[1], buf[Wn-2] ));    \
    771                     dst[2] = (arrtype)_pd_scale_( PD_SINGULAR( buf[2], buf[Wn-1] ));    \
    772                 }                                                                       \
    773             }                                                                           \
    774         }                                                                               \
    775         else if( W == 3 )                                                               \
    776         {                                                                               \
    777             if( Wd == 1 )                                                               \
    778             {                                                                           \
    779                 for( ; rows--; dst += dst_step, buf += Wn )                             \
    780                 {                                                                       \
    781                     if( channels == 1 )                                                 \
    782                         dst[0] = (arrtype)_pd_scale_( PD_LT(buf[0], buf[1], buf[2] ));  \
    783                     else                                                                \
    784                     {                                                                   \
    785                         dst[0] = (arrtype)_pd_scale_( PD_LT(buf[0], buf[3], buf[6] ));  \
    786                         dst[1] = (arrtype)_pd_scale_( PD_LT(buf[1], buf[4], buf[7] ));  \
    787                         dst[2] = (arrtype)_pd_scale_( PD_LT(buf[2], buf[5], buf[8] ));  \
    788                     }                                                                   \
    789                 }                                                                       \
    790             }                                                                           \
    791             else                                                                        \
    792             {                                                                           \
    793                 for( ; rows--; dst += dst_step, buf += Wn )                             \
    794                 {                                                                       \
    795                     if( channels == 1 )                                                 \
    796                     {                                                                   \
    797                         dst[0] = (arrtype)_pd_scale_( PD_LT(buf[0], buf[1], buf[2] ));  \
    798                         dst[1] = (arrtype)_pd_scale_( PD_LT(buf[2], buf[1], buf[0] ));  \
    799                     }                                                                   \
    800                     else                                                                \
    801                     {                                                                   \
    802                         dst[0] = (arrtype)_pd_scale_( PD_LT(buf[0], buf[3], buf[6] ));  \
    803                         dst[1] = (arrtype)_pd_scale_( PD_LT(buf[1], buf[4], buf[7] ));  \
    804                         dst[2] = (arrtype)_pd_scale_( PD_LT(buf[2], buf[5], buf[8] ));  \
    805                         dst[3] = (arrtype)_pd_scale_( PD_LT(buf[6], buf[3], buf[0] ));  \
    806                         dst[4] = (arrtype)_pd_scale_( PD_LT(buf[7], buf[4], buf[1] ));  \
    807                         dst[5] = (arrtype)_pd_scale_( PD_LT(buf[8], buf[5], buf[2] ));  \
    808                     }                                                                   \
    809                 }                                                                       \
    810             }                                                                           \
    811         }                                                                               \
    812         else                                                                            \
    813         {                                                                               \
    814             for( ; rows--; dst += dst_step, buf += Wn )                                 \
    815             {                                                                           \
    816                 if( channels == 1 )                                                     \
    817                 {                                                                       \
    818                     /* left part of the bottom row */                                   \
    819                     dst[0] = (arrtype)_pd_scale_( PD_LT( buf[0], buf[1], buf[2] ));     \
    820                                                                                         \
    821                     /* middle part of the bottom row */                                 \
    822                     for( i = 1; i < Wd_; i++ )                                          \
    823                     {                                                                   \
    824                         dst[i] = (arrtype)_pd_scale_( PD_FILTER(buf[i*2-2], buf[i*2-1], \
    825                                                     buf[i*2],buf[i*2+1], buf[i*2+2] )); \
    826                     }                                                                   \
    827                                                                                         \
    828                     /* right part of the bottom row */                                  \
    829                     if( !(W & 1) )                                                      \
    830                         dst[i] = (arrtype)_pd_scale_( PD_RB( buf[i*2-2],buf[i*2-1],     \
    831                                                     buf[i*2], buf[i*2+1] ));            \
    832                     else if( cols > 1 )                                                 \
    833                         dst[i] = (arrtype)_pd_scale_( PD_LT( buf[i*2-2],                \
    834                                                     buf[i*2-1], buf[i*2] ));            \
    835                 }                                                                       \
    836                 else                                                                    \
    837                 {                                                                       \
    838                     /* left part of the bottom row */                                   \
    839                     dst[0] = (arrtype)_pd_scale_( PD_LT( buf[0], buf[3], buf[6] ));     \
    840                     dst[1] = (arrtype)_pd_scale_( PD_LT( buf[1], buf[4], buf[7] ));     \
    841                     dst[2] = (arrtype)_pd_scale_( PD_LT( buf[2], buf[5], buf[8] ));     \
    842                                                                                         \
    843                     /* middle part of the bottom row */                                 \
    844                     for( i = 3; i < Wd_*3; i++ )                                        \
    845                     {                                                                   \
    846                         dst[i] = (arrtype)_pd_scale_( PD_FILTER(buf[i*2-6], buf[i*2-3], \
    847                                                       buf[i*2],buf[i*2+3], buf[i*2+6]));\
    848                     }                                                                   \
    849                                                                                         \
    850                     /* right part of the bottom row */                                  \
    851                     if( !(W & 1) )                                                      \
    852                     {                                                                   \
    853                         dst[i] = (arrtype)_pd_scale_( PD_RB( buf[i*2-6],buf[i*2-3],     \
    854                                                     buf[i*2], buf[i*2+3] ));            \
    855                         dst[i+1] = (arrtype)_pd_scale_( PD_RB( buf[i*2-5],buf[i*2-2],   \
    856                                                     buf[i*2+1], buf[i*2+4] ));          \
    857                         dst[i+2] = (arrtype)_pd_scale_( PD_RB( buf[i*2-4],buf[i*2-1],   \
    858                                                     buf[i*2+2], buf[i*2+5] ));          \
    859                     }                                                                   \
    860                     else if( cols > 1 )                                                 \
    861                     {                                                                   \
    862                         dst[i] = (arrtype)_pd_scale_( PD_LT( buf[i*2-6], buf[i*2-3], buf[i*2] ));   \
    863                         dst[i+1] = (arrtype)_pd_scale_( PD_LT( buf[i*2-5], buf[i*2-2], buf[i*2+1]));\
    864                         dst[i+2] = (arrtype)_pd_scale_( PD_LT( buf[i*2-4], buf[i*2-1], buf[i*2+2]));\
    865                     }                                                                   \
    866                 }                                                                       \
    867             }                                                                           \
    868         }                                                                               \
    869     }                                                                                   \
    870                                                                                         \
    871     if( !local_alloc )                                                                  \
    872         cvFree( &buf0 );                                                                \
    873                                                                                         \
    874     return CV_OK;                                                                       \
    875 }
    876 
    877 
    878 #define ICV_DEF_INIT_PYR_TABLE( FUNCNAME )                          \
    879 static void icvInit##FUNCNAME##Table( CvFuncTable* tab )            \
    880 {                                                                   \
    881     tab->fn_2d[CV_8U] = (void*)icv##FUNCNAME##_8u_CnR;              \
    882     tab->fn_2d[CV_8S] = 0;                                          \
    883     tab->fn_2d[CV_16S] = (void*)icv##FUNCNAME##_16s_CnR;            \
    884     tab->fn_2d[CV_16U] = (void*)icv##FUNCNAME##_16u_CnR;            \
    885     tab->fn_2d[CV_32F] = (void*)icv##FUNCNAME##_32f_CnR;            \
    886     tab->fn_2d[CV_64F] = (void*)icv##FUNCNAME##_64f_CnR;            \
    887 }
    888 
    889 static void icvInitPyrDownBorderTable( CvFuncTable* tab );
    890 
    891 ICV_DEF_INIT_PYR_TABLE( PyrUpG5x5 )
    892 ICV_DEF_INIT_PYR_TABLE( PyrDownG5x5 )
    893 
    894 typedef CvStatus (CV_STDCALL * CvPyrDownBorderFunc)( const void* src, int srcstep,
    895                                                      CvSize srcsize, void* dst,
    896                                                      int dststep, CvSize dstsize, int cn );
    897 
    898 ////////////////////////////// IPP pyramid functions /////////////////////////////////////
    899 
    900 icvPyrDown_Gauss5x5_8u_C1R_t icvPyrDown_Gauss5x5_8u_C1R_p = 0;
    901 icvPyrDown_Gauss5x5_8u_C3R_t icvPyrDown_Gauss5x5_8u_C3R_p = 0;
    902 icvPyrDown_Gauss5x5_32f_C1R_t icvPyrDown_Gauss5x5_32f_C1R_p = 0;
    903 icvPyrDown_Gauss5x5_32f_C3R_t icvPyrDown_Gauss5x5_32f_C3R_p = 0;
    904 
    905 icvPyrUp_Gauss5x5_8u_C1R_t icvPyrUp_Gauss5x5_8u_C1R_p = 0;
    906 icvPyrUp_Gauss5x5_8u_C3R_t icvPyrUp_Gauss5x5_8u_C3R_p = 0;
    907 icvPyrUp_Gauss5x5_32f_C1R_t icvPyrUp_Gauss5x5_32f_C1R_p = 0;
    908 icvPyrUp_Gauss5x5_32f_C3R_t icvPyrUp_Gauss5x5_32f_C3R_p = 0;
    909 
    910 icvPyrUpGetBufSize_Gauss5x5_t icvPyrUpGetBufSize_Gauss5x5_p = 0;
    911 icvPyrDownGetBufSize_Gauss5x5_t icvPyrDownGetBufSize_Gauss5x5_p = 0;
    912 
    913 typedef CvStatus (CV_STDCALL * CvPyramidFunc)
    914 ( const void* src, int srcstep, void* dst,
    915   int dststep, CvSize size, void* buffer, int cn );
    916 
    917 typedef CvStatus (CV_STDCALL * CvPyramidIPPFunc)
    918 ( const void* src, int srcstep, void* dst, int dststep, CvSize size, void* buffer );
    919 
    920 //////////////////////////////////////////////////////////////////////////////////////////
    921 
    922 /****************************************************************************************\
    923 *                                 External functions                                     *
    924 \****************************************************************************************/
    925 
    926 CV_IMPL void
    927 cvPyrUp( const void* srcarr, void* dstarr, int _filter )
    928 {
    929     static CvFuncTable pyrup_tab;
    930     static int inittab = 0;
    931 
    932     void *buffer = 0;
    933     int local_alloc = 0;
    934 
    935     CV_FUNCNAME( "cvPyrUp" );
    936 
    937     __BEGIN__;
    938 
    939     int coi1 = 0, coi2 = 0;
    940     int buffer_size = 0;
    941     int type, depth, cn;
    942     CvMat srcstub, *src = (CvMat*)srcarr;
    943     CvMat dststub, *dst = (CvMat*)dstarr;
    944     CvFilter filter = (CvFilter) _filter;
    945     CvPyramidFunc func;
    946     CvPyramidIPPFunc ipp_func = 0;
    947     int use_ipp = 0;
    948     CvSize size;
    949 
    950     if( !inittab )
    951     {
    952         icvInitPyrUpG5x5Table( &pyrup_tab );
    953         inittab = 1;
    954     }
    955 
    956     CV_CALL( src = cvGetMat( src, &srcstub, &coi1 ));
    957     CV_CALL( dst = cvGetMat( dst, &dststub, &coi2 ));
    958 
    959     if( coi1 != 0 || coi2 != 0 )
    960         CV_ERROR( CV_BadCOI, "" );
    961 
    962     if( filter != CV_GAUSSIAN_5x5 )
    963         CV_ERROR( CV_StsBadArg, "this filter type not supported" );
    964 
    965     if( !CV_ARE_TYPES_EQ( src, dst ))
    966         CV_ERROR( CV_StsUnmatchedFormats, "" );
    967 
    968     if( src->cols*2 != dst->cols || src->rows*2 != dst->rows )
    969         CV_ERROR( CV_StsUnmatchedSizes, "" );
    970 
    971     size = cvGetMatSize(src);
    972     type = CV_MAT_TYPE(src->type);
    973     depth = CV_MAT_DEPTH(type);
    974     cn = CV_MAT_CN(type);
    975 
    976     if( cn != 1 && cn != 3 )
    977         CV_ERROR( CV_StsUnsupportedFormat, "The images must have 1 or 3 channel" );
    978 
    979     func = (CvPyramidFunc)pyrup_tab.fn_2d[depth];
    980 
    981     if( !func )
    982         CV_ERROR( CV_StsUnsupportedFormat, "" );
    983 
    984     if( icvPyrUpGetBufSize_Gauss5x5_p )
    985     {
    986         ipp_func = type == CV_8UC1 ? icvPyrUp_Gauss5x5_8u_C1R_p :
    987                    type == CV_8UC3 ? icvPyrUp_Gauss5x5_8u_C3R_p :
    988                    type == CV_32FC1 ? icvPyrUp_Gauss5x5_32f_C1R_p :
    989                    type == CV_32FC3 ? icvPyrUp_Gauss5x5_32f_C3R_p : 0;
    990 
    991         use_ipp = ipp_func && icvPyrUpGetBufSize_Gauss5x5_p( size.width,
    992                     icvDepthToDataType(type), cn, &buffer_size ) >= 0;
    993     }
    994 
    995     if( !use_ipp )
    996         icvPyrUpG5x5_GetBufSize( size.width, icvDepthToDataType(type), cn, &buffer_size );
    997 
    998     if( buffer_size <= CV_MAX_LOCAL_SIZE )
    999     {
   1000         buffer = cvStackAlloc( buffer_size );
   1001         local_alloc = 1;
   1002     }
   1003     else
   1004         CV_CALL( buffer = cvAlloc( buffer_size ));
   1005 
   1006     if( !use_ipp )
   1007         func( src->data.ptr, src->step, dst->data.ptr, dst->step, size, buffer, cn );
   1008     else
   1009         IPPI_CALL( ipp_func( src->data.ptr, src->step ? src->step : CV_STUB_STEP,
   1010             dst->data.ptr, dst->step ? dst->step : CV_STUB_STEP, size, buffer ));
   1011     __END__;
   1012 
   1013     if( buffer && !local_alloc )
   1014         cvFree( &buffer );
   1015 }
   1016 
   1017 
   1018 CV_IMPL void
   1019 cvPyrDown( const void* srcarr, void* dstarr, int _filter )
   1020 {
   1021     static CvFuncTable pyrdown_tab;
   1022     static CvFuncTable pyrdownborder_tab;
   1023     static int inittab = 0;
   1024 
   1025     void *buffer = 0;
   1026     int local_alloc = 0;
   1027 
   1028     CV_FUNCNAME( "cvPyrDown" );
   1029 
   1030     __BEGIN__;
   1031 
   1032     int coi1 = 0, coi2 = 0;
   1033     int buffer_size = 0;
   1034     int type, depth, cn;
   1035     CvMat srcstub, *src = (CvMat*)srcarr;
   1036     CvMat dststub, *dst = (CvMat*)dstarr;
   1037     CvFilter filter = (CvFilter) _filter;
   1038     CvPyramidFunc func;
   1039     CvPyramidIPPFunc ipp_func = 0;
   1040     int use_ipp = 0;
   1041     CvSize src_size, src_size2, dst_size;
   1042 
   1043     if( !inittab )
   1044     {
   1045         icvInitPyrDownG5x5Table( &pyrdown_tab );
   1046         icvInitPyrDownBorderTable( &pyrdownborder_tab );
   1047         inittab = 1;
   1048     }
   1049 
   1050     CV_CALL( src = cvGetMat( src, &srcstub, &coi1 ));
   1051     CV_CALL( dst = cvGetMat( dst, &dststub, &coi2 ));
   1052 
   1053     if( coi1 != 0 || coi2 != 0 )
   1054         CV_ERROR( CV_BadCOI, "" );
   1055 
   1056     if( filter != CV_GAUSSIAN_5x5 )
   1057         CV_ERROR( CV_StsBadArg, "this filter type not supported" );
   1058 
   1059     if( !CV_ARE_TYPES_EQ( src, dst ))
   1060         CV_ERROR( CV_StsUnmatchedFormats, "" );
   1061 
   1062     src_size = cvGetMatSize(src);
   1063     dst_size = cvGetMatSize(dst);
   1064     src_size2.width = src_size.width & -2;
   1065     src_size2.height = src_size.height & -2;
   1066 
   1067     if( (unsigned)(dst_size.width - src_size.width/2) > 1 ||
   1068         (unsigned)(dst_size.height - src_size.height/2) > 1 )
   1069         CV_ERROR( CV_StsUnmatchedSizes, "" );
   1070 
   1071     // current restriction of PyrDownBorder*
   1072     if( (src_size.width <= 2 && dst_size.width != 1) ||
   1073         (src_size.height <= 2 && dst_size.height != 1) )
   1074         CV_ERROR( CV_StsUnmatchedSizes, "" );
   1075 
   1076     /*if( src->data.ptr == dst->data.ptr )
   1077         CV_ERROR( CV_StsInplaceNotSupported, "" );*/
   1078 
   1079     type = CV_MAT_TYPE(src->type);
   1080     depth = CV_MAT_DEPTH(type);
   1081     cn = CV_MAT_CN(type);
   1082 
   1083     if( cn != 1 && cn != 3 )
   1084         CV_ERROR( CV_StsUnsupportedFormat, "The images must have 1 or 3 channel" );
   1085 
   1086     func = (CvPyramidFunc)pyrdown_tab.fn_2d[depth];
   1087 
   1088     if( !func )
   1089         CV_ERROR( CV_StsUnsupportedFormat, "" );
   1090 
   1091     if( icvPyrDownGetBufSize_Gauss5x5_p )
   1092     {
   1093         ipp_func = type == CV_8UC1 ? icvPyrDown_Gauss5x5_8u_C1R_p :
   1094                    type == CV_8UC3 ? icvPyrDown_Gauss5x5_8u_C3R_p :
   1095                    type == CV_32FC1 ? icvPyrDown_Gauss5x5_32f_C1R_p :
   1096                    type == CV_32FC3 ? icvPyrDown_Gauss5x5_32f_C3R_p : 0;
   1097 
   1098         use_ipp = ipp_func && icvPyrDownGetBufSize_Gauss5x5_p( src_size2.width,
   1099                     icvDepthToDataType(type), cn, &buffer_size ) >= 0;
   1100     }
   1101 
   1102     if( !use_ipp )
   1103         icvPyrDownG5x5_GetBufSize( src_size2.width,
   1104             icvDepthToDataType(type), cn, &buffer_size );
   1105 
   1106     if( buffer_size <= CV_MAX_LOCAL_SIZE )
   1107     {
   1108         buffer = cvStackAlloc( buffer_size );
   1109         local_alloc = 1;
   1110     }
   1111     else
   1112         CV_CALL( buffer = cvAlloc( buffer_size ));
   1113 
   1114     if( !use_ipp )
   1115         func( src->data.ptr, src->step, dst->data.ptr,
   1116               dst->step, src_size2, buffer, cn );
   1117     else
   1118         IPPI_CALL( ipp_func( src->data.ptr, src->step ? src->step : CV_STUB_STEP,
   1119             dst->data.ptr, dst->step ? dst->step : CV_STUB_STEP, src_size2, buffer ));
   1120 
   1121     if( src_size.width != dst_size.width*2 || src_size.height != dst_size.height*2 )
   1122     {
   1123         CvPyrDownBorderFunc border_func = (CvPyrDownBorderFunc)
   1124                             pyrdownborder_tab.fn_2d[CV_MAT_DEPTH(type)];
   1125 
   1126         if( !border_func )
   1127             CV_ERROR( CV_StsUnsupportedFormat, "" );
   1128 
   1129         IPPI_CALL( border_func( src->data.ptr, src->step, src_size,
   1130                                 dst->data.ptr, dst->step, dst_size, CV_MAT_CN(type) ));
   1131     }
   1132 
   1133     __END__;
   1134 
   1135     if( buffer && !local_alloc )
   1136         cvFree( &buffer );
   1137 }
   1138 
   1139 
   1140 CV_IMPL void
   1141 cvReleasePyramid( CvMat*** _pyramid, int extra_layers )
   1142 {
   1143     CV_FUNCNAME( "cvReleasePyramid" );
   1144 
   1145     __BEGIN__;
   1146 
   1147     CvMat** pyramid;
   1148     int i;
   1149 
   1150     if( !_pyramid )
   1151         CV_ERROR( CV_StsNullPtr, "" );
   1152 
   1153     pyramid = *_pyramid;
   1154 
   1155     if( pyramid )
   1156     {
   1157         for( i = 0; i <= extra_layers; i++ )
   1158             cvReleaseMat( &pyramid[i] );
   1159     }
   1160 
   1161     cvFree( _pyramid );
   1162 
   1163     __END__;
   1164 }
   1165 
   1166 
   1167 CV_IMPL CvMat**
   1168 cvCreatePyramid( const CvArr* srcarr, int extra_layers, double rate,
   1169                  const CvSize* layer_sizes, CvArr* bufarr,
   1170                  int calc, int filter )
   1171 {
   1172     CvMat** pyramid = 0;
   1173     const float eps = 0.1f;
   1174 
   1175     CV_FUNCNAME( "cvCreatePyramid" );
   1176 
   1177     __BEGIN__;
   1178 
   1179     int i, elem_size, layer_step;
   1180     CvMat stub, *src;
   1181     CvSize size, layer_size;
   1182     uchar* ptr = 0;
   1183 
   1184     CV_CALL( src = cvGetMat( srcarr, &stub ));
   1185 
   1186     if( extra_layers < 0 )
   1187         CV_ERROR( CV_StsOutOfRange, "The number of extra layers must be non negative" );
   1188 
   1189     elem_size = CV_ELEM_SIZE(src->type);
   1190     size = cvGetMatSize(src);
   1191 
   1192     if( bufarr )
   1193     {
   1194         CvMat bstub, *buf;
   1195         int bufsize = 0;
   1196 
   1197         CV_CALL( buf = cvGetMat( bufarr, &bstub ));
   1198         bufsize = buf->rows*buf->cols*CV_ELEM_SIZE(buf->type);
   1199         layer_size = size;
   1200         for( i = 1; i <= extra_layers; i++ )
   1201         {
   1202             if( !layer_sizes )
   1203             {
   1204                 layer_size.width = cvRound(layer_size.width*rate+eps);
   1205                 layer_size.height = cvRound(layer_size.height*rate+eps);
   1206             }
   1207             else
   1208                 layer_size = layer_sizes[i-1];
   1209             layer_step = layer_size.width*elem_size;
   1210             bufsize -= layer_step*layer_size.height;
   1211         }
   1212 
   1213         if( bufsize < 0 )
   1214             CV_ERROR( CV_StsOutOfRange, "The buffer is too small to fit the pyramid" );
   1215         ptr = buf->data.ptr;
   1216     }
   1217 
   1218     CV_CALL( pyramid = (CvMat**)cvAlloc( (extra_layers+1)*sizeof(pyramid[0]) ));
   1219     memset( pyramid, 0, (extra_layers+1)*sizeof(pyramid[0]) );
   1220 
   1221     pyramid[0] = cvCreateMatHeader( size.height, size.width, src->type );
   1222     cvSetData( pyramid[0], src->data.ptr, src->step );
   1223     layer_size = size;
   1224 
   1225     for( i = 1; i <= extra_layers; i++ )
   1226     {
   1227         if( !layer_sizes )
   1228         {
   1229             layer_size.width = cvRound(layer_size.width*rate + eps);
   1230             layer_size.height = cvRound(layer_size.height*rate + eps);
   1231         }
   1232         else
   1233             layer_size = layer_sizes[i];
   1234 
   1235         if( bufarr )
   1236         {
   1237             pyramid[i] = cvCreateMatHeader( layer_size.height, layer_size.width, src->type );
   1238             layer_step = layer_size.width*elem_size;
   1239             cvSetData( pyramid[i], ptr, layer_step );
   1240             ptr += layer_step*layer_size.height;
   1241         }
   1242         else
   1243             pyramid[i] = cvCreateMat( layer_size.height, layer_size.width, src->type );
   1244 
   1245         if( calc )
   1246             cvPyrDown( pyramid[i-1], pyramid[i], filter );
   1247             //cvResize( pyramid[i-1], pyramid[i], CV_INTER_LINEAR );
   1248     }
   1249 
   1250     __END__;
   1251 
   1252     if( cvGetErrStatus() < 0 )
   1253         cvReleasePyramid( &pyramid, extra_layers );
   1254 
   1255     return pyramid;
   1256 }
   1257 
   1258 
   1259 /* MSVC .NET 2003 spends a long time building this, thus, as the code
   1260    is not performance-critical, we turn off the optimization here */
   1261 #if defined _MSC_VER && _MSC_VER > 1300 && !defined CV_ICC
   1262 #pragma optimize("", off)
   1263 #endif
   1264 
   1265 ICV_DEF_PYR_BORDER_FUNC( 8u, uchar, int, PD_SCALE_INT )
   1266 ICV_DEF_PYR_BORDER_FUNC( 16u, ushort, int, PD_SCALE_INT )
   1267 ICV_DEF_PYR_BORDER_FUNC( 16s, short, int, PD_SCALE_INT )
   1268 ICV_DEF_PYR_BORDER_FUNC( 32f, float, float, PD_SCALE_FLT )
   1269 ICV_DEF_PYR_BORDER_FUNC( 64f, double, double, PD_SCALE_FLT )
   1270 
   1271 #define ICV_DEF_INIT_PYR_BORDER_TABLE( FUNCNAME )                   \
   1272 static void icvInit##FUNCNAME##Table( CvFuncTable* tab )            \
   1273 {                                                                   \
   1274     tab->fn_2d[CV_8U] = (void*)icv##FUNCNAME##_8u_CnR;              \
   1275     tab->fn_2d[CV_8S] = 0;                                          \
   1276     tab->fn_2d[CV_16U] = (void*)icv##FUNCNAME##_16u_CnR;            \
   1277     tab->fn_2d[CV_16S] = (void*)icv##FUNCNAME##_16s_CnR;            \
   1278     tab->fn_2d[CV_32F] = (void*)icv##FUNCNAME##_32f_CnR;            \
   1279     tab->fn_2d[CV_64F] = (void*)icv##FUNCNAME##_64f_CnR;            \
   1280 }
   1281 
   1282 ICV_DEF_INIT_PYR_BORDER_TABLE( PyrDownBorder )
   1283 
   1284 /* End of file. */
   1285