Home | History | Annotate | Download | only in b_BitFeatureEm
      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