| /* |
| * Copyright (C) 2008 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| /* ---- includes ----------------------------------------------------------- */ |
| |
| #include "b_BasicEm/Functions.h" |
| #include "b_BasicEm/Math.h" |
| #include "b_BitFeatureEm/LocalScanner.h" |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| /* ========================================================================= */ |
| /* */ |
| /* ---- \ghd{ auxiliary functions } ---------------------------------------- */ |
| /* */ |
| /* ========================================================================= */ |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| /** allocates arays */ |
| void bbf_LocalScanner_alloc( struct bbs_Context* cpA, |
| struct bbf_LocalScanner* ptrA, |
| struct bbs_MemTbl* mtpA ) |
| { |
| struct bbs_MemTbl memTblL = *mtpA; |
| struct bbs_MemSeg* espL = bbs_MemTbl_segPtr( cpA, &memTblL, 0 ); |
| struct bbs_MemSeg* sspL = bbs_MemTbl_sharedSegPtr( cpA, &memTblL, 0 ); |
| |
| /* filter patch dimension */ |
| uint32 proL = ptrA->maxRadiusE; |
| uint32 pwoL = ( proL << 1 ) + 1; |
| |
| /* output image size (bit image) */ |
| uint32 woL = ptrA->maxImageWidthE; |
| uint32 hoL = ptrA->maxImageHeightE; |
| |
| if( ptrA->minScaleExpE > 0 ) |
| { |
| /* allocate working image */ |
| bbs_UInt8Arr_create( cpA, &ptrA->workImageBufferE, ( woL >> 1 ) * ( hoL >> 1 ), espL ); |
| bbs_UInt8Arr_fill( cpA, &ptrA->workImageBufferE, 0 ); |
| } |
| |
| /* allocate bit image */ |
| bim_UInt32Image_create( cpA, &ptrA->bitImageE, woL, ( hoL >> 5 ) + ( ( ( hoL & 0x1F ) != 0 ) ? 1 : 0 ), espL ); |
| bim_UInt32Image_setAllPixels( cpA, &ptrA->bitImageE, 0, 0 ); |
| |
| /* allocate patch buffer */ |
| bbs_UInt32Arr_create( cpA, &ptrA->patchBufferE, ptrA->bitImageE.widthE, espL ); |
| bbs_UInt32Arr_fill( cpA, &ptrA->patchBufferE, 0 ); |
| |
| /* allocate table */ |
| bim_UInt32Image_create( cpA, &ptrA->satE, woL + pwoL, pwoL + 1, sspL ); |
| } |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| /** downscales original image by factor 2 */ |
| void bbf_LocalScanner_downscale0( struct bbs_Context* cpA, struct bbf_LocalScanner* ptrA ) |
| { |
| int32 w0L = ptrA->origWidthE; |
| int32 h0L = ptrA->origHeightE; |
| |
| int32 w1L = ( w0L - ptrA->xOffE ) >> 1; |
| int32 h1L = ( h0L - ptrA->yOffE ) >> 1; |
| |
| const uint8* iArrL = ptrA->origImagePtrE + ptrA->xOffE + ptrA->yOffE * w0L; |
| uint8* oArrL = ptrA->workImageBufferE.arrPtrE; |
| |
| int32 iL, jL; |
| int32 kL = 0; |
| |
| bbs_UInt8Arr_size( cpA, &ptrA->workImageBufferE, w1L * h1L ); |
| ptrA->workImagePtrE = ptrA->workImageBufferE.arrPtrE; |
| ptrA->workWidthE = w1L; |
| ptrA->workHeightE = h1L; |
| |
| for( jL = 0; jL < h1L; jL++ ) |
| { |
| for( iL = 0; iL < w1L; iL++ ) |
| { |
| int32 idxL = jL * 2 * w0L + iL * 2; |
| oArrL[ kL++ ] = ( ( uint32 )iArrL[ idxL ] + |
| iArrL[ idxL + 1 ] + |
| iArrL[ idxL + w0L ] + |
| iArrL[ idxL + w0L + 1 ] + 2 ) >> 2; |
| } |
| } |
| } |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| /** downscales work image by factor 2 */ |
| void bbf_LocalScanner_downscale1( struct bbs_Context* cpA, struct bbf_LocalScanner* ptrA ) |
| { |
| int32 w0L = ptrA->workWidthE; |
| int32 h0L = ptrA->workHeightE; |
| int32 w1L = w0L >> 1; |
| int32 h1L = h0L >> 1; |
| |
| uint8* arrL = ptrA->workImageBufferE.arrPtrE; |
| |
| int32 iL, jL; |
| int32 kL = 0; |
| |
| for( jL = 0; jL < h1L; jL++ ) |
| { |
| for( iL = 0; iL < w1L; iL++ ) |
| { |
| int32 idxL = jL * 2 * w0L + iL * 2; |
| arrL[ kL++ ] = ( ( uint32 )arrL[ idxL ] + |
| arrL[ idxL + 1 ] + |
| arrL[ idxL + w0L ] + |
| arrL[ idxL + w0L + 1 ] + 2 ) >> 2; |
| } |
| } |
| |
| ptrA->workWidthE = w1L; |
| ptrA->workHeightE = h1L; |
| } |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| /** downscales by factor 2 */ |
| void bbf_LocalScanner_downscale( struct bbs_Context* cpA, struct bbf_LocalScanner* ptrA ) |
| { |
| uint32 iL; |
| if( ptrA->scaleExpE > 0 ) bbf_LocalScanner_downscale0( cpA, ptrA ); |
| for( iL = 1; iL < ptrA->scaleExpE; iL++ ) bbf_LocalScanner_downscale1( cpA, ptrA ); |
| } |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| /** computes bit image */ |
| void bbf_LocalScanner_createBitImage( struct bbs_Context* cpA, struct bbf_LocalScanner* ptrA ) |
| { |
| bbs_DEF_fNameL( "void bbf_LocalScanner_createBitImage( struct bbs_Context* cpA, struct bbf_LocalScanner* ptrA )" ) |
| |
| uint32 iL, jL; |
| |
| uint32 proL = ptrA->bitParamE.outerRadiusE; |
| uint32 priL = ptrA->bitParamE.innerRadiusE; |
| uint32 pwoL = ( proL << 1 ) + 1; |
| uint32 pwiL = ( priL << 1 ) + 1; |
| |
| /* areas of inner and outer rectangles */ |
| uint32 poAreaL = pwoL * pwoL; |
| uint32 piAreaL = pwiL * pwiL; |
| |
| uint32 wL, hL; /* input image size */ |
| |
| uint32 wsL, hsL; |
| uint32* satL; |
| uint32 satSizeL; |
| uint32 swi1L = 0; /* writing index */ |
| uint32 swi2L = 0; /* writing index */ |
| uint32 sriL = 0; /* reading index */ |
| uint32 siL[ 8 ]; |
| |
| uint32 bitMaskL; |
| uint32* bitRowL; |
| |
| |
| if( proL <= priL ) |
| { |
| bbs_ERROR1( "%s:\n outer radius <= inner radius", fNameL ); |
| return; |
| } |
| |
| /* input image size */ |
| wL = ptrA->workWidthE; |
| hL = ptrA->workHeightE; |
| |
| if( wL <= pwoL || hL <= pwoL ) |
| { |
| bbs_ERROR1( "%s:\n image is too small", fNameL ); |
| return; |
| } |
| |
| ptrA->currentWidthE = wL; |
| ptrA->currentHeightE = hL; |
| |
| /* reset scan region */ |
| ptrA->workScanRegionE = bts_Int16Rect_create( 0, 0, ptrA->currentWidthE, ptrA->currentHeightE ); |
| |
| /* initialize bit image */ |
| bim_UInt32Image_size( cpA, &ptrA->bitImageE, wL, ( hL >> 5 ) + ( ( ( hL & 0x1F ) != 0 ) ? 1 : 0 ) ); |
| bim_UInt32Image_setAllPixels( cpA, &ptrA->bitImageE, 0, 0 ); |
| |
| bitMaskL = 1; |
| bitRowL = ( uint32* )ptrA->bitImageE.arrE.arrPtrE; |
| |
| /* width of table */ |
| wsL = wL + pwoL; |
| |
| /* height of table */ |
| hsL = pwoL + 1; |
| |
| bim_UInt32Image_size( cpA, &ptrA->satE, wsL, hsL ); |
| |
| satL = ( uint32* )ptrA->satE.arrE.arrPtrE; |
| satSizeL = ptrA->satE.arrE.sizeE; |
| |
| /* compute table and bit image */ |
| for( iL = wsL * ( proL + 1 ); iL > 0; iL-- ) satL[ swi1L++ ] = 0; |
| swi2L = swi1L - wsL; |
| |
| for( jL = 0; jL < hL + proL; jL++ ) |
| { |
| if( jL < hL ) /* rescale area */ |
| { |
| const uint8* arr0L = &ptrA->workImagePtrE[ jL * wL ]; |
| uint32 hSumL = 0; |
| for( iL = 0; iL <= proL; iL++ ) satL[ swi1L++ ] = 0; |
| swi2L += iL; |
| for( iL = 0; iL < wL; iL++ ) satL[ swi1L++ ] = ( hSumL += arr0L[ iL ] ) + satL[ swi2L++ ]; |
| for( iL = 0; iL < proL; iL++ ) satL[ swi1L++ ] = hSumL + satL[ swi2L++ ]; |
| } |
| else /* image is processed - fill in 0s */ |
| { |
| for( iL = 0; iL < wsL; iL++ ) satL[ swi1L++ ] = satL[ swi2L++ ]; |
| } |
| |
| swi1L = ( swi1L < satSizeL ) ? swi1L : 0; |
| swi2L = ( swi2L < satSizeL ) ? swi2L : 0; |
| |
| /* fill line in bit image */ |
| if( jL >= proL ) |
| { |
| const uint32* rSatL = satL; |
| |
| /* table coordinate indices for outer rectangle */ |
| siL[ 0 ] = sriL; |
| siL[ 1 ] = siL[ 0 ] + pwoL; |
| siL[ 2 ] = siL[ 0 ] + pwoL * wsL; |
| siL[ 2 ] -= ( siL[ 2 ] >= satSizeL ) ? satSizeL : 0; |
| siL[ 3 ] = siL[ 2 ] + pwoL; |
| |
| /* table coordinate indices for inner rectangle */ |
| siL[ 4 ] = siL[ 0 ] + ( proL - priL ) * wsL + ( proL - priL ); |
| siL[ 4 ] -= ( siL[ 4 ] >= satSizeL ) ? satSizeL : 0; |
| siL[ 5 ] = siL[ 4 ] + pwiL; |
| siL[ 6 ] = siL[ 4 ] + pwiL * wsL; |
| siL[ 6 ] -= ( siL[ 6 ] >= satSizeL ) ? satSizeL : 0; |
| siL[ 7 ] = siL[ 6 ] + pwiL; |
| sriL += wsL; |
| if( sriL == satSizeL ) sriL = 0; |
| |
| for( iL = 0; iL < wL; iL++ ) |
| { |
| uint32 oAvgL = ( rSatL[ siL[ 0 ] ] - rSatL[ siL[ 1 ] ] - rSatL[ siL[ 2 ] ] + rSatL[ siL[ 3 ] ] ) * piAreaL; |
| uint32 iAvgL = ( rSatL[ siL[ 4 ] ] - rSatL[ siL[ 5 ] ] - rSatL[ siL[ 6 ] ] + rSatL[ siL[ 7 ] ] ) * poAreaL; |
| bitRowL[ iL ] |= ( iAvgL > oAvgL ) ? bitMaskL : 0; |
| rSatL++; |
| } |
| if( ( bitMaskL <<= 1 ) == 0 ) |
| { |
| bitRowL += wL; |
| bitMaskL = 1; |
| } |
| } |
| } |
| } |
| |
| /* -------------------------------------------------------------------------- */ |
| |
| /** inilialize patch buffer */ |
| void bbf_LocalScanner_initPatchBuffer( struct bbs_Context* cpA, struct bbf_LocalScanner* ptrA ) |
| { |
| int32 ybL = ptrA->workScanRegionE.y1E >> 5; |
| int32 yoL = ptrA->workScanRegionE.y1E & 0x1F; |
| int32 xbL = ptrA->workScanRegionE.x1E; |
| uint32 wsrWidthL = ptrA->workScanRegionE.x2E - ptrA->workScanRegionE.x1E; |
| |
| bbs_UInt32Arr_size( cpA, &ptrA->patchBufferE, ptrA->bitImageE.widthE ); |
| |
| if( yoL == 0 ) |
| { |
| bbs_memcpy32( ptrA->patchBufferE.arrPtrE + xbL, |
| ptrA->bitImageE.arrE.arrPtrE + ybL * ptrA->bitImageE.widthE + xbL, |
| wsrWidthL ); |
| } |
| else if( ybL == ( int32 )ptrA->bitImageE.heightE - 1 ) |
| { |
| uint32* dstL = ptrA->patchBufferE.arrPtrE + xbL; |
| const uint32* srcL = ptrA->bitImageE.arrE.arrPtrE + ybL * ptrA->bitImageE.widthE + xbL; |
| uint32 iL; |
| for( iL = 0; iL < wsrWidthL; iL++ ) dstL[ iL ] = srcL[ iL ] >> yoL; |
| } |
| else |
| { |
| uint32* dstL = ptrA->patchBufferE.arrPtrE + xbL; |
| const uint32* src0L = ptrA->bitImageE.arrE.arrPtrE + ybL * ptrA->bitImageE.widthE + xbL; |
| const uint32* src1L = src0L + ptrA->bitImageE.widthE; |
| uint32 iL; |
| uint32 slL = 32 - yoL; |
| for( iL = 0; iL < wsrWidthL; iL++ ) dstL[ iL ] = ( src0L[ iL ] >> yoL ) | ( src1L[ iL ] << slL ); |
| } |
| } |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| /* sets work scan region from original scan region according to scale exponent */ |
| void bbf_LocalScanner_setWorkScanRegion( struct bbs_Context* cpA, struct bbf_LocalScanner* ptrA ) |
| { |
| int32 xMinL = ptrA->origScanRegionE.x1E >> ptrA->scaleExpE; |
| int32 yMinL = ptrA->origScanRegionE.y1E >> ptrA->scaleExpE; |
| int32 xMaxL = ptrA->origScanRegionE.x2E >> ptrA->scaleExpE; |
| int32 yMaxL = ptrA->origScanRegionE.y2E >> ptrA->scaleExpE; |
| ptrA->workScanRegionE.x1E = ( xMinL < 0 ) ? 0 : xMinL; |
| ptrA->workScanRegionE.y1E = ( yMinL < 0 ) ? 0 : yMinL; |
| ptrA->workScanRegionE.x2E = ( xMaxL > ( int32 )ptrA->currentWidthE ) ? ptrA->currentWidthE : xMaxL; |
| ptrA->workScanRegionE.y2E = ( yMaxL > ( int32 )ptrA->currentHeightE ) ? ptrA->currentHeightE : yMaxL; |
| } |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| /* ========================================================================= */ |
| /* */ |
| /* ---- \ghd{ constructor / destructor } ----------------------------------- */ |
| /* */ |
| /* ========================================================================= */ |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| void bbf_LocalScanner_init( struct bbs_Context* cpA, |
| struct bbf_LocalScanner* ptrA ) |
| { |
| ptrA->xE = 0; |
| ptrA->yE = 0; |
| ptrA->xOffE = 0; |
| ptrA->yOffE = 0; |
| ptrA->currentWidthE = 0; |
| ptrA->currentHeightE = 0; |
| ptrA->workWidthE = 0; |
| ptrA->workHeightE = 0; |
| ptrA->workImagePtrE = NULL; |
| ptrA->origWidthE = 0; |
| ptrA->origHeightE = 0; |
| ptrA->origImagePtrE = NULL; |
| bbf_BitParam_init( cpA, &ptrA->bitParamE ); |
| bbs_UInt8Arr_init( cpA, &ptrA->workImageBufferE ); |
| bim_UInt32Image_init( cpA, &ptrA->satE ); |
| bim_UInt32Image_init( cpA, &ptrA->bitImageE ); |
| bbs_UInt32Arr_init( cpA, &ptrA->patchBufferE ); |
| bts_Int16Rect_init( cpA, &ptrA->origScanRegionE ); |
| bts_Int16Rect_init( cpA, &ptrA->workScanRegionE ); |
| |
| ptrA->patchWidthE = 0; |
| ptrA->patchHeightE = 0; |
| ptrA->scaleExpE = 0; |
| ptrA->maxImageWidthE = 0; |
| ptrA->maxImageHeightE = 0; |
| ptrA->minScaleExpE = 0; |
| ptrA->maxRadiusE = 0; |
| } |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| void bbf_LocalScanner_exit( struct bbs_Context* cpA, |
| struct bbf_LocalScanner* ptrA ) |
| { |
| ptrA->xE = 0; |
| ptrA->yE = 0; |
| ptrA->xOffE = 0; |
| ptrA->yOffE = 0; |
| ptrA->currentWidthE = 0; |
| ptrA->currentHeightE = 0; |
| ptrA->workWidthE = 0; |
| ptrA->workHeightE = 0; |
| ptrA->workImagePtrE = NULL; |
| ptrA->origWidthE = 0; |
| ptrA->origHeightE = 0; |
| ptrA->origImagePtrE = NULL; |
| bbf_BitParam_exit( cpA, &ptrA->bitParamE ); |
| bbs_UInt8Arr_exit( cpA, &ptrA->workImageBufferE ); |
| bim_UInt32Image_exit( cpA, &ptrA->satE ); |
| bim_UInt32Image_exit( cpA, &ptrA->bitImageE ); |
| bbs_UInt32Arr_exit( cpA, &ptrA->patchBufferE ); |
| bts_Int16Rect_exit( cpA, &ptrA->origScanRegionE ); |
| bts_Int16Rect_exit( cpA, &ptrA->workScanRegionE ); |
| |
| ptrA->patchWidthE = 0; |
| ptrA->patchHeightE = 0; |
| ptrA->scaleExpE = 0; |
| ptrA->maxImageWidthE = 0; |
| ptrA->maxImageHeightE = 0; |
| ptrA->minScaleExpE = 0; |
| ptrA->maxRadiusE = 0; |
| } |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| /* ========================================================================= */ |
| /* */ |
| /* ---- \ghd{ operators } -------------------------------------------------- */ |
| /* */ |
| /* ========================================================================= */ |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| void bbf_LocalScanner_copy( struct bbs_Context* cpA, |
| struct bbf_LocalScanner* ptrA, |
| const struct bbf_LocalScanner* srcPtrA ) |
| { |
| bbs_ERROR0( "bbf_LocalScanner_copy:\n Function is not available" ); |
| } |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| flag bbf_LocalScanner_equal( struct bbs_Context* cpA, |
| const struct bbf_LocalScanner* ptrA, |
| const struct bbf_LocalScanner* srcPtrA ) |
| { |
| bbs_ERROR0( "bbf_LocalScanner_equal:\n Function is not available" ); |
| return FALSE; |
| } |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| /* ========================================================================= */ |
| /* */ |
| /* ---- \ghd{ query functions } -------------------------------------------- */ |
| /* */ |
| /* ========================================================================= */ |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| uint32 bbf_LocalScanner_positions( const struct bbf_LocalScanner* ptrA ) |
| { |
| int32 wL = ptrA->workScanRegionE.x2E - ptrA->workScanRegionE.x1E - ptrA->patchWidthE; |
| int32 hL = ptrA->workScanRegionE.y2E - ptrA->workScanRegionE.y1E - ptrA->patchHeightE; |
| return ( ( wL < 0 ) ? 0 : wL ) * ( ( hL < 0 ) ? 0 : hL ); |
| } |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| uint32 bbf_LocalScanner_scanIndex( const struct bbf_LocalScanner* ptrA ) |
| { |
| int32 wL = ptrA->workScanRegionE.x2E - ptrA->workScanRegionE.x1E - ptrA->patchWidthE; |
| return ( ptrA->yE - ptrA->workScanRegionE.y1E ) * wL + ( ptrA->xE - ptrA->workScanRegionE.x1E ); |
| } |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| void bbf_LocalScanner_pos( const struct bbf_LocalScanner* ptrA, int32* xPtrA, int32* yPtrA ) |
| { |
| *xPtrA = ( ( ptrA->xE << ptrA->scaleExpE ) + ptrA->xOffE ) << 16; |
| *yPtrA = ( ( ptrA->yE << ptrA->scaleExpE ) + ptrA->yOffE ) << 16; |
| } |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| void bbf_LocalScanner_idxPos( const struct bbf_LocalScanner* ptrA, uint32 scanIndexA, int32* xPtrA, int32* yPtrA ) |
| { |
| uint32 wL = ptrA->workScanRegionE.x2E - ptrA->workScanRegionE.x1E - ptrA->patchWidthE; |
| int32 xL = ( scanIndexA % wL ) + ptrA->workScanRegionE.x1E; |
| int32 yL = ( scanIndexA / wL ) + ptrA->workScanRegionE.y1E; |
| *xPtrA = ( ( xL << ptrA->scaleExpE ) + ptrA->xOffE ) << 16; |
| *yPtrA = ( ( yL << ptrA->scaleExpE ) + ptrA->yOffE ) << 16; |
| } |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| /* ========================================================================= */ |
| /* */ |
| /* ---- \ghd{ modify functions } ------------------------------------------- */ |
| /* */ |
| /* ========================================================================= */ |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| void bbf_LocalScanner_create( struct bbs_Context* cpA, |
| struct bbf_LocalScanner* ptrA, |
| uint32 patchWidthA, |
| uint32 patchHeightA, |
| uint32 scaleExpA, |
| uint32 maxImageWidthA, |
| uint32 maxImageHeightA, |
| uint32 minScaleExpA, |
| uint32 maxRadiusA, |
| struct bbs_MemTbl* mtpA ) |
| { |
| ptrA->patchWidthE = patchWidthA; |
| ptrA->patchHeightE = patchHeightA; |
| ptrA->scaleExpE = scaleExpA; |
| ptrA->maxImageWidthE = maxImageWidthA; |
| ptrA->maxImageHeightE = maxImageHeightA; |
| ptrA->minScaleExpE = minScaleExpA; |
| ptrA->maxRadiusE = maxRadiusA; |
| bbf_LocalScanner_alloc( cpA, ptrA, mtpA ); |
| } |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| void bbf_LocalScanner_bitParam( struct bbs_Context* cpA, |
| struct bbf_LocalScanner* ptrA, |
| const struct bbf_BitParam* bitParamPtrA ) |
| { |
| if( !bbf_BitParam_equal( cpA, &ptrA->bitParamE, bitParamPtrA ) ) |
| { |
| bbf_BitParam_copy( cpA, &ptrA->bitParamE, bitParamPtrA ); |
| bbf_LocalScanner_createBitImage( cpA, ptrA ); |
| } |
| |
| bbf_LocalScanner_resetScan( cpA, ptrA ); |
| } |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| void bbf_LocalScanner_origScanRegion( struct bbs_Context* cpA, |
| struct bbf_LocalScanner* ptrA, |
| const struct bts_Int16Rect* scanRegionPtrA ) |
| { |
| ptrA->origScanRegionE = *scanRegionPtrA; |
| bbf_LocalScanner_setWorkScanRegion( cpA, ptrA ); |
| bbf_LocalScanner_resetScan( cpA, ptrA ); |
| } |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| /* ========================================================================= */ |
| /* */ |
| /* ---- \ghd{ I/O } -------------------------------------------------------- */ |
| /* */ |
| /* ========================================================================= */ |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| uint32 bbf_LocalScanner_memSize( struct bbs_Context* cpA, |
| const struct bbf_LocalScanner* ptrA ) |
| { |
| uint32 memSizeL = bbs_SIZEOF16( uint32 ) + |
| bbs_SIZEOF16( uint32 ); /* version */ |
| |
| memSizeL += bbs_SIZEOF16( ptrA->patchWidthE ); |
| memSizeL += bbs_SIZEOF16( ptrA->patchHeightE ); |
| memSizeL += bbs_SIZEOF16( ptrA->scaleExpE ); |
| memSizeL += bbs_SIZEOF16( ptrA->maxImageWidthE ); |
| memSizeL += bbs_SIZEOF16( ptrA->maxImageHeightE ); |
| memSizeL += bbs_SIZEOF16( ptrA->minScaleExpE ); |
| memSizeL += bbs_SIZEOF16( ptrA->maxRadiusE ); |
| |
| return memSizeL; |
| } |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| uint32 bbf_LocalScanner_memWrite( struct bbs_Context* cpA, |
| const struct bbf_LocalScanner* ptrA, |
| uint16* memPtrA ) |
| { |
| uint32 memSizeL = bbf_LocalScanner_memSize( cpA, ptrA ); |
| memPtrA += bbs_memWrite32( &memSizeL, memPtrA ); |
| memPtrA += bbs_memWriteUInt32( bbf_LOCAL_SCANNER_VERSION, memPtrA ); |
| |
| memPtrA += bbs_memWrite32( &ptrA->patchWidthE, memPtrA ); |
| memPtrA += bbs_memWrite32( &ptrA->patchHeightE, memPtrA ); |
| memPtrA += bbs_memWrite32( &ptrA->scaleExpE, memPtrA ); |
| memPtrA += bbs_memWrite32( &ptrA->maxImageWidthE, memPtrA ); |
| memPtrA += bbs_memWrite32( &ptrA->maxImageHeightE, memPtrA ); |
| memPtrA += bbs_memWrite32( &ptrA->minScaleExpE, memPtrA ); |
| memPtrA += bbs_memWrite32( &ptrA->maxRadiusE, memPtrA ); |
| return memSizeL; |
| } |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| uint32 bbf_LocalScanner_memRead( struct bbs_Context* cpA, |
| struct bbf_LocalScanner* ptrA, |
| const uint16* memPtrA, |
| struct bbs_MemTbl* mtpA ) |
| { |
| uint32 memSizeL, versionL; |
| |
| if( bbs_Context_error( cpA ) ) return 0; |
| memPtrA += bbs_memRead32( &memSizeL, memPtrA ); |
| memPtrA += bbs_memReadVersion32( cpA, &versionL, bbf_LOCAL_SCANNER_VERSION, memPtrA ); |
| |
| memPtrA += bbs_memRead32( &ptrA->patchWidthE, memPtrA ); |
| memPtrA += bbs_memRead32( &ptrA->patchHeightE, memPtrA ); |
| memPtrA += bbs_memRead32( &ptrA->scaleExpE, memPtrA ); |
| memPtrA += bbs_memRead32( &ptrA->maxImageWidthE, memPtrA ); |
| memPtrA += bbs_memRead32( &ptrA->maxImageHeightE, memPtrA ); |
| memPtrA += bbs_memRead32( &ptrA->minScaleExpE, memPtrA ); |
| memPtrA += bbs_memRead32( &ptrA->maxRadiusE, memPtrA ); |
| |
| if( memSizeL != bbf_LocalScanner_memSize( cpA, ptrA ) ) |
| { |
| bbs_ERR0( bbs_ERR_CORRUPT_DATA, "uint32 bbf_LocalScanner_memRead( struct bem_ScanGradientMove* ptrA, const uint16* memPtrA ):\n" |
| "size mismatch" ); |
| return 0; |
| } |
| |
| if( bbs_Context_error( cpA ) ) return 0; |
| |
| /* allocate arrays */ |
| bbf_LocalScanner_alloc( cpA, ptrA, mtpA ); |
| |
| if( bbs_Context_error( cpA ) ) return 0; |
| |
| return memSizeL; |
| } |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| /* ========================================================================= */ |
| /* */ |
| /* ---- \ghd{ exec functions } --------------------------------------------- */ |
| /* */ |
| /* ========================================================================= */ |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| void bbf_LocalScanner_resetScan( struct bbs_Context* cpA, |
| struct bbf_LocalScanner* ptrA ) |
| { |
| ptrA->xE = ptrA->workScanRegionE.x1E; |
| ptrA->yE = ptrA->workScanRegionE.y1E; |
| bbf_LocalScanner_initPatchBuffer( cpA, ptrA ); |
| } |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| void bbf_LocalScanner_assign( struct bbs_Context* cpA, |
| struct bbf_LocalScanner* ptrA, |
| const uint8* imagePtrA, |
| uint32 imageWidthA, |
| uint32 imageHeightA, |
| const struct bbf_BitParam* paramPtrA ) |
| { |
| if( ptrA->scaleExpE == 0 ) |
| { |
| ptrA->workImagePtrE = imagePtrA; |
| ptrA->workWidthE = imageWidthA; |
| ptrA->workHeightE = imageHeightA; |
| } |
| else |
| { |
| ptrA->origImagePtrE = imagePtrA; |
| ptrA->origWidthE = imageWidthA; |
| ptrA->origHeightE = imageHeightA; |
| } |
| |
| ptrA->bitParamE = *paramPtrA; |
| ptrA->xOffE = 0; |
| ptrA->yOffE = 0; |
| ptrA->origScanRegionE = bts_Int16Rect_create( 0, 0, imageWidthA, imageHeightA ); |
| bbf_LocalScanner_downscale( cpA, ptrA ); |
| bbf_LocalScanner_createBitImage( cpA, ptrA ); |
| bbf_LocalScanner_resetScan( cpA, ptrA ); |
| } |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| const uint32* bbf_LocalScanner_getPatch( const struct bbf_LocalScanner* ptrA ) |
| { |
| return ptrA->patchBufferE.arrPtrE + ptrA->xE; |
| } |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| flag bbf_LocalScanner_next( struct bbs_Context* cpA, struct bbf_LocalScanner* ptrA ) |
| { |
| if( ( ptrA->xE + 1 ) < ptrA->workScanRegionE.x2E - ( int32 )ptrA->patchWidthE ) |
| { |
| ptrA->xE++; |
| return TRUE; |
| } |
| |
| if( ( ptrA->yE + 1 ) >= ptrA->workScanRegionE.y2E - ( int32 )ptrA->patchHeightE ) return FALSE; |
| |
| ptrA->xE = ptrA->workScanRegionE.x1E; |
| ptrA->yE++; |
| |
| { |
| uint32 offL = ( ptrA->yE & 0x1F ); |
| uint32 rowL = ( ptrA->yE >> 5 ) + ( offL > 0 ? 1 : 0 ); |
| |
| uint32 widthL = ptrA->bitImageE.widthE; |
| uint32 sizeL = ptrA->workScanRegionE.x2E - ptrA->workScanRegionE.x1E; |
| uint32* dstL = ( uint32* )ptrA->patchBufferE.arrPtrE + ptrA->xE; |
| uint32 iL; |
| |
| if( rowL < ptrA->bitImageE.heightE ) |
| { |
| uint32* srcL = ptrA->bitImageE.arrE.arrPtrE + rowL * widthL + ptrA->xE; |
| if( offL > 0 ) |
| { |
| uint32 shlL = 32 - offL; |
| for( iL = 0; iL < sizeL; iL++ ) dstL[ iL ] = ( dstL[ iL ] >> 1 ) | ( srcL[ iL ] << shlL ); |
| } |
| else |
| { |
| bbs_memcpy32( dstL, srcL, sizeL ); |
| } |
| } |
| else |
| { |
| for( iL = 0; iL < sizeL; iL++ ) dstL[ iL ] >>= 1; |
| } |
| } |
| |
| return TRUE; |
| } |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| void bbf_LocalScanner_goToXY( struct bbs_Context* cpA, struct bbf_LocalScanner* ptrA, int32 xA, int32 yA ) |
| { |
| bbs_DEF_fNameL( "void bbf_LocalScanner_goToXY( struct bbs_Context* cpA, struct bbf_LocalScanner* ptrA, int32 xA, int32 yA )" ) |
| if( xA < ptrA->workScanRegionE.x1E || xA >= ptrA->workScanRegionE.x2E - ( int32 )ptrA->patchWidthE ) |
| { |
| bbs_ERROR1( "%s:\nxA out of range", fNameL ); |
| return; |
| } |
| ptrA->xE = xA; |
| if( ptrA->yE == yA ) return; |
| if( yA < ptrA->workScanRegionE.y1E || yA >= ptrA->workScanRegionE.y2E - ( int32 )ptrA->patchHeightE ) |
| { |
| bbs_ERROR1( "%s:\nyA out of range", fNameL ); |
| return; |
| } |
| ptrA->yE = yA; |
| |
| { |
| uint32 offL = ( ptrA->yE & 0x1F ); |
| uint32 rowL = ( ptrA->yE >> 5 ) + ( offL > 0 ? 1 : 0 ); |
| |
| uint32 sizeL = ptrA->workScanRegionE.x2E - ptrA->workScanRegionE.x1E; |
| uint32 imgWidthL = ptrA->bitImageE.widthE; |
| uint32 imgOffsL = ptrA->workScanRegionE.x1E; |
| uint32* dstL = ptrA->patchBufferE.arrPtrE + imgOffsL; |
| uint32 iL; |
| |
| if( rowL < ptrA->bitImageE.heightE ) |
| { |
| if( offL > 0 ) |
| { |
| uint32* src1L = ptrA->bitImageE.arrE.arrPtrE + rowL * imgWidthL + imgOffsL; |
| uint32* src0L = src1L - imgWidthL; |
| uint32 shlL = 32 - offL; |
| for( iL = 0; iL < sizeL; iL++ ) dstL[ iL ] = ( src0L[ iL ] >> offL ) | ( src1L[ iL ] << shlL ); |
| } |
| else |
| { |
| bbs_memcpy32( dstL, ptrA->bitImageE.arrE.arrPtrE + rowL * imgWidthL + imgOffsL, sizeL ); |
| } |
| } |
| else |
| { |
| uint32* srcL = ptrA->bitImageE.arrE.arrPtrE + ( rowL - 1 ) * imgWidthL + imgOffsL; |
| for( iL = 0; iL < sizeL; iL++ ) dstL[ iL ] = srcL[ iL ] >> offL; |
| } |
| } |
| } |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| void bbf_LocalScanner_goToIndex( struct bbs_Context* cpA, struct bbf_LocalScanner* ptrA, uint32 scanIndexA ) |
| { |
| uint32 wL = ptrA->workScanRegionE.x2E - ptrA->workScanRegionE.x1E - ptrA->patchWidthE; |
| bbf_LocalScanner_goToXY( cpA, ptrA, |
| ( scanIndexA % wL ) + ptrA->workScanRegionE.x1E, |
| ( scanIndexA / wL ) + ptrA->workScanRegionE.y1E ); |
| } |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| flag bbf_LocalScanner_nextOffset( struct bbs_Context* cpA, struct bbf_LocalScanner* ptrA ) |
| { |
| int32 maxL = ( 1 << ptrA->scaleExpE ); |
| if( ptrA->yOffE == maxL ) return FALSE; |
| |
| ptrA->xOffE++; |
| |
| if( ptrA->xOffE == maxL ) |
| { |
| ptrA->xOffE = 0; |
| ptrA->yOffE++; |
| if( ptrA->yOffE == maxL ) return FALSE; |
| } |
| |
| bbf_LocalScanner_downscale( cpA, ptrA ); |
| bbf_LocalScanner_createBitImage( cpA, ptrA ); |
| bbf_LocalScanner_setWorkScanRegion( cpA, ptrA ); |
| bbf_LocalScanner_resetScan( cpA, ptrA ); |
| |
| return TRUE; |
| } |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| /* ========================================================================= */ |