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 */
bbf_Scanner_scalePrd(uint32 scaleA,uint32 factorA)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 */
bbf_Scanner_alloc(struct bbs_Context * cpA,struct bbf_Scanner * ptrA,struct bbs_MemTbl * mtpA,flag maximizeSharedMemoryA)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 */
bbf_Scanner_downscale(struct bbs_Context * cpA,struct bbf_Scanner * ptrA)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  */
bbf_Scanner_copyImage(struct bbs_Context * cpA,struct bbf_Scanner * ptrA,const void * imagePtrA,uint32 imageWidthA,uint32 imageHeightA,const struct bts_Int16Rect * roiPtrA)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 */
bbf_Scanner_createBitImage(struct bbs_Context * cpA,struct bbf_Scanner * ptrA)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 */
bbf_Scanner_initPatchBuffer(struct bbs_Context * cpA,struct bbf_Scanner * ptrA)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 
bbf_Scanner_init(struct bbs_Context * cpA,struct bbf_Scanner * ptrA)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 
bbf_Scanner_exit(struct bbs_Context * cpA,struct bbf_Scanner * ptrA)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 
bbf_Scanner_copy(struct bbs_Context * cpA,struct bbf_Scanner * ptrA,const struct bbf_Scanner * srcPtrA)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 
bbf_Scanner_equal(struct bbs_Context * cpA,const struct bbf_Scanner * ptrA,const struct bbf_Scanner * srcPtrA)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 
bbf_Scanner_positions(const struct bbf_Scanner * ptrA)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 
bbf_Scanner_scanIndex(const struct bbf_Scanner * ptrA)582 uint32 bbf_Scanner_scanIndex( const struct bbf_Scanner* ptrA )
583 {
584 	return ptrA->yE * ptrA->currentWidthE + ptrA->xE;
585 }
586 
587 /* ------------------------------------------------------------------------- */
588 
bbf_Scanner_pos(const struct bbf_Scanner * ptrA,int32 * xPtrA,int32 * yPtrA,uint32 * scalePtrA)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 
bbf_Scanner_idxPos(const struct bbf_Scanner * ptrA,uint32 scanIndexA,int32 * xPtrA,int32 * yPtrA,uint32 * scalePtrA)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 
bbf_Scanner_create(struct bbs_Context * cpA,struct bbf_Scanner * ptrA,flag maximizeSharedMemoryA,uint32 maxImageWidthA,uint32 maxImageHeightA,uint32 maxRadiusA,uint32 patchWidthA,uint32 patchHeightA,uint32 minScaleA,uint32 maxScaleA,uint32 scaleStepA,uint32 borderWidthA,uint32 borderHeightA,uint32 bufferSizeA,struct bbs_MemTbl * mtpA)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 
bbf_Scanner_bitParam(struct bbs_Context * cpA,struct bbf_Scanner * ptrA,const struct bbf_BitParam * bitParamPtrA)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 
bbf_Scanner_memSize(struct bbs_Context * cpA,const struct bbf_Scanner * ptrA)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 
bbf_Scanner_memWrite(struct bbs_Context * cpA,const struct bbf_Scanner * ptrA,uint16 * memPtrA)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 
bbf_Scanner_memRead(struct bbs_Context * cpA,struct bbf_Scanner * ptrA,const uint16 * memPtrA,struct bbs_MemTbl * mtpA)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 
bbf_Scanner_resetScan(struct bbs_Context * cpA,struct bbf_Scanner * ptrA)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 
bbf_Scanner_assign(struct bbs_Context * cpA,struct bbf_Scanner * ptrA,const void * imagePtrA,uint32 imageWidthA,uint32 imageHeightA,const struct bts_Int16Rect * roiPtrA,const struct bbf_BitParam * paramPtrA)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 
bbf_Scanner_nextScale(struct bbs_Context * cpA,struct bbf_Scanner * ptrA)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 
bbf_Scanner_getPatch(const struct bbf_Scanner * ptrA)835 const uint32* bbf_Scanner_getPatch( const struct bbf_Scanner* ptrA )
836 {
837 	return ptrA->patchBufferE.arrPtrE + ptrA->xE;
838 }
839 
840 /* ------------------------------------------------------------------------- */
841 
bbf_Scanner_next(struct bbs_Context * cpA,struct bbf_Scanner * ptrA)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 
bbf_Scanner_goToXY(struct bbs_Context * cpA,struct bbf_Scanner * ptrA,int32 xA,int32 yA)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 
bbf_Scanner_goToIndex(struct bbs_Context * cpA,struct bbf_Scanner * ptrA,uint32 scanIndexA)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 
bbf_Scanner_goToUls(struct bbs_Context * cpA,struct bbf_Scanner * ptrA,int32 xA,int32 yA,uint32 scaleA)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 */
bbf_Scanner_resetOutPos(struct bbs_Context * cpA,struct bbf_Scanner * ptrA)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 */
bbf_Scanner_resetIntPos(struct bbs_Context * cpA,struct bbf_Scanner * ptrA)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 */
bbf_Scanner_addIntPos(struct bbs_Context * cpA,struct bbf_Scanner * ptrA,uint32 idxA,int32 actA)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 */
bbf_Scanner_addOutPos(struct bbs_Context * cpA,struct bbf_Scanner * ptrA,int32 xA,int32 yA,uint32 scaleA,int32 actA)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 */
bbf_Scanner_removeOutOverlaps(struct bbs_Context * cpA,struct bbf_Scanner * ptrA,uint32 overlapThrA)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 */
bbf_Scanner_removeIntOverlaps(struct bbs_Context * cpA,struct bbf_Scanner * ptrA,uint32 overlapThrA)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