auto import from //depot/cupcake/@135843
[android/platform/external/neven.git] / Embedded / common / src / b_BitFeatureEm / Scanner.c
1 /*
2  * Copyright (C) 2008 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 /* ---- includes ----------------------------------------------------------- */
18
19 #include "b_BasicEm/Functions.h"
20 #include "b_BasicEm/Math.h"
21 #include "b_BitFeatureEm/Scanner.h"
22
23 /* ------------------------------------------------------------------------- */
24
25 /* ========================================================================= */
26 /*                                                                           */
27 /* ---- \ghd{ auxiliary functions } ---------------------------------------- */
28 /*                                                                           */
29 /* ========================================================================= */
30
31 /* ------------------------------------------------------------------------- */
32
33 /** multiplies a scale with a 0.32 scale factor */
34 uint32 bbf_Scanner_scalePrd( uint32 scaleA, uint32 factorA /*0.32 */ )\
35 {
36         return      ( scaleA >> 16     ) * ( factorA >> 16     ) + 
37                         ( ( ( scaleA & 0x0FFFF ) * ( factorA >> 16     ) ) >> 16 ) +
38                         ( ( ( scaleA >> 16     ) * ( factorA & 0x0FFFF ) ) >> 16 );
39 }
40
41 /* ------------------------------------------------------------------------- */
42
43 /** allocates arays */
44 void bbf_Scanner_alloc( struct bbs_Context* cpA,
45                                                 struct bbf_Scanner* ptrA, 
46                                                 struct bbs_MemTbl* mtpA,
47                                                 flag maximizeSharedMemoryA )
48 {
49         struct bbs_MemTbl memTblL = *mtpA;
50         struct bbs_MemSeg* espL = bbs_MemTbl_segPtr( cpA, &memTblL, 0 );
51         struct bbs_MemSeg* sspL = bbs_MemTbl_sharedSegPtr( cpA, &memTblL, 0 );
52         struct bbs_MemSeg* mspL = maximizeSharedMemoryA ? sspL : espL;
53
54         /* filter patch dimension */
55         uint32 proL = ptrA->maxRadiusE;
56         uint32 pwoL = ( proL << 1 ) + 1;
57
58         /* output image size (bit image) */
59         uint32 woL = ptrA->maxImageWidthE;
60         uint32 hoL = ptrA->maxImageHeightE;
61
62         /* extended output image size (bit image) considering borders */
63         uint32 xwoL = woL + ( ptrA->borderWidthE  << 1 );
64         uint32 xhoL = hoL + ( ptrA->borderHeightE << 1 );
65
66         /* allocate working image */
67         bbs_UInt16Arr_create( cpA, &ptrA->workImageE, ( ( woL >> 1 ) + ( woL & 1 ) ) * hoL, mspL );
68         if( bbs_Context_error( cpA ) ) return;
69         bbs_UInt16Arr_fill( cpA, &ptrA->workImageE, 0 );
70
71         /* allocate bit image */
72         bim_UInt32Image_create( cpA, &ptrA->bitImageE, xwoL, ( xhoL >> 5 ) + ( ( ( xhoL & 0x1F ) != 0 ) ? 1 : 0 ), mspL );
73         if( bbs_Context_error( cpA ) ) return;
74         bim_UInt32Image_setAllPixels( cpA, &ptrA->bitImageE, 0, 0 );
75
76         /* allocate patch buffer */
77         bbs_UInt32Arr_create( cpA, &ptrA->patchBufferE, ptrA->bitImageE.widthE, mspL );
78         if( bbs_Context_error( cpA ) ) return;
79         bbs_UInt32Arr_fill( cpA, &ptrA->patchBufferE, 0 );
80
81         /* allocate line buffer */
82         bbs_UInt16Arr_create( cpA, &ptrA->lineBufE, woL + ( woL & 1 ), sspL );
83
84         /* allocate table */
85         bim_UInt32Image_create( cpA, &ptrA->satE, woL + pwoL, pwoL + 1, sspL );
86
87         /* allocate buffers */
88         bbs_UInt32Arr_create( cpA, &ptrA->idxArrE, ptrA->bufferSizeE, mspL );
89         bbs_Int32Arr_create(  cpA, &ptrA->actArrE, ptrA->bufferSizeE, mspL );
90
91         bbs_Int32Arr_create(  cpA, &ptrA->outArrE, ptrA->bufferSizeE >> 1, espL );
92 }
93
94 /* ------------------------------------------------------------------------- */
95
96 /** downscales work image */
97 void bbf_Scanner_downscale( struct bbs_Context* cpA, struct bbf_Scanner* ptrA )
98 {
99         uint32 w0L = ptrA->workWidthE;
100         uint32 h0L = ptrA->workHeightE;
101         uint32 w1L = w0L >> 1;
102         uint32 h1L = h0L >> 1;
103         uint32 w20L = ( w0L >> 1 ) + ( w0L & 1 );
104         uint16* arrL = ptrA->workImageE.arrPtrE;
105
106         uint32 iL, jL;
107         uint32 kL = 0;
108         for( jL = 0; jL < h1L; jL++ )
109         {
110                 for( iL = 0; iL < ( w1L >> 1 ); iL++ )
111                 {
112                         uint16 loL, hiL;
113                         uint32 idxL = jL * 2 * w20L + iL * 2;
114
115                         loL = ( ( arrL[ idxL ] & 0x00FF ) + ( arrL[ idxL ] >> 8 ) + ( arrL[ idxL + w20L ] & 0x00FF ) + ( arrL[ idxL + w20L ] >> 8 ) + 2 ) >> 2;
116                         idxL++;
117                         hiL = ( ( arrL[ idxL ] & 0x00FF ) + ( arrL[ idxL ] >> 8 ) + ( arrL[ idxL + w20L ] & 0x00FF ) + ( arrL[ idxL + w20L ] >> 8 ) + 2 ) >> 2;
118
119                         arrL[ kL ] = loL | ( hiL << 8 );
120                         kL++;
121                 }
122                 if( ( w1L & 1 ) != 0 )
123                 {
124                         uint32 idxL = jL * 2 * w20L + iL;
125                         arrL[ kL++ ] = ( ( arrL[ idxL ] & 0x00FF ) + ( arrL[ idxL ] >> 8 ) + ( arrL[ idxL + w20L ] & 0x00FF ) + ( arrL[ idxL + w20L ] >> 8 ) + 2 ) >> 2;
126                 }
127         }
128
129         ptrA->workWidthE = w1L;
130         ptrA->workHeightE = h1L;
131         ptrA->scaleExpE++;
132 }
133
134 /* ------------------------------------------------------------------------- */
135
136 /** copies image
137  * handling for 8 bit images is implemented 
138  * 16 bit image handling for the whole class needs to be added in this function only
139  */
140 void bbf_Scanner_copyImage( struct bbs_Context* cpA, struct bbf_Scanner* ptrA, const void* imagePtrA, uint32 imageWidthA, uint32 imageHeightA, const struct bts_Int16Rect* roiPtrA )
141 {
142         bbs_DEF_fNameL( "void bbf_Scanner_copyImage( struct bbs_Context* cpA, struct bbf_Scanner* ptrA, const struct bim_UInt16ByteImage* imagePtrA, const struct bts_Int16Rect* roiPtrA )" )
143
144         if( imageWidthA > ptrA->maxImageWidthE || imageHeightA > ptrA->maxImageHeightE ) 
145         {
146                 bbs_ERROR5( "%s:\n Input image (%ix%i)is too large; Scanner is configured for maximal (%ix%i)", 
147                         fNameL, imageWidthA, imageHeightA, ptrA->maxImageWidthE, ptrA->maxImageHeightE );
148                 return;
149         }
150
151         if( roiPtrA == 0 )
152         {
153                 uint32 iL, jL;
154                 const uint8*  srcL = ( uint8* )imagePtrA;
155                 uint16* dstL = ptrA->workImageE.arrPtrE;
156                 ptrA->workWidthE  = imageWidthA;
157                 ptrA->workHeightE = imageHeightA;
158                 for( iL = 0; iL < ptrA->workHeightE; iL++ )
159                 {
160                         for( jL = ptrA->workWidthE >> 1; jL > 0; jL-- )
161                         {
162                                 *dstL++ = ( uint16 )srcL[ 0 ] | ( uint16 )srcL[ 1 ] << 8;
163                                 srcL += 2;
164                         }
165
166                         /* uneven width */
167                         if( ptrA->workWidthE & 1 ) *dstL++ = *srcL++;
168                 }
169         }
170         else
171         {
172                 uint32 iL, jL;
173                 const uint8* srcL = ( uint8* )imagePtrA + roiPtrA->y1E * imageWidthA + roiPtrA->x1E;
174                 uint16* dstL = ptrA->workImageE.arrPtrE;
175
176                 if( roiPtrA->x2E <= roiPtrA->x1E || roiPtrA->y2E <= roiPtrA->y1E )
177                 {
178                         bbs_ERROR1( "%s:\n ROI is invalid or zero", fNameL );
179                         return;
180                 }
181                 if( roiPtrA->x1E < 0 || roiPtrA->y1E < 0 || roiPtrA->x2E > ( int32 )imageWidthA || roiPtrA->y2E > ( int32 )imageHeightA )
182                 {
183                         bbs_ERROR1( "%s:\n ROI exceeds image boundary", fNameL );
184                         return;
185                 }
186
187                 ptrA->workWidthE  = roiPtrA->x2E - roiPtrA->x1E;
188                 ptrA->workHeightE = roiPtrA->y2E - roiPtrA->y1E;
189                 for( iL = 0; iL < ptrA->workHeightE; iL++ )
190                 {
191                         for( jL = ptrA->workWidthE >> 1; jL > 0; jL-- )
192                         {
193                                 *dstL++ = ( uint16 )srcL[ 0 ] | ( uint16 )srcL[ 1 ] << 8;
194                                 srcL += 2;
195                         }
196
197                         /* uneven width */
198                         if( ptrA->workWidthE & 1 ) *dstL++ = *srcL++;
199
200                         srcL += imageWidthA - ptrA->workWidthE;
201                 }
202         }
203 }
204
205 /* ------------------------------------------------------------------------- */
206
207 /** creates bit image */
208 void bbf_Scanner_createBitImage( struct bbs_Context* cpA, struct bbf_Scanner* ptrA )
209 {
210         bbs_DEF_fNameL( "void bbf_Scanner_createBitImage( struct bbs_Context* cpA, struct bbf_Scanner* ptrA )" )
211
212
213         /* declarations */
214         uint32 proL, priL, pwoL, pwiL;
215         uint32 wiL, wi2L, hiL, woL, hoL, xwoL, xhoL; /* image size specifies */
216         uint32 stepL;    /* scan step (16.16) */
217         uint32 bitMaskL; /* current bit mask */
218         uint32* bitRowL; /* pointer to bit-row */
219         uint32 wsL, hsL; /* size of summed area table (ringbuffer) */
220         uint32 satSizeL; 
221         uint32* satL;     /* pointer to summed area table */
222         uint16* lBufL;    /* pointer to line buffer */
223         uint32 yfL;       /* fixed point y-coordinate (16.16) */
224         uint32 iL, jL;
225
226         uint32 swi1L; /* table writing index */
227         uint32 swi2L; /* table writing index */
228         uint32 sriL;  /* table reading index */
229
230         uint32 poAreaL, piAreaL; /* areas of inner and outer rectangles */
231         uint32 siL[ 8 ]; /* table indices */
232
233
234         proL = ptrA->bitParamE.outerRadiusE;
235         priL = ptrA->bitParamE.innerRadiusE;
236         pwoL = ( proL << 1 ) + 1;
237         pwiL = ( priL << 1 ) + 1;
238
239         if( ptrA->borderHeightE >= 32 )
240         {
241                 bbs_ERROR1( "%s:\n borderHeightE >= 32", fNameL );
242                 return;
243         }
244
245         if( proL <= priL )
246         {
247                 bbs_ERROR1( "%s:\n outer radius <= inner radius", fNameL );
248                 return;
249         }
250
251         /* input image size (bit image) */
252         wiL = ptrA->workWidthE;
253         hiL = ptrA->workHeightE;
254         wi2L = ( wiL >> 1 ) + ( wiL & 1 );
255
256         /* 16.16 */
257         stepL = ptrA->scaleE >> ( ptrA->scaleExpE + 4 );
258
259         /* output image size (bit image) */
260         woL = ( wiL << 16 ) / stepL;
261         hoL = ( hiL << 16 ) / stepL;
262
263         if( woL <= pwoL || hoL <= pwoL )
264         {
265                 bbs_ERROR1( "%s:\n scaled image is too small", fNameL );
266                 return;
267         }
268
269         if( woL * stepL >= ( wiL << 16 ) ) woL--;
270         if( hoL * stepL >= ( hiL << 16 ) ) hoL--;
271
272         /* extended output image size (bit image) considering borders */
273         xwoL = woL + ( ptrA->borderWidthE  << 1 );
274         xhoL = hoL + ( ptrA->borderHeightE << 1 );
275
276         ptrA->currentWidthE  = xwoL;
277         ptrA->currentHeightE = xhoL;
278
279         /* initialize bit image */
280         bim_UInt32Image_size( cpA, &ptrA->bitImageE, xwoL, ( xhoL >> 5 ) + ( ( ( xhoL & 0x1F ) != 0 ) ? 1 : 0 ) );
281         bim_UInt32Image_setAllPixels( cpA, &ptrA->bitImageE, 0, 0 );
282
283         bitMaskL = ( uint32 )1 << ptrA->borderHeightE;
284         bitRowL = ( uint32* )ptrA->bitImageE.arrE.arrPtrE + ptrA->borderWidthE;
285
286         /* width of table */
287         wsL = woL + pwoL;
288
289         /* height of table */
290         hsL = pwoL + 1;
291
292         bim_UInt32Image_size( cpA, &ptrA->satE, wsL, hsL );
293
294         satL = ptrA->satE.arrE.arrPtrE;
295         satSizeL = wsL * hsL;
296
297         lBufL = ptrA->lineBufE.arrPtrE;
298
299         yfL = 0; /* fixed point y-coordinate ( 16.16 )*/
300
301         swi1L = 0; /* table writing index */
302         swi2L = 0; /* table writing index */
303         sriL = 0;  /* table reading index */
304
305         /* areas of inner and outer rectangles */
306         poAreaL = pwoL * pwoL;
307         piAreaL = pwiL * pwiL;
308
309         /* interpolate pixels; compute table and bit image */
310
311         for( iL = wsL * ( proL + 1 ); iL > 0; iL-- ) satL[ swi1L++ ] = 0;
312         swi2L = swi1L - wsL;
313
314         for( jL = 0; jL < hoL + proL; jL++ )
315         {
316                 if( jL < hoL ) /* rescale area */
317                 {
318                         uint32 ypL = ( yfL >> 16 );
319                         uint32 yoff1L = yfL & 0x0FFFF;
320                         uint32 yoff0L = 0x010000 - yoff1L;
321                         const uint16* arr0L = ptrA->workImageE.arrPtrE + ypL * wi2L;
322                         const uint16* arr1L = arr0L + wi2L;
323
324                         
325                         uint32 xfL   = 0; /* fixed point x-coordinate (16.16) */
326                         uint32 hSumL = 0;
327
328                         yfL += stepL;
329
330                         for( iL = 0; iL <= proL; iL++ ) satL[ swi1L++ ] = 0;
331                         swi2L += iL;
332
333                         /* fill line buffer */
334                         for( iL = 0; iL < wi2L; iL++ )
335                         {
336                                 lBufL[ iL * 2     ] = ( ( ( arr0L[ iL ] & 0x0FF ) * yoff0L ) + ( ( arr1L[ iL ] & 0x0FF ) * yoff1L ) ) >> 10;
337                                 lBufL[ iL * 2 + 1 ] = ( ( ( arr0L[ iL ] >> 8    ) * yoff0L ) + ( ( arr1L[ iL ] >> 8    ) * yoff1L ) ) >> 10;
338                         }
339
340                         for( iL = 0; iL < woL; iL++ )
341                         {
342                                 uint32 xpL = ( xfL >> 16 );
343                                 uint32 xoff1L = xfL & 0x0FFFF;
344                                 uint16 pixL = ( lBufL[ xpL ] * ( 0x010000 - xoff1L ) + lBufL[ xpL + 1 ] * xoff1L ) >> 22;
345                                 satL[ swi1L ] = ( hSumL += pixL ) + satL[ swi2L ];
346                                 xfL += stepL;
347                                 swi1L++;
348                                 swi2L++;
349                         }
350
351                         for( iL = 0; iL < proL; iL++ )
352                         {
353                                 satL[ swi1L ] = hSumL + satL[ swi2L ];
354                                 swi1L++;
355                                 swi2L++;
356                         }
357                 }
358                 else /* image is processed - fill in 0s */
359                 {
360                         for( iL = 0; iL < wsL; iL++ ) satL[ swi1L++ ] = satL[ swi2L++ ];
361                 }
362
363                 swi1L = ( swi1L < satSizeL ) ? swi1L : 0;
364                 swi2L = ( swi2L < satSizeL ) ? swi2L : 0;
365
366                 /* fill line in bit image */
367                 if( jL >= proL ) 
368                 {
369                         const uint32* rSatL = satL;
370
371                         /* table coordinate indices for outer rectangle */
372                         siL[ 0 ] = sriL;
373                         siL[ 1 ] = siL[ 0 ] + pwoL;
374                         siL[ 2 ] = siL[ 0 ] + pwoL * wsL;
375                         siL[ 2 ] -= ( siL[ 2 ] >= satSizeL ) ? satSizeL : 0;
376                         siL[ 3 ] = siL[ 2 ] + pwoL;
377
378                         /* table coordinate indices for inner rectangle */
379                         siL[ 4 ] = siL[ 0 ] + ( proL - priL ) * wsL + ( proL - priL );
380                         siL[ 4 ] -= ( siL[ 4 ] >= satSizeL ) ? satSizeL : 0;
381                         siL[ 5 ] = siL[ 4 ] + pwiL;
382                         siL[ 6 ] = siL[ 4 ] + pwiL * wsL;
383                         siL[ 6 ] -= ( siL[ 6 ] >= satSizeL ) ? satSizeL : 0;
384                         siL[ 7 ] = siL[ 6 ] + pwiL;
385                         sriL += wsL;
386                         if( sriL == satSizeL ) sriL = 0;
387
388                         for( iL = 0; iL < woL; iL++ )
389                         {
390                                 uint32 oAvgL = ( rSatL[ siL[ 0 ] ] - rSatL[ siL[ 1 ] ] - rSatL[ siL[ 2 ] ] + rSatL[ siL[ 3 ] ] ) * piAreaL;
391                                 uint32 iAvgL = ( rSatL[ siL[ 4 ] ] - rSatL[ siL[ 5 ] ] - rSatL[ siL[ 6 ] ] + rSatL[ siL[ 7 ] ] ) * poAreaL;
392                                 bitRowL[ iL ] |= ( iAvgL > oAvgL ) ? bitMaskL : 0;
393                                 rSatL++;
394                         }
395                         if( ( bitMaskL <<= 1 ) == 0 )
396                         {
397                                 bitRowL += xwoL;
398                                 bitMaskL = 1;
399                         }
400                 }
401         }
402 }
403
404 /* ------------------------------------------------------------------------- */
405
406 /** initialize patch buffer */
407 void bbf_Scanner_initPatchBuffer( struct bbs_Context* cpA, struct bbf_Scanner* ptrA )
408 {
409         bbs_UInt32Arr_size( cpA, &ptrA->patchBufferE, ptrA->bitImageE.widthE ); 
410         bbs_memcpy32( ptrA->patchBufferE.arrPtrE, ptrA->bitImageE.arrE.arrPtrE, ptrA->bitImageE.widthE );
411 }
412
413 /* ------------------------------------------------------------------------- */
414
415 /* ========================================================================= */
416 /*                                                                           */
417 /* ---- \ghd{ constructor / destructor } ----------------------------------- */
418 /*                                                                           */
419 /* ========================================================================= */
420
421 /* ------------------------------------------------------------------------- */
422
423 void bbf_Scanner_init( struct bbs_Context* cpA,
424                                            struct bbf_Scanner* ptrA )
425 {
426         ptrA->scaleExpE = 0;
427         ptrA->scaleE = 0;
428         ptrA->xE = 0;
429         ptrA->yE = 0;
430         ptrA->effMaxScaleE = 0;
431         ptrA->currentWidthE = 0;
432         ptrA->currentHeightE = 0;
433         ptrA->workWidthE = 0;
434         ptrA->workHeightE = 0;
435         bbf_BitParam_init( cpA, &ptrA->bitParamE );
436         bbs_UInt16Arr_init( cpA, &ptrA->workImageE );
437         bim_UInt32Image_init( cpA, &ptrA->satE );
438         bim_UInt32Image_init( cpA, &ptrA->bitImageE );
439         bbs_UInt32Arr_init( cpA, &ptrA->patchBufferE );
440         bbs_UInt16Arr_init( cpA, &ptrA->lineBufE );
441
442         bbs_UInt32Arr_init( cpA, &ptrA->idxArrE );
443         bbs_Int32Arr_init( cpA, &ptrA->actArrE );
444         bbs_Int32Arr_init( cpA, &ptrA->outArrE );
445         ptrA->outCountE = 0;
446         ptrA->intCountE = 0;
447         ptrA->bufferSizeE = 1024;
448
449         ptrA->maxImageWidthE = 0;
450         ptrA->maxImageHeightE = 0;
451         ptrA->maxRadiusE = 0;
452         ptrA->patchWidthE = 0;
453         ptrA->patchHeightE = 0;
454         ptrA->minScaleE = 0;
455         ptrA->maxScaleE = 0;
456         ptrA->scaleStepE = 0;
457         ptrA->borderWidthE = 0;
458         ptrA->borderHeightE = 0;
459 }
460
461 /* ------------------------------------------------------------------------- */
462
463 void bbf_Scanner_exit( struct bbs_Context* cpA,
464                                        struct bbf_Scanner* ptrA )
465 {
466         ptrA->scaleExpE = 0;
467         ptrA->scaleE = 0;
468         ptrA->xE = 0;
469         ptrA->yE = 0;
470         ptrA->effMaxScaleE = 0;
471         ptrA->currentWidthE = 0;
472         ptrA->currentHeightE = 0;
473         ptrA->workWidthE = 0;
474         ptrA->workHeightE = 0;
475         bbf_BitParam_exit( cpA, &ptrA->bitParamE );
476         bbs_UInt16Arr_exit( cpA, &ptrA->workImageE );
477         bim_UInt32Image_exit( cpA, &ptrA->satE );
478         bim_UInt32Image_exit( cpA, &ptrA->bitImageE );
479         bbs_UInt32Arr_exit( cpA, &ptrA->patchBufferE );
480         bbs_UInt16Arr_exit( cpA, &ptrA->lineBufE );
481
482         bbs_UInt32Arr_exit( cpA, &ptrA->idxArrE );
483         bbs_Int32Arr_exit( cpA, &ptrA->actArrE );
484         bbs_Int32Arr_exit( cpA, &ptrA->outArrE );
485         ptrA->outCountE = 0;
486         ptrA->intCountE = 0;
487         ptrA->bufferSizeE = 1024;
488
489         ptrA->maxImageWidthE = 0;
490         ptrA->maxImageHeightE = 0;
491         ptrA->maxRadiusE = 0;
492         ptrA->patchWidthE = 0;
493         ptrA->patchHeightE = 0;
494         ptrA->minScaleE = 0;
495         ptrA->maxScaleE = 0;
496         ptrA->scaleStepE = 0;
497         ptrA->borderWidthE = 0;
498         ptrA->borderHeightE = 0;
499 }
500
501 /* ------------------------------------------------------------------------- */
502
503 /* ========================================================================= */
504 /*                                                                           */
505 /* ---- \ghd{ operators } -------------------------------------------------- */
506 /*                                                                           */
507 /* ========================================================================= */
508
509 /* ------------------------------------------------------------------------- */
510
511 void bbf_Scanner_copy( struct bbs_Context* cpA,
512                                        struct bbf_Scanner* ptrA, 
513                                            const struct bbf_Scanner* srcPtrA )
514 {
515         ptrA->scaleExpE = srcPtrA->scaleExpE;
516         ptrA->scaleE = srcPtrA->scaleE;
517         ptrA->xE = srcPtrA->xE;
518         ptrA->yE = srcPtrA->yE;
519         ptrA->effMaxScaleE = srcPtrA->effMaxScaleE;
520         ptrA->currentWidthE = srcPtrA->currentWidthE;
521         ptrA->currentHeightE = srcPtrA->currentHeightE;
522         ptrA->workWidthE = srcPtrA->workWidthE;
523         ptrA->workHeightE = srcPtrA->workHeightE;
524
525         bbf_BitParam_copy( cpA, &ptrA->bitParamE, &srcPtrA->bitParamE );
526         bbs_UInt16Arr_copy( cpA, &ptrA->workImageE, &srcPtrA->workImageE );
527         bim_UInt32Image_copy( cpA, &ptrA->satE, &srcPtrA->satE );
528         bim_UInt32Image_copy( cpA, &ptrA->bitImageE, &srcPtrA->bitImageE );
529         bbs_UInt32Arr_copy( cpA, &ptrA->patchBufferE, &srcPtrA->patchBufferE );
530         bbs_UInt16Arr_copy( cpA, &ptrA->lineBufE, &srcPtrA->lineBufE );
531
532         ptrA->maxImageWidthE = srcPtrA->maxImageWidthE;
533         ptrA->maxImageHeightE = srcPtrA->maxImageHeightE;
534         ptrA->maxRadiusE = srcPtrA->maxRadiusE;
535         ptrA->patchWidthE = srcPtrA->patchWidthE;
536         ptrA->patchHeightE = srcPtrA->patchHeightE;
537         ptrA->minScaleE = srcPtrA->minScaleE;
538         ptrA->maxScaleE = srcPtrA->maxScaleE;
539         ptrA->scaleStepE = srcPtrA->scaleStepE;
540         ptrA->borderWidthE = srcPtrA->borderWidthE;
541         ptrA->borderHeightE = srcPtrA->borderHeightE;
542 }
543
544 /* ------------------------------------------------------------------------- */
545
546 flag bbf_Scanner_equal( struct bbs_Context* cpA,
547                                         const struct bbf_Scanner* ptrA, 
548                                                 const struct bbf_Scanner* srcPtrA )
549 {
550         if( ptrA->maxImageWidthE != srcPtrA->maxImageWidthE ) return FALSE;
551         if( ptrA->maxImageHeightE != srcPtrA->maxImageHeightE ) return FALSE;
552         if( ptrA->maxRadiusE != srcPtrA->maxRadiusE ) return FALSE;
553         if( ptrA->patchWidthE != srcPtrA->patchWidthE ) return FALSE;
554         if( ptrA->patchHeightE != srcPtrA->patchHeightE ) return FALSE;
555         if( ptrA->minScaleE != srcPtrA->minScaleE ) return FALSE;
556         if( ptrA->maxScaleE != srcPtrA->maxScaleE ) return FALSE;
557         if( ptrA->scaleStepE != srcPtrA->scaleStepE ) return FALSE;
558         if( ptrA->borderWidthE != srcPtrA->borderWidthE ) return FALSE;
559         if( ptrA->borderHeightE != srcPtrA->borderHeightE ) return FALSE;
560         return TRUE;
561 }
562
563 /* ------------------------------------------------------------------------- */
564
565 /* ========================================================================= */
566 /*                                                                           */
567 /* ---- \ghd{ query functions } -------------------------------------------- */
568 /*                                                                           */
569 /* ========================================================================= */
570
571 /* ------------------------------------------------------------------------- */
572
573 uint32 bbf_Scanner_positions( const struct bbf_Scanner* ptrA )
574 {
575         int32 wL = ( int32 )ptrA->currentWidthE - ptrA->patchWidthE;
576         int32 hL = ( int32 )ptrA->currentHeightE - ptrA->patchHeightE;
577         return ( wL >= 0 ? wL : 0 ) * ( hL >= 0 ? hL : 0 );
578 }
579
580 /* ------------------------------------------------------------------------- */
581
582 uint32 bbf_Scanner_scanIndex( const struct bbf_Scanner* ptrA )
583 {
584         return ptrA->yE * ptrA->currentWidthE + ptrA->xE;
585 }
586
587 /* ------------------------------------------------------------------------- */
588
589 void bbf_Scanner_pos( const struct bbf_Scanner* ptrA, 
590                                           int32* xPtrA, int32* yPtrA, uint32* scalePtrA )
591 {
592         /* 16.16 */
593         *xPtrA = ( int32 )( ptrA->xE - ptrA->borderWidthE ) * ( int32 )( ptrA->scaleE >> 4 );
594
595         /* 16.16 */
596         *yPtrA = ( int32 )( ptrA->yE - ptrA->borderHeightE ) * ( int32 )( ptrA->scaleE >> 4 );
597
598         /* 12.20 */
599         *scalePtrA = ptrA->scaleE;
600 }
601
602 /* ------------------------------------------------------------------------- */
603
604 void bbf_Scanner_idxPos( const struct bbf_Scanner* ptrA, uint32 scanIndexA,
605                                              int32* xPtrA, int32* yPtrA, uint32* scalePtrA )
606 {
607         int32 yL = scanIndexA / ptrA->currentWidthE;
608         int32 xL = scanIndexA - ( yL * ptrA->currentWidthE );
609
610         /* 16.16 */
611         *xPtrA = ( int32 )( xL - ptrA->borderWidthE  ) * ( int32 )( ptrA->scaleE >> 4 );
612
613         /* 16.16 */
614         *yPtrA = ( int32 )( yL - ptrA->borderHeightE ) * ( int32 )( ptrA->scaleE >> 4 );
615
616         *scalePtrA = ptrA->scaleE;
617 }
618
619 /* ------------------------------------------------------------------------- */
620
621 /* ========================================================================= */
622 /*                                                                           */
623 /* ---- \ghd{ modify functions } ------------------------------------------- */
624 /*                                                                           */
625 /* ========================================================================= */
626
627 /* ------------------------------------------------------------------------- */
628         
629 void bbf_Scanner_create( struct bbs_Context* cpA,
630                                                  struct bbf_Scanner* ptrA, 
631                                                  flag maximizeSharedMemoryA,
632                                                  uint32 maxImageWidthA,
633                                                  uint32 maxImageHeightA,
634                                                  uint32 maxRadiusA,
635                                                  uint32 patchWidthA,
636                                                  uint32 patchHeightA,
637                                                  uint32 minScaleA,
638                                                  uint32 maxScaleA,
639                                                  uint32 scaleStepA,
640                                                  uint32 borderWidthA,
641                                                  uint32 borderHeightA,
642                                                  uint32 bufferSizeA,
643                                                  struct bbs_MemTbl* mtpA )
644 {
645         ptrA->maxImageWidthE = maxImageWidthA;
646         ptrA->maxImageHeightE = maxImageHeightA;
647         ptrA->maxRadiusE = maxRadiusA;
648         ptrA->patchWidthE = patchWidthA;
649         ptrA->patchHeightE = patchHeightA;
650         ptrA->minScaleE = minScaleA;
651         ptrA->maxScaleE = maxScaleA;
652         ptrA->scaleStepE = scaleStepA;
653         ptrA->borderWidthE = borderWidthA;
654         ptrA->borderHeightE = borderHeightA;
655         ptrA->bufferSizeE = bufferSizeA;
656         bbf_Scanner_alloc( cpA, ptrA, mtpA, maximizeSharedMemoryA );
657 }
658
659 /* ------------------------------------------------------------------------- */
660         
661 void bbf_Scanner_bitParam( struct bbs_Context* cpA,
662                                                    struct bbf_Scanner* ptrA,
663                                                    const struct bbf_BitParam* bitParamPtrA )
664 {
665         if( !bbf_BitParam_equal( cpA, &ptrA->bitParamE, bitParamPtrA ) )
666         {
667                 bbf_BitParam_copy( cpA, &ptrA->bitParamE, bitParamPtrA );
668                 bbf_Scanner_createBitImage( cpA, ptrA );
669         }
670
671         bbf_Scanner_resetScan( cpA, ptrA );
672 }
673
674 /* ------------------------------------------------------------------------- */
675         
676 /* ========================================================================= */
677 /*                                                                           */
678 /* ---- \ghd{ I/O } -------------------------------------------------------- */
679 /*                                                                           */
680 /* ========================================================================= */
681
682 /* ------------------------------------------------------------------------- */
683         
684 uint32 bbf_Scanner_memSize( struct bbs_Context* cpA,
685                                                         const struct bbf_Scanner* ptrA )
686 {
687         uint32 memSizeL = bbs_SIZEOF16( uint32 ) +
688                                           bbs_SIZEOF16( uint32 ); /* version */
689         memSizeL += bbs_SIZEOF16( ptrA->maxImageWidthE );
690         memSizeL += bbs_SIZEOF16( ptrA->maxImageHeightE );
691         memSizeL += bbs_SIZEOF16( ptrA->maxRadiusE );
692         memSizeL += bbs_SIZEOF16( ptrA->patchWidthE );
693         memSizeL += bbs_SIZEOF16( ptrA->patchHeightE );
694         memSizeL += bbs_SIZEOF16( ptrA->minScaleE );
695         memSizeL += bbs_SIZEOF16( ptrA->maxScaleE );
696         memSizeL += bbs_SIZEOF16( ptrA->scaleStepE );
697         memSizeL += bbs_SIZEOF16( ptrA->borderWidthE );
698         memSizeL += bbs_SIZEOF16( ptrA->borderHeightE );
699         return memSizeL; 
700 }
701
702 /* ------------------------------------------------------------------------- */
703         
704 uint32 bbf_Scanner_memWrite( struct bbs_Context* cpA,
705                                                      const struct bbf_Scanner* ptrA, 
706                                                      uint16* memPtrA )
707 {
708         uint32 memSizeL = bbf_Scanner_memSize( cpA, ptrA );
709         memPtrA += bbs_memWrite32( &memSizeL, memPtrA );
710         memPtrA += bbs_memWriteUInt32( bbf_SCANNER_VERSION, memPtrA );
711         memPtrA += bbs_memWrite32( &ptrA->maxImageWidthE, memPtrA );
712         memPtrA += bbs_memWrite32( &ptrA->maxImageHeightE, memPtrA );
713         memPtrA += bbs_memWrite32( &ptrA->maxRadiusE, memPtrA );
714         memPtrA += bbs_memWrite32( &ptrA->patchWidthE, memPtrA );
715         memPtrA += bbs_memWrite32( &ptrA->patchHeightE, memPtrA );
716         memPtrA += bbs_memWrite32( &ptrA->minScaleE, memPtrA );
717         memPtrA += bbs_memWrite32( &ptrA->maxScaleE, memPtrA );
718         memPtrA += bbs_memWrite32( &ptrA->scaleStepE, memPtrA );
719         memPtrA += bbs_memWrite32( &ptrA->borderWidthE, memPtrA );
720         memPtrA += bbs_memWrite32( &ptrA->borderHeightE, memPtrA );
721         return memSizeL;
722 }
723
724 /* ------------------------------------------------------------------------- */
725
726 uint32 bbf_Scanner_memRead( struct bbs_Context* cpA,
727                                                     struct bbf_Scanner* ptrA, 
728                                                     const uint16* memPtrA, 
729                                                     struct bbs_MemTbl* mtpA )
730 {
731         uint32 memSizeL, versionL;
732
733         if( bbs_Context_error( cpA ) ) return 0;
734         memPtrA += bbs_memRead32( &memSizeL, memPtrA );
735         memPtrA += bbs_memReadVersion32( cpA, &versionL, bbf_SCANNER_VERSION, memPtrA );
736
737         memPtrA += bbs_memRead32( &ptrA->maxImageWidthE, memPtrA );
738         memPtrA += bbs_memRead32( &ptrA->maxImageHeightE, memPtrA );
739         memPtrA += bbs_memRead32( &ptrA->maxRadiusE, memPtrA );
740         memPtrA += bbs_memRead32( &ptrA->patchWidthE, memPtrA );
741         memPtrA += bbs_memRead32( &ptrA->patchHeightE, memPtrA );
742         memPtrA += bbs_memRead32( &ptrA->minScaleE, memPtrA );
743         memPtrA += bbs_memRead32( &ptrA->maxScaleE, memPtrA );
744         memPtrA += bbs_memRead32( &ptrA->scaleStepE, memPtrA );
745         memPtrA += bbs_memRead32( &ptrA->borderWidthE, memPtrA );
746         memPtrA += bbs_memRead32( &ptrA->borderHeightE, memPtrA );
747
748         if( memSizeL != bbf_Scanner_memSize( cpA, ptrA ) )
749         {
750                 bbs_ERR0( bbs_ERR_CORRUPT_DATA, "uint32 bbf_Scanner_memRead( struct bem_ScanGradientMove* ptrA, const uint16* memPtrA ):\n"
751                                 "size mismatch" );
752                 return 0;
753         }
754
755         if( bbs_Context_error( cpA ) ) return 0;
756
757         /* allocate arrays */
758         bbf_Scanner_alloc( cpA, ptrA, mtpA, FALSE );
759
760         if( bbs_Context_error( cpA ) ) return 0;
761
762         return memSizeL;
763 }
764
765 /* ------------------------------------------------------------------------- */
766         
767 /* ========================================================================= */
768 /*                                                                           */
769 /* ---- \ghd{ exec functions } --------------------------------------------- */
770 /*                                                                           */
771 /* ========================================================================= */
772         
773 /* ------------------------------------------------------------------------- */
774
775 void bbf_Scanner_resetScan( struct bbs_Context* cpA, struct bbf_Scanner* ptrA )
776 {
777         ptrA->xE = 0;
778         ptrA->yE = 0;
779         bbf_Scanner_initPatchBuffer( cpA, ptrA );
780 }
781
782 /* ------------------------------------------------------------------------- */
783
784 void bbf_Scanner_assign( struct bbs_Context* cpA, struct bbf_Scanner* ptrA,
785                                              const void* imagePtrA,
786                                                  uint32 imageWidthA,
787                                                  uint32 imageHeightA,
788                                                  const struct bts_Int16Rect* roiPtrA,
789                                                  const struct bbf_BitParam* paramPtrA )
790 {
791         /* copy image */
792         bbf_Scanner_copyImage( cpA, ptrA, imagePtrA, imageWidthA, imageHeightA, roiPtrA );
793
794         ptrA->scaleE = ptrA->minScaleE;
795         bbf_BitParam_copy( cpA, &ptrA->bitParamE, paramPtrA );
796
797         /* compute effective max scale */
798         {
799                 /* 16.16 */
800                 uint32 maxHScaleL = ( ptrA->workWidthE << 16 ) / ( ptrA->patchWidthE + 1 );
801                 uint32 maxVScaleL = ( ptrA->workHeightE << 16 ) / ( ptrA->patchHeightE + 1 );
802
803                 /* 12.20 */
804                 ptrA->effMaxScaleE = maxHScaleL < maxVScaleL ? ( maxHScaleL << 4 ) : ( maxVScaleL << 4 );
805                 
806                 if( ptrA->maxScaleE > 0 ) ptrA->effMaxScaleE = ptrA->effMaxScaleE < ptrA->maxScaleE ? ptrA->effMaxScaleE : ptrA->maxScaleE;
807         }
808
809         ptrA->scaleExpE = 0;
810
811         /* downscale work image if necessary */
812         while( ptrA->scaleE > ( ( uint32 )( 2 << ptrA->scaleExpE ) << 20 ) ) bbf_Scanner_downscale( cpA, ptrA );
813
814         bbf_Scanner_createBitImage( cpA, ptrA );
815         bbf_Scanner_resetScan( cpA, ptrA );
816 }
817
818 /* ------------------------------------------------------------------------- */
819
820 flag bbf_Scanner_nextScale( struct bbs_Context* cpA, struct bbf_Scanner* ptrA )
821 {
822         if( ptrA->scaleE + bbf_Scanner_scalePrd( ptrA->scaleE, ptrA->scaleStepE ) >= ptrA->effMaxScaleE ) return FALSE;
823         ptrA->scaleE += bbf_Scanner_scalePrd( ptrA->scaleE, ptrA->scaleStepE );
824
825         /* downscale work image if necessary */
826         while( ptrA->scaleE > ( ( uint32 )( 2 << ptrA->scaleExpE ) << 20 ) ) bbf_Scanner_downscale( cpA, ptrA );
827
828         bbf_Scanner_createBitImage( cpA, ptrA );
829         bbf_Scanner_resetScan( cpA, ptrA );
830         return TRUE;
831 }
832
833 /* ------------------------------------------------------------------------- */
834
835 const uint32* bbf_Scanner_getPatch( const struct bbf_Scanner* ptrA )
836 {
837         return ptrA->patchBufferE.arrPtrE + ptrA->xE;
838 }
839
840 /* ------------------------------------------------------------------------- */
841
842 flag bbf_Scanner_next( struct bbs_Context* cpA, struct bbf_Scanner* ptrA )
843 {
844         if( ( ptrA->xE + 1 ) < ( int32 )( ptrA->currentWidthE - ptrA->patchWidthE ) )
845         {
846                 ptrA->xE++;
847                 return TRUE;
848         }
849
850         if( ( ptrA->yE + 1 ) >= ( int32 )( ptrA->currentHeightE - ptrA->patchHeightE ) ) return FALSE;
851
852         ptrA->xE = 0;
853         ptrA->yE++;
854
855         {
856                 uint32 offL = ( ptrA->yE & 0x1F );
857                 uint32 rowL = ( ptrA->yE >> 5 ) + ( offL > 0 ? 1 : 0 );
858
859                 uint32 sizeL = ptrA->bitImageE.widthE;
860                 uint32* dstL = ptrA->patchBufferE.arrPtrE;
861                 uint32 iL;
862
863                 if( rowL < ptrA->bitImageE.heightE )
864                 {
865                         uint32* srcL = ( uint32* )ptrA->bitImageE.arrE.arrPtrE + rowL * sizeL;
866                         if( offL > 0 )
867                         {
868                                 uint32 shlL = 32 - offL;
869                                 for( iL = 0; iL < sizeL; iL++ ) dstL[ iL ] = ( dstL[ iL ] >> 1 ) | ( srcL[ iL ] << shlL );
870                         }
871                         else
872                         {
873                                 bbs_memcpy32( dstL, srcL, sizeL );
874                         }
875                 }
876                 else
877                 {
878                         for( iL = 0; iL < sizeL; iL++ ) dstL[ iL ] >>= 1;
879                 }
880         }
881
882         return TRUE;
883 }
884
885 /* ------------------------------------------------------------------------- */
886
887 void bbf_Scanner_goToXY( struct bbs_Context* cpA, struct bbf_Scanner* ptrA, int32 xA, int32 yA )
888 {
889         bbs_DEF_fNameL( "void bbf_Scanner_goToXY( struct bbs_Context* cpA, struct bbf_Scanner* ptrA, int32 xA, int32 yA )" )
890
891         if( xA > ( int32 )( ptrA->currentWidthE - ptrA->patchWidthE ) )
892         {
893                 bbs_ERROR1( "%s:\nyA out of range", fNameL );
894                 return;
895         }
896
897         ptrA->xE = xA;
898
899         if( ptrA->yE == yA ) return;
900
901         if( yA >= ( int32 )( ptrA->currentHeightE - ptrA->patchHeightE ) )
902         {
903                 bbs_ERROR1( "%s:\nyA out of range", fNameL );
904                 return;
905         }
906
907         if( yA == ptrA->yE + 1 )
908         {
909                 uint32 offL, rowL;
910                 uint32 sizeL;
911                 uint32* dstL;
912                 uint32 iL;
913
914                 ptrA->yE = yA;
915                 offL = ( ptrA->yE & 0x1F );
916                 rowL = ( ptrA->yE >> 5 ) + ( offL > 0 ? 1 : 0 );
917
918                 sizeL = ptrA->bitImageE.widthE;
919                 dstL = ptrA->patchBufferE.arrPtrE;
920
921                 if( rowL < ptrA->bitImageE.heightE )
922                 {
923                         uint32* srcL = ptrA->bitImageE.arrE.arrPtrE + rowL * sizeL;
924                         if( offL > 0 )
925                         {
926                                 uint32 shlL = 32 - offL;
927                                 for( iL = 0; iL < sizeL; iL++ ) dstL[ iL ] = ( dstL[ iL ] >> 1 ) | ( srcL[ iL ] << shlL );
928                         }
929                         else
930                         {
931                                 bbs_memcpy32( dstL, srcL, sizeL );
932                         }
933                 }
934                 else
935                 {
936                         for( iL = 0; iL < sizeL; iL++ ) dstL[ iL ] >>= 1;
937                 }
938         }
939         else
940         {
941                 uint32 offL, rowL;
942                 uint32 sizeL;
943                 uint32* dstL;
944                 uint32 iL;
945
946                 ptrA->yE = yA;
947                 offL = ( ptrA->yE & 0x1F );
948                 rowL = ( ptrA->yE >> 5 ) + ( offL > 0 ? 1 : 0 );
949
950                 sizeL = ptrA->bitImageE.widthE;
951                 dstL = ptrA->patchBufferE.arrPtrE;
952
953                 if( rowL < ptrA->bitImageE.heightE )
954                 {
955                         if( offL > 0 )
956                         {
957                                 uint32* src1L = ptrA->bitImageE.arrE.arrPtrE + rowL * sizeL;
958                                 uint32* src0L = src1L - sizeL;
959                                 uint32 shlL = 32 - offL;
960                                 for( iL = 0; iL < sizeL; iL++ ) dstL[ iL ] = ( src0L[ iL ] >> offL ) | ( src1L[ iL ] << shlL );
961                         }
962                         else
963                         {
964                                 bbs_memcpy32( dstL, ptrA->bitImageE.arrE.arrPtrE + rowL * sizeL, sizeL );
965                         }
966                 }
967                 else
968                 {
969                         uint32* srcL = ptrA->bitImageE.arrE.arrPtrE + ( rowL - 1 ) * sizeL;
970                         for( iL = 0; iL < sizeL; iL++ ) dstL[ iL ] = srcL[ iL ] >> offL;
971                 }
972         }
973 }
974
975 /* ------------------------------------------------------------------------- */
976
977 void bbf_Scanner_goToIndex( struct bbs_Context* cpA, struct bbf_Scanner* ptrA, uint32 scanIndexA )
978 {
979         int32 yL = scanIndexA / ptrA->currentWidthE; 
980         int32 xL = scanIndexA - yL * ptrA->currentWidthE;
981         bbf_Scanner_goToXY( cpA, ptrA, xL, yL ); 
982 }
983
984 /* ------------------------------------------------------------------------- */
985
986 void bbf_Scanner_goToUls( struct bbs_Context* cpA, struct bbf_Scanner* ptrA, 
987                                                   int32 xA, int32 yA, uint32 scaleA )
988 {
989         int32 xL = ( xA / ( int32 )( ptrA->scaleE >> 4 ) ) + ptrA->borderWidthE;
990         int32 yL = ( yA / ( int32 )( ptrA->scaleE >> 4 ) ) + ptrA->borderHeightE;
991
992         if( ptrA->scaleE != scaleA )
993         {
994                 bbs_ERROR0( "bbf_Scanner_goToUls:\nScales no not match" );
995                 return;
996         }
997
998         bbf_Scanner_goToXY( cpA, ptrA, xL, yL );
999 }
1000
1001 /* ------------------------------------------------------------------------- */
1002
1003 /* resets output positions */
1004 void bbf_Scanner_resetOutPos( struct bbs_Context* cpA, struct bbf_Scanner* ptrA ) 
1005 {
1006         ptrA->outCountE = 0;
1007 }
1008
1009 /* ------------------------------------------------------------------------- */
1010
1011 /* resets internal positions */
1012 void bbf_Scanner_resetIntPos( struct bbs_Context* cpA, struct bbf_Scanner* ptrA )
1013 {
1014         ptrA->intCountE = 0;
1015 }
1016
1017 /* ------------------------------------------------------------------------- */
1018
1019 /* add internal position */
1020 void bbf_Scanner_addIntPos( struct bbs_Context* cpA, 
1021                                                         struct bbf_Scanner* ptrA,
1022                                                         uint32 idxA,
1023                                                         int32 actA )
1024 {
1025         if( ptrA->intCountE < ptrA->idxArrE.sizeE )
1026         {
1027         ptrA->idxArrE.arrPtrE[ ptrA->intCountE ] = idxA;
1028         ptrA->actArrE.arrPtrE[ ptrA->intCountE ] = actA;
1029                 ptrA->intCountE++;
1030         }
1031         else
1032         {
1033                 /* When buffer is full then replace lowest confidence-entry with new input 
1034                  * This fallback solution causes soft degradation of performance when the buffer limit is reached.
1035                  */
1036                 int32 minActL = 0x7FFFFFFF;
1037                 uint32 minIdxL = 0;
1038                 uint32 iL;
1039                 int32* actArrL = ptrA->actArrE.arrPtrE;
1040                 for( iL = 0; iL < ptrA->intCountE; iL++ )
1041                 {
1042                         if( actArrL[ iL ] < minActL ) 
1043                         {
1044                                 minActL = actArrL[ iL ];
1045                                 minIdxL = iL;
1046                         }
1047                 }
1048
1049                 if( actA > minActL )
1050                 {
1051                         ptrA->idxArrE.arrPtrE[ minIdxL ] = idxA;
1052                         ptrA->actArrE.arrPtrE[ minIdxL ] = actA;
1053                 }
1054         }
1055 }
1056
1057 /* ------------------------------------------------------------------------- */
1058
1059 /* add external position */
1060 void bbf_Scanner_addOutPos( struct bbs_Context* cpA, 
1061                                                         struct bbf_Scanner* ptrA, 
1062                                                         int32 xA, 
1063                                                         int32 yA, 
1064                                                         uint32 scaleA, 
1065                                                         int32 actA )
1066 {
1067         if( ( ptrA->outCountE * 4 ) < ptrA->outArrE.sizeE )
1068         {
1069         ptrA->outArrE.arrPtrE[ ptrA->outCountE * 4 + 0 ] = xA;
1070         ptrA->outArrE.arrPtrE[ ptrA->outCountE * 4 + 1 ] = yA;
1071         ptrA->outArrE.arrPtrE[ ptrA->outCountE * 4 + 2 ] = scaleA;
1072         ptrA->outArrE.arrPtrE[ ptrA->outCountE * 4 + 3 ] = actA;
1073                 ptrA->outCountE++;
1074         }
1075         else
1076         {
1077                 /* When buffer is full then replace lowest confidence-entry with new input 
1078                  * This fallback solution causes soft degradation of performance when the buffer limit is reached.
1079                  */
1080                 int32 minActL = 0x7FFFFFFF;
1081                 uint32 minIdxL = 0;
1082                 uint32 iL;
1083                 int32* outArrL = ptrA->outArrE.arrPtrE;
1084                 for( iL = 0; iL < ptrA->outCountE; iL++ )
1085                 {
1086                         if( outArrL[ iL * 4 + 3 ] < minActL ) 
1087                         {
1088                                 minActL = outArrL[ iL * 4 + 3 ];
1089                                 minIdxL = iL;
1090                         }
1091                 }
1092
1093                 if( actA > minActL )
1094                 {
1095                         ptrA->idxArrE.arrPtrE[ minIdxL * 4 + 0 ] = xA;
1096                         ptrA->idxArrE.arrPtrE[ minIdxL * 4 + 1 ] = yA;
1097                         ptrA->idxArrE.arrPtrE[ minIdxL * 4 + 2 ] = scaleA;
1098                         ptrA->idxArrE.arrPtrE[ minIdxL * 4 + 3 ] = actA;
1099                 }
1100         }
1101 }
1102
1103 /* ------------------------------------------------------------------------- */
1104
1105 /* remove overlaps */
1106 uint32 bbf_Scanner_removeOutOverlaps( struct bbs_Context* cpA, 
1107                                                                   struct bbf_Scanner* ptrA,
1108                                                                           uint32 overlapThrA )
1109 {
1110         uint32 begIdxL = 0;                                /* begin index */
1111         uint32 endIdxL = ptrA->outCountE;  /* end index */
1112         uint32 iL;
1113         uint32 rw0L = ptrA->patchWidthE;
1114         uint32 rh0L = ptrA->patchHeightE;
1115         int32* outArrL = ptrA->outArrE.arrPtrE;
1116
1117         if( overlapThrA >= 0x010000 ) return ptrA->outCountE;
1118
1119         while( endIdxL - begIdxL > 1 )
1120         {
1121                 int32 x1L, y1L, s1L, a1L;
1122                 int32 r1wL, r1hL;
1123                 uint32 r1aL;
1124
1125                 /* find maximum activity */
1126                 uint32 maxIdxL  = 0;
1127
1128                 {
1129                         int32 maxActL = ( int32 )0x80000000;
1130                         for( iL = begIdxL; iL < endIdxL; iL++ )
1131                         {
1132                                 if( outArrL[ iL * 4 + 3 ] > maxActL )
1133                                 {
1134                                         maxActL = outArrL[ iL * 4 + 3 ];
1135                                         maxIdxL = iL;
1136                                 }
1137                         }
1138                 }
1139
1140                 /* swap with position 0 */
1141                 x1L = outArrL[ maxIdxL * 4 + 0 ];
1142                 y1L = outArrL[ maxIdxL * 4 + 1 ];
1143                 s1L = outArrL[ maxIdxL * 4 + 2 ];
1144                 a1L = outArrL[ maxIdxL * 4 + 3 ];
1145
1146                 outArrL[ maxIdxL * 4 + 0 ] = outArrL[ begIdxL * 4 + 0 ];
1147                 outArrL[ maxIdxL * 4 + 1 ] = outArrL[ begIdxL * 4 + 1 ];
1148                 outArrL[ maxIdxL * 4 + 2 ] = outArrL[ begIdxL * 4 + 2 ];
1149                 outArrL[ maxIdxL * 4 + 3 ] = outArrL[ begIdxL * 4 + 3 ];
1150
1151                 outArrL[ begIdxL * 4 + 0 ] = x1L;
1152                 outArrL[ begIdxL * 4 + 1 ] = y1L;
1153                 outArrL[ begIdxL * 4 + 2 ] = s1L;
1154                 outArrL[ begIdxL * 4 + 3 ] = a1L;
1155
1156                 /* rectangle */
1157                 r1wL = ( rw0L * ( s1L >> 12 ) + 128 ) >> 8;
1158                 r1hL = ( rh0L * ( s1L >> 12 ) + 128 ) >> 8;
1159                 r1aL = ( uint32 )r1wL * ( uint32 )r1hL;
1160
1161                 /* remove coordinate fractions */
1162                 x1L = ( x1L + ( 1 << 15 ) ) >> 16;
1163                 y1L = ( y1L + ( 1 << 15 ) ) >> 16;
1164
1165                 /* compare to other rectangles and remove overlaps */
1166                 for( iL = endIdxL - 1; iL > begIdxL; iL-- )
1167                 {
1168                         int32* x2pL = &outArrL[ iL * 4 + 0 ];
1169                         int32* y2pL = &outArrL[ iL * 4 + 1 ];
1170                         int32* s2pL = &outArrL[ iL * 4 + 2 ];
1171                         int32* a2pL = &outArrL[ iL * 4 + 3 ];
1172
1173                         int32 x2L = ( *x2pL + ( 1 << 15 ) ) >> 16;
1174                         int32 y2L = ( *y2pL + ( 1 << 15 ) ) >> 16;
1175
1176                         /* rectangle */
1177                         int32 r2wL = ( rw0L * ( *s2pL >> 12 ) + 128 ) >> 8;
1178                         int32 r2hL = ( rh0L * ( *s2pL >> 12 ) + 128 ) >> 8;
1179                         uint32 r2aL = r2wL * r2hL;
1180
1181                         /* intersection */
1182                         int32 rx1L = x1L > x2L ? x1L : x2L;
1183                         int32 rx2L = ( x1L + r1wL ) < ( x2L + r2wL ) ? ( x1L + r1wL ) : ( x2L + r2wL );
1184                         int32 ry1L = y1L > y2L ? y1L : y2L;
1185                         int32 ry2L = ( y1L + r1hL ) < ( y2L + r2hL ) ? ( y1L + r1hL ) : ( y2L + r2hL );
1186                         uint32 riwL;
1187
1188                         rx2L = ( rx2L > rx1L ) ? rx2L : rx1L;
1189                         ry2L = ( ry2L > ry1L ) ? ry2L : ry1L;
1190                         riwL = ( uint32 )( rx2L - rx1L ) * ( uint32 )( ry2L - ry1L );
1191
1192                         if( riwL > ( ( ( overlapThrA >> 8 ) * ( r1aL < r2aL ? r1aL : r2aL ) ) >> 8 ) )
1193                         {
1194                                 endIdxL--;
1195                                 *x2pL = outArrL[ endIdxL * 4 + 0 ];
1196                                 *y2pL = outArrL[ endIdxL * 4 + 1 ];
1197                                 *s2pL = outArrL[ endIdxL * 4 + 2 ];
1198                                 *a2pL = outArrL[ endIdxL * 4 + 3 ];
1199                         }
1200                 }
1201
1202                 begIdxL++;
1203         }
1204
1205         ptrA->outCountE = endIdxL;
1206
1207         return endIdxL;
1208 }
1209
1210 /* ------------------------------------------------------------------------- */
1211
1212 /* remove internal overlaps */
1213 uint32 bbf_Scanner_removeIntOverlaps( struct bbs_Context* cpA, 
1214                                                                       struct bbf_Scanner* ptrA,
1215                                                                           uint32 overlapThrA )
1216 {
1217     uint32 begIdxL = 0;          /* begin index */
1218     uint32 endIdxL = ptrA->intCountE;  /* end index */
1219         uint32 iL;
1220         uint32 rw0L   = ptrA->patchWidthE;
1221         uint32 rh0L   = ptrA->patchHeightE;
1222         int32 minAreaL = ( overlapThrA * rw0L * rh0L ) >> 16;
1223
1224         int32*  actArrL = ptrA->actArrE.arrPtrE;
1225         uint32* idxArrL = ptrA->idxArrE.arrPtrE;
1226
1227         if( overlapThrA >= 0x010000 ) return ptrA->intCountE;
1228
1229         while( endIdxL - begIdxL > 1 )
1230         {
1231                 /* find maximum activity */
1232                 int32 a1L = ( int32 )0x80000000;
1233                 uint32 i1L = 0;
1234                 uint32 maxIdxL  = 0;
1235                 int32 x1L, y1L;
1236
1237                 for( iL = begIdxL; iL < endIdxL; iL++ )
1238                 {
1239             if( actArrL[ iL ] > a1L )
1240                         {
1241                                 a1L = actArrL[ iL ];
1242                                 maxIdxL = iL;
1243                         }
1244                 }
1245
1246                 /* swap with position 0 */
1247                 i1L = idxArrL[ maxIdxL ];
1248                 idxArrL[ maxIdxL ] = idxArrL[ begIdxL ];
1249                 actArrL[ maxIdxL ] = actArrL[ begIdxL ];
1250                 idxArrL[ begIdxL ] = i1L;
1251                 actArrL[ begIdxL ] = a1L;
1252
1253                 /* upper left coordinates */
1254                 y1L = i1L / ptrA->currentWidthE;
1255                 x1L = i1L - ( y1L * ptrA->currentWidthE );
1256
1257                 /* compare to other rectangles and remove overlaps */
1258                 for( iL = endIdxL - 1; iL > begIdxL; iL-- )
1259                 {
1260                         int32*  a2pL = &actArrL[ iL ];
1261                         uint32* i2pL = &idxArrL[ iL ];
1262
1263                         int32 y2L = *i2pL / ptrA->currentWidthE;
1264                         int32 x2L = *i2pL - ( y2L * ptrA->currentWidthE );
1265
1266                         int32 dxL = rw0L - ( x1L > x2L ? x1L - x2L : x2L - x1L );
1267                         int32 dyL = rh0L - ( y1L > y2L ? y1L - y2L : y2L - y1L );
1268
1269                         dxL = dxL > 0 ? dxL : 0;
1270                         dyL = dyL > 0 ? dyL : 0;
1271
1272                         if( dxL * dyL > minAreaL )
1273                         {
1274                                 endIdxL--;
1275                                 *a2pL = actArrL[ endIdxL ];
1276                                 *i2pL = idxArrL[ endIdxL ];
1277                         }
1278                 }
1279
1280                 begIdxL++;
1281         }
1282
1283         ptrA->intCountE = endIdxL;
1284
1285         return ptrA->intCountE;
1286 }
1287
1288 /* ------------------------------------------------------------------------- */
1289
1290 /* ========================================================================= */