1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 /* ---- includes ----------------------------------------------------------- */ 18 19 #include "b_BasicEm/Functions.h" 20 #include "b_BasicEm/Math.h" 21 #include "b_BitFeatureEm/Scanner.h" 22 23 /* ------------------------------------------------------------------------- */ 24 25 /* ========================================================================= */ 26 /* */ 27 /* ---- \ghd{ auxiliary functions } ---------------------------------------- */ 28 /* */ 29 /* ========================================================================= */ 30 31 /* ------------------------------------------------------------------------- */ 32 33 /** multiplies a scale with a 0.32 scale factor */ 34 uint32 bbf_Scanner_scalePrd( uint32 scaleA, uint32 factorA /*0.32 */ )\ 35 { 36 return ( scaleA >> 16 ) * ( factorA >> 16 ) + 37 ( ( ( scaleA & 0x0FFFF ) * ( factorA >> 16 ) ) >> 16 ) + 38 ( ( ( scaleA >> 16 ) * ( factorA & 0x0FFFF ) ) >> 16 ); 39 } 40 41 /* ------------------------------------------------------------------------- */ 42 43 /** allocates arays */ 44 void bbf_Scanner_alloc( struct bbs_Context* cpA, 45 struct bbf_Scanner* ptrA, 46 struct bbs_MemTbl* mtpA, 47 flag maximizeSharedMemoryA ) 48 { 49 struct bbs_MemTbl memTblL = *mtpA; 50 struct bbs_MemSeg* espL = bbs_MemTbl_segPtr( cpA, &memTblL, 0 ); 51 struct bbs_MemSeg* sspL = bbs_MemTbl_sharedSegPtr( cpA, &memTblL, 0 ); 52 struct bbs_MemSeg* mspL = maximizeSharedMemoryA ? sspL : espL; 53 54 /* filter patch dimension */ 55 uint32 proL = ptrA->maxRadiusE; 56 uint32 pwoL = ( proL << 1 ) + 1; 57 58 /* output image size (bit image) */ 59 uint32 woL = ptrA->maxImageWidthE; 60 uint32 hoL = ptrA->maxImageHeightE; 61 62 /* extended output image size (bit image) considering borders */ 63 uint32 xwoL = woL + ( ptrA->borderWidthE << 1 ); 64 uint32 xhoL = hoL + ( ptrA->borderHeightE << 1 ); 65 66 /* allocate working image */ 67 bbs_UInt16Arr_create( cpA, &ptrA->workImageE, ( ( woL >> 1 ) + ( woL & 1 ) ) * hoL, mspL ); 68 if( bbs_Context_error( cpA ) ) return; 69 bbs_UInt16Arr_fill( cpA, &ptrA->workImageE, 0 ); 70 71 /* allocate bit image */ 72 bim_UInt32Image_create( cpA, &ptrA->bitImageE, xwoL, ( xhoL >> 5 ) + ( ( ( xhoL & 0x1F ) != 0 ) ? 1 : 0 ), mspL ); 73 if( bbs_Context_error( cpA ) ) return; 74 bim_UInt32Image_setAllPixels( cpA, &ptrA->bitImageE, 0, 0 ); 75 76 /* allocate patch buffer */ 77 bbs_UInt32Arr_create( cpA, &ptrA->patchBufferE, ptrA->bitImageE.widthE, mspL ); 78 if( bbs_Context_error( cpA ) ) return; 79 bbs_UInt32Arr_fill( cpA, &ptrA->patchBufferE, 0 ); 80 81 /* allocate line buffer */ 82 bbs_UInt16Arr_create( cpA, &ptrA->lineBufE, woL + ( woL & 1 ), sspL ); 83 84 /* allocate table */ 85 bim_UInt32Image_create( cpA, &ptrA->satE, woL + pwoL, pwoL + 1, sspL ); 86 87 /* allocate buffers */ 88 bbs_UInt32Arr_create( cpA, &ptrA->idxArrE, ptrA->bufferSizeE, mspL ); 89 bbs_Int32Arr_create( cpA, &ptrA->actArrE, ptrA->bufferSizeE, mspL ); 90 91 bbs_Int32Arr_create( cpA, &ptrA->outArrE, ptrA->bufferSizeE >> 1, espL ); 92 } 93 94 /* ------------------------------------------------------------------------- */ 95 96 /** downscales work image */ 97 void bbf_Scanner_downscale( struct bbs_Context* cpA, struct bbf_Scanner* ptrA ) 98 { 99 uint32 w0L = ptrA->workWidthE; 100 uint32 h0L = ptrA->workHeightE; 101 uint32 w1L = w0L >> 1; 102 uint32 h1L = h0L >> 1; 103 uint32 w20L = ( w0L >> 1 ) + ( w0L & 1 ); 104 uint16* arrL = ptrA->workImageE.arrPtrE; 105 106 uint32 iL, jL; 107 uint32 kL = 0; 108 for( jL = 0; jL < h1L; jL++ ) 109 { 110 for( iL = 0; iL < ( w1L >> 1 ); iL++ ) 111 { 112 uint16 loL, hiL; 113 uint32 idxL = jL * 2 * w20L + iL * 2; 114 115 loL = ( ( arrL[ idxL ] & 0x00FF ) + ( arrL[ idxL ] >> 8 ) + ( arrL[ idxL + w20L ] & 0x00FF ) + ( arrL[ idxL + w20L ] >> 8 ) + 2 ) >> 2; 116 idxL++; 117 hiL = ( ( arrL[ idxL ] & 0x00FF ) + ( arrL[ idxL ] >> 8 ) + ( arrL[ idxL + w20L ] & 0x00FF ) + ( arrL[ idxL + w20L ] >> 8 ) + 2 ) >> 2; 118 119 arrL[ kL ] = loL | ( hiL << 8 ); 120 kL++; 121 } 122 if( ( w1L & 1 ) != 0 ) 123 { 124 uint32 idxL = jL * 2 * w20L + iL; 125 arrL[ kL++ ] = ( ( arrL[ idxL ] & 0x00FF ) + ( arrL[ idxL ] >> 8 ) + ( arrL[ idxL + w20L ] & 0x00FF ) + ( arrL[ idxL + w20L ] >> 8 ) + 2 ) >> 2; 126 } 127 } 128 129 ptrA->workWidthE = w1L; 130 ptrA->workHeightE = h1L; 131 ptrA->scaleExpE++; 132 } 133 134 /* ------------------------------------------------------------------------- */ 135 136 /** copies image 137 * handling for 8 bit images is implemented 138 * 16 bit image handling for the whole class needs to be added in this function only 139 */ 140 void bbf_Scanner_copyImage( struct bbs_Context* cpA, struct bbf_Scanner* ptrA, const void* imagePtrA, uint32 imageWidthA, uint32 imageHeightA, const struct bts_Int16Rect* roiPtrA ) 141 { 142 bbs_DEF_fNameL( "void bbf_Scanner_copyImage( struct bbs_Context* cpA, struct bbf_Scanner* ptrA, const struct bim_UInt16ByteImage* imagePtrA, const struct bts_Int16Rect* roiPtrA )" ) 143 144 if( imageWidthA > ptrA->maxImageWidthE || imageHeightA > ptrA->maxImageHeightE ) 145 { 146 bbs_ERROR5( "%s:\n Input image (%ix%i)is too large; Scanner is configured for maximal (%ix%i)", 147 fNameL, imageWidthA, imageHeightA, ptrA->maxImageWidthE, ptrA->maxImageHeightE ); 148 return; 149 } 150 151 if( roiPtrA == 0 ) 152 { 153 uint32 iL, jL; 154 const uint8* srcL = ( uint8* )imagePtrA; 155 uint16* dstL = ptrA->workImageE.arrPtrE; 156 ptrA->workWidthE = imageWidthA; 157 ptrA->workHeightE = imageHeightA; 158 for( iL = 0; iL < ptrA->workHeightE; iL++ ) 159 { 160 for( jL = ptrA->workWidthE >> 1; jL > 0; jL-- ) 161 { 162 *dstL++ = ( uint16 )srcL[ 0 ] | ( uint16 )srcL[ 1 ] << 8; 163 srcL += 2; 164 } 165 166 /* uneven width */ 167 if( ptrA->workWidthE & 1 ) *dstL++ = *srcL++; 168 } 169 } 170 else 171 { 172 uint32 iL, jL; 173 const uint8* srcL = ( uint8* )imagePtrA + roiPtrA->y1E * imageWidthA + roiPtrA->x1E; 174 uint16* dstL = ptrA->workImageE.arrPtrE; 175 176 if( roiPtrA->x2E <= roiPtrA->x1E || roiPtrA->y2E <= roiPtrA->y1E ) 177 { 178 bbs_ERROR1( "%s:\n ROI is invalid or zero", fNameL ); 179 return; 180 } 181 if( roiPtrA->x1E < 0 || roiPtrA->y1E < 0 || roiPtrA->x2E > ( int32 )imageWidthA || roiPtrA->y2E > ( int32 )imageHeightA ) 182 { 183 bbs_ERROR1( "%s:\n ROI exceeds image boundary", fNameL ); 184 return; 185 } 186 187 ptrA->workWidthE = roiPtrA->x2E - roiPtrA->x1E; 188 ptrA->workHeightE = roiPtrA->y2E - roiPtrA->y1E; 189 for( iL = 0; iL < ptrA->workHeightE; iL++ ) 190 { 191 for( jL = ptrA->workWidthE >> 1; jL > 0; jL-- ) 192 { 193 *dstL++ = ( uint16 )srcL[ 0 ] | ( uint16 )srcL[ 1 ] << 8; 194 srcL += 2; 195 } 196 197 /* uneven width */ 198 if( ptrA->workWidthE & 1 ) *dstL++ = *srcL++; 199 200 srcL += imageWidthA - ptrA->workWidthE; 201 } 202 } 203 } 204 205 /* ------------------------------------------------------------------------- */ 206 207 /** creates bit image */ 208 void bbf_Scanner_createBitImage( struct bbs_Context* cpA, struct bbf_Scanner* ptrA ) 209 { 210 bbs_DEF_fNameL( "void bbf_Scanner_createBitImage( struct bbs_Context* cpA, struct bbf_Scanner* ptrA )" ) 211 212 213 /* declarations */ 214 uint32 proL, priL, pwoL, pwiL; 215 uint32 wiL, wi2L, hiL, woL, hoL, xwoL, xhoL; /* image size specifies */ 216 uint32 stepL; /* scan step (16.16) */ 217 uint32 bitMaskL; /* current bit mask */ 218 uint32* bitRowL; /* pointer to bit-row */ 219 uint32 wsL, hsL; /* size of summed area table (ringbuffer) */ 220 uint32 satSizeL; 221 uint32* satL; /* pointer to summed area table */ 222 uint16* lBufL; /* pointer to line buffer */ 223 uint32 yfL; /* fixed point y-coordinate (16.16) */ 224 uint32 iL, jL; 225 226 uint32 swi1L; /* table writing index */ 227 uint32 swi2L; /* table writing index */ 228 uint32 sriL; /* table reading index */ 229 230 uint32 poAreaL, piAreaL; /* areas of inner and outer rectangles */ 231 uint32 siL[ 8 ]; /* table indices */ 232 233 234 proL = ptrA->bitParamE.outerRadiusE; 235 priL = ptrA->bitParamE.innerRadiusE; 236 pwoL = ( proL << 1 ) + 1; 237 pwiL = ( priL << 1 ) + 1; 238 239 if( ptrA->borderHeightE >= 32 ) 240 { 241 bbs_ERROR1( "%s:\n borderHeightE >= 32", fNameL ); 242 return; 243 } 244 245 if( proL <= priL ) 246 { 247 bbs_ERROR1( "%s:\n outer radius <= inner radius", fNameL ); 248 return; 249 } 250 251 /* input image size (bit image) */ 252 wiL = ptrA->workWidthE; 253 hiL = ptrA->workHeightE; 254 wi2L = ( wiL >> 1 ) + ( wiL & 1 ); 255 256 /* 16.16 */ 257 stepL = ptrA->scaleE >> ( ptrA->scaleExpE + 4 ); 258 259 /* output image size (bit image) */ 260 woL = ( wiL << 16 ) / stepL; 261 hoL = ( hiL << 16 ) / stepL; 262 263 if( woL <= pwoL || hoL <= pwoL ) 264 { 265 bbs_ERROR1( "%s:\n scaled image is too small", fNameL ); 266 return; 267 } 268 269 if( woL * stepL >= ( wiL << 16 ) ) woL--; 270 if( hoL * stepL >= ( hiL << 16 ) ) hoL--; 271 272 /* extended output image size (bit image) considering borders */ 273 xwoL = woL + ( ptrA->borderWidthE << 1 ); 274 xhoL = hoL + ( ptrA->borderHeightE << 1 ); 275 276 ptrA->currentWidthE = xwoL; 277 ptrA->currentHeightE = xhoL; 278 279 /* initialize bit image */ 280 bim_UInt32Image_size( cpA, &ptrA->bitImageE, xwoL, ( xhoL >> 5 ) + ( ( ( xhoL & 0x1F ) != 0 ) ? 1 : 0 ) ); 281 bim_UInt32Image_setAllPixels( cpA, &ptrA->bitImageE, 0, 0 ); 282 283 bitMaskL = ( uint32 )1 << ptrA->borderHeightE; 284 bitRowL = ( uint32* )ptrA->bitImageE.arrE.arrPtrE + ptrA->borderWidthE; 285 286 /* width of table */ 287 wsL = woL + pwoL; 288 289 /* height of table */ 290 hsL = pwoL + 1; 291 292 bim_UInt32Image_size( cpA, &ptrA->satE, wsL, hsL ); 293 294 satL = ptrA->satE.arrE.arrPtrE; 295 satSizeL = wsL * hsL; 296 297 lBufL = ptrA->lineBufE.arrPtrE; 298 299 yfL = 0; /* fixed point y-coordinate ( 16.16 )*/ 300 301 swi1L = 0; /* table writing index */ 302 swi2L = 0; /* table writing index */ 303 sriL = 0; /* table reading index */ 304 305 /* areas of inner and outer rectangles */ 306 poAreaL = pwoL * pwoL; 307 piAreaL = pwiL * pwiL; 308 309 /* interpolate pixels; compute table and bit image */ 310 311 for( iL = wsL * ( proL + 1 ); iL > 0; iL-- ) satL[ swi1L++ ] = 0; 312 swi2L = swi1L - wsL; 313 314 for( jL = 0; jL < hoL + proL; jL++ ) 315 { 316 if( jL < hoL ) /* rescale area */ 317 { 318 uint32 ypL = ( yfL >> 16 ); 319 uint32 yoff1L = yfL & 0x0FFFF; 320 uint32 yoff0L = 0x010000 - yoff1L; 321 const uint16* arr0L = ptrA->workImageE.arrPtrE + ypL * wi2L; 322 const uint16* arr1L = arr0L + wi2L; 323 324 325 uint32 xfL = 0; /* fixed point x-coordinate (16.16) */ 326 uint32 hSumL = 0; 327 328 yfL += stepL; 329 330 for( iL = 0; iL <= proL; iL++ ) satL[ swi1L++ ] = 0; 331 swi2L += iL; 332 333 /* fill line buffer */ 334 for( iL = 0; iL < wi2L; iL++ ) 335 { 336 lBufL[ iL * 2 ] = ( ( ( arr0L[ iL ] & 0x0FF ) * yoff0L ) + ( ( arr1L[ iL ] & 0x0FF ) * yoff1L ) ) >> 10; 337 lBufL[ iL * 2 + 1 ] = ( ( ( arr0L[ iL ] >> 8 ) * yoff0L ) + ( ( arr1L[ iL ] >> 8 ) * yoff1L ) ) >> 10; 338 } 339 340 for( iL = 0; iL < woL; iL++ ) 341 { 342 uint32 xpL = ( xfL >> 16 ); 343 uint32 xoff1L = xfL & 0x0FFFF; 344 uint16 pixL = ( lBufL[ xpL ] * ( 0x010000 - xoff1L ) + lBufL[ xpL + 1 ] * xoff1L ) >> 22; 345 satL[ swi1L ] = ( hSumL += pixL ) + satL[ swi2L ]; 346 xfL += stepL; 347 swi1L++; 348 swi2L++; 349 } 350 351 for( iL = 0; iL < proL; iL++ ) 352 { 353 satL[ swi1L ] = hSumL + satL[ swi2L ]; 354 swi1L++; 355 swi2L++; 356 } 357 } 358 else /* image is processed - fill in 0s */ 359 { 360 for( iL = 0; iL < wsL; iL++ ) satL[ swi1L++ ] = satL[ swi2L++ ]; 361 } 362 363 swi1L = ( swi1L < satSizeL ) ? swi1L : 0; 364 swi2L = ( swi2L < satSizeL ) ? swi2L : 0; 365 366 /* fill line in bit image */ 367 if( jL >= proL ) 368 { 369 const uint32* rSatL = satL; 370 371 /* table coordinate indices for outer rectangle */ 372 siL[ 0 ] = sriL; 373 siL[ 1 ] = siL[ 0 ] + pwoL; 374 siL[ 2 ] = siL[ 0 ] + pwoL * wsL; 375 siL[ 2 ] -= ( siL[ 2 ] >= satSizeL ) ? satSizeL : 0; 376 siL[ 3 ] = siL[ 2 ] + pwoL; 377 378 /* table coordinate indices for inner rectangle */ 379 siL[ 4 ] = siL[ 0 ] + ( proL - priL ) * wsL + ( proL - priL ); 380 siL[ 4 ] -= ( siL[ 4 ] >= satSizeL ) ? satSizeL : 0; 381 siL[ 5 ] = siL[ 4 ] + pwiL; 382 siL[ 6 ] = siL[ 4 ] + pwiL * wsL; 383 siL[ 6 ] -= ( siL[ 6 ] >= satSizeL ) ? satSizeL : 0; 384 siL[ 7 ] = siL[ 6 ] + pwiL; 385 sriL += wsL; 386 if( sriL == satSizeL ) sriL = 0; 387 388 for( iL = 0; iL < woL; iL++ ) 389 { 390 uint32 oAvgL = ( rSatL[ siL[ 0 ] ] - rSatL[ siL[ 1 ] ] - rSatL[ siL[ 2 ] ] + rSatL[ siL[ 3 ] ] ) * piAreaL; 391 uint32 iAvgL = ( rSatL[ siL[ 4 ] ] - rSatL[ siL[ 5 ] ] - rSatL[ siL[ 6 ] ] + rSatL[ siL[ 7 ] ] ) * poAreaL; 392 bitRowL[ iL ] |= ( iAvgL > oAvgL ) ? bitMaskL : 0; 393 rSatL++; 394 } 395 if( ( bitMaskL <<= 1 ) == 0 ) 396 { 397 bitRowL += xwoL; 398 bitMaskL = 1; 399 } 400 } 401 } 402 } 403 404 /* ------------------------------------------------------------------------- */ 405 406 /** initialize patch buffer */ 407 void bbf_Scanner_initPatchBuffer( struct bbs_Context* cpA, struct bbf_Scanner* ptrA ) 408 { 409 bbs_UInt32Arr_size( cpA, &ptrA->patchBufferE, ptrA->bitImageE.widthE ); 410 bbs_memcpy32( ptrA->patchBufferE.arrPtrE, ptrA->bitImageE.arrE.arrPtrE, ptrA->bitImageE.widthE ); 411 } 412 413 /* ------------------------------------------------------------------------- */ 414 415 /* ========================================================================= */ 416 /* */ 417 /* ---- \ghd{ constructor / destructor } ----------------------------------- */ 418 /* */ 419 /* ========================================================================= */ 420 421 /* ------------------------------------------------------------------------- */ 422 423 void bbf_Scanner_init( struct bbs_Context* cpA, 424 struct bbf_Scanner* ptrA ) 425 { 426 ptrA->scaleExpE = 0; 427 ptrA->scaleE = 0; 428 ptrA->xE = 0; 429 ptrA->yE = 0; 430 ptrA->effMaxScaleE = 0; 431 ptrA->currentWidthE = 0; 432 ptrA->currentHeightE = 0; 433 ptrA->workWidthE = 0; 434 ptrA->workHeightE = 0; 435 bbf_BitParam_init( cpA, &ptrA->bitParamE ); 436 bbs_UInt16Arr_init( cpA, &ptrA->workImageE ); 437 bim_UInt32Image_init( cpA, &ptrA->satE ); 438 bim_UInt32Image_init( cpA, &ptrA->bitImageE ); 439 bbs_UInt32Arr_init( cpA, &ptrA->patchBufferE ); 440 bbs_UInt16Arr_init( cpA, &ptrA->lineBufE ); 441 442 bbs_UInt32Arr_init( cpA, &ptrA->idxArrE ); 443 bbs_Int32Arr_init( cpA, &ptrA->actArrE ); 444 bbs_Int32Arr_init( cpA, &ptrA->outArrE ); 445 ptrA->outCountE = 0; 446 ptrA->intCountE = 0; 447 ptrA->bufferSizeE = 1024; 448 449 ptrA->maxImageWidthE = 0; 450 ptrA->maxImageHeightE = 0; 451 ptrA->maxRadiusE = 0; 452 ptrA->patchWidthE = 0; 453 ptrA->patchHeightE = 0; 454 ptrA->minScaleE = 0; 455 ptrA->maxScaleE = 0; 456 ptrA->scaleStepE = 0; 457 ptrA->borderWidthE = 0; 458 ptrA->borderHeightE = 0; 459 } 460 461 /* ------------------------------------------------------------------------- */ 462 463 void bbf_Scanner_exit( struct bbs_Context* cpA, 464 struct bbf_Scanner* ptrA ) 465 { 466 ptrA->scaleExpE = 0; 467 ptrA->scaleE = 0; 468 ptrA->xE = 0; 469 ptrA->yE = 0; 470 ptrA->effMaxScaleE = 0; 471 ptrA->currentWidthE = 0; 472 ptrA->currentHeightE = 0; 473 ptrA->workWidthE = 0; 474 ptrA->workHeightE = 0; 475 bbf_BitParam_exit( cpA, &ptrA->bitParamE ); 476 bbs_UInt16Arr_exit( cpA, &ptrA->workImageE ); 477 bim_UInt32Image_exit( cpA, &ptrA->satE ); 478 bim_UInt32Image_exit( cpA, &ptrA->bitImageE ); 479 bbs_UInt32Arr_exit( cpA, &ptrA->patchBufferE ); 480 bbs_UInt16Arr_exit( cpA, &ptrA->lineBufE ); 481 482 bbs_UInt32Arr_exit( cpA, &ptrA->idxArrE ); 483 bbs_Int32Arr_exit( cpA, &ptrA->actArrE ); 484 bbs_Int32Arr_exit( cpA, &ptrA->outArrE ); 485 ptrA->outCountE = 0; 486 ptrA->intCountE = 0; 487 ptrA->bufferSizeE = 1024; 488 489 ptrA->maxImageWidthE = 0; 490 ptrA->maxImageHeightE = 0; 491 ptrA->maxRadiusE = 0; 492 ptrA->patchWidthE = 0; 493 ptrA->patchHeightE = 0; 494 ptrA->minScaleE = 0; 495 ptrA->maxScaleE = 0; 496 ptrA->scaleStepE = 0; 497 ptrA->borderWidthE = 0; 498 ptrA->borderHeightE = 0; 499 } 500 501 /* ------------------------------------------------------------------------- */ 502 503 /* ========================================================================= */ 504 /* */ 505 /* ---- \ghd{ operators } -------------------------------------------------- */ 506 /* */ 507 /* ========================================================================= */ 508 509 /* ------------------------------------------------------------------------- */ 510 511 void bbf_Scanner_copy( struct bbs_Context* cpA, 512 struct bbf_Scanner* ptrA, 513 const struct bbf_Scanner* srcPtrA ) 514 { 515 ptrA->scaleExpE = srcPtrA->scaleExpE; 516 ptrA->scaleE = srcPtrA->scaleE; 517 ptrA->xE = srcPtrA->xE; 518 ptrA->yE = srcPtrA->yE; 519 ptrA->effMaxScaleE = srcPtrA->effMaxScaleE; 520 ptrA->currentWidthE = srcPtrA->currentWidthE; 521 ptrA->currentHeightE = srcPtrA->currentHeightE; 522 ptrA->workWidthE = srcPtrA->workWidthE; 523 ptrA->workHeightE = srcPtrA->workHeightE; 524 525 bbf_BitParam_copy( cpA, &ptrA->bitParamE, &srcPtrA->bitParamE ); 526 bbs_UInt16Arr_copy( cpA, &ptrA->workImageE, &srcPtrA->workImageE ); 527 bim_UInt32Image_copy( cpA, &ptrA->satE, &srcPtrA->satE ); 528 bim_UInt32Image_copy( cpA, &ptrA->bitImageE, &srcPtrA->bitImageE ); 529 bbs_UInt32Arr_copy( cpA, &ptrA->patchBufferE, &srcPtrA->patchBufferE ); 530 bbs_UInt16Arr_copy( cpA, &ptrA->lineBufE, &srcPtrA->lineBufE ); 531 532 ptrA->maxImageWidthE = srcPtrA->maxImageWidthE; 533 ptrA->maxImageHeightE = srcPtrA->maxImageHeightE; 534 ptrA->maxRadiusE = srcPtrA->maxRadiusE; 535 ptrA->patchWidthE = srcPtrA->patchWidthE; 536 ptrA->patchHeightE = srcPtrA->patchHeightE; 537 ptrA->minScaleE = srcPtrA->minScaleE; 538 ptrA->maxScaleE = srcPtrA->maxScaleE; 539 ptrA->scaleStepE = srcPtrA->scaleStepE; 540 ptrA->borderWidthE = srcPtrA->borderWidthE; 541 ptrA->borderHeightE = srcPtrA->borderHeightE; 542 } 543 544 /* ------------------------------------------------------------------------- */ 545 546 flag bbf_Scanner_equal( struct bbs_Context* cpA, 547 const struct bbf_Scanner* ptrA, 548 const struct bbf_Scanner* srcPtrA ) 549 { 550 if( ptrA->maxImageWidthE != srcPtrA->maxImageWidthE ) return FALSE; 551 if( ptrA->maxImageHeightE != srcPtrA->maxImageHeightE ) return FALSE; 552 if( ptrA->maxRadiusE != srcPtrA->maxRadiusE ) return FALSE; 553 if( ptrA->patchWidthE != srcPtrA->patchWidthE ) return FALSE; 554 if( ptrA->patchHeightE != srcPtrA->patchHeightE ) return FALSE; 555 if( ptrA->minScaleE != srcPtrA->minScaleE ) return FALSE; 556 if( ptrA->maxScaleE != srcPtrA->maxScaleE ) return FALSE; 557 if( ptrA->scaleStepE != srcPtrA->scaleStepE ) return FALSE; 558 if( ptrA->borderWidthE != srcPtrA->borderWidthE ) return FALSE; 559 if( ptrA->borderHeightE != srcPtrA->borderHeightE ) return FALSE; 560 return TRUE; 561 } 562 563 /* ------------------------------------------------------------------------- */ 564 565 /* ========================================================================= */ 566 /* */ 567 /* ---- \ghd{ query functions } -------------------------------------------- */ 568 /* */ 569 /* ========================================================================= */ 570 571 /* ------------------------------------------------------------------------- */ 572 573 uint32 bbf_Scanner_positions( const struct bbf_Scanner* ptrA ) 574 { 575 int32 wL = ( int32 )ptrA->currentWidthE - ptrA->patchWidthE; 576 int32 hL = ( int32 )ptrA->currentHeightE - ptrA->patchHeightE; 577 return ( wL >= 0 ? wL : 0 ) * ( hL >= 0 ? hL : 0 ); 578 } 579 580 /* ------------------------------------------------------------------------- */ 581 582 uint32 bbf_Scanner_scanIndex( const struct bbf_Scanner* ptrA ) 583 { 584 return ptrA->yE * ptrA->currentWidthE + ptrA->xE; 585 } 586 587 /* ------------------------------------------------------------------------- */ 588 589 void bbf_Scanner_pos( const struct bbf_Scanner* ptrA, 590 int32* xPtrA, int32* yPtrA, uint32* scalePtrA ) 591 { 592 /* 16.16 */ 593 *xPtrA = ( int32 )( ptrA->xE - ptrA->borderWidthE ) * ( int32 )( ptrA->scaleE >> 4 ); 594 595 /* 16.16 */ 596 *yPtrA = ( int32 )( ptrA->yE - ptrA->borderHeightE ) * ( int32 )( ptrA->scaleE >> 4 ); 597 598 /* 12.20 */ 599 *scalePtrA = ptrA->scaleE; 600 } 601 602 /* ------------------------------------------------------------------------- */ 603 604 void bbf_Scanner_idxPos( const struct bbf_Scanner* ptrA, uint32 scanIndexA, 605 int32* xPtrA, int32* yPtrA, uint32* scalePtrA ) 606 { 607 int32 yL = scanIndexA / ptrA->currentWidthE; 608 int32 xL = scanIndexA - ( yL * ptrA->currentWidthE ); 609 610 /* 16.16 */ 611 *xPtrA = ( int32 )( xL - ptrA->borderWidthE ) * ( int32 )( ptrA->scaleE >> 4 ); 612 613 /* 16.16 */ 614 *yPtrA = ( int32 )( yL - ptrA->borderHeightE ) * ( int32 )( ptrA->scaleE >> 4 ); 615 616 *scalePtrA = ptrA->scaleE; 617 } 618 619 /* ------------------------------------------------------------------------- */ 620 621 /* ========================================================================= */ 622 /* */ 623 /* ---- \ghd{ modify functions } ------------------------------------------- */ 624 /* */ 625 /* ========================================================================= */ 626 627 /* ------------------------------------------------------------------------- */ 628 629 void bbf_Scanner_create( struct bbs_Context* cpA, 630 struct bbf_Scanner* ptrA, 631 flag maximizeSharedMemoryA, 632 uint32 maxImageWidthA, 633 uint32 maxImageHeightA, 634 uint32 maxRadiusA, 635 uint32 patchWidthA, 636 uint32 patchHeightA, 637 uint32 minScaleA, 638 uint32 maxScaleA, 639 uint32 scaleStepA, 640 uint32 borderWidthA, 641 uint32 borderHeightA, 642 uint32 bufferSizeA, 643 struct bbs_MemTbl* mtpA ) 644 { 645 ptrA->maxImageWidthE = maxImageWidthA; 646 ptrA->maxImageHeightE = maxImageHeightA; 647 ptrA->maxRadiusE = maxRadiusA; 648 ptrA->patchWidthE = patchWidthA; 649 ptrA->patchHeightE = patchHeightA; 650 ptrA->minScaleE = minScaleA; 651 ptrA->maxScaleE = maxScaleA; 652 ptrA->scaleStepE = scaleStepA; 653 ptrA->borderWidthE = borderWidthA; 654 ptrA->borderHeightE = borderHeightA; 655 ptrA->bufferSizeE = bufferSizeA; 656 bbf_Scanner_alloc( cpA, ptrA, mtpA, maximizeSharedMemoryA ); 657 } 658 659 /* ------------------------------------------------------------------------- */ 660 661 void bbf_Scanner_bitParam( struct bbs_Context* cpA, 662 struct bbf_Scanner* ptrA, 663 const struct bbf_BitParam* bitParamPtrA ) 664 { 665 if( !bbf_BitParam_equal( cpA, &ptrA->bitParamE, bitParamPtrA ) ) 666 { 667 bbf_BitParam_copy( cpA, &ptrA->bitParamE, bitParamPtrA ); 668 bbf_Scanner_createBitImage( cpA, ptrA ); 669 } 670 671 bbf_Scanner_resetScan( cpA, ptrA ); 672 } 673 674 /* ------------------------------------------------------------------------- */ 675 676 /* ========================================================================= */ 677 /* */ 678 /* ---- \ghd{ I/O } -------------------------------------------------------- */ 679 /* */ 680 /* ========================================================================= */ 681 682 /* ------------------------------------------------------------------------- */ 683 684 uint32 bbf_Scanner_memSize( struct bbs_Context* cpA, 685 const struct bbf_Scanner* ptrA ) 686 { 687 uint32 memSizeL = bbs_SIZEOF16( uint32 ) + 688 bbs_SIZEOF16( uint32 ); /* version */ 689 memSizeL += bbs_SIZEOF16( ptrA->maxImageWidthE ); 690 memSizeL += bbs_SIZEOF16( ptrA->maxImageHeightE ); 691 memSizeL += bbs_SIZEOF16( ptrA->maxRadiusE ); 692 memSizeL += bbs_SIZEOF16( ptrA->patchWidthE ); 693 memSizeL += bbs_SIZEOF16( ptrA->patchHeightE ); 694 memSizeL += bbs_SIZEOF16( ptrA->minScaleE ); 695 memSizeL += bbs_SIZEOF16( ptrA->maxScaleE ); 696 memSizeL += bbs_SIZEOF16( ptrA->scaleStepE ); 697 memSizeL += bbs_SIZEOF16( ptrA->borderWidthE ); 698 memSizeL += bbs_SIZEOF16( ptrA->borderHeightE ); 699 return memSizeL; 700 } 701 702 /* ------------------------------------------------------------------------- */ 703 704 uint32 bbf_Scanner_memWrite( struct bbs_Context* cpA, 705 const struct bbf_Scanner* ptrA, 706 uint16* memPtrA ) 707 { 708 uint32 memSizeL = bbf_Scanner_memSize( cpA, ptrA ); 709 memPtrA += bbs_memWrite32( &memSizeL, memPtrA ); 710 memPtrA += bbs_memWriteUInt32( bbf_SCANNER_VERSION, memPtrA ); 711 memPtrA += bbs_memWrite32( &ptrA->maxImageWidthE, memPtrA ); 712 memPtrA += bbs_memWrite32( &ptrA->maxImageHeightE, memPtrA ); 713 memPtrA += bbs_memWrite32( &ptrA->maxRadiusE, memPtrA ); 714 memPtrA += bbs_memWrite32( &ptrA->patchWidthE, memPtrA ); 715 memPtrA += bbs_memWrite32( &ptrA->patchHeightE, memPtrA ); 716 memPtrA += bbs_memWrite32( &ptrA->minScaleE, memPtrA ); 717 memPtrA += bbs_memWrite32( &ptrA->maxScaleE, memPtrA ); 718 memPtrA += bbs_memWrite32( &ptrA->scaleStepE, memPtrA ); 719 memPtrA += bbs_memWrite32( &ptrA->borderWidthE, memPtrA ); 720 memPtrA += bbs_memWrite32( &ptrA->borderHeightE, memPtrA ); 721 return memSizeL; 722 } 723 724 /* ------------------------------------------------------------------------- */ 725 726 uint32 bbf_Scanner_memRead( struct bbs_Context* cpA, 727 struct bbf_Scanner* ptrA, 728 const uint16* memPtrA, 729 struct bbs_MemTbl* mtpA ) 730 { 731 uint32 memSizeL, versionL; 732 733 if( bbs_Context_error( cpA ) ) return 0; 734 memPtrA += bbs_memRead32( &memSizeL, memPtrA ); 735 memPtrA += bbs_memReadVersion32( cpA, &versionL, bbf_SCANNER_VERSION, memPtrA ); 736 737 memPtrA += bbs_memRead32( &ptrA->maxImageWidthE, memPtrA ); 738 memPtrA += bbs_memRead32( &ptrA->maxImageHeightE, memPtrA ); 739 memPtrA += bbs_memRead32( &ptrA->maxRadiusE, memPtrA ); 740 memPtrA += bbs_memRead32( &ptrA->patchWidthE, memPtrA ); 741 memPtrA += bbs_memRead32( &ptrA->patchHeightE, memPtrA ); 742 memPtrA += bbs_memRead32( &ptrA->minScaleE, memPtrA ); 743 memPtrA += bbs_memRead32( &ptrA->maxScaleE, memPtrA ); 744 memPtrA += bbs_memRead32( &ptrA->scaleStepE, memPtrA ); 745 memPtrA += bbs_memRead32( &ptrA->borderWidthE, memPtrA ); 746 memPtrA += bbs_memRead32( &ptrA->borderHeightE, memPtrA ); 747 748 if( memSizeL != bbf_Scanner_memSize( cpA, ptrA ) ) 749 { 750 bbs_ERR0( bbs_ERR_CORRUPT_DATA, "uint32 bbf_Scanner_memRead( struct bem_ScanGradientMove* ptrA, const uint16* memPtrA ):\n" 751 "size mismatch" ); 752 return 0; 753 } 754 755 if( bbs_Context_error( cpA ) ) return 0; 756 757 /* allocate arrays */ 758 bbf_Scanner_alloc( cpA, ptrA, mtpA, FALSE ); 759 760 if( bbs_Context_error( cpA ) ) return 0; 761 762 return memSizeL; 763 } 764 765 /* ------------------------------------------------------------------------- */ 766 767 /* ========================================================================= */ 768 /* */ 769 /* ---- \ghd{ exec functions } --------------------------------------------- */ 770 /* */ 771 /* ========================================================================= */ 772 773 /* ------------------------------------------------------------------------- */ 774 775 void bbf_Scanner_resetScan( struct bbs_Context* cpA, struct bbf_Scanner* ptrA ) 776 { 777 ptrA->xE = 0; 778 ptrA->yE = 0; 779 bbf_Scanner_initPatchBuffer( cpA, ptrA ); 780 } 781 782 /* ------------------------------------------------------------------------- */ 783 784 void bbf_Scanner_assign( struct bbs_Context* cpA, struct bbf_Scanner* ptrA, 785 const void* imagePtrA, 786 uint32 imageWidthA, 787 uint32 imageHeightA, 788 const struct bts_Int16Rect* roiPtrA, 789 const struct bbf_BitParam* paramPtrA ) 790 { 791 /* copy image */ 792 bbf_Scanner_copyImage( cpA, ptrA, imagePtrA, imageWidthA, imageHeightA, roiPtrA ); 793 794 ptrA->scaleE = ptrA->minScaleE; 795 bbf_BitParam_copy( cpA, &ptrA->bitParamE, paramPtrA ); 796 797 /* compute effective max scale */ 798 { 799 /* 16.16 */ 800 uint32 maxHScaleL = ( ptrA->workWidthE << 16 ) / ( ptrA->patchWidthE + 1 ); 801 uint32 maxVScaleL = ( ptrA->workHeightE << 16 ) / ( ptrA->patchHeightE + 1 ); 802 803 /* 12.20 */ 804 ptrA->effMaxScaleE = maxHScaleL < maxVScaleL ? ( maxHScaleL << 4 ) : ( maxVScaleL << 4 ); 805 806 if( ptrA->maxScaleE > 0 ) ptrA->effMaxScaleE = ptrA->effMaxScaleE < ptrA->maxScaleE ? ptrA->effMaxScaleE : ptrA->maxScaleE; 807 } 808 809 ptrA->scaleExpE = 0; 810 811 /* downscale work image if necessary */ 812 while( ptrA->scaleE > ( ( uint32 )( 2 << ptrA->scaleExpE ) << 20 ) ) bbf_Scanner_downscale( cpA, ptrA ); 813 814 bbf_Scanner_createBitImage( cpA, ptrA ); 815 bbf_Scanner_resetScan( cpA, ptrA ); 816 } 817 818 /* ------------------------------------------------------------------------- */ 819 820 flag bbf_Scanner_nextScale( struct bbs_Context* cpA, struct bbf_Scanner* ptrA ) 821 { 822 if( ptrA->scaleE + bbf_Scanner_scalePrd( ptrA->scaleE, ptrA->scaleStepE ) >= ptrA->effMaxScaleE ) return FALSE; 823 ptrA->scaleE += bbf_Scanner_scalePrd( ptrA->scaleE, ptrA->scaleStepE ); 824 825 /* downscale work image if necessary */ 826 while( ptrA->scaleE > ( ( uint32 )( 2 << ptrA->scaleExpE ) << 20 ) ) bbf_Scanner_downscale( cpA, ptrA ); 827 828 bbf_Scanner_createBitImage( cpA, ptrA ); 829 bbf_Scanner_resetScan( cpA, ptrA ); 830 return TRUE; 831 } 832 833 /* ------------------------------------------------------------------------- */ 834 835 const uint32* bbf_Scanner_getPatch( const struct bbf_Scanner* ptrA ) 836 { 837 return ptrA->patchBufferE.arrPtrE + ptrA->xE; 838 } 839 840 /* ------------------------------------------------------------------------- */ 841 842 flag bbf_Scanner_next( struct bbs_Context* cpA, struct bbf_Scanner* ptrA ) 843 { 844 if( ( ptrA->xE + 1 ) < ( int32 )( ptrA->currentWidthE - ptrA->patchWidthE ) ) 845 { 846 ptrA->xE++; 847 return TRUE; 848 } 849 850 if( ( ptrA->yE + 1 ) >= ( int32 )( ptrA->currentHeightE - ptrA->patchHeightE ) ) return FALSE; 851 852 ptrA->xE = 0; 853 ptrA->yE++; 854 855 { 856 uint32 offL = ( ptrA->yE & 0x1F ); 857 uint32 rowL = ( ptrA->yE >> 5 ) + ( offL > 0 ? 1 : 0 ); 858 859 uint32 sizeL = ptrA->bitImageE.widthE; 860 uint32* dstL = ptrA->patchBufferE.arrPtrE; 861 uint32 iL; 862 863 if( rowL < ptrA->bitImageE.heightE ) 864 { 865 uint32* srcL = ( uint32* )ptrA->bitImageE.arrE.arrPtrE + rowL * sizeL; 866 if( offL > 0 ) 867 { 868 uint32 shlL = 32 - offL; 869 for( iL = 0; iL < sizeL; iL++ ) dstL[ iL ] = ( dstL[ iL ] >> 1 ) | ( srcL[ iL ] << shlL ); 870 } 871 else 872 { 873 bbs_memcpy32( dstL, srcL, sizeL ); 874 } 875 } 876 else 877 { 878 for( iL = 0; iL < sizeL; iL++ ) dstL[ iL ] >>= 1; 879 } 880 } 881 882 return TRUE; 883 } 884 885 /* ------------------------------------------------------------------------- */ 886 887 void bbf_Scanner_goToXY( struct bbs_Context* cpA, struct bbf_Scanner* ptrA, int32 xA, int32 yA ) 888 { 889 bbs_DEF_fNameL( "void bbf_Scanner_goToXY( struct bbs_Context* cpA, struct bbf_Scanner* ptrA, int32 xA, int32 yA )" ) 890 891 if( xA > ( int32 )( ptrA->currentWidthE - ptrA->patchWidthE ) ) 892 { 893 bbs_ERROR1( "%s:\nyA out of range", fNameL ); 894 return; 895 } 896 897 ptrA->xE = xA; 898 899 if( ptrA->yE == yA ) return; 900 901 if( yA >= ( int32 )( ptrA->currentHeightE - ptrA->patchHeightE ) ) 902 { 903 bbs_ERROR1( "%s:\nyA out of range", fNameL ); 904 return; 905 } 906 907 if( yA == ptrA->yE + 1 ) 908 { 909 uint32 offL, rowL; 910 uint32 sizeL; 911 uint32* dstL; 912 uint32 iL; 913 914 ptrA->yE = yA; 915 offL = ( ptrA->yE & 0x1F ); 916 rowL = ( ptrA->yE >> 5 ) + ( offL > 0 ? 1 : 0 ); 917 918 sizeL = ptrA->bitImageE.widthE; 919 dstL = ptrA->patchBufferE.arrPtrE; 920 921 if( rowL < ptrA->bitImageE.heightE ) 922 { 923 uint32* srcL = ptrA->bitImageE.arrE.arrPtrE + rowL * sizeL; 924 if( offL > 0 ) 925 { 926 uint32 shlL = 32 - offL; 927 for( iL = 0; iL < sizeL; iL++ ) dstL[ iL ] = ( dstL[ iL ] >> 1 ) | ( srcL[ iL ] << shlL ); 928 } 929 else 930 { 931 bbs_memcpy32( dstL, srcL, sizeL ); 932 } 933 } 934 else 935 { 936 for( iL = 0; iL < sizeL; iL++ ) dstL[ iL ] >>= 1; 937 } 938 } 939 else 940 { 941 uint32 offL, rowL; 942 uint32 sizeL; 943 uint32* dstL; 944 uint32 iL; 945 946 ptrA->yE = yA; 947 offL = ( ptrA->yE & 0x1F ); 948 rowL = ( ptrA->yE >> 5 ) + ( offL > 0 ? 1 : 0 ); 949 950 sizeL = ptrA->bitImageE.widthE; 951 dstL = ptrA->patchBufferE.arrPtrE; 952 953 if( rowL < ptrA->bitImageE.heightE ) 954 { 955 if( offL > 0 ) 956 { 957 uint32* src1L = ptrA->bitImageE.arrE.arrPtrE + rowL * sizeL; 958 uint32* src0L = src1L - sizeL; 959 uint32 shlL = 32 - offL; 960 for( iL = 0; iL < sizeL; iL++ ) dstL[ iL ] = ( src0L[ iL ] >> offL ) | ( src1L[ iL ] << shlL ); 961 } 962 else 963 { 964 bbs_memcpy32( dstL, ptrA->bitImageE.arrE.arrPtrE + rowL * sizeL, sizeL ); 965 } 966 } 967 else 968 { 969 uint32* srcL = ptrA->bitImageE.arrE.arrPtrE + ( rowL - 1 ) * sizeL; 970 for( iL = 0; iL < sizeL; iL++ ) dstL[ iL ] = srcL[ iL ] >> offL; 971 } 972 } 973 } 974 975 /* ------------------------------------------------------------------------- */ 976 977 void bbf_Scanner_goToIndex( struct bbs_Context* cpA, struct bbf_Scanner* ptrA, uint32 scanIndexA ) 978 { 979 int32 yL = scanIndexA / ptrA->currentWidthE; 980 int32 xL = scanIndexA - yL * ptrA->currentWidthE; 981 bbf_Scanner_goToXY( cpA, ptrA, xL, yL ); 982 } 983 984 /* ------------------------------------------------------------------------- */ 985 986 void bbf_Scanner_goToUls( struct bbs_Context* cpA, struct bbf_Scanner* ptrA, 987 int32 xA, int32 yA, uint32 scaleA ) 988 { 989 int32 xL = ( xA / ( int32 )( ptrA->scaleE >> 4 ) ) + ptrA->borderWidthE; 990 int32 yL = ( yA / ( int32 )( ptrA->scaleE >> 4 ) ) + ptrA->borderHeightE; 991 992 if( ptrA->scaleE != scaleA ) 993 { 994 bbs_ERROR0( "bbf_Scanner_goToUls:\nScales no not match" ); 995 return; 996 } 997 998 bbf_Scanner_goToXY( cpA, ptrA, xL, yL ); 999 } 1000 1001 /* ------------------------------------------------------------------------- */ 1002 1003 /* resets output positions */ 1004 void bbf_Scanner_resetOutPos( struct bbs_Context* cpA, struct bbf_Scanner* ptrA ) 1005 { 1006 ptrA->outCountE = 0; 1007 } 1008 1009 /* ------------------------------------------------------------------------- */ 1010 1011 /* resets internal positions */ 1012 void bbf_Scanner_resetIntPos( struct bbs_Context* cpA, struct bbf_Scanner* ptrA ) 1013 { 1014 ptrA->intCountE = 0; 1015 } 1016 1017 /* ------------------------------------------------------------------------- */ 1018 1019 /* add internal position */ 1020 void bbf_Scanner_addIntPos( struct bbs_Context* cpA, 1021 struct bbf_Scanner* ptrA, 1022 uint32 idxA, 1023 int32 actA ) 1024 { 1025 if( ptrA->intCountE < ptrA->idxArrE.sizeE ) 1026 { 1027 ptrA->idxArrE.arrPtrE[ ptrA->intCountE ] = idxA; 1028 ptrA->actArrE.arrPtrE[ ptrA->intCountE ] = actA; 1029 ptrA->intCountE++; 1030 } 1031 else 1032 { 1033 /* When buffer is full then replace lowest confidence-entry with new input 1034 * This fallback solution causes soft degradation of performance when the buffer limit is reached. 1035 */ 1036 int32 minActL = 0x7FFFFFFF; 1037 uint32 minIdxL = 0; 1038 uint32 iL; 1039 int32* actArrL = ptrA->actArrE.arrPtrE; 1040 for( iL = 0; iL < ptrA->intCountE; iL++ ) 1041 { 1042 if( actArrL[ iL ] < minActL ) 1043 { 1044 minActL = actArrL[ iL ]; 1045 minIdxL = iL; 1046 } 1047 } 1048 1049 if( actA > minActL ) 1050 { 1051 ptrA->idxArrE.arrPtrE[ minIdxL ] = idxA; 1052 ptrA->actArrE.arrPtrE[ minIdxL ] = actA; 1053 } 1054 } 1055 } 1056 1057 /* ------------------------------------------------------------------------- */ 1058 1059 /* add external position */ 1060 void bbf_Scanner_addOutPos( struct bbs_Context* cpA, 1061 struct bbf_Scanner* ptrA, 1062 int32 xA, 1063 int32 yA, 1064 uint32 scaleA, 1065 int32 actA ) 1066 { 1067 if( ( ptrA->outCountE * 4 ) < ptrA->outArrE.sizeE ) 1068 { 1069 ptrA->outArrE.arrPtrE[ ptrA->outCountE * 4 + 0 ] = xA; 1070 ptrA->outArrE.arrPtrE[ ptrA->outCountE * 4 + 1 ] = yA; 1071 ptrA->outArrE.arrPtrE[ ptrA->outCountE * 4 + 2 ] = scaleA; 1072 ptrA->outArrE.arrPtrE[ ptrA->outCountE * 4 + 3 ] = actA; 1073 ptrA->outCountE++; 1074 } 1075 else 1076 { 1077 /* When buffer is full then replace lowest confidence-entry with new input 1078 * This fallback solution causes soft degradation of performance when the buffer limit is reached. 1079 */ 1080 int32 minActL = 0x7FFFFFFF; 1081 uint32 minIdxL = 0; 1082 uint32 iL; 1083 int32* outArrL = ptrA->outArrE.arrPtrE; 1084 for( iL = 0; iL < ptrA->outCountE; iL++ ) 1085 { 1086 if( outArrL[ iL * 4 + 3 ] < minActL ) 1087 { 1088 minActL = outArrL[ iL * 4 + 3 ]; 1089 minIdxL = iL; 1090 } 1091 } 1092 1093 if( actA > minActL ) 1094 { 1095 ptrA->idxArrE.arrPtrE[ minIdxL * 4 + 0 ] = xA; 1096 ptrA->idxArrE.arrPtrE[ minIdxL * 4 + 1 ] = yA; 1097 ptrA->idxArrE.arrPtrE[ minIdxL * 4 + 2 ] = scaleA; 1098 ptrA->idxArrE.arrPtrE[ minIdxL * 4 + 3 ] = actA; 1099 } 1100 } 1101 } 1102 1103 /* ------------------------------------------------------------------------- */ 1104 1105 /* remove overlaps */ 1106 uint32 bbf_Scanner_removeOutOverlaps( struct bbs_Context* cpA, 1107 struct bbf_Scanner* ptrA, 1108 uint32 overlapThrA ) 1109 { 1110 uint32 begIdxL = 0; /* begin index */ 1111 uint32 endIdxL = ptrA->outCountE; /* end index */ 1112 uint32 iL; 1113 uint32 rw0L = ptrA->patchWidthE; 1114 uint32 rh0L = ptrA->patchHeightE; 1115 int32* outArrL = ptrA->outArrE.arrPtrE; 1116 1117 if( overlapThrA >= 0x010000 ) return ptrA->outCountE; 1118 1119 while( endIdxL - begIdxL > 1 ) 1120 { 1121 int32 x1L, y1L, s1L, a1L; 1122 int32 r1wL, r1hL; 1123 uint32 r1aL; 1124 1125 /* find maximum activity */ 1126 uint32 maxIdxL = 0; 1127 1128 { 1129 int32 maxActL = ( int32 )0x80000000; 1130 for( iL = begIdxL; iL < endIdxL; iL++ ) 1131 { 1132 if( outArrL[ iL * 4 + 3 ] > maxActL ) 1133 { 1134 maxActL = outArrL[ iL * 4 + 3 ]; 1135 maxIdxL = iL; 1136 } 1137 } 1138 } 1139 1140 /* swap with position 0 */ 1141 x1L = outArrL[ maxIdxL * 4 + 0 ]; 1142 y1L = outArrL[ maxIdxL * 4 + 1 ]; 1143 s1L = outArrL[ maxIdxL * 4 + 2 ]; 1144 a1L = outArrL[ maxIdxL * 4 + 3 ]; 1145 1146 outArrL[ maxIdxL * 4 + 0 ] = outArrL[ begIdxL * 4 + 0 ]; 1147 outArrL[ maxIdxL * 4 + 1 ] = outArrL[ begIdxL * 4 + 1 ]; 1148 outArrL[ maxIdxL * 4 + 2 ] = outArrL[ begIdxL * 4 + 2 ]; 1149 outArrL[ maxIdxL * 4 + 3 ] = outArrL[ begIdxL * 4 + 3 ]; 1150 1151 outArrL[ begIdxL * 4 + 0 ] = x1L; 1152 outArrL[ begIdxL * 4 + 1 ] = y1L; 1153 outArrL[ begIdxL * 4 + 2 ] = s1L; 1154 outArrL[ begIdxL * 4 + 3 ] = a1L; 1155 1156 /* rectangle */ 1157 r1wL = ( rw0L * ( s1L >> 12 ) + 128 ) >> 8; 1158 r1hL = ( rh0L * ( s1L >> 12 ) + 128 ) >> 8; 1159 r1aL = ( uint32 )r1wL * ( uint32 )r1hL; 1160 1161 /* remove coordinate fractions */ 1162 x1L = ( x1L + ( 1 << 15 ) ) >> 16; 1163 y1L = ( y1L + ( 1 << 15 ) ) >> 16; 1164 1165 /* compare to other rectangles and remove overlaps */ 1166 for( iL = endIdxL - 1; iL > begIdxL; iL-- ) 1167 { 1168 int32* x2pL = &outArrL[ iL * 4 + 0 ]; 1169 int32* y2pL = &outArrL[ iL * 4 + 1 ]; 1170 int32* s2pL = &outArrL[ iL * 4 + 2 ]; 1171 int32* a2pL = &outArrL[ iL * 4 + 3 ]; 1172 1173 int32 x2L = ( *x2pL + ( 1 << 15 ) ) >> 16; 1174 int32 y2L = ( *y2pL + ( 1 << 15 ) ) >> 16; 1175 1176 /* rectangle */ 1177 int32 r2wL = ( rw0L * ( *s2pL >> 12 ) + 128 ) >> 8; 1178 int32 r2hL = ( rh0L * ( *s2pL >> 12 ) + 128 ) >> 8; 1179 uint32 r2aL = r2wL * r2hL; 1180 1181 /* intersection */ 1182 int32 rx1L = x1L > x2L ? x1L : x2L; 1183 int32 rx2L = ( x1L + r1wL ) < ( x2L + r2wL ) ? ( x1L + r1wL ) : ( x2L + r2wL ); 1184 int32 ry1L = y1L > y2L ? y1L : y2L; 1185 int32 ry2L = ( y1L + r1hL ) < ( y2L + r2hL ) ? ( y1L + r1hL ) : ( y2L + r2hL ); 1186 uint32 riwL; 1187 1188 rx2L = ( rx2L > rx1L ) ? rx2L : rx1L; 1189 ry2L = ( ry2L > ry1L ) ? ry2L : ry1L; 1190 riwL = ( uint32 )( rx2L - rx1L ) * ( uint32 )( ry2L - ry1L ); 1191 1192 if( riwL > ( ( ( overlapThrA >> 8 ) * ( r1aL < r2aL ? r1aL : r2aL ) ) >> 8 ) ) 1193 { 1194 endIdxL--; 1195 *x2pL = outArrL[ endIdxL * 4 + 0 ]; 1196 *y2pL = outArrL[ endIdxL * 4 + 1 ]; 1197 *s2pL = outArrL[ endIdxL * 4 + 2 ]; 1198 *a2pL = outArrL[ endIdxL * 4 + 3 ]; 1199 } 1200 } 1201 1202 begIdxL++; 1203 } 1204 1205 ptrA->outCountE = endIdxL; 1206 1207 return endIdxL; 1208 } 1209 1210 /* ------------------------------------------------------------------------- */ 1211 1212 /* remove internal overlaps */ 1213 uint32 bbf_Scanner_removeIntOverlaps( struct bbs_Context* cpA, 1214 struct bbf_Scanner* ptrA, 1215 uint32 overlapThrA ) 1216 { 1217 uint32 begIdxL = 0; /* begin index */ 1218 uint32 endIdxL = ptrA->intCountE; /* end index */ 1219 uint32 iL; 1220 uint32 rw0L = ptrA->patchWidthE; 1221 uint32 rh0L = ptrA->patchHeightE; 1222 int32 minAreaL = ( overlapThrA * rw0L * rh0L ) >> 16; 1223 1224 int32* actArrL = ptrA->actArrE.arrPtrE; 1225 uint32* idxArrL = ptrA->idxArrE.arrPtrE; 1226 1227 if( overlapThrA >= 0x010000 ) return ptrA->intCountE; 1228 1229 while( endIdxL - begIdxL > 1 ) 1230 { 1231 /* find maximum activity */ 1232 int32 a1L = ( int32 )0x80000000; 1233 uint32 i1L = 0; 1234 uint32 maxIdxL = 0; 1235 int32 x1L, y1L; 1236 1237 for( iL = begIdxL; iL < endIdxL; iL++ ) 1238 { 1239 if( actArrL[ iL ] > a1L ) 1240 { 1241 a1L = actArrL[ iL ]; 1242 maxIdxL = iL; 1243 } 1244 } 1245 1246 /* swap with position 0 */ 1247 i1L = idxArrL[ maxIdxL ]; 1248 idxArrL[ maxIdxL ] = idxArrL[ begIdxL ]; 1249 actArrL[ maxIdxL ] = actArrL[ begIdxL ]; 1250 idxArrL[ begIdxL ] = i1L; 1251 actArrL[ begIdxL ] = a1L; 1252 1253 /* upper left coordinates */ 1254 y1L = i1L / ptrA->currentWidthE; 1255 x1L = i1L - ( y1L * ptrA->currentWidthE ); 1256 1257 /* compare to other rectangles and remove overlaps */ 1258 for( iL = endIdxL - 1; iL > begIdxL; iL-- ) 1259 { 1260 int32* a2pL = &actArrL[ iL ]; 1261 uint32* i2pL = &idxArrL[ iL ]; 1262 1263 int32 y2L = *i2pL / ptrA->currentWidthE; 1264 int32 x2L = *i2pL - ( y2L * ptrA->currentWidthE ); 1265 1266 int32 dxL = rw0L - ( x1L > x2L ? x1L - x2L : x2L - x1L ); 1267 int32 dyL = rh0L - ( y1L > y2L ? y1L - y2L : y2L - y1L ); 1268 1269 dxL = dxL > 0 ? dxL : 0; 1270 dyL = dyL > 0 ? dyL : 0; 1271 1272 if( dxL * dyL > minAreaL ) 1273 { 1274 endIdxL--; 1275 *a2pL = actArrL[ endIdxL ]; 1276 *i2pL = idxArrL[ endIdxL ]; 1277 } 1278 } 1279 1280 begIdxL++; 1281 } 1282 1283 ptrA->intCountE = endIdxL; 1284 1285 return ptrA->intCountE; 1286 } 1287 1288 /* ------------------------------------------------------------------------- */ 1289 1290 /* ========================================================================= */ 1291