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