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 */
bbf_LocalScanner_alloc(struct bbs_Context * cpA,struct bbf_LocalScanner * ptrA,struct bbs_MemTbl * mtpA)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 */
bbf_LocalScanner_downscale0(struct bbs_Context * cpA,struct bbf_LocalScanner * ptrA)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 */
bbf_LocalScanner_downscale1(struct bbs_Context * cpA,struct bbf_LocalScanner * ptrA)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 */
bbf_LocalScanner_downscale(struct bbs_Context * cpA,struct bbf_LocalScanner * ptrA)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 */
bbf_LocalScanner_createBitImage(struct bbs_Context * cpA,struct bbf_LocalScanner * ptrA)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 */
bbf_LocalScanner_initPatchBuffer(struct bbs_Context * cpA,struct bbf_LocalScanner * ptrA)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 */
bbf_LocalScanner_setWorkScanRegion(struct bbs_Context * cpA,struct bbf_LocalScanner * ptrA)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 
bbf_LocalScanner_init(struct bbs_Context * cpA,struct bbf_LocalScanner * ptrA)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 
bbf_LocalScanner_exit(struct bbs_Context * cpA,struct bbf_LocalScanner * ptrA)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 
bbf_LocalScanner_copy(struct bbs_Context * cpA,struct bbf_LocalScanner * ptrA,const struct bbf_LocalScanner * srcPtrA)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 
bbf_LocalScanner_equal(struct bbs_Context * cpA,const struct bbf_LocalScanner * ptrA,const struct bbf_LocalScanner * srcPtrA)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 
bbf_LocalScanner_positions(const struct bbf_LocalScanner * ptrA)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 
bbf_LocalScanner_scanIndex(const struct bbf_LocalScanner * ptrA)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 
bbf_LocalScanner_pos(const struct bbf_LocalScanner * ptrA,int32 * xPtrA,int32 * yPtrA)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 
bbf_LocalScanner_idxPos(const struct bbf_LocalScanner * ptrA,uint32 scanIndexA,int32 * xPtrA,int32 * yPtrA)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 
bbf_LocalScanner_create(struct bbs_Context * cpA,struct bbf_LocalScanner * ptrA,uint32 patchWidthA,uint32 patchHeightA,uint32 scaleExpA,uint32 maxImageWidthA,uint32 maxImageHeightA,uint32 minScaleExpA,uint32 maxRadiusA,struct bbs_MemTbl * mtpA)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 
bbf_LocalScanner_bitParam(struct bbs_Context * cpA,struct bbf_LocalScanner * ptrA,const struct bbf_BitParam * bitParamPtrA)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 
bbf_LocalScanner_origScanRegion(struct bbs_Context * cpA,struct bbf_LocalScanner * ptrA,const struct bts_Int16Rect * scanRegionPtrA)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 
bbf_LocalScanner_memSize(struct bbs_Context * cpA,const struct bbf_LocalScanner * ptrA)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 
bbf_LocalScanner_memWrite(struct bbs_Context * cpA,const struct bbf_LocalScanner * ptrA,uint16 * memPtrA)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 
bbf_LocalScanner_memRead(struct bbs_Context * cpA,struct bbf_LocalScanner * ptrA,const uint16 * memPtrA,struct bbs_MemTbl * mtpA)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 
bbf_LocalScanner_resetScan(struct bbs_Context * cpA,struct bbf_LocalScanner * ptrA)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 
bbf_LocalScanner_assign(struct bbs_Context * cpA,struct bbf_LocalScanner * ptrA,const uint8 * imagePtrA,uint32 imageWidthA,uint32 imageHeightA,const struct bbf_BitParam * paramPtrA)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 
bbf_LocalScanner_getPatch(const struct bbf_LocalScanner * ptrA)669 const uint32* bbf_LocalScanner_getPatch( const struct bbf_LocalScanner* ptrA )
670 {
671 	return ptrA->patchBufferE.arrPtrE + ptrA->xE;
672 }
673 
674 /* ------------------------------------------------------------------------- */
675 
bbf_LocalScanner_next(struct bbs_Context * cpA,struct bbf_LocalScanner * ptrA)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 
bbf_LocalScanner_goToXY(struct bbs_Context * cpA,struct bbf_LocalScanner * ptrA,int32 xA,int32 yA)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 
bbf_LocalScanner_goToIndex(struct bbs_Context * cpA,struct bbf_LocalScanner * ptrA,uint32 scanIndexA)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 
bbf_LocalScanner_nextOffset(struct bbs_Context * cpA,struct bbf_LocalScanner * ptrA)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