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/LocalScanner.h"
     22 
     23 /* ------------------------------------------------------------------------- */
     24 
     25 /* ========================================================================= */
     26 /*                                                                           */
     27 /* ---- \ghd{ auxiliary functions } ---------------------------------------- */
     28 /*                                                                           */
     29 /* ========================================================================= */
     30 
     31 /* ------------------------------------------------------------------------- */
     32 
     33 /** allocates arays */
     34 void bbf_LocalScanner_alloc( struct bbs_Context* cpA,
     35 							 struct bbf_LocalScanner* ptrA,
     36 							 struct bbs_MemTbl* mtpA )
     37 {
     38 	struct bbs_MemTbl memTblL = *mtpA;
     39 	struct bbs_MemSeg* espL = bbs_MemTbl_segPtr( cpA, &memTblL, 0 );
     40 	struct bbs_MemSeg* sspL = bbs_MemTbl_sharedSegPtr( cpA, &memTblL, 0 );
     41 
     42 	/* filter patch dimension */
     43 	uint32 proL = ptrA->maxRadiusE;
     44 	uint32 pwoL = ( proL << 1 ) + 1;
     45 
     46 	/* output image size (bit image) */
     47 	uint32 woL = ptrA->maxImageWidthE;
     48 	uint32 hoL = ptrA->maxImageHeightE;
     49 
     50 	if( ptrA->minScaleExpE > 0 )
     51 	{
     52 		/* allocate working image */
     53 		bbs_UInt8Arr_create( cpA, &ptrA->workImageBufferE, ( woL >> 1 ) * ( hoL >> 1 ), espL );
     54 		bbs_UInt8Arr_fill( cpA, &ptrA->workImageBufferE, 0 );
     55 	}
     56 
     57 	/* allocate bit image */
     58 	bim_UInt32Image_create( cpA, &ptrA->bitImageE, woL, ( hoL >> 5 ) + ( ( ( hoL & 0x1F ) != 0 ) ? 1 : 0 ), espL );
     59 	bim_UInt32Image_setAllPixels( cpA, &ptrA->bitImageE, 0, 0 );
     60 
     61 	/* allocate patch buffer */
     62 	bbs_UInt32Arr_create( cpA, &ptrA->patchBufferE, ptrA->bitImageE.widthE, espL );
     63 	bbs_UInt32Arr_fill( cpA, &ptrA->patchBufferE, 0 );
     64 
     65 	/* allocate table */
     66 	bim_UInt32Image_create( cpA, &ptrA->satE, woL + pwoL, pwoL + 1, sspL );
     67 }
     68 
     69 /* ------------------------------------------------------------------------- */
     70 
     71 /** downscales original image by factor 2 */
     72 void bbf_LocalScanner_downscale0( struct bbs_Context* cpA, struct bbf_LocalScanner* ptrA )
     73 {
     74 	int32 w0L = ptrA->origWidthE;
     75 	int32 h0L = ptrA->origHeightE;
     76 
     77 	int32 w1L = ( w0L - ptrA->xOffE ) >> 1;
     78 	int32 h1L = ( h0L - ptrA->yOffE ) >> 1;
     79 
     80 	const uint8* iArrL = ptrA->origImagePtrE + ptrA->xOffE + ptrA->yOffE * w0L;
     81 		  uint8* oArrL = ptrA->workImageBufferE.arrPtrE;
     82 
     83 	int32 iL, jL;
     84 	int32 kL = 0;
     85 
     86 	bbs_UInt8Arr_size( cpA, &ptrA->workImageBufferE, w1L * h1L );
     87 	ptrA->workImagePtrE = ptrA->workImageBufferE.arrPtrE;
     88 	ptrA->workWidthE = w1L;
     89 	ptrA->workHeightE = h1L;
     90 
     91 	for( jL = 0; jL < h1L; jL++ )
     92 	{
     93 		for( iL = 0; iL < w1L; iL++ )
     94 		{
     95 			int32 idxL = jL * 2 * w0L + iL * 2;
     96 			oArrL[ kL++ ] = ( ( uint32 )iArrL[ idxL           ] +
     97 										iArrL[ idxL + 1       ] +
     98 										iArrL[ idxL + w0L     ] +
     99 										iArrL[ idxL + w0L + 1 ] + 2 ) >> 2;
    100 		}
    101 	}
    102 }
    103 
    104 /* ------------------------------------------------------------------------- */
    105 
    106 /** downscales work image by factor 2 */
    107 void bbf_LocalScanner_downscale1( struct bbs_Context* cpA, struct bbf_LocalScanner* ptrA )
    108 {
    109 	int32 w0L = ptrA->workWidthE;
    110 	int32 h0L = ptrA->workHeightE;
    111 	int32 w1L = w0L >> 1;
    112 	int32 h1L = h0L >> 1;
    113 
    114     uint8* arrL = ptrA->workImageBufferE.arrPtrE;
    115 
    116 	int32 iL, jL;
    117 	int32 kL = 0;
    118 
    119 	for( jL = 0; jL < h1L; jL++ )
    120 	{
    121 		for( iL = 0; iL < w1L; iL++ )
    122 		{
    123 			int32 idxL = jL * 2 * w0L + iL * 2;
    124 			arrL[ kL++ ] = ( ( uint32 )arrL[ idxL ] +
    125 									   arrL[ idxL + 1 ] +
    126 									   arrL[ idxL + w0L ] +
    127 									   arrL[ idxL + w0L + 1 ] + 2 ) >> 2;
    128 		}
    129 	}
    130 
    131 	ptrA->workWidthE = w1L;
    132 	ptrA->workHeightE = h1L;
    133 }
    134 
    135 /* ------------------------------------------------------------------------- */
    136 
    137 /** downscales by factor 2 */
    138 void bbf_LocalScanner_downscale( struct bbs_Context* cpA, struct bbf_LocalScanner* ptrA )
    139 {
    140 	uint32 iL;
    141 	if( ptrA->scaleExpE > 0 ) bbf_LocalScanner_downscale0( cpA, ptrA );
    142 	for( iL = 1; iL < ptrA->scaleExpE; iL++ ) bbf_LocalScanner_downscale1( cpA, ptrA );
    143 }
    144 
    145 /* ------------------------------------------------------------------------- */
    146 
    147 /** computes bit image */
    148 void bbf_LocalScanner_createBitImage( struct bbs_Context* cpA, struct bbf_LocalScanner* ptrA )
    149 {
    150 	bbs_DEF_fNameL( "void bbf_LocalScanner_createBitImage( struct bbs_Context* cpA, struct bbf_LocalScanner* ptrA )" )
    151 
    152 	uint32 iL, jL;
    153 
    154 	uint32 proL = ptrA->bitParamE.outerRadiusE;
    155 	uint32 priL = ptrA->bitParamE.innerRadiusE;
    156 	uint32 pwoL = ( proL << 1 ) + 1;
    157 	uint32 pwiL = ( priL << 1 ) + 1;
    158 
    159 	/* areas of inner and outer rectangles */
    160 	uint32 poAreaL = pwoL * pwoL;
    161 	uint32 piAreaL = pwiL * pwiL;
    162 
    163 	uint32 wL, hL; /* input image size */
    164 
    165 	uint32 wsL, hsL;
    166 	uint32* satL;
    167 	uint32 satSizeL;
    168 	uint32 swi1L = 0; /* writing index */
    169 	uint32 swi2L = 0; /* writing index */
    170 	uint32 sriL = 0;  /* reading index */
    171 	uint32 siL[ 8 ];
    172 
    173 	uint32  bitMaskL;
    174 	uint32* bitRowL;
    175 
    176 
    177 	if( proL <= priL )
    178 	{
    179 		bbs_ERROR1( "%s:\n outer radius <= inner radius", fNameL );
    180 		return;
    181 	}
    182 
    183 	/* input image size */
    184 	wL = ptrA->workWidthE;
    185 	hL = ptrA->workHeightE;
    186 
    187 	if( wL <= pwoL || hL <= pwoL )
    188 	{
    189 		bbs_ERROR1( "%s:\n image is too small", fNameL );
    190 		return;
    191 	}
    192 
    193 	ptrA->currentWidthE  = wL;
    194 	ptrA->currentHeightE = hL;
    195 
    196 	/* reset scan region */
    197 	ptrA->workScanRegionE = bts_Int16Rect_create( 0, 0, ptrA->currentWidthE, ptrA->currentHeightE );
    198 
    199 	/* initialize bit image */
    200 	bim_UInt32Image_size( cpA, &ptrA->bitImageE, wL, ( hL >> 5 ) + ( ( ( hL & 0x1F ) != 0 ) ? 1 : 0 ) );
    201 	bim_UInt32Image_setAllPixels( cpA, &ptrA->bitImageE, 0, 0 );
    202 
    203 	bitMaskL = 1;
    204 	bitRowL = ( uint32* )ptrA->bitImageE.arrE.arrPtrE;
    205 
    206 	/* width of table */
    207 	wsL = wL + pwoL;
    208 
    209 	/* height of table */
    210 	hsL = pwoL + 1;
    211 
    212 	bim_UInt32Image_size( cpA, &ptrA->satE, wsL, hsL );
    213 
    214 	satL = ( uint32* )ptrA->satE.arrE.arrPtrE;
    215 	satSizeL = ptrA->satE.arrE.sizeE;
    216 
    217 	/* compute table and bit image */
    218 	for( iL = wsL * ( proL + 1 ); iL > 0; iL-- ) satL[ swi1L++ ] = 0;
    219 	swi2L = swi1L - wsL;
    220 
    221 	for( jL = 0; jL < hL + proL; jL++ )
    222 	{
    223 		if( jL < hL ) /* rescale area */
    224 		{
    225 			const uint8* arr0L = &ptrA->workImagePtrE[ jL * wL ];
    226 			uint32 hSumL = 0;
    227 			for( iL = 0; iL <= proL; iL++ ) satL[ swi1L++ ] = 0;
    228 			swi2L += iL;
    229 			for( iL = 0; iL < wL; iL++ )   satL[ swi1L++ ] = ( hSumL += arr0L[ iL ] ) + satL[ swi2L++ ];
    230 			for( iL = 0; iL < proL; iL++ ) satL[ swi1L++ ] =   hSumL                  + satL[ swi2L++ ];
    231 		}
    232 		else /* image is processed - fill in 0s */
    233 		{
    234 			for( iL = 0; iL < wsL; iL++ ) satL[ swi1L++ ] = satL[ swi2L++ ];
    235 		}
    236 
    237 		swi1L = ( swi1L < satSizeL ) ? swi1L : 0;
    238 		swi2L = ( swi2L < satSizeL ) ? swi2L : 0;
    239 
    240 		/* fill line in bit image */
    241 		if( jL >= proL )
    242 		{
    243 			const uint32* rSatL = satL;
    244 
    245 			/* table coordinate indices for outer rectangle */
    246 			siL[ 0 ] = sriL;
    247 			siL[ 1 ] = siL[ 0 ] + pwoL;
    248 			siL[ 2 ] = siL[ 0 ] + pwoL * wsL;
    249 			siL[ 2 ] -= ( siL[ 2 ] >= satSizeL ) ? satSizeL : 0;
    250 			siL[ 3 ] = siL[ 2 ] + pwoL;
    251 
    252 			/* table coordinate indices for inner rectangle */
    253 			siL[ 4 ] = siL[ 0 ] + ( proL - priL ) * wsL + ( proL - priL );
    254 			siL[ 4 ] -= ( siL[ 4 ] >= satSizeL ) ? satSizeL : 0;
    255 			siL[ 5 ] = siL[ 4 ] + pwiL;
    256 			siL[ 6 ] = siL[ 4 ] + pwiL * wsL;
    257 			siL[ 6 ] -= ( siL[ 6 ] >= satSizeL ) ? satSizeL : 0;
    258 			siL[ 7 ] = siL[ 6 ] + pwiL;
    259 			sriL += wsL;
    260 			if( sriL == satSizeL ) sriL = 0;
    261 
    262 			for( iL = 0; iL < wL; iL++ )
    263 			{
    264 				uint32 oAvgL = ( rSatL[ siL[ 0 ] ] - rSatL[ siL[ 1 ] ] - rSatL[ siL[ 2 ] ] + rSatL[ siL[ 3 ] ] ) * piAreaL;
    265 				uint32 iAvgL = ( rSatL[ siL[ 4 ] ] - rSatL[ siL[ 5 ] ] - rSatL[ siL[ 6 ] ] + rSatL[ siL[ 7 ] ] ) * poAreaL;
    266 				bitRowL[ iL ] |= ( iAvgL > oAvgL ) ? bitMaskL : 0;
    267 				rSatL++;
    268 			}
    269 			if( ( bitMaskL <<= 1 ) == 0 )
    270 			{
    271 				bitRowL += wL;
    272 				bitMaskL = 1;
    273 			}
    274 		}
    275 	}
    276 }
    277 
    278 /* -------------------------------------------------------------------------- */
    279 
    280 /** inilialize patch buffer */
    281 void bbf_LocalScanner_initPatchBuffer( struct bbs_Context* cpA, struct bbf_LocalScanner* ptrA )
    282 {
    283 	int32 ybL = ptrA->workScanRegionE.y1E >> 5;
    284 	int32 yoL = ptrA->workScanRegionE.y1E & 0x1F;
    285 	int32 xbL = ptrA->workScanRegionE.x1E;
    286 	uint32 wsrWidthL = ptrA->workScanRegionE.x2E - ptrA->workScanRegionE.x1E;
    287 
    288 	bbs_UInt32Arr_size( cpA, &ptrA->patchBufferE, ptrA->bitImageE.widthE );
    289 
    290 	if( yoL == 0 )
    291 	{
    292 		bbs_memcpy32( ptrA->patchBufferE.arrPtrE + xbL,
    293 			          ptrA->bitImageE.arrE.arrPtrE + ybL * ptrA->bitImageE.widthE + xbL,
    294 					  wsrWidthL );
    295 	}
    296 	else if( ybL == ( int32 )ptrA->bitImageE.heightE - 1 )
    297 	{
    298 		uint32* dstL = ptrA->patchBufferE.arrPtrE + xbL;
    299 		const uint32* srcL = ptrA->bitImageE.arrE.arrPtrE + ybL * ptrA->bitImageE.widthE + xbL;
    300 		uint32 iL;
    301 		for( iL = 0; iL < wsrWidthL; iL++ ) dstL[ iL ] = srcL[ iL ] >> yoL;
    302 	}
    303 	else
    304 	{
    305 		uint32* dstL = ptrA->patchBufferE.arrPtrE + xbL;
    306 		const uint32* src0L = ptrA->bitImageE.arrE.arrPtrE + ybL * ptrA->bitImageE.widthE + xbL;
    307 		const uint32* src1L = src0L + ptrA->bitImageE.widthE;
    308 		uint32 iL;
    309 		uint32 slL = 32 - yoL;
    310 		for( iL = 0; iL < wsrWidthL; iL++ ) dstL[ iL ] = ( src0L[ iL ] >> yoL ) | ( src1L[ iL ] << slL );
    311 	}
    312 }
    313 
    314 /* ------------------------------------------------------------------------- */
    315 
    316 /* sets work scan region from original scan region according to scale exponent */
    317 void bbf_LocalScanner_setWorkScanRegion( struct bbs_Context* cpA, struct bbf_LocalScanner* ptrA )
    318 {
    319 	int32 xMinL = ptrA->origScanRegionE.x1E >> ptrA->scaleExpE;
    320 	int32 yMinL = ptrA->origScanRegionE.y1E >> ptrA->scaleExpE;
    321 	int32 xMaxL = ptrA->origScanRegionE.x2E >> ptrA->scaleExpE;
    322 	int32 yMaxL = ptrA->origScanRegionE.y2E >> ptrA->scaleExpE;
    323 	ptrA->workScanRegionE.x1E = ( xMinL < 0 ) ? 0 : xMinL;
    324 	ptrA->workScanRegionE.y1E = ( yMinL < 0 ) ? 0 : yMinL;
    325 	ptrA->workScanRegionE.x2E = ( xMaxL > ( int32 )ptrA->currentWidthE ) ? ptrA->currentWidthE : xMaxL;
    326 	ptrA->workScanRegionE.y2E = ( yMaxL > ( int32 )ptrA->currentHeightE ) ? ptrA->currentHeightE : yMaxL;
    327 }
    328 
    329 /* ------------------------------------------------------------------------- */
    330 
    331 /* ========================================================================= */
    332 /*                                                                           */
    333 /* ---- \ghd{ constructor / destructor } ----------------------------------- */
    334 /*                                                                           */
    335 /* ========================================================================= */
    336 
    337 /* ------------------------------------------------------------------------- */
    338 
    339 void bbf_LocalScanner_init( struct bbs_Context* cpA,
    340 					        struct bbf_LocalScanner* ptrA )
    341 {
    342 	ptrA->xE = 0;
    343 	ptrA->yE = 0;
    344 	ptrA->xOffE = 0;
    345 	ptrA->yOffE = 0;
    346 	ptrA->currentWidthE = 0;
    347 	ptrA->currentHeightE = 0;
    348 	ptrA->workWidthE = 0;
    349 	ptrA->workHeightE = 0;
    350 	ptrA->workImagePtrE = NULL;
    351 	ptrA->origWidthE = 0;
    352 	ptrA->origHeightE = 0;
    353 	ptrA->origImagePtrE = NULL;
    354 	bbf_BitParam_init( cpA, &ptrA->bitParamE );
    355 	bbs_UInt8Arr_init( cpA, &ptrA->workImageBufferE );
    356 	bim_UInt32Image_init( cpA, &ptrA->satE );
    357 	bim_UInt32Image_init( cpA, &ptrA->bitImageE );
    358 	bbs_UInt32Arr_init( cpA, &ptrA->patchBufferE );
    359 	bts_Int16Rect_init( cpA, &ptrA->origScanRegionE );
    360 	bts_Int16Rect_init( cpA, &ptrA->workScanRegionE );
    361 
    362 	ptrA->patchWidthE = 0;
    363 	ptrA->patchHeightE = 0;
    364 	ptrA->scaleExpE = 0;
    365 	ptrA->maxImageWidthE = 0;
    366 	ptrA->maxImageHeightE = 0;
    367 	ptrA->minScaleExpE = 0;
    368 	ptrA->maxRadiusE = 0;
    369 }
    370 
    371 /* ------------------------------------------------------------------------- */
    372 
    373 void bbf_LocalScanner_exit( struct bbs_Context* cpA,
    374 				            struct bbf_LocalScanner* ptrA )
    375 {
    376 	ptrA->xE = 0;
    377 	ptrA->yE = 0;
    378 	ptrA->xOffE = 0;
    379 	ptrA->yOffE = 0;
    380 	ptrA->currentWidthE = 0;
    381 	ptrA->currentHeightE = 0;
    382 	ptrA->workWidthE = 0;
    383 	ptrA->workHeightE = 0;
    384 	ptrA->workImagePtrE = NULL;
    385 	ptrA->origWidthE = 0;
    386 	ptrA->origHeightE = 0;
    387 	ptrA->origImagePtrE = NULL;
    388 	bbf_BitParam_exit( cpA, &ptrA->bitParamE );
    389 	bbs_UInt8Arr_exit( cpA, &ptrA->workImageBufferE );
    390 	bim_UInt32Image_exit( cpA, &ptrA->satE );
    391 	bim_UInt32Image_exit( cpA, &ptrA->bitImageE );
    392 	bbs_UInt32Arr_exit( cpA, &ptrA->patchBufferE );
    393 	bts_Int16Rect_exit( cpA, &ptrA->origScanRegionE );
    394 	bts_Int16Rect_exit( cpA, &ptrA->workScanRegionE );
    395 
    396 	ptrA->patchWidthE = 0;
    397 	ptrA->patchHeightE = 0;
    398 	ptrA->scaleExpE = 0;
    399 	ptrA->maxImageWidthE = 0;
    400 	ptrA->maxImageHeightE = 0;
    401 	ptrA->minScaleExpE = 0;
    402 	ptrA->maxRadiusE = 0;
    403 }
    404 
    405 /* ------------------------------------------------------------------------- */
    406 
    407 /* ========================================================================= */
    408 /*                                                                           */
    409 /* ---- \ghd{ operators } -------------------------------------------------- */
    410 /*                                                                           */
    411 /* ========================================================================= */
    412 
    413 /* ------------------------------------------------------------------------- */
    414 
    415 void bbf_LocalScanner_copy( struct bbs_Context* cpA,
    416 				            struct bbf_LocalScanner* ptrA,
    417 					        const struct bbf_LocalScanner* srcPtrA )
    418 {
    419 	bbs_ERROR0( "bbf_LocalScanner_copy:\n Function is not available" );
    420 }
    421 
    422 /* ------------------------------------------------------------------------- */
    423 
    424 flag bbf_LocalScanner_equal( struct bbs_Context* cpA,
    425 							 const struct bbf_LocalScanner* ptrA,
    426 							 const struct bbf_LocalScanner* srcPtrA )
    427 {
    428 	bbs_ERROR0( "bbf_LocalScanner_equal:\n Function is not available" );
    429 	return FALSE;
    430 }
    431 
    432 /* ------------------------------------------------------------------------- */
    433 
    434 /* ========================================================================= */
    435 /*                                                                           */
    436 /* ---- \ghd{ query functions } -------------------------------------------- */
    437 /*                                                                           */
    438 /* ========================================================================= */
    439 
    440 /* ------------------------------------------------------------------------- */
    441 
    442 uint32 bbf_LocalScanner_positions( const struct bbf_LocalScanner* ptrA )
    443 {
    444 	int32 wL = ptrA->workScanRegionE.x2E - ptrA->workScanRegionE.x1E - ptrA->patchWidthE;
    445 	int32 hL = ptrA->workScanRegionE.y2E - ptrA->workScanRegionE.y1E - ptrA->patchHeightE;
    446 	return ( ( wL < 0 ) ? 0 : wL ) * ( ( hL < 0 ) ? 0 : hL );
    447 }
    448 
    449 /* ------------------------------------------------------------------------- */
    450 
    451 uint32 bbf_LocalScanner_scanIndex( const struct bbf_LocalScanner* ptrA )
    452 {
    453 	int32 wL = ptrA->workScanRegionE.x2E - ptrA->workScanRegionE.x1E - ptrA->patchWidthE;
    454 	return ( ptrA->yE - ptrA->workScanRegionE.y1E ) * wL + ( ptrA->xE - ptrA->workScanRegionE.x1E );
    455 }
    456 
    457 /* ------------------------------------------------------------------------- */
    458 
    459 void bbf_LocalScanner_pos( const struct bbf_LocalScanner* ptrA, int32* xPtrA, int32* yPtrA )
    460 {
    461 	*xPtrA = ( ( ptrA->xE << ptrA->scaleExpE ) + ptrA->xOffE ) << 16;
    462 	*yPtrA = ( ( ptrA->yE << ptrA->scaleExpE ) + ptrA->yOffE ) << 16;
    463 }
    464 
    465 /* ------------------------------------------------------------------------- */
    466 
    467 void bbf_LocalScanner_idxPos( const struct bbf_LocalScanner* ptrA, uint32 scanIndexA, int32* xPtrA, int32* yPtrA )
    468 {
    469 	uint32 wL = ptrA->workScanRegionE.x2E - ptrA->workScanRegionE.x1E - ptrA->patchWidthE;
    470 	int32 xL = ( scanIndexA % wL ) + ptrA->workScanRegionE.x1E;
    471 	int32 yL = ( scanIndexA / wL ) + ptrA->workScanRegionE.y1E;
    472 	*xPtrA = ( ( xL << ptrA->scaleExpE ) + ptrA->xOffE ) << 16;
    473 	*yPtrA = ( ( yL << ptrA->scaleExpE ) + ptrA->yOffE ) << 16;
    474 }
    475 
    476 /* ------------------------------------------------------------------------- */
    477 
    478 /* ========================================================================= */
    479 /*                                                                           */
    480 /* ---- \ghd{ modify functions } ------------------------------------------- */
    481 /*                                                                           */
    482 /* ========================================================================= */
    483 
    484 /* ------------------------------------------------------------------------- */
    485 
    486 void bbf_LocalScanner_create( struct bbs_Context* cpA,
    487 							  struct bbf_LocalScanner* ptrA,
    488 							  uint32 patchWidthA,
    489 							  uint32 patchHeightA,
    490 							  uint32 scaleExpA,
    491 							  uint32 maxImageWidthA,
    492 							  uint32 maxImageHeightA,
    493 							  uint32 minScaleExpA,
    494 							  uint32 maxRadiusA,
    495 							  struct bbs_MemTbl* mtpA )
    496 {
    497 	ptrA->patchWidthE = patchWidthA;
    498 	ptrA->patchHeightE = patchHeightA;
    499 	ptrA->scaleExpE = scaleExpA;
    500 	ptrA->maxImageWidthE = maxImageWidthA;
    501 	ptrA->maxImageHeightE = maxImageHeightA;
    502 	ptrA->minScaleExpE = minScaleExpA;
    503 	ptrA->maxRadiusE = maxRadiusA;
    504 	bbf_LocalScanner_alloc( cpA, ptrA, mtpA );
    505 }
    506 
    507 /* ------------------------------------------------------------------------- */
    508 
    509 void bbf_LocalScanner_bitParam( struct bbs_Context* cpA,
    510 							    struct bbf_LocalScanner* ptrA,
    511 								const struct bbf_BitParam* bitParamPtrA )
    512 {
    513 	if( !bbf_BitParam_equal( cpA, &ptrA->bitParamE, bitParamPtrA ) )
    514 	{
    515 		bbf_BitParam_copy( cpA, &ptrA->bitParamE, bitParamPtrA );
    516 		bbf_LocalScanner_createBitImage( cpA, ptrA );
    517 	}
    518 
    519 	bbf_LocalScanner_resetScan( cpA, ptrA );
    520 }
    521 
    522 /* ------------------------------------------------------------------------- */
    523 
    524 void bbf_LocalScanner_origScanRegion( struct bbs_Context* cpA,
    525 									  struct bbf_LocalScanner* ptrA,
    526 									  const struct bts_Int16Rect* scanRegionPtrA )
    527 {
    528 	ptrA->origScanRegionE = *scanRegionPtrA;
    529 	bbf_LocalScanner_setWorkScanRegion( cpA, ptrA );
    530 	bbf_LocalScanner_resetScan( cpA, ptrA );
    531 }
    532 
    533 /* ------------------------------------------------------------------------- */
    534 
    535 /* ========================================================================= */
    536 /*                                                                           */
    537 /* ---- \ghd{ I/O } -------------------------------------------------------- */
    538 /*                                                                           */
    539 /* ========================================================================= */
    540 
    541 /* ------------------------------------------------------------------------- */
    542 
    543 uint32 bbf_LocalScanner_memSize( struct bbs_Context* cpA,
    544 								 const struct bbf_LocalScanner* ptrA )
    545 {
    546 	uint32 memSizeL = bbs_SIZEOF16( uint32 ) +
    547 					  bbs_SIZEOF16( uint32 ); /* version */
    548 
    549 	memSizeL += bbs_SIZEOF16( ptrA->patchWidthE );
    550 	memSizeL += bbs_SIZEOF16( ptrA->patchHeightE );
    551 	memSizeL += bbs_SIZEOF16( ptrA->scaleExpE );
    552 	memSizeL += bbs_SIZEOF16( ptrA->maxImageWidthE );
    553 	memSizeL += bbs_SIZEOF16( ptrA->maxImageHeightE );
    554 	memSizeL += bbs_SIZEOF16( ptrA->minScaleExpE );
    555 	memSizeL += bbs_SIZEOF16( ptrA->maxRadiusE );
    556 
    557 	return memSizeL;
    558 }
    559 
    560 /* ------------------------------------------------------------------------- */
    561 
    562 uint32 bbf_LocalScanner_memWrite( struct bbs_Context* cpA,
    563 						     const struct bbf_LocalScanner* ptrA,
    564 						     uint16* memPtrA )
    565 {
    566 	uint32 memSizeL = bbf_LocalScanner_memSize( cpA, ptrA );
    567 	memPtrA += bbs_memWrite32( &memSizeL, memPtrA );
    568 	memPtrA += bbs_memWriteUInt32( bbf_LOCAL_SCANNER_VERSION, memPtrA );
    569 
    570 	memPtrA += bbs_memWrite32( &ptrA->patchWidthE, memPtrA );
    571 	memPtrA += bbs_memWrite32( &ptrA->patchHeightE, memPtrA );
    572 	memPtrA += bbs_memWrite32( &ptrA->scaleExpE, memPtrA );
    573 	memPtrA += bbs_memWrite32( &ptrA->maxImageWidthE, memPtrA );
    574 	memPtrA += bbs_memWrite32( &ptrA->maxImageHeightE, memPtrA );
    575 	memPtrA += bbs_memWrite32( &ptrA->minScaleExpE, memPtrA );
    576 	memPtrA += bbs_memWrite32( &ptrA->maxRadiusE, memPtrA );
    577 	return memSizeL;
    578 }
    579 
    580 /* ------------------------------------------------------------------------- */
    581 
    582 uint32 bbf_LocalScanner_memRead( struct bbs_Context* cpA,
    583 						    struct bbf_LocalScanner* ptrA,
    584 						    const uint16* memPtrA,
    585 						    struct bbs_MemTbl* mtpA )
    586 {
    587 	uint32 memSizeL, versionL;
    588 
    589 	if( bbs_Context_error( cpA ) ) return 0;
    590 	memPtrA += bbs_memRead32( &memSizeL, memPtrA );
    591 	memPtrA += bbs_memReadVersion32( cpA, &versionL, bbf_LOCAL_SCANNER_VERSION, memPtrA );
    592 
    593 	memPtrA += bbs_memRead32( &ptrA->patchWidthE, memPtrA );
    594 	memPtrA += bbs_memRead32( &ptrA->patchHeightE, memPtrA );
    595 	memPtrA += bbs_memRead32( &ptrA->scaleExpE, memPtrA );
    596 	memPtrA += bbs_memRead32( &ptrA->maxImageWidthE, memPtrA );
    597 	memPtrA += bbs_memRead32( &ptrA->maxImageHeightE, memPtrA );
    598 	memPtrA += bbs_memRead32( &ptrA->minScaleExpE, memPtrA );
    599 	memPtrA += bbs_memRead32( &ptrA->maxRadiusE, memPtrA );
    600 
    601 	if( memSizeL != bbf_LocalScanner_memSize( cpA, ptrA ) )
    602 	{
    603 		bbs_ERR0( bbs_ERR_CORRUPT_DATA, "uint32 bbf_LocalScanner_memRead( struct bem_ScanGradientMove* ptrA, const uint16* memPtrA ):\n"
    604 			        "size mismatch" );
    605 		return 0;
    606 	}
    607 
    608 	if( bbs_Context_error( cpA ) ) return 0;
    609 
    610 	/* allocate arrays */
    611 	bbf_LocalScanner_alloc( cpA, ptrA, mtpA );
    612 
    613 	if( bbs_Context_error( cpA ) ) return 0;
    614 
    615 	return memSizeL;
    616 }
    617 
    618 /* ------------------------------------------------------------------------- */
    619 
    620 /* ========================================================================= */
    621 /*                                                                           */
    622 /* ---- \ghd{ exec functions } --------------------------------------------- */
    623 /*                                                                           */
    624 /* ========================================================================= */
    625 
    626 /* ------------------------------------------------------------------------- */
    627 
    628 void bbf_LocalScanner_resetScan( struct bbs_Context* cpA,
    629 								 struct bbf_LocalScanner* ptrA )
    630 {
    631 	ptrA->xE = ptrA->workScanRegionE.x1E;
    632 	ptrA->yE = ptrA->workScanRegionE.y1E;
    633 	bbf_LocalScanner_initPatchBuffer( cpA, ptrA );
    634 }
    635 
    636 /* ------------------------------------------------------------------------- */
    637 
    638 void bbf_LocalScanner_assign( struct bbs_Context* cpA,
    639 							  struct bbf_LocalScanner* ptrA,
    640 							  const uint8* imagePtrA,
    641 							  uint32 imageWidthA,
    642 							  uint32 imageHeightA,
    643 							  const struct bbf_BitParam* paramPtrA )
    644 {
    645 	if( ptrA->scaleExpE == 0 )
    646 	{
    647 		ptrA->workImagePtrE = imagePtrA;
    648 		ptrA->workWidthE = imageWidthA;
    649 		ptrA->workHeightE = imageHeightA;
    650 	}
    651 	else
    652 	{
    653 		ptrA->origImagePtrE = imagePtrA;
    654 		ptrA->origWidthE = imageWidthA;
    655 		ptrA->origHeightE = imageHeightA;
    656 	}
    657 
    658 	ptrA->bitParamE = *paramPtrA;
    659 	ptrA->xOffE = 0;
    660 	ptrA->yOffE = 0;
    661 	ptrA->origScanRegionE = bts_Int16Rect_create( 0, 0, imageWidthA, imageHeightA );
    662 	bbf_LocalScanner_downscale( cpA, ptrA );
    663 	bbf_LocalScanner_createBitImage( cpA, ptrA );
    664 	bbf_LocalScanner_resetScan( cpA, ptrA );
    665 }
    666 
    667 /* ------------------------------------------------------------------------- */
    668 
    669 const uint32* bbf_LocalScanner_getPatch( const struct bbf_LocalScanner* ptrA )
    670 {
    671 	return ptrA->patchBufferE.arrPtrE + ptrA->xE;
    672 }
    673 
    674 /* ------------------------------------------------------------------------- */
    675 
    676 flag bbf_LocalScanner_next( struct bbs_Context* cpA, struct bbf_LocalScanner* ptrA )
    677 {
    678 	if( ( ptrA->xE + 1 ) < ptrA->workScanRegionE.x2E - ( int32 )ptrA->patchWidthE )
    679 	{
    680 		ptrA->xE++;
    681 		return TRUE;
    682 	}
    683 
    684 	if( ( ptrA->yE + 1 ) >= ptrA->workScanRegionE.y2E - ( int32 )ptrA->patchHeightE ) return FALSE;
    685 
    686 	ptrA->xE = ptrA->workScanRegionE.x1E;
    687 	ptrA->yE++;
    688 
    689 	{
    690 		uint32 offL = ( ptrA->yE & 0x1F );
    691 		uint32 rowL = ( ptrA->yE >> 5 ) + ( offL > 0 ? 1 : 0 );
    692 
    693 		uint32 widthL = ptrA->bitImageE.widthE;
    694 		uint32 sizeL = ptrA->workScanRegionE.x2E - ptrA->workScanRegionE.x1E;
    695 		uint32* dstL = ( uint32* )ptrA->patchBufferE.arrPtrE + ptrA->xE;
    696 		uint32 iL;
    697 
    698 		if( rowL < ptrA->bitImageE.heightE )
    699 		{
    700 			uint32* srcL = ptrA->bitImageE.arrE.arrPtrE + rowL * widthL + ptrA->xE;
    701 			if( offL > 0 )
    702 			{
    703 				uint32 shlL = 32 - offL;
    704 				for( iL = 0; iL < sizeL; iL++ ) dstL[ iL ] = ( dstL[ iL ] >> 1 ) | ( srcL[ iL ] << shlL );
    705 			}
    706 			else
    707 			{
    708 				bbs_memcpy32( dstL, srcL, sizeL );
    709 			}
    710 		}
    711 		else
    712 		{
    713 			for( iL = 0; iL < sizeL; iL++ ) dstL[ iL ] >>= 1;
    714 		}
    715 	}
    716 
    717 	return TRUE;
    718 }
    719 
    720 /* ------------------------------------------------------------------------- */
    721 
    722 void bbf_LocalScanner_goToXY( struct bbs_Context* cpA, struct bbf_LocalScanner* ptrA, int32 xA, int32 yA )
    723 {
    724 	bbs_DEF_fNameL( "void bbf_LocalScanner_goToXY( struct bbs_Context* cpA, struct bbf_LocalScanner* ptrA, int32 xA, int32 yA )" )
    725 	if( xA < ptrA->workScanRegionE.x1E || xA >= ptrA->workScanRegionE.x2E - ( int32 )ptrA->patchWidthE )
    726 	{
    727 		bbs_ERROR1( "%s:\nxA out of range", fNameL );
    728 		return;
    729 	}
    730 	ptrA->xE = xA;
    731 	if( ptrA->yE == yA ) return;
    732 	if( yA < ptrA->workScanRegionE.y1E || yA >= ptrA->workScanRegionE.y2E - ( int32 )ptrA->patchHeightE )
    733 	{
    734 		bbs_ERROR1( "%s:\nyA out of range", fNameL );
    735 		return;
    736 	}
    737 	ptrA->yE = yA;
    738 
    739 	{
    740 		uint32 offL = ( ptrA->yE & 0x1F );
    741 		uint32 rowL = ( ptrA->yE >> 5 ) + ( offL > 0 ? 1 : 0 );
    742 
    743 		uint32 sizeL = ptrA->workScanRegionE.x2E - ptrA->workScanRegionE.x1E;
    744 		uint32 imgWidthL = ptrA->bitImageE.widthE;
    745 		uint32 imgOffsL = ptrA->workScanRegionE.x1E;
    746 		uint32* dstL = ptrA->patchBufferE.arrPtrE + imgOffsL;
    747 		uint32 iL;
    748 
    749 		if( rowL < ptrA->bitImageE.heightE )
    750 		{
    751 			if( offL > 0 )
    752 			{
    753 				uint32* src1L = ptrA->bitImageE.arrE.arrPtrE + rowL * imgWidthL + imgOffsL;
    754 				uint32* src0L = src1L - imgWidthL;
    755 				uint32 shlL = 32 - offL;
    756 				for( iL = 0; iL < sizeL; iL++ ) dstL[ iL ] = ( src0L[ iL ] >> offL ) | ( src1L[ iL ] << shlL );
    757 			}
    758 			else
    759 			{
    760 				bbs_memcpy32( dstL, ptrA->bitImageE.arrE.arrPtrE + rowL * imgWidthL + imgOffsL, sizeL );
    761 			}
    762 		}
    763 		else
    764 		{
    765 			uint32* srcL = ptrA->bitImageE.arrE.arrPtrE + ( rowL - 1 ) * imgWidthL + imgOffsL;
    766 			for( iL = 0; iL < sizeL; iL++ ) dstL[ iL ] = srcL[ iL ] >> offL;
    767 		}
    768 	}
    769 }
    770 
    771 /* ------------------------------------------------------------------------- */
    772 
    773 void bbf_LocalScanner_goToIndex( struct bbs_Context* cpA, struct bbf_LocalScanner* ptrA, uint32 scanIndexA )
    774 {
    775 	uint32 wL = ptrA->workScanRegionE.x2E - ptrA->workScanRegionE.x1E - ptrA->patchWidthE;
    776 	bbf_LocalScanner_goToXY( cpA, ptrA,
    777 							 ( scanIndexA % wL ) + ptrA->workScanRegionE.x1E,
    778 							 ( scanIndexA / wL ) + ptrA->workScanRegionE.y1E );
    779 }
    780 
    781 /* ------------------------------------------------------------------------- */
    782 
    783 flag bbf_LocalScanner_nextOffset( struct bbs_Context* cpA, struct bbf_LocalScanner* ptrA )
    784 {
    785 	int32 maxL = ( 1 << ptrA->scaleExpE );
    786 	if( ptrA->yOffE == maxL ) return FALSE;
    787 
    788 	ptrA->xOffE++;
    789 
    790 	if( ptrA->xOffE == maxL )
    791 	{
    792 		ptrA->xOffE = 0;
    793 		ptrA->yOffE++;
    794 		if( ptrA->yOffE == maxL ) return FALSE;
    795 	}
    796 
    797 	bbf_LocalScanner_downscale( cpA, ptrA );
    798 	bbf_LocalScanner_createBitImage( cpA, ptrA );
    799 	bbf_LocalScanner_setWorkScanRegion( cpA, ptrA );
    800 	bbf_LocalScanner_resetScan( cpA, ptrA );
    801 
    802 	return TRUE;
    803 }
    804 
    805 /* ------------------------------------------------------------------------- */
    806 
    807 /* ========================================================================= */
    808