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 arithmetic operations: +, - ... 45 // 46 // */ 47 48 #include "_cxcore.h" 49 50 /****************************************************************************************\ 51 * Arithmetic operations (+, -) without mask * 52 \****************************************************************************************/ 53 54 #define ICV_DEF_BIN_ARI_OP_CASE( __op__, worktype, cast_macro, len )\ 55 { \ 56 int i; \ 57 \ 58 for( i = 0; i <= (len) - 4; i += 4 ) \ 59 { \ 60 worktype t0 = __op__((src1)[i], (src2)[i]); \ 61 worktype t1 = __op__((src1)[i+1], (src2)[i+1]); \ 62 \ 63 (dst)[i] = cast_macro( t0 ); \ 64 (dst)[i+1] = cast_macro( t1 ); \ 65 \ 66 t0 = __op__((src1)[i+2],(src2)[i+2]); \ 67 t1 = __op__((src1)[i+3],(src2)[i+3]); \ 68 \ 69 (dst)[i+2] = cast_macro( t0 ); \ 70 (dst)[i+3] = cast_macro( t1 ); \ 71 } \ 72 \ 73 for( ; i < (len); i++ ) \ 74 { \ 75 worktype t0 = __op__((src1)[i],(src2)[i]); \ 76 (dst)[i] = cast_macro( t0 ); \ 77 } \ 78 } 79 80 #define ICV_DEF_BIN_ARI_OP_2D( __op__, name, type, worktype, cast_macro ) \ 81 IPCVAPI_IMPL( CvStatus, name, \ 82 ( const type* src1, int step1, const type* src2, int step2, \ 83 type* dst, int step, CvSize size ), \ 84 (src1, step1, src2, step2, dst, step, size) ) \ 85 { \ 86 step1/=sizeof(src1[0]); step2/=sizeof(src2[0]); step/=sizeof(dst[0]); \ 87 \ 88 if( size.width == 1 ) \ 89 { \ 90 for( ; size.height--; src1 += step1, src2 += step2, dst += step ) \ 91 { \ 92 worktype t0 = __op__((src1)[0],(src2)[0]); \ 93 (dst)[0] = cast_macro( t0 ); \ 94 } \ 95 } \ 96 else \ 97 { \ 98 for( ; size.height--; src1 += step1, src2 += step2, dst += step ) \ 99 { \ 100 ICV_DEF_BIN_ARI_OP_CASE( __op__, worktype, \ 101 cast_macro, size.width ); \ 102 } \ 103 } \ 104 \ 105 return CV_OK; \ 106 } 107 108 109 #define ICV_DEF_BIN_ARI_OP_2D_SFS(__op__, name, type, worktype, cast_macro) \ 110 IPCVAPI_IMPL( CvStatus, name, \ 111 ( const type* src1, int step1, const type* src2, int step2, \ 112 type* dst, int step, CvSize size, int /*scalefactor*/ ), \ 113 (src1, step1, src2, step2, dst, step, size, 0) ) \ 114 { \ 115 step1/=sizeof(src1[0]); step2/=sizeof(src2[0]); step/=sizeof(dst[0]); \ 116 \ 117 if( size.width == 1 ) \ 118 { \ 119 for( ; size.height--; src1 += step1, src2 += step2, dst += step ) \ 120 { \ 121 worktype t0 = __op__((src1)[0],(src2)[0]); \ 122 (dst)[0] = cast_macro( t0 ); \ 123 } \ 124 } \ 125 else \ 126 { \ 127 for( ; size.height--; src1 += step1, src2 += step2, dst += step ) \ 128 { \ 129 ICV_DEF_BIN_ARI_OP_CASE( __op__, worktype, \ 130 cast_macro, size.width ); \ 131 } \ 132 } \ 133 \ 134 return CV_OK; \ 135 } 136 137 138 #define ICV_DEF_UN_ARI_OP_CASE( __op__, worktype, cast_macro, \ 139 src, scalar, dst, len ) \ 140 { \ 141 int i; \ 142 \ 143 for( ; ((len) -= 12) >= 0; (dst) += 12, (src) += 12 ) \ 144 { \ 145 worktype t0 = __op__((scalar)[0], (src)[0]); \ 146 worktype t1 = __op__((scalar)[1], (src)[1]); \ 147 \ 148 (dst)[0] = cast_macro( t0 ); \ 149 (dst)[1] = cast_macro( t1 ); \ 150 \ 151 t0 = __op__((scalar)[2], (src)[2]); \ 152 t1 = __op__((scalar)[3], (src)[3]); \ 153 \ 154 (dst)[2] = cast_macro( t0 ); \ 155 (dst)[3] = cast_macro( t1 ); \ 156 \ 157 t0 = __op__((scalar)[4], (src)[4]); \ 158 t1 = __op__((scalar)[5], (src)[5]); \ 159 \ 160 (dst)[4] = cast_macro( t0 ); \ 161 (dst)[5] = cast_macro( t1 ); \ 162 \ 163 t0 = __op__((scalar)[6], (src)[6]); \ 164 t1 = __op__((scalar)[7], (src)[7]); \ 165 \ 166 (dst)[6] = cast_macro( t0 ); \ 167 (dst)[7] = cast_macro( t1 ); \ 168 \ 169 t0 = __op__((scalar)[8], (src)[8]); \ 170 t1 = __op__((scalar)[9], (src)[9]); \ 171 \ 172 (dst)[8] = cast_macro( t0 ); \ 173 (dst)[9] = cast_macro( t1 ); \ 174 \ 175 t0 = __op__((scalar)[10], (src)[10]); \ 176 t1 = __op__((scalar)[11], (src)[11]); \ 177 \ 178 (dst)[10] = cast_macro( t0 ); \ 179 (dst)[11] = cast_macro( t1 ); \ 180 } \ 181 \ 182 for( (len) += 12, i = 0; i < (len); i++ ) \ 183 { \ 184 worktype t0 = __op__((scalar)[i],(src)[i]); \ 185 (dst)[i] = cast_macro( t0 ); \ 186 } \ 187 } 188 189 190 #define ICV_DEF_UN_ARI_OP_2D( __op__, name, type, worktype, cast_macro ) \ 191 static CvStatus CV_STDCALL name \ 192 ( const type* src, int step1, type* dst, int step, \ 193 CvSize size, const worktype* scalar ) \ 194 { \ 195 step1 /= sizeof(src[0]); step /= sizeof(dst[0]); \ 196 \ 197 if( size.width == 1 ) \ 198 { \ 199 for( ; size.height--; src += step1, dst += step ) \ 200 { \ 201 worktype t0 = __op__(*(scalar),*(src)); \ 202 *(dst) = cast_macro( t0 ); \ 203 } \ 204 } \ 205 else \ 206 { \ 207 for( ; size.height--; src += step1, dst += step ) \ 208 { \ 209 const type *tsrc = src; \ 210 type *tdst = dst; \ 211 int width = size.width; \ 212 \ 213 ICV_DEF_UN_ARI_OP_CASE( __op__, worktype, cast_macro, \ 214 tsrc, scalar, tdst, width ); \ 215 } \ 216 } \ 217 \ 218 return CV_OK; \ 219 } 220 221 222 #define ICV_DEF_BIN_ARI_ALL( __op__, name, cast_8u ) \ 223 ICV_DEF_BIN_ARI_OP_2D_SFS( __op__, icv##name##_8u_C1R, uchar, int, cast_8u ) \ 224 ICV_DEF_BIN_ARI_OP_2D_SFS( __op__, icv##name##_16u_C1R, ushort, int, CV_CAST_16U ) \ 225 ICV_DEF_BIN_ARI_OP_2D_SFS( __op__, icv##name##_16s_C1R, short, int, CV_CAST_16S ) \ 226 ICV_DEF_BIN_ARI_OP_2D( __op__, icv##name##_32s_C1R, int, int, CV_CAST_32S ) \ 227 ICV_DEF_BIN_ARI_OP_2D( __op__, icv##name##_32f_C1R, float, float, CV_CAST_32F ) \ 228 ICV_DEF_BIN_ARI_OP_2D( __op__, icv##name##_64f_C1R, double, double, CV_CAST_64F ) 229 230 #define ICV_DEF_UN_ARI_ALL( __op__, name ) \ 231 ICV_DEF_UN_ARI_OP_2D( __op__, icv##name##_8u_C1R, uchar, int, CV_CAST_8U ) \ 232 ICV_DEF_UN_ARI_OP_2D( __op__, icv##name##_16u_C1R, ushort, int, CV_CAST_16U ) \ 233 ICV_DEF_UN_ARI_OP_2D( __op__, icv##name##_16s_C1R, short, int, CV_CAST_16S ) \ 234 ICV_DEF_UN_ARI_OP_2D( __op__, icv##name##_32s_C1R, int, int, CV_CAST_32S ) \ 235 ICV_DEF_UN_ARI_OP_2D( __op__, icv##name##_32f_C1R, float, float, CV_CAST_32F ) \ 236 ICV_DEF_UN_ARI_OP_2D( __op__, icv##name##_64f_C1R, double, double, CV_CAST_64F ) 237 238 #undef CV_SUB_R 239 #define CV_SUB_R(a,b) ((b) - (a)) 240 241 ICV_DEF_BIN_ARI_ALL( CV_ADD, Add, CV_FAST_CAST_8U ) 242 ICV_DEF_BIN_ARI_ALL( CV_SUB_R, Sub, CV_FAST_CAST_8U ) 243 244 ICV_DEF_UN_ARI_ALL( CV_ADD, AddC ) 245 ICV_DEF_UN_ARI_ALL( CV_SUB, SubRC ) 246 247 #define ICV_DEF_INIT_ARITHM_FUNC_TAB( FUNCNAME, FLAG ) \ 248 static void icvInit##FUNCNAME##FLAG##Table( CvFuncTable* tab )\ 249 { \ 250 tab->fn_2d[CV_8U] = (void*)icv##FUNCNAME##_8u_##FLAG; \ 251 tab->fn_2d[CV_8S] = 0; \ 252 tab->fn_2d[CV_16U] = (void*)icv##FUNCNAME##_16u_##FLAG; \ 253 tab->fn_2d[CV_16S] = (void*)icv##FUNCNAME##_16s_##FLAG; \ 254 tab->fn_2d[CV_32S] = (void*)icv##FUNCNAME##_32s_##FLAG; \ 255 tab->fn_2d[CV_32F] = (void*)icv##FUNCNAME##_32f_##FLAG; \ 256 tab->fn_2d[CV_64F] = (void*)icv##FUNCNAME##_64f_##FLAG; \ 257 } 258 259 ICV_DEF_INIT_ARITHM_FUNC_TAB( Sub, C1R ) 260 ICV_DEF_INIT_ARITHM_FUNC_TAB( SubRC, C1R ) 261 ICV_DEF_INIT_ARITHM_FUNC_TAB( Add, C1R ) 262 ICV_DEF_INIT_ARITHM_FUNC_TAB( AddC, C1R ) 263 264 /****************************************************************************************\ 265 * External Functions for Arithmetic Operations * 266 \****************************************************************************************/ 267 268 /*************************************** S U B ******************************************/ 269 270 CV_IMPL void 271 cvSub( const void* srcarr1, const void* srcarr2, 272 void* dstarr, const void* maskarr ) 273 { 274 static CvFuncTable sub_tab; 275 static int inittab = 0; 276 int local_alloc = 1; 277 uchar* buffer = 0; 278 279 CV_FUNCNAME( "cvSub" ); 280 281 __BEGIN__; 282 283 const CvArr* tmp; 284 int y, dy, type, depth, cn, cont_flag = 0; 285 int src1_step, src2_step, dst_step, tdst_step, mask_step; 286 CvMat srcstub1, srcstub2, *src1, *src2; 287 CvMat dststub, *dst = (CvMat*)dstarr; 288 CvMat maskstub, *mask = (CvMat*)maskarr; 289 CvMat dstbuf, *tdst; 290 CvFunc2D_3A func; 291 CvFunc2D_3A1I func_sfs; 292 CvCopyMaskFunc copym_func; 293 CvSize size, tsize; 294 295 CV_SWAP( srcarr1, srcarr2, tmp ); // to comply with IPP 296 src1 = (CvMat*)srcarr1; 297 src2 = (CvMat*)srcarr2; 298 299 if( !CV_IS_MAT(src1) || !CV_IS_MAT(src2) || !CV_IS_MAT(dst)) 300 { 301 if( CV_IS_MATND(src1) || CV_IS_MATND(src2) || CV_IS_MATND(dst)) 302 { 303 CvArr* arrs[] = { src1, src2, dst }; 304 CvMatND stubs[3]; 305 CvNArrayIterator iterator; 306 307 if( maskarr ) 308 CV_ERROR( CV_StsBadMask, 309 "This operation on multi-dimensional arrays does not support mask" ); 310 311 CV_CALL( cvInitNArrayIterator( 3, arrs, 0, stubs, &iterator )); 312 313 type = iterator.hdr[0]->type; 314 iterator.size.width *= CV_MAT_CN(type); 315 316 if( !inittab ) 317 { 318 icvInitSubC1RTable( &sub_tab ); 319 inittab = 1; 320 } 321 322 depth = CV_MAT_DEPTH(type); 323 if( depth <= CV_16S ) 324 { 325 func_sfs = (CvFunc2D_3A1I)(sub_tab.fn_2d[depth]); 326 if( !func_sfs ) 327 CV_ERROR( CV_StsUnsupportedFormat, "" ); 328 329 do 330 { 331 IPPI_CALL( func_sfs( iterator.ptr[0], CV_STUB_STEP, 332 iterator.ptr[1], CV_STUB_STEP, 333 iterator.ptr[2], CV_STUB_STEP, 334 iterator.size, 0 )); 335 } 336 while( cvNextNArraySlice( &iterator )); 337 } 338 else 339 { 340 func = (CvFunc2D_3A)(sub_tab.fn_2d[depth]); 341 if( !func ) 342 CV_ERROR( CV_StsUnsupportedFormat, "" ); 343 344 do 345 { 346 IPPI_CALL( func( iterator.ptr[0], CV_STUB_STEP, 347 iterator.ptr[1], CV_STUB_STEP, 348 iterator.ptr[2], CV_STUB_STEP, 349 iterator.size )); 350 } 351 while( cvNextNArraySlice( &iterator )); 352 } 353 EXIT; 354 } 355 else 356 { 357 int coi1 = 0, coi2 = 0, coi3 = 0; 358 359 CV_CALL( src1 = cvGetMat( src1, &srcstub1, &coi1 )); 360 CV_CALL( src2 = cvGetMat( src2, &srcstub2, &coi2 )); 361 CV_CALL( dst = cvGetMat( dst, &dststub, &coi3 )); 362 if( coi1 + coi2 + coi3 != 0 ) 363 CV_ERROR( CV_BadCOI, "" ); 364 } 365 } 366 367 if( !CV_ARE_TYPES_EQ( src1, src2 ) || !CV_ARE_TYPES_EQ( src1, dst )) 368 CV_ERROR_FROM_CODE( CV_StsUnmatchedFormats ); 369 370 if( !CV_ARE_SIZES_EQ( src1, src2 ) || !CV_ARE_SIZES_EQ( src1, dst )) 371 CV_ERROR_FROM_CODE( CV_StsUnmatchedSizes ); 372 373 type = CV_MAT_TYPE(src1->type); 374 size = cvGetMatSize( src1 ); 375 depth = CV_MAT_DEPTH(type); 376 cn = CV_MAT_CN(type); 377 378 if( !mask ) 379 { 380 if( CV_IS_MAT_CONT( src1->type & src2->type & dst->type )) 381 { 382 int len = size.width*size.height*cn; 383 384 if( len <= CV_MAX_INLINE_MAT_OP_SIZE*CV_MAX_INLINE_MAT_OP_SIZE ) 385 { 386 if( depth == CV_32F ) 387 { 388 const float* src1data = (const float*)(src1->data.ptr); 389 const float* src2data = (const float*)(src2->data.ptr); 390 float* dstdata = (float*)(dst->data.ptr); 391 392 do 393 { 394 dstdata[len-1] = (float)(src2data[len-1] - src1data[len-1]); 395 } 396 while( --len ); 397 398 EXIT; 399 } 400 401 if( depth == CV_64F ) 402 { 403 const double* src1data = (const double*)(src1->data.ptr); 404 const double* src2data = (const double*)(src2->data.ptr); 405 double* dstdata = (double*)(dst->data.ptr); 406 407 do 408 { 409 dstdata[len-1] = src2data[len-1] - src1data[len-1]; 410 } 411 while( --len ); 412 413 EXIT; 414 } 415 } 416 cont_flag = 1; 417 } 418 419 dy = size.height; 420 copym_func = 0; 421 tdst = dst; 422 } 423 else 424 { 425 int buf_size, elem_size; 426 427 if( !CV_IS_MAT(mask) ) 428 CV_CALL( mask = cvGetMat( mask, &maskstub )); 429 430 if( !CV_IS_MASK_ARR(mask)) 431 CV_ERROR( CV_StsBadMask, "" ); 432 433 if( !CV_ARE_SIZES_EQ( mask, dst )) 434 CV_ERROR( CV_StsUnmatchedSizes, "" ); 435 436 cont_flag = CV_IS_MAT_CONT( src1->type & src2->type & dst->type & mask->type ); 437 elem_size = CV_ELEM_SIZE(type); 438 439 dy = CV_MAX_LOCAL_SIZE/(elem_size*size.height); 440 dy = MAX(dy,1); 441 dy = MIN(dy,size.height); 442 dstbuf = cvMat( dy, size.width, type ); 443 if( !cont_flag ) 444 dstbuf.step = cvAlign( dstbuf.step, 8 ); 445 buf_size = dstbuf.step ? dstbuf.step*dy : size.width*elem_size; 446 if( buf_size > CV_MAX_LOCAL_SIZE ) 447 { 448 CV_CALL( buffer = (uchar*)cvAlloc( buf_size )); 449 local_alloc = 0; 450 } 451 else 452 buffer = (uchar*)cvStackAlloc( buf_size ); 453 dstbuf.data.ptr = buffer; 454 tdst = &dstbuf; 455 456 copym_func = icvGetCopyMaskFunc( elem_size ); 457 } 458 459 if( !inittab ) 460 { 461 icvInitSubC1RTable( &sub_tab ); 462 inittab = 1; 463 } 464 465 if( depth <= CV_16S ) 466 { 467 func = 0; 468 func_sfs = (CvFunc2D_3A1I)(sub_tab.fn_2d[depth]); 469 if( !func_sfs ) 470 CV_ERROR( CV_StsUnsupportedFormat, "" ); 471 } 472 else 473 { 474 func_sfs = 0; 475 func = (CvFunc2D_3A)(sub_tab.fn_2d[depth]); 476 if( !func ) 477 CV_ERROR( CV_StsUnsupportedFormat, "" ); 478 } 479 480 src1_step = src1->step; 481 src2_step = src2->step; 482 dst_step = dst->step; 483 tdst_step = tdst->step; 484 mask_step = mask ? mask->step : 0; 485 486 for( y = 0; y < size.height; y += dy ) 487 { 488 tsize.width = size.width; 489 tsize.height = dy; 490 if( y + dy > size.height ) 491 tsize.height = size.height - y; 492 if( cont_flag || tsize.height == 1 ) 493 { 494 tsize.width *= tsize.height; 495 tsize.height = 1; 496 src1_step = src2_step = tdst_step = dst_step = mask_step = CV_STUB_STEP; 497 } 498 499 IPPI_CALL( depth <= CV_16S ? 500 func_sfs( src1->data.ptr + y*src1->step, src1_step, 501 src2->data.ptr + y*src2->step, src2_step, 502 tdst->data.ptr, tdst_step, 503 cvSize( tsize.width*cn, tsize.height ), 0 ) : 504 func( src1->data.ptr + y*src1->step, src1_step, 505 src2->data.ptr + y*src2->step, src2_step, 506 tdst->data.ptr, tdst_step, 507 cvSize( tsize.width*cn, tsize.height ))); 508 509 if( mask ) 510 { 511 IPPI_CALL( copym_func( tdst->data.ptr, tdst_step, dst->data.ptr + y*dst->step, 512 dst_step, tsize, mask->data.ptr + y*mask->step, mask_step )); 513 } 514 } 515 516 __END__; 517 518 if( !local_alloc ) 519 cvFree( &buffer ); 520 } 521 522 523 CV_IMPL void 524 cvSubRS( const void* srcarr, CvScalar scalar, void* dstarr, const void* maskarr ) 525 { 526 static CvFuncTable subr_tab; 527 static int inittab = 0; 528 int local_alloc = 1; 529 uchar* buffer = 0; 530 531 CV_FUNCNAME( "cvSubRS" ); 532 533 __BEGIN__; 534 535 int sctype, y, dy, type, depth, cn, coi = 0, cont_flag = 0; 536 int src_step, dst_step, tdst_step, mask_step; 537 CvMat srcstub, *src = (CvMat*)srcarr; 538 CvMat dststub, *dst = (CvMat*)dstarr; 539 CvMat maskstub, *mask = (CvMat*)maskarr; 540 CvMat dstbuf, *tdst; 541 CvFunc2D_2A1P func; 542 CvCopyMaskFunc copym_func; 543 double buf[12]; 544 int is_nd = 0; 545 CvSize size, tsize; 546 547 if( !inittab ) 548 { 549 icvInitSubRCC1RTable( &subr_tab ); 550 inittab = 1; 551 } 552 553 if( !CV_IS_MAT(src) ) 554 { 555 if( CV_IS_MATND(src) ) 556 is_nd = 1; 557 else 558 { 559 CV_CALL( src = cvGetMat( src, &srcstub, &coi )); 560 if( coi != 0 ) 561 CV_ERROR( CV_BadCOI, "" ); 562 } 563 } 564 565 if( !CV_IS_MAT(dst) ) 566 { 567 if( CV_IS_MATND(dst) ) 568 is_nd = 1; 569 else 570 { 571 CV_CALL( dst = cvGetMat( dst, &dststub, &coi )); 572 if( coi != 0 ) 573 CV_ERROR( CV_BadCOI, "" ); 574 } 575 } 576 577 if( is_nd ) 578 { 579 CvArr* arrs[] = { src, dst }; 580 CvMatND stubs[2]; 581 CvNArrayIterator iterator; 582 583 if( maskarr ) 584 CV_ERROR( CV_StsBadMask, 585 "This operation on multi-dimensional arrays does not support mask" ); 586 587 CV_CALL( cvInitNArrayIterator( 2, arrs, 0, stubs, &iterator )); 588 589 sctype = type = CV_MAT_TYPE(iterator.hdr[0]->type); 590 if( CV_MAT_DEPTH(sctype) < CV_32S ) 591 sctype = (type & CV_MAT_CN_MASK) | CV_32SC1; 592 iterator.size.width *= CV_MAT_CN(type); 593 594 func = (CvFunc2D_2A1P)(subr_tab.fn_2d[CV_MAT_DEPTH(type)]); 595 if( !func ) 596 CV_ERROR( CV_StsUnsupportedFormat, "" ); 597 598 CV_CALL( cvScalarToRawData( &scalar, buf, sctype, 1 )); 599 600 do 601 { 602 IPPI_CALL( func( iterator.ptr[0], CV_STUB_STEP, 603 iterator.ptr[1], CV_STUB_STEP, 604 iterator.size, buf )); 605 } 606 while( cvNextNArraySlice( &iterator )); 607 EXIT; 608 } 609 610 if( !CV_ARE_TYPES_EQ( src, dst )) 611 CV_ERROR_FROM_CODE( CV_StsUnmatchedFormats ); 612 613 if( !CV_ARE_SIZES_EQ( src, dst )) 614 CV_ERROR_FROM_CODE( CV_StsUnmatchedSizes ); 615 616 sctype = type = CV_MAT_TYPE(src->type); 617 depth = CV_MAT_DEPTH(type); 618 cn = CV_MAT_CN(type); 619 if( depth < CV_32S ) 620 sctype = (type & CV_MAT_CN_MASK) | CV_32SC1; 621 622 size = cvGetMatSize( src ); 623 624 if( !maskarr ) 625 { 626 if( CV_IS_MAT_CONT( src->type & dst->type )) 627 { 628 if( size.width <= CV_MAX_INLINE_MAT_OP_SIZE ) 629 { 630 int len = size.width * size.height; 631 632 if( type == CV_32FC1 ) 633 { 634 const float* srcdata = (const float*)(src->data.ptr); 635 float* dstdata = (float*)(dst->data.ptr); 636 637 do 638 { 639 dstdata[len-1] = (float)(scalar.val[0] - srcdata[len-1]); 640 } 641 while( --len ); 642 643 EXIT; 644 } 645 646 if( type == CV_64FC1 ) 647 { 648 const double* srcdata = (const double*)(src->data.ptr); 649 double* dstdata = (double*)(dst->data.ptr); 650 651 do 652 { 653 dstdata[len-1] = scalar.val[0] - srcdata[len-1]; 654 } 655 while( --len ); 656 657 EXIT; 658 } 659 } 660 cont_flag = 1; 661 } 662 663 dy = size.height; 664 copym_func = 0; 665 tdst = dst; 666 } 667 else 668 { 669 int buf_size, elem_size; 670 671 if( !CV_IS_MAT(mask) ) 672 CV_CALL( mask = cvGetMat( mask, &maskstub )); 673 674 if( !CV_IS_MASK_ARR(mask)) 675 CV_ERROR( CV_StsBadMask, "" ); 676 677 if( !CV_ARE_SIZES_EQ( mask, dst )) 678 CV_ERROR( CV_StsUnmatchedSizes, "" ); 679 680 cont_flag = CV_IS_MAT_CONT( src->type & dst->type & mask->type ); 681 elem_size = CV_ELEM_SIZE(type); 682 683 dy = CV_MAX_LOCAL_SIZE/(elem_size*size.height); 684 dy = MAX(dy,1); 685 dy = MIN(dy,size.height); 686 dstbuf = cvMat( dy, size.width, type ); 687 if( !cont_flag ) 688 dstbuf.step = cvAlign( dstbuf.step, 8 ); 689 buf_size = dstbuf.step ? dstbuf.step*dy : size.width*elem_size; 690 if( buf_size > CV_MAX_LOCAL_SIZE ) 691 { 692 CV_CALL( buffer = (uchar*)cvAlloc( buf_size )); 693 local_alloc = 0; 694 } 695 else 696 buffer = (uchar*)cvStackAlloc( buf_size ); 697 dstbuf.data.ptr = buffer; 698 tdst = &dstbuf; 699 700 copym_func = icvGetCopyMaskFunc( elem_size ); 701 } 702 703 func = (CvFunc2D_2A1P)(subr_tab.fn_2d[depth]); 704 if( !func ) 705 CV_ERROR( CV_StsUnsupportedFormat, "" ); 706 707 src_step = src->step; 708 dst_step = dst->step; 709 tdst_step = tdst->step; 710 mask_step = mask ? mask->step : 0; 711 712 CV_CALL( cvScalarToRawData( &scalar, buf, sctype, 1 )); 713 714 for( y = 0; y < size.height; y += dy ) 715 { 716 tsize.width = size.width; 717 tsize.height = dy; 718 if( y + dy > size.height ) 719 tsize.height = size.height - y; 720 if( cont_flag || tsize.height == 1 ) 721 { 722 tsize.width *= tsize.height; 723 tsize.height = 1; 724 src_step = tdst_step = dst_step = mask_step = CV_STUB_STEP; 725 } 726 727 IPPI_CALL( func( src->data.ptr + y*src->step, src_step, 728 tdst->data.ptr, tdst_step, 729 cvSize( tsize.width*cn, tsize.height ), buf )); 730 if( mask ) 731 { 732 IPPI_CALL( copym_func( tdst->data.ptr, tdst_step, dst->data.ptr + y*dst->step, 733 dst_step, tsize, mask->data.ptr + y*mask->step, mask_step )); 734 } 735 } 736 737 __END__; 738 739 if( !local_alloc ) 740 cvFree( &buffer ); 741 } 742 743 744 /******************************* A D D ********************************/ 745 746 CV_IMPL void 747 cvAdd( const void* srcarr1, const void* srcarr2, 748 void* dstarr, const void* maskarr ) 749 { 750 static CvFuncTable add_tab; 751 static int inittab = 0; 752 int local_alloc = 1; 753 uchar* buffer = 0; 754 755 CV_FUNCNAME( "cvAdd" ); 756 757 __BEGIN__; 758 759 int y, dy, type, depth, cn, cont_flag = 0; 760 int src1_step, src2_step, dst_step, tdst_step, mask_step; 761 CvMat srcstub1, *src1 = (CvMat*)srcarr1; 762 CvMat srcstub2, *src2 = (CvMat*)srcarr2; 763 CvMat dststub, *dst = (CvMat*)dstarr; 764 CvMat maskstub, *mask = (CvMat*)maskarr; 765 CvMat dstbuf, *tdst; 766 CvFunc2D_3A func; 767 CvFunc2D_3A1I func_sfs; 768 CvCopyMaskFunc copym_func; 769 CvSize size, tsize; 770 771 if( !CV_IS_MAT(src1) || !CV_IS_MAT(src2) || !CV_IS_MAT(dst)) 772 { 773 if( CV_IS_MATND(src1) || CV_IS_MATND(src2) || CV_IS_MATND(dst)) 774 { 775 CvArr* arrs[] = { src1, src2, dst }; 776 CvMatND stubs[3]; 777 CvNArrayIterator iterator; 778 779 if( maskarr ) 780 CV_ERROR( CV_StsBadMask, 781 "This operation on multi-dimensional arrays does not support mask" ); 782 783 CV_CALL( cvInitNArrayIterator( 3, arrs, 0, stubs, &iterator )); 784 785 type = iterator.hdr[0]->type; 786 iterator.size.width *= CV_MAT_CN(type); 787 788 if( !inittab ) 789 { 790 icvInitAddC1RTable( &add_tab ); 791 inittab = 1; 792 } 793 794 depth = CV_MAT_DEPTH(type); 795 if( depth <= CV_16S ) 796 { 797 func_sfs = (CvFunc2D_3A1I)(add_tab.fn_2d[depth]); 798 if( !func_sfs ) 799 CV_ERROR( CV_StsUnsupportedFormat, "" ); 800 801 do 802 { 803 IPPI_CALL( func_sfs( iterator.ptr[0], CV_STUB_STEP, 804 iterator.ptr[1], CV_STUB_STEP, 805 iterator.ptr[2], CV_STUB_STEP, 806 iterator.size, 0 )); 807 } 808 while( cvNextNArraySlice( &iterator )); 809 } 810 else 811 { 812 func = (CvFunc2D_3A)(add_tab.fn_2d[depth]); 813 if( !func ) 814 CV_ERROR( CV_StsUnsupportedFormat, "" ); 815 816 do 817 { 818 IPPI_CALL( func( iterator.ptr[0], CV_STUB_STEP, 819 iterator.ptr[1], CV_STUB_STEP, 820 iterator.ptr[2], CV_STUB_STEP, 821 iterator.size )); 822 } 823 while( cvNextNArraySlice( &iterator )); 824 } 825 EXIT; 826 } 827 else 828 { 829 int coi1 = 0, coi2 = 0, coi3 = 0; 830 831 CV_CALL( src1 = cvGetMat( src1, &srcstub1, &coi1 )); 832 CV_CALL( src2 = cvGetMat( src2, &srcstub2, &coi2 )); 833 CV_CALL( dst = cvGetMat( dst, &dststub, &coi3 )); 834 if( coi1 + coi2 + coi3 != 0 ) 835 CV_ERROR( CV_BadCOI, "" ); 836 } 837 } 838 839 if( !CV_ARE_TYPES_EQ( src1, src2 ) || !CV_ARE_TYPES_EQ( src1, dst )) 840 CV_ERROR_FROM_CODE( CV_StsUnmatchedFormats ); 841 842 if( !CV_ARE_SIZES_EQ( src1, src2 ) || !CV_ARE_SIZES_EQ( src1, dst )) 843 CV_ERROR_FROM_CODE( CV_StsUnmatchedSizes ); 844 845 type = CV_MAT_TYPE(src1->type); 846 size = cvGetMatSize( src1 ); 847 depth = CV_MAT_DEPTH(type); 848 cn = CV_MAT_CN(type); 849 850 if( !mask ) 851 { 852 if( CV_IS_MAT_CONT( src1->type & src2->type & dst->type )) 853 { 854 int len = size.width*size.height*cn; 855 856 if( len <= CV_MAX_INLINE_MAT_OP_SIZE*CV_MAX_INLINE_MAT_OP_SIZE ) 857 { 858 if( depth == CV_32F ) 859 { 860 const float* src1data = (const float*)(src1->data.ptr); 861 const float* src2data = (const float*)(src2->data.ptr); 862 float* dstdata = (float*)(dst->data.ptr); 863 864 do 865 { 866 dstdata[len-1] = (float)(src1data[len-1] + src2data[len-1]); 867 } 868 while( --len ); 869 870 EXIT; 871 } 872 873 if( depth == CV_64F ) 874 { 875 const double* src1data = (const double*)(src1->data.ptr); 876 const double* src2data = (const double*)(src2->data.ptr); 877 double* dstdata = (double*)(dst->data.ptr); 878 879 do 880 { 881 dstdata[len-1] = src1data[len-1] + src2data[len-1]; 882 } 883 while( --len ); 884 885 EXIT; 886 } 887 } 888 cont_flag = 1; 889 } 890 891 dy = size.height; 892 copym_func = 0; 893 tdst = dst; 894 } 895 else 896 { 897 int buf_size, elem_size; 898 899 if( !CV_IS_MAT(mask) ) 900 CV_CALL( mask = cvGetMat( mask, &maskstub )); 901 902 if( !CV_IS_MASK_ARR(mask)) 903 CV_ERROR( CV_StsBadMask, "" ); 904 905 if( !CV_ARE_SIZES_EQ( mask, dst )) 906 CV_ERROR( CV_StsUnmatchedSizes, "" ); 907 908 cont_flag = CV_IS_MAT_CONT( src1->type & src2->type & dst->type & mask->type ); 909 elem_size = CV_ELEM_SIZE(type); 910 911 dy = CV_MAX_LOCAL_SIZE/(elem_size*size.height); 912 dy = MAX(dy,1); 913 dy = MIN(dy,size.height); 914 dstbuf = cvMat( dy, size.width, type ); 915 if( !cont_flag ) 916 dstbuf.step = cvAlign( dstbuf.step, 8 ); 917 buf_size = dstbuf.step ? dstbuf.step*dy : size.width*elem_size; 918 if( buf_size > CV_MAX_LOCAL_SIZE ) 919 { 920 CV_CALL( buffer = (uchar*)cvAlloc( buf_size )); 921 local_alloc = 0; 922 } 923 else 924 buffer = (uchar*)cvStackAlloc( buf_size ); 925 dstbuf.data.ptr = buffer; 926 tdst = &dstbuf; 927 928 copym_func = icvGetCopyMaskFunc( elem_size ); 929 } 930 931 if( !inittab ) 932 { 933 icvInitAddC1RTable( &add_tab ); 934 inittab = 1; 935 } 936 937 if( depth <= CV_16S ) 938 { 939 func = 0; 940 func_sfs = (CvFunc2D_3A1I)(add_tab.fn_2d[depth]); 941 if( !func_sfs ) 942 CV_ERROR( CV_StsUnsupportedFormat, "" ); 943 } 944 else 945 { 946 func_sfs = 0; 947 func = (CvFunc2D_3A)(add_tab.fn_2d[depth]); 948 if( !func ) 949 CV_ERROR( CV_StsUnsupportedFormat, "" ); 950 } 951 952 src1_step = src1->step; 953 src2_step = src2->step; 954 dst_step = dst->step; 955 tdst_step = tdst->step; 956 mask_step = mask ? mask->step : 0; 957 958 for( y = 0; y < size.height; y += dy ) 959 { 960 tsize.width = size.width; 961 tsize.height = dy; 962 if( y + dy > size.height ) 963 tsize.height = size.height - y; 964 if( cont_flag || tsize.height == 1 ) 965 { 966 tsize.width *= tsize.height; 967 tsize.height = 1; 968 src1_step = src2_step = tdst_step = dst_step = mask_step = CV_STUB_STEP; 969 } 970 971 IPPI_CALL( depth <= CV_16S ? 972 func_sfs( src1->data.ptr + y*src1->step, src1_step, 973 src2->data.ptr + y*src2->step, src2_step, 974 tdst->data.ptr, tdst_step, 975 cvSize( tsize.width*cn, tsize.height ), 0 ) : 976 func( src1->data.ptr + y*src1->step, src1_step, 977 src2->data.ptr + y*src2->step, src2_step, 978 tdst->data.ptr, tdst_step, 979 cvSize( tsize.width*cn, tsize.height ))); 980 981 if( mask ) 982 { 983 IPPI_CALL( copym_func( tdst->data.ptr, tdst_step, dst->data.ptr + y*dst->step, 984 dst_step, tsize, mask->data.ptr + y*mask->step, mask_step )); 985 } 986 } 987 988 __END__; 989 990 if( !local_alloc ) 991 cvFree( &buffer ); 992 } 993 994 995 CV_IMPL void 996 cvAddS( const void* srcarr, CvScalar scalar, void* dstarr, const void* maskarr ) 997 { 998 static CvFuncTable add_tab; 999 static int inittab = 0; 1000 int local_alloc = 1; 1001 uchar* buffer = 0; 1002 1003 CV_FUNCNAME( "cvAddS" ); 1004 1005 __BEGIN__; 1006 1007 int sctype, y, dy, type, depth, cn, coi = 0, cont_flag = 0; 1008 int src_step, dst_step, tdst_step, mask_step; 1009 CvMat srcstub, *src = (CvMat*)srcarr; 1010 CvMat dststub, *dst = (CvMat*)dstarr; 1011 CvMat maskstub, *mask = (CvMat*)maskarr; 1012 CvMat dstbuf, *tdst; 1013 CvFunc2D_2A1P func; 1014 CvCopyMaskFunc copym_func; 1015 double buf[12]; 1016 int is_nd = 0; 1017 CvSize size, tsize; 1018 1019 if( !inittab ) 1020 { 1021 icvInitAddCC1RTable( &add_tab ); 1022 inittab = 1; 1023 } 1024 1025 if( !CV_IS_MAT(src) ) 1026 { 1027 if( CV_IS_MATND(src) ) 1028 is_nd = 1; 1029 else 1030 { 1031 CV_CALL( src = cvGetMat( src, &srcstub, &coi )); 1032 if( coi != 0 ) 1033 CV_ERROR( CV_BadCOI, "" ); 1034 } 1035 } 1036 1037 if( !CV_IS_MAT(dst) ) 1038 { 1039 if( CV_IS_MATND(dst) ) 1040 is_nd = 1; 1041 else 1042 { 1043 CV_CALL( dst = cvGetMat( dst, &dststub, &coi )); 1044 if( coi != 0 ) 1045 CV_ERROR( CV_BadCOI, "" ); 1046 } 1047 } 1048 1049 if( is_nd ) 1050 { 1051 CvArr* arrs[] = { src, dst }; 1052 CvMatND stubs[2]; 1053 CvNArrayIterator iterator; 1054 1055 if( maskarr ) 1056 CV_ERROR( CV_StsBadMask, 1057 "This operation on multi-dimensional arrays does not support mask" ); 1058 1059 CV_CALL( cvInitNArrayIterator( 2, arrs, 0, stubs, &iterator )); 1060 1061 sctype = type = CV_MAT_TYPE(iterator.hdr[0]->type); 1062 if( CV_MAT_DEPTH(sctype) < CV_32S ) 1063 sctype = (type & CV_MAT_CN_MASK) | CV_32SC1; 1064 iterator.size.width *= CV_MAT_CN(type); 1065 1066 func = (CvFunc2D_2A1P)(add_tab.fn_2d[CV_MAT_DEPTH(type)]); 1067 if( !func ) 1068 CV_ERROR( CV_StsUnsupportedFormat, "" ); 1069 1070 CV_CALL( cvScalarToRawData( &scalar, buf, sctype, 1 )); 1071 1072 do 1073 { 1074 IPPI_CALL( func( iterator.ptr[0], CV_STUB_STEP, 1075 iterator.ptr[1], CV_STUB_STEP, 1076 iterator.size, buf )); 1077 } 1078 while( cvNextNArraySlice( &iterator )); 1079 EXIT; 1080 } 1081 1082 if( !CV_ARE_TYPES_EQ( src, dst )) 1083 CV_ERROR_FROM_CODE( CV_StsUnmatchedFormats ); 1084 1085 if( !CV_ARE_SIZES_EQ( src, dst )) 1086 CV_ERROR_FROM_CODE( CV_StsUnmatchedSizes ); 1087 1088 sctype = type = CV_MAT_TYPE(src->type); 1089 depth = CV_MAT_DEPTH(type); 1090 cn = CV_MAT_CN(type); 1091 if( depth < CV_32S ) 1092 sctype = (type & CV_MAT_CN_MASK) | CV_32SC1; 1093 1094 size = cvGetMatSize( src ); 1095 1096 if( !maskarr ) 1097 { 1098 if( CV_IS_MAT_CONT( src->type & dst->type )) 1099 { 1100 if( size.width <= CV_MAX_INLINE_MAT_OP_SIZE ) 1101 { 1102 int len = size.width * size.height; 1103 1104 if( type == CV_32FC1 ) 1105 { 1106 const float* srcdata = (const float*)(src->data.ptr); 1107 float* dstdata = (float*)(dst->data.ptr); 1108 1109 do 1110 { 1111 dstdata[len-1] = (float)(scalar.val[0] + srcdata[len-1]); 1112 } 1113 while( --len ); 1114 1115 EXIT; 1116 } 1117 1118 if( type == CV_64FC1 ) 1119 { 1120 const double* srcdata = (const double*)(src->data.ptr); 1121 double* dstdata = (double*)(dst->data.ptr); 1122 1123 do 1124 { 1125 dstdata[len-1] = scalar.val[0] + srcdata[len-1]; 1126 } 1127 while( --len ); 1128 1129 EXIT; 1130 } 1131 } 1132 cont_flag = 1; 1133 } 1134 1135 dy = size.height; 1136 copym_func = 0; 1137 tdst = dst; 1138 } 1139 else 1140 { 1141 int buf_size, elem_size; 1142 1143 if( !CV_IS_MAT(mask) ) 1144 CV_CALL( mask = cvGetMat( mask, &maskstub )); 1145 1146 if( !CV_IS_MASK_ARR(mask)) 1147 CV_ERROR( CV_StsBadMask, "" ); 1148 1149 if( !CV_ARE_SIZES_EQ( mask, dst )) 1150 CV_ERROR( CV_StsUnmatchedSizes, "" ); 1151 1152 cont_flag = CV_IS_MAT_CONT( src->type & dst->type & mask->type ); 1153 elem_size = CV_ELEM_SIZE(type); 1154 1155 dy = CV_MAX_LOCAL_SIZE/(elem_size*size.height); 1156 dy = MAX(dy,1); 1157 dy = MIN(dy,size.height); 1158 dstbuf = cvMat( dy, size.width, type ); 1159 if( !cont_flag ) 1160 dstbuf.step = cvAlign( dstbuf.step, 8 ); 1161 buf_size = dstbuf.step ? dstbuf.step*dy : size.width*elem_size; 1162 if( buf_size > CV_MAX_LOCAL_SIZE ) 1163 { 1164 CV_CALL( buffer = (uchar*)cvAlloc( buf_size )); 1165 local_alloc = 0; 1166 } 1167 else 1168 buffer = (uchar*)cvStackAlloc( buf_size ); 1169 dstbuf.data.ptr = buffer; 1170 tdst = &dstbuf; 1171 1172 copym_func = icvGetCopyMaskFunc( elem_size ); 1173 } 1174 1175 func = (CvFunc2D_2A1P)(add_tab.fn_2d[depth]); 1176 if( !func ) 1177 CV_ERROR( CV_StsUnsupportedFormat, "" ); 1178 1179 src_step = src->step; 1180 dst_step = dst->step; 1181 tdst_step = tdst->step; 1182 mask_step = mask ? mask->step : 0; 1183 1184 CV_CALL( cvScalarToRawData( &scalar, buf, sctype, 1 )); 1185 1186 for( y = 0; y < size.height; y += dy ) 1187 { 1188 tsize.width = size.width; 1189 tsize.height = dy; 1190 if( y + dy > size.height ) 1191 tsize.height = size.height - y; 1192 if( cont_flag || tsize.height == 1 ) 1193 { 1194 tsize.width *= tsize.height; 1195 tsize.height = 1; 1196 src_step = tdst_step = dst_step = mask_step = CV_STUB_STEP; 1197 } 1198 1199 IPPI_CALL( func( src->data.ptr + y*src->step, src_step, 1200 tdst->data.ptr, tdst_step, 1201 cvSize( tsize.width*cn, tsize.height ), buf )); 1202 if( mask ) 1203 { 1204 IPPI_CALL( copym_func( tdst->data.ptr, tdst_step, dst->data.ptr + y*dst->step, 1205 dst_step, tsize, mask->data.ptr + y*mask->step, mask_step )); 1206 } 1207 } 1208 1209 __END__; 1210 1211 if( !local_alloc ) 1212 cvFree( &buffer ); 1213 } 1214 1215 1216 /***************************************** M U L ****************************************/ 1217 1218 #define ICV_DEF_MUL_OP_CASE( flavor, arrtype, worktype, _cast_macro1_, \ 1219 _cast_macro2_, _cvt_macro_ ) \ 1220 static CvStatus CV_STDCALL \ 1221 icvMul_##flavor##_C1R( const arrtype* src1, int step1, \ 1222 const arrtype* src2, int step2, \ 1223 arrtype* dst, int step, \ 1224 CvSize size, double scale ) \ 1225 { \ 1226 step1 /= sizeof(src1[0]); step2 /= sizeof(src2[0]); step /= sizeof(dst[0]); \ 1227 \ 1228 if( fabs(scale - 1.) < DBL_EPSILON ) \ 1229 { \ 1230 for( ; size.height--; src1+=step1, src2+=step2, dst+=step ) \ 1231 { \ 1232 int i; \ 1233 for( i = 0; i <= size.width - 4; i += 4 ) \ 1234 { \ 1235 worktype t0 = src1[i] * src2[i]; \ 1236 worktype t1 = src1[i+1] * src2[i+1]; \ 1237 \ 1238 dst[i] = _cast_macro2_(t0); \ 1239 dst[i+1] = _cast_macro2_(t1); \ 1240 \ 1241 t0 = src1[i+2] * src2[i+2]; \ 1242 t1 = src1[i+3] * src2[i+3]; \ 1243 \ 1244 dst[i+2] = _cast_macro2_(t0); \ 1245 dst[i+3] = _cast_macro2_(t1); \ 1246 } \ 1247 \ 1248 for( ; i < size.width; i++ ) \ 1249 { \ 1250 worktype t0 = src1[i] * src2[i]; \ 1251 dst[i] = _cast_macro2_(t0); \ 1252 } \ 1253 } \ 1254 } \ 1255 else \ 1256 { \ 1257 for( ; size.height--; src1+=step1, src2+=step2, dst+=step ) \ 1258 { \ 1259 int i; \ 1260 for( i = 0; i <= size.width - 4; i += 4 ) \ 1261 { \ 1262 double ft0 = scale*_cvt_macro_(src1[i])*_cvt_macro_(src2[i]); \ 1263 double ft1 = scale*_cvt_macro_(src1[i+1])*_cvt_macro_(src2[i+1]); \ 1264 worktype t0 = _cast_macro1_(ft0); \ 1265 worktype t1 = _cast_macro1_(ft1); \ 1266 \ 1267 dst[i] = _cast_macro2_(t0); \ 1268 dst[i+1] = _cast_macro2_(t1); \ 1269 \ 1270 ft0 = scale*_cvt_macro_(src1[i+2])*_cvt_macro_(src2[i+2]); \ 1271 ft1 = scale*_cvt_macro_(src1[i+3])*_cvt_macro_(src2[i+3]); \ 1272 t0 = _cast_macro1_(ft0); \ 1273 t1 = _cast_macro1_(ft1); \ 1274 \ 1275 dst[i+2] = _cast_macro2_(t0); \ 1276 dst[i+3] = _cast_macro2_(t1); \ 1277 } \ 1278 \ 1279 for( ; i < size.width; i++ ) \ 1280 { \ 1281 worktype t0; \ 1282 t0 = _cast_macro1_(scale*_cvt_macro_(src1[i])*_cvt_macro_(src2[i])); \ 1283 dst[i] = _cast_macro2_(t0); \ 1284 } \ 1285 } \ 1286 } \ 1287 \ 1288 return CV_OK; \ 1289 } 1290 1291 1292 ICV_DEF_MUL_OP_CASE( 8u, uchar, int, cvRound, CV_CAST_8U, CV_8TO32F ) 1293 ICV_DEF_MUL_OP_CASE( 16u, ushort, int, cvRound, CV_CAST_16U, CV_NOP ) 1294 ICV_DEF_MUL_OP_CASE( 16s, short, int, cvRound, CV_CAST_16S, CV_NOP ) 1295 ICV_DEF_MUL_OP_CASE( 32s, int, int, cvRound, CV_CAST_32S, CV_NOP ) 1296 ICV_DEF_MUL_OP_CASE( 32f, float, double, CV_NOP, CV_CAST_32F, CV_NOP ) 1297 ICV_DEF_MUL_OP_CASE( 64f, double, double, CV_NOP, CV_CAST_64F, CV_NOP ) 1298 1299 1300 ICV_DEF_INIT_ARITHM_FUNC_TAB( Mul, C1R ) 1301 1302 1303 typedef CvStatus (CV_STDCALL * CvScaledElWiseFunc)( const void* src1, int step1, 1304 const void* src2, int step2, 1305 void* dst, int step, 1306 CvSize size, double scale ); 1307 1308 CV_IMPL void 1309 cvMul( const void* srcarr1, const void* srcarr2, void* dstarr, double scale ) 1310 { 1311 static CvFuncTable mul_tab; 1312 static int inittab = 0; 1313 1314 CV_FUNCNAME( "cvMul" ); 1315 1316 __BEGIN__; 1317 1318 int type, depth, coi = 0; 1319 int src1_step, src2_step, dst_step; 1320 int is_nd = 0; 1321 CvMat srcstub1, *src1 = (CvMat*)srcarr1; 1322 CvMat srcstub2, *src2 = (CvMat*)srcarr2; 1323 CvMat dststub, *dst = (CvMat*)dstarr; 1324 CvSize size; 1325 CvScaledElWiseFunc func; 1326 1327 if( !inittab ) 1328 { 1329 icvInitMulC1RTable( &mul_tab ); 1330 inittab = 1; 1331 } 1332 1333 if( !CV_IS_MAT(src1) ) 1334 { 1335 if( CV_IS_MATND(src1) ) 1336 is_nd = 1; 1337 else 1338 { 1339 CV_CALL( src1 = cvGetMat( src1, &srcstub1, &coi )); 1340 if( coi != 0 ) 1341 CV_ERROR( CV_BadCOI, "" ); 1342 } 1343 } 1344 1345 if( !CV_IS_MAT(src2) ) 1346 { 1347 if( CV_IS_MATND(src2) ) 1348 is_nd = 1; 1349 else 1350 { 1351 CV_CALL( src2 = cvGetMat( src2, &srcstub2, &coi )); 1352 if( coi != 0 ) 1353 CV_ERROR( CV_BadCOI, "" ); 1354 } 1355 } 1356 1357 if( !CV_IS_MAT(dst) ) 1358 { 1359 if( CV_IS_MATND(dst) ) 1360 is_nd = 1; 1361 else 1362 { 1363 CV_CALL( dst = cvGetMat( dst, &dststub, &coi )); 1364 if( coi != 0 ) 1365 CV_ERROR( CV_BadCOI, "" ); 1366 } 1367 } 1368 1369 if( is_nd ) 1370 { 1371 CvArr* arrs[] = { src1, src2, dst }; 1372 CvMatND stubs[3]; 1373 CvNArrayIterator iterator; 1374 1375 CV_CALL( cvInitNArrayIterator( 3, arrs, 0, stubs, &iterator )); 1376 1377 type = iterator.hdr[0]->type; 1378 iterator.size.width *= CV_MAT_CN(type); 1379 1380 func = (CvScaledElWiseFunc)(mul_tab.fn_2d[CV_MAT_DEPTH(type)]); 1381 if( !func ) 1382 CV_ERROR( CV_StsUnsupportedFormat, "" ); 1383 1384 do 1385 { 1386 IPPI_CALL( func( iterator.ptr[0], CV_STUB_STEP, 1387 iterator.ptr[1], CV_STUB_STEP, 1388 iterator.ptr[2], CV_STUB_STEP, 1389 iterator.size, scale )); 1390 } 1391 while( cvNextNArraySlice( &iterator )); 1392 EXIT; 1393 } 1394 1395 if( !CV_ARE_TYPES_EQ( src1, src2 ) || !CV_ARE_TYPES_EQ( src1, dst )) 1396 CV_ERROR_FROM_CODE( CV_StsUnmatchedFormats ); 1397 1398 if( !CV_ARE_SIZES_EQ( src1, src2 ) || !CV_ARE_SIZES_EQ( src1, dst )) 1399 CV_ERROR_FROM_CODE( CV_StsUnmatchedSizes ); 1400 1401 type = CV_MAT_TYPE(src1->type); 1402 size = cvGetMatSize( src1 ); 1403 1404 depth = CV_MAT_DEPTH(type); 1405 size.width *= CV_MAT_CN( type ); 1406 1407 if( CV_IS_MAT_CONT( src1->type & src2->type & dst->type )) 1408 { 1409 size.width *= size.height; 1410 1411 if( size.width <= CV_MAX_INLINE_MAT_OP_SIZE && scale == 1 ) 1412 { 1413 if( depth == CV_32F ) 1414 { 1415 const float* src1data = (const float*)(src1->data.ptr); 1416 const float* src2data = (const float*)(src2->data.ptr); 1417 float* dstdata = (float*)(dst->data.ptr); 1418 1419 do 1420 { 1421 dstdata[size.width-1] = (float) 1422 (src1data[size.width-1] * src2data[size.width-1]); 1423 } 1424 while( --size.width ); 1425 1426 EXIT; 1427 } 1428 1429 if( depth == CV_64F ) 1430 { 1431 const double* src1data = (const double*)(src1->data.ptr); 1432 const double* src2data = (const double*)(src2->data.ptr); 1433 double* dstdata = (double*)(dst->data.ptr); 1434 1435 do 1436 { 1437 dstdata[size.width-1] = 1438 src1data[size.width-1] * src2data[size.width-1]; 1439 } 1440 while( --size.width ); 1441 1442 EXIT; 1443 } 1444 } 1445 1446 src1_step = src2_step = dst_step = CV_STUB_STEP; 1447 size.height = 1; 1448 } 1449 else 1450 { 1451 src1_step = src1->step; 1452 src2_step = src2->step; 1453 dst_step = dst->step; 1454 } 1455 1456 func = (CvScaledElWiseFunc)(mul_tab.fn_2d[CV_MAT_DEPTH(type)]); 1457 1458 if( !func ) 1459 CV_ERROR( CV_StsUnsupportedFormat, "" ); 1460 1461 IPPI_CALL( func( src1->data.ptr, src1_step, src2->data.ptr, src2_step, 1462 dst->data.ptr, dst_step, size, scale )); 1463 1464 __END__; 1465 } 1466 1467 1468 /***************************************** D I V ****************************************/ 1469 1470 #define ICV_DEF_DIV_OP_CASE( flavor, arrtype, worktype, checktype, _start_row_macro_, \ 1471 _cast_macro1_, _cast_macro2_, _cvt_macro_, _check_macro_, isrc ) \ 1472 \ 1473 static CvStatus CV_STDCALL \ 1474 icvDiv_##flavor##_C1R( const arrtype* src1, int step1, \ 1475 const arrtype* src2, int step2, \ 1476 arrtype* dst, int step, \ 1477 CvSize size, double scale ) \ 1478 { \ 1479 step1 /= sizeof(src1[0]); step2 /= sizeof(src2[0]); step /= sizeof(dst[0]); \ 1480 \ 1481 for( ; size.height--; src1+=step1, src2+=step2, dst+=step ) \ 1482 { \ 1483 _start_row_macro_(checktype, src2); \ 1484 for( i = 0; i <= size.width - 4; i += 4 ) \ 1485 { \ 1486 if( _check_macro_(isrc[i]) && _check_macro_(isrc[i+1]) && \ 1487 _check_macro_(isrc[i+2]) && _check_macro_(isrc[i+3])) \ 1488 { \ 1489 double a = (double)_cvt_macro_(src2[i]) * _cvt_macro_(src2[i+1]); \ 1490 double b = (double)_cvt_macro_(src2[i+2]) * _cvt_macro_(src2[i+3]); \ 1491 double d = scale/(a * b); \ 1492 \ 1493 b *= d; \ 1494 a *= d; \ 1495 \ 1496 worktype z0 = _cast_macro1_(src2[i+1] * _cvt_macro_(src1[i]) * b); \ 1497 worktype z1 = _cast_macro1_(src2[i] * _cvt_macro_(src1[i+1]) * b); \ 1498 worktype z2 = _cast_macro1_(src2[i+3] * _cvt_macro_(src1[i+2]) * a); \ 1499 worktype z3 = _cast_macro1_(src2[i+2] * _cvt_macro_(src1[i+3]) * a); \ 1500 \ 1501 dst[i] = _cast_macro2_(z0); \ 1502 dst[i+1] = _cast_macro2_(z1); \ 1503 dst[i+2] = _cast_macro2_(z2); \ 1504 dst[i+3] = _cast_macro2_(z3); \ 1505 } \ 1506 else \ 1507 { \ 1508 worktype z0 = _check_macro_(isrc[i]) ? \ 1509 _cast_macro1_(_cvt_macro_(src1[i])*scale/_cvt_macro_(src2[i])) : 0; \ 1510 worktype z1 = _check_macro_(isrc[i+1]) ? \ 1511 _cast_macro1_(_cvt_macro_(src1[i+1])*scale/_cvt_macro_(src2[i+1])):0;\ 1512 worktype z2 = _check_macro_(isrc[i+2]) ? \ 1513 _cast_macro1_(_cvt_macro_(src1[i+2])*scale/_cvt_macro_(src2[i+2])):0;\ 1514 worktype z3 = _check_macro_(isrc[i+3]) ? \ 1515 _cast_macro1_(_cvt_macro_(src1[i+3])*scale/_cvt_macro_(src2[i+3])):0;\ 1516 \ 1517 dst[i] = _cast_macro2_(z0); \ 1518 dst[i+1] = _cast_macro2_(z1); \ 1519 dst[i+2] = _cast_macro2_(z2); \ 1520 dst[i+3] = _cast_macro2_(z3); \ 1521 } \ 1522 } \ 1523 \ 1524 for( ; i < size.width; i++ ) \ 1525 { \ 1526 worktype z0 = _check_macro_(isrc[i]) ? \ 1527 _cast_macro1_(_cvt_macro_(src1[i])*scale/_cvt_macro_(src2[i])) : 0; \ 1528 dst[i] = _cast_macro2_(z0); \ 1529 } \ 1530 } \ 1531 \ 1532 return CV_OK; \ 1533 } 1534 1535 1536 #define ICV_DEF_RECIP_OP_CASE( flavor, arrtype, worktype, checktype, \ 1537 _start_row_macro_, _cast_macro1_, _cast_macro2_, \ 1538 _cvt_macro_, _check_macro_, isrc ) \ 1539 \ 1540 static CvStatus CV_STDCALL \ 1541 icvRecip_##flavor##_C1R( const arrtype* src, int step1, \ 1542 arrtype* dst, int step, \ 1543 CvSize size, double scale ) \ 1544 { \ 1545 step1 /= sizeof(src[0]); step /= sizeof(dst[0]); \ 1546 \ 1547 for( ; size.height--; src+=step1, dst+=step ) \ 1548 { \ 1549 _start_row_macro_(checktype, src); \ 1550 for( i = 0; i <= size.width - 4; i += 4 ) \ 1551 { \ 1552 if( _check_macro_(isrc[i]) && _check_macro_(isrc[i+1]) && \ 1553 _check_macro_(isrc[i+2]) && _check_macro_(isrc[i+3])) \ 1554 { \ 1555 double a = (double)_cvt_macro_(src[i]) * _cvt_macro_(src[i+1]); \ 1556 double b = (double)_cvt_macro_(src[i+2]) * _cvt_macro_(src[i+3]);\ 1557 double d = scale/(a * b); \ 1558 \ 1559 b *= d; \ 1560 a *= d; \ 1561 \ 1562 worktype z0 = _cast_macro1_(src[i+1] * b); \ 1563 worktype z1 = _cast_macro1_(src[i] * b); \ 1564 worktype z2 = _cast_macro1_(src[i+3] * a); \ 1565 worktype z3 = _cast_macro1_(src[i+2] * a); \ 1566 \ 1567 dst[i] = _cast_macro2_(z0); \ 1568 dst[i+1] = _cast_macro2_(z1); \ 1569 dst[i+2] = _cast_macro2_(z2); \ 1570 dst[i+3] = _cast_macro2_(z3); \ 1571 } \ 1572 else \ 1573 { \ 1574 worktype z0 = _check_macro_(isrc[i]) ? \ 1575 _cast_macro1_(scale/_cvt_macro_(src[i])) : 0; \ 1576 worktype z1 = _check_macro_(isrc[i+1]) ? \ 1577 _cast_macro1_(scale/_cvt_macro_(src[i+1])):0; \ 1578 worktype z2 = _check_macro_(isrc[i+2]) ? \ 1579 _cast_macro1_(scale/_cvt_macro_(src[i+2])):0; \ 1580 worktype z3 = _check_macro_(isrc[i+3]) ? \ 1581 _cast_macro1_(scale/_cvt_macro_(src[i+3])):0; \ 1582 \ 1583 dst[i] = _cast_macro2_(z0); \ 1584 dst[i+1] = _cast_macro2_(z1); \ 1585 dst[i+2] = _cast_macro2_(z2); \ 1586 dst[i+3] = _cast_macro2_(z3); \ 1587 } \ 1588 } \ 1589 \ 1590 for( ; i < size.width; i++ ) \ 1591 { \ 1592 worktype z0 = _check_macro_(isrc[i]) ? \ 1593 _cast_macro1_(scale/_cvt_macro_(src[i])) : 0; \ 1594 dst[i] = _cast_macro2_(z0); \ 1595 } \ 1596 } \ 1597 \ 1598 return CV_OK; \ 1599 } 1600 1601 1602 #define div_start_row_int(checktype, divisor) \ 1603 int i 1604 1605 #define div_start_row_flt(checktype, divisor) \ 1606 const checktype* isrc = (const checktype*)divisor; int i 1607 1608 #define div_check_zero_flt(x) (((x) & 0x7fffffff) != 0) 1609 #define div_check_zero_dbl(x) (((x) & CV_BIG_INT(0x7fffffffffffffff)) != 0) 1610 1611 #if defined WIN64 && defined EM64T && defined _MSC_VER && !defined CV_ICC 1612 #pragma optimize("",off) 1613 #endif 1614 1615 ICV_DEF_DIV_OP_CASE( 8u, uchar, int, uchar, div_start_row_int, 1616 cvRound, CV_CAST_8U, CV_8TO32F, CV_NONZERO, src2 ) 1617 1618 #if defined WIN64 && defined EM64T && defined _MSC_VER && !defined CV_ICC 1619 #pragma optimize("",on) 1620 #endif 1621 1622 1623 ICV_DEF_DIV_OP_CASE( 16u, ushort, int, ushort, div_start_row_int, 1624 cvRound, CV_CAST_16U, CV_CAST_64F, CV_NONZERO, src2 ) 1625 ICV_DEF_DIV_OP_CASE( 16s, short, int, short, div_start_row_int, 1626 cvRound, CV_CAST_16S, CV_NOP, CV_NONZERO, src2 ) 1627 ICV_DEF_DIV_OP_CASE( 32s, int, int, int, div_start_row_int, 1628 cvRound, CV_CAST_32S, CV_CAST_64F, CV_NONZERO, src2 ) 1629 ICV_DEF_DIV_OP_CASE( 32f, float, double, int, div_start_row_flt, 1630 CV_NOP, CV_CAST_32F, CV_NOP, div_check_zero_flt, isrc ) 1631 ICV_DEF_DIV_OP_CASE( 64f, double, double, int64, div_start_row_flt, 1632 CV_NOP, CV_CAST_64F, CV_NOP, div_check_zero_dbl, isrc ) 1633 1634 ICV_DEF_RECIP_OP_CASE( 8u, uchar, int, uchar, div_start_row_int, 1635 cvRound, CV_CAST_8U, CV_8TO32F, CV_NONZERO, src ) 1636 ICV_DEF_RECIP_OP_CASE( 16u, ushort, int, ushort, div_start_row_int, 1637 cvRound, CV_CAST_16U, CV_CAST_64F, CV_NONZERO, src ) 1638 ICV_DEF_RECIP_OP_CASE( 16s, short, int, short, div_start_row_int, 1639 cvRound, CV_CAST_16S, CV_NOP, CV_NONZERO, src ) 1640 ICV_DEF_RECIP_OP_CASE( 32s, int, int, int, div_start_row_int, 1641 cvRound, CV_CAST_32S, CV_CAST_64F, CV_NONZERO, src ) 1642 ICV_DEF_RECIP_OP_CASE( 32f, float, double, int, div_start_row_flt, 1643 CV_NOP, CV_CAST_32F, CV_NOP, div_check_zero_flt, isrc ) 1644 ICV_DEF_RECIP_OP_CASE( 64f, double, double, int64, div_start_row_flt, 1645 CV_NOP, CV_CAST_64F, CV_NOP, div_check_zero_dbl, isrc ) 1646 1647 ICV_DEF_INIT_ARITHM_FUNC_TAB( Div, C1R ) 1648 ICV_DEF_INIT_ARITHM_FUNC_TAB( Recip, C1R ) 1649 1650 typedef CvStatus (CV_STDCALL * CvRecipFunc)( const void* src, int step1, 1651 void* dst, int step, 1652 CvSize size, double scale ); 1653 1654 CV_IMPL void 1655 cvDiv( const void* srcarr1, const void* srcarr2, void* dstarr, double scale ) 1656 { 1657 static CvFuncTable div_tab; 1658 static CvFuncTable recip_tab; 1659 static int inittab = 0; 1660 1661 CV_FUNCNAME( "cvDiv" ); 1662 1663 __BEGIN__; 1664 1665 int type, coi = 0; 1666 int is_nd = 0; 1667 int src1_step, src2_step, dst_step; 1668 int src1_cont_flag = CV_MAT_CONT_FLAG; 1669 CvMat srcstub1, *src1 = (CvMat*)srcarr1; 1670 CvMat srcstub2, *src2 = (CvMat*)srcarr2; 1671 CvMat dststub, *dst = (CvMat*)dstarr; 1672 CvSize size; 1673 1674 if( !inittab ) 1675 { 1676 icvInitDivC1RTable( &div_tab ); 1677 icvInitRecipC1RTable( &recip_tab ); 1678 inittab = 1; 1679 } 1680 1681 if( !CV_IS_MAT(src2) ) 1682 { 1683 if( CV_IS_MATND(src2)) 1684 is_nd = 1; 1685 else 1686 { 1687 CV_CALL( src2 = cvGetMat( src2, &srcstub2, &coi )); 1688 if( coi != 0 ) 1689 CV_ERROR( CV_BadCOI, "" ); 1690 } 1691 } 1692 1693 if( src1 ) 1694 { 1695 if( CV_IS_MATND(src1)) 1696 is_nd = 1; 1697 else 1698 { 1699 if( !CV_IS_MAT(src1) ) 1700 { 1701 CV_CALL( src1 = cvGetMat( src1, &srcstub1, &coi )); 1702 if( coi != 0 ) 1703 CV_ERROR( CV_BadCOI, "" ); 1704 } 1705 1706 if( !CV_ARE_TYPES_EQ( src1, src2 )) 1707 CV_ERROR_FROM_CODE( CV_StsUnmatchedFormats ); 1708 1709 if( !CV_ARE_SIZES_EQ( src1, src2 )) 1710 CV_ERROR_FROM_CODE( CV_StsUnmatchedSizes ); 1711 src1_cont_flag = src1->type; 1712 } 1713 } 1714 1715 if( !CV_IS_MAT(dst) ) 1716 { 1717 if( CV_IS_MATND(dst)) 1718 is_nd = 1; 1719 else 1720 { 1721 CV_CALL( dst = cvGetMat( dst, &dststub, &coi )); 1722 if( coi != 0 ) 1723 CV_ERROR( CV_BadCOI, "" ); 1724 } 1725 } 1726 1727 if( is_nd ) 1728 { 1729 CvArr* arrs[] = { dst, src2, src1 }; 1730 CvMatND stubs[3]; 1731 CvNArrayIterator iterator; 1732 1733 CV_CALL( cvInitNArrayIterator( 2 + (src1 != 0), arrs, 0, stubs, &iterator )); 1734 1735 type = iterator.hdr[0]->type; 1736 iterator.size.width *= CV_MAT_CN(type); 1737 1738 if( src1 ) 1739 { 1740 CvScaledElWiseFunc func = 1741 (CvScaledElWiseFunc)(div_tab.fn_2d[CV_MAT_DEPTH(type)]); 1742 if( !func ) 1743 CV_ERROR( CV_StsUnsupportedFormat, "" ); 1744 1745 do 1746 { 1747 IPPI_CALL( func( iterator.ptr[2], CV_STUB_STEP, 1748 iterator.ptr[1], CV_STUB_STEP, 1749 iterator.ptr[0], CV_STUB_STEP, 1750 iterator.size, scale )); 1751 } 1752 while( cvNextNArraySlice( &iterator )); 1753 } 1754 else 1755 { 1756 CvRecipFunc func = (CvRecipFunc)(recip_tab.fn_2d[CV_MAT_DEPTH(type)]); 1757 1758 if( !func ) 1759 CV_ERROR( CV_StsUnsupportedFormat, "" ); 1760 1761 do 1762 { 1763 IPPI_CALL( func( iterator.ptr[1], CV_STUB_STEP, 1764 iterator.ptr[0], CV_STUB_STEP, 1765 iterator.size, scale )); 1766 } 1767 while( cvNextNArraySlice( &iterator )); 1768 } 1769 EXIT; 1770 } 1771 1772 if( !CV_ARE_TYPES_EQ( src2, dst )) 1773 CV_ERROR_FROM_CODE( CV_StsUnmatchedFormats ); 1774 1775 if( !CV_ARE_SIZES_EQ( src2, dst )) 1776 CV_ERROR_FROM_CODE( CV_StsUnmatchedSizes ); 1777 1778 type = CV_MAT_TYPE(src2->type); 1779 size = cvGetMatSize( src2 ); 1780 size.width *= CV_MAT_CN( type ); 1781 1782 if( CV_IS_MAT_CONT( src1_cont_flag & src2->type & dst->type )) 1783 { 1784 size.width *= size.height; 1785 src1_step = src2_step = dst_step = CV_STUB_STEP; 1786 size.height = 1; 1787 } 1788 else 1789 { 1790 src1_step = src1 ? src1->step : 0; 1791 src2_step = src2->step; 1792 dst_step = dst->step; 1793 } 1794 1795 if( src1 ) 1796 { 1797 CvScaledElWiseFunc func = (CvScaledElWiseFunc)(div_tab.fn_2d[CV_MAT_DEPTH(type)]); 1798 1799 if( !func ) 1800 CV_ERROR( CV_StsUnsupportedFormat, "" ); 1801 1802 IPPI_CALL( func( src1->data.ptr, src1_step, src2->data.ptr, src2_step, 1803 dst->data.ptr, dst_step, size, scale )); 1804 } 1805 else 1806 { 1807 CvRecipFunc func = (CvRecipFunc)(recip_tab.fn_2d[CV_MAT_DEPTH(type)]); 1808 1809 if( !func ) 1810 CV_ERROR( CV_StsUnsupportedFormat, "" ); 1811 1812 IPPI_CALL( func( src2->data.ptr, src2_step, 1813 dst->data.ptr, dst_step, size, scale )); 1814 } 1815 1816 __END__; 1817 } 1818 1819 /******************************* A D D W E I G T E D ******************************/ 1820 1821 #define ICV_DEF_ADD_WEIGHTED_OP(flavor, arrtype, worktype, load_macro, \ 1822 cast_macro1, cast_macro2) \ 1823 static CvStatus CV_STDCALL \ 1824 icvAddWeighted_##flavor##_C1R( const arrtype* src1, int step1, double alpha, \ 1825 const arrtype* src2, int step2, double beta, \ 1826 double gamma, arrtype* dst, int step, CvSize size )\ 1827 { \ 1828 step1 /= sizeof(src1[0]); step2 /= sizeof(src2[0]); step /= sizeof(dst[0]); \ 1829 \ 1830 for( ; size.height--; src1 += step1, src2 += step2, dst += step ) \ 1831 { \ 1832 int i; \ 1833 \ 1834 for( i = 0; i <= size.width - 4; i += 4 ) \ 1835 { \ 1836 worktype t0 = cast_macro1(load_macro((src1)[i])*alpha + \ 1837 load_macro((src2)[i])*beta + gamma); \ 1838 worktype t1 = cast_macro1(load_macro((src1)[i+1])*alpha + \ 1839 load_macro((src2)[i+1])*beta + gamma); \ 1840 \ 1841 (dst)[i] = cast_macro2( t0 ); \ 1842 (dst)[i+1] = cast_macro2( t1 ); \ 1843 \ 1844 t0 = cast_macro1(load_macro((src1)[i+2])*alpha + \ 1845 load_macro((src2)[i+2])*beta + gamma); \ 1846 t1 = cast_macro1(load_macro((src1)[i+3])*alpha + \ 1847 load_macro((src2)[i+3])*beta + gamma); \ 1848 \ 1849 (dst)[i+2] = cast_macro2( t0 ); \ 1850 (dst)[i+3] = cast_macro2( t1 ); \ 1851 } \ 1852 \ 1853 for( ; i < size.width; i++ ) \ 1854 { \ 1855 worktype t0 = cast_macro1(load_macro((src1)[i])*alpha + \ 1856 load_macro((src2)[i])*beta + gamma); \ 1857 (dst)[i] = cast_macro2( t0 ); \ 1858 } \ 1859 } \ 1860 \ 1861 return CV_OK; \ 1862 } 1863 1864 1865 #undef shift 1866 #define shift 14 1867 1868 static CvStatus CV_STDCALL 1869 icvAddWeighted_8u_fast_C1R( const uchar* src1, int step1, double alpha, 1870 const uchar* src2, int step2, double beta, 1871 double gamma, uchar* dst, int step, CvSize size ) 1872 { 1873 int tab1[256], tab2[256]; 1874 double t = 0; 1875 int j, t0, t1, t2, t3; 1876 1877 alpha *= 1 << shift; 1878 gamma = gamma*(1 << shift) + (1 << (shift - 1)); 1879 beta *= 1 << shift; 1880 1881 for( j = 0; j < 256; j++ ) 1882 { 1883 tab1[j] = cvRound(t); 1884 tab2[j] = cvRound(gamma); 1885 t += alpha; 1886 gamma += beta; 1887 } 1888 1889 t0 = (tab1[0] + tab2[0]) >> shift; 1890 t1 = (tab1[0] + tab2[255]) >> shift; 1891 t2 = (tab1[255] + tab2[0]) >> shift; 1892 t3 = (tab1[255] + tab2[255]) >> shift; 1893 1894 if( (unsigned)(t0+256) < 768 && (unsigned)(t1+256) < 768 && 1895 (unsigned)(t2+256) < 768 && (unsigned)(t3+256) < 768 ) 1896 { 1897 // use faster table-based convertion back to 8u 1898 for( ; size.height--; src1 += step1, src2 += step2, dst += step ) 1899 { 1900 int i; 1901 1902 for( i = 0; i <= size.width - 4; i += 4 ) 1903 { 1904 t0 = CV_FAST_CAST_8U((tab1[src1[i]] + tab2[src2[i]]) >> shift); 1905 t1 = CV_FAST_CAST_8U((tab1[src1[i+1]] + tab2[src2[i+1]]) >> shift); 1906 1907 dst[i] = (uchar)t0; 1908 dst[i+1] = (uchar)t1; 1909 1910 t0 = CV_FAST_CAST_8U((tab1[src1[i+2]] + tab2[src2[i+2]]) >> shift); 1911 t1 = CV_FAST_CAST_8U((tab1[src1[i+3]] + tab2[src2[i+3]]) >> shift); 1912 1913 dst[i+2] = (uchar)t0; 1914 dst[i+3] = (uchar)t1; 1915 } 1916 1917 for( ; i < size.width; i++ ) 1918 { 1919 t0 = CV_FAST_CAST_8U((tab1[src1[i]] + tab2[src2[i]]) >> shift); 1920 dst[i] = (uchar)t0; 1921 } 1922 } 1923 } 1924 else 1925 { 1926 // use universal macro for convertion back to 8u 1927 for( ; size.height--; src1 += step1, src2 += step2, dst += step ) 1928 { 1929 int i; 1930 1931 for( i = 0; i <= size.width - 4; i += 4 ) 1932 { 1933 t0 = (tab1[src1[i]] + tab2[src2[i]]) >> shift; 1934 t1 = (tab1[src1[i+1]] + tab2[src2[i+1]]) >> shift; 1935 1936 dst[i] = CV_CAST_8U( t0 ); 1937 dst[i+1] = CV_CAST_8U( t1 ); 1938 1939 t0 = (tab1[src1[i+2]] + tab2[src2[i+2]]) >> shift; 1940 t1 = (tab1[src1[i+3]] + tab2[src2[i+3]]) >> shift; 1941 1942 dst[i+2] = CV_CAST_8U( t0 ); 1943 dst[i+3] = CV_CAST_8U( t1 ); 1944 } 1945 1946 for( ; i < size.width; i++ ) 1947 { 1948 t0 = (tab1[src1[i]] + tab2[src2[i]]) >> shift; 1949 dst[i] = CV_CAST_8U( t0 ); 1950 } 1951 } 1952 } 1953 1954 return CV_OK; 1955 } 1956 1957 1958 ICV_DEF_ADD_WEIGHTED_OP( 8u, uchar, int, CV_8TO32F, cvRound, CV_CAST_8U ) 1959 ICV_DEF_ADD_WEIGHTED_OP( 16u, ushort, int, CV_NOP, cvRound, CV_CAST_16U ) 1960 ICV_DEF_ADD_WEIGHTED_OP( 16s, short, int, CV_NOP, cvRound, CV_CAST_16S ) 1961 ICV_DEF_ADD_WEIGHTED_OP( 32s, int, int, CV_NOP, cvRound, CV_CAST_32S ) 1962 ICV_DEF_ADD_WEIGHTED_OP( 32f, float, double, CV_NOP, CV_NOP, CV_CAST_32F ) 1963 ICV_DEF_ADD_WEIGHTED_OP( 64f, double, double, CV_NOP, CV_NOP, CV_CAST_64F ) 1964 1965 1966 ICV_DEF_INIT_ARITHM_FUNC_TAB( AddWeighted, C1R ) 1967 1968 typedef CvStatus (CV_STDCALL *CvAddWeightedFunc)( const void* src1, int step1, double alpha, 1969 const void* src2, int step2, double beta, 1970 double gamma, void* dst, 1971 int step, CvSize size ); 1972 1973 CV_IMPL void 1974 cvAddWeighted( const CvArr* srcAarr, double alpha, 1975 const CvArr* srcBarr, double beta, 1976 double gamma, CvArr* dstarr ) 1977 { 1978 static CvFuncTable addw_tab; 1979 static int inittab = 0; 1980 1981 CV_FUNCNAME( "cvAddWeighted" ); 1982 1983 __BEGIN__; 1984 1985 CvMat srcA_stub, *srcA = (CvMat*)srcAarr; 1986 CvMat srcB_stub, *srcB = (CvMat*)srcBarr; 1987 CvMat dst_stub, *dst = (CvMat*)dstarr; 1988 int coi1, coi2, coi; 1989 int srcA_step, srcB_step, dst_step; 1990 int type; 1991 CvAddWeightedFunc func; 1992 CvSize size; 1993 1994 if( !inittab ) 1995 { 1996 icvInitAddWeightedC1RTable( &addw_tab ); 1997 inittab = 1; 1998 } 1999 2000 CV_CALL( srcA = cvGetMat( srcA, &srcA_stub, &coi1 )); 2001 CV_CALL( srcB = cvGetMat( srcB, &srcB_stub, &coi2 )); 2002 CV_CALL( dst = cvGetMat( dst, &dst_stub, &coi )); 2003 2004 if( coi1 || coi2 || coi ) 2005 CV_ERROR( CV_BadCOI, "COI must not be set" ); 2006 2007 if( !CV_ARE_TYPES_EQ( srcA, srcB ) || 2008 !CV_ARE_TYPES_EQ( srcA, dst )) 2009 CV_ERROR( CV_StsUnmatchedFormats, 2010 "All input/output arrays should have the same type"); 2011 2012 if( !CV_ARE_SIZES_EQ( srcA, srcB ) || 2013 !CV_ARE_SIZES_EQ( srcA, dst )) 2014 CV_ERROR( CV_StsUnmatchedSizes, 2015 "All input/output arrays should have the same sizes"); 2016 2017 size = cvGetMatSize( srcA ); 2018 type = CV_MAT_TYPE( srcA->type ); 2019 size.width *= CV_MAT_CN( type ); 2020 srcA_step = srcA->step; 2021 srcB_step = srcB->step; 2022 dst_step = dst->step; 2023 2024 if( CV_IS_MAT_CONT( type & srcB->type & dst->type )) 2025 { 2026 size.width *= size.height; 2027 size.height = 1; 2028 srcA_step = srcB_step = dst_step = CV_AUTOSTEP; 2029 } 2030 2031 if( type == CV_8UC1 && size.width * size.height >= 1024 && 2032 fabs(alpha) < 256 && fabs(beta) < 256 && fabs(gamma) < 256*256 ) 2033 { 2034 func = (CvAddWeightedFunc)icvAddWeighted_8u_fast_C1R; 2035 } 2036 else 2037 { 2038 func = (CvAddWeightedFunc)addw_tab.fn_2d[CV_MAT_DEPTH(type)]; 2039 if( !func ) 2040 CV_ERROR( CV_StsUnsupportedFormat, "This array type is not supported" ); 2041 } 2042 2043 IPPI_CALL( func( srcA->data.ptr, srcA_step, alpha, srcB->data.ptr, srcB_step, 2044 beta, gamma, dst->data.ptr, dst_step, size )); 2045 2046 __END__; 2047 } 2048 2049 2050 /* End of file. */ 2051