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