| /* |
| * 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/Math.h" |
| #include "b_BasicEM/Memory.h" |
| #include "b_BasicEM/Int16Arr.h" |
| #include "b_BasicEM/Int32Arr.h" |
| |
| #include "b_ImageEM/ToneDownBGSupp.h" |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| /* ========================================================================= */ |
| /* */ |
| /* ---- \ghd{ auxiliary functions } ---------------------------------------- */ |
| /* */ |
| /* ========================================================================= */ |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| /* ========================================================================= */ |
| /* */ |
| /* ---- \ghd{ constructor / destructor } ----------------------------------- */ |
| /* */ |
| /* ========================================================================= */ |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| /* ========================================================================= */ |
| /* */ |
| /* ---- \ghd{ operators } -------------------------------------------------- */ |
| /* */ |
| /* ========================================================================= */ |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| /* ========================================================================= */ |
| /* */ |
| /* ---- \ghd{ query functions } -------------------------------------------- */ |
| /* */ |
| /* ========================================================================= */ |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| /* ========================================================================= */ |
| /* */ |
| /* ---- \ghd{ modify functions } ------------------------------------------- */ |
| /* */ |
| /* ========================================================================= */ |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| /* ========================================================================= */ |
| /* */ |
| /* ---- \ghd{ I/O } -------------------------------------------------------- */ |
| /* */ |
| /* ========================================================================= */ |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| /* ========================================================================= */ |
| /* */ |
| /* ---- \ghd{ exec functions } --------------------------------------------- */ |
| /* */ |
| /* ========================================================================= */ |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| void bim_ToneDownBGSupp_BGGreyLevelOutside( struct bim_UInt8Image* imgA, |
| struct bts_Int16Rect* rectA, |
| int16 rectExpansionA, |
| uint32* meanBGGrayLevelA ) |
| { |
| /* image access */ |
| int16 iL, jL; |
| uint8 *imgPtrL = 0; |
| uint8 *imgPtrMaxL = 0; |
| |
| /* the sum is possibly a large number. e.g. for a 512x512 byte image, maximum brightness, sumL is 7x10E7 */ |
| uint32 sumL, ctrL; |
| |
| /* the rectangle vertices */ |
| int16 rectXMinL, rectXMaxL, rectYMinL, rectYMaxL; |
| int16 rectIxXMinL, rectIxXMaxL, rectIxYMinL, rectIxYMaxL; |
| |
| /* expand the rectangle */ |
| |
| /* expand rectangle. the result is called the ROI */ |
| rectXMinL = rectA->x1E + rectExpansionA; |
| rectXMaxL = rectA->x2E - rectExpansionA; |
| rectYMinL = rectA->y1E + rectExpansionA; |
| rectYMaxL = rectA->y2E - rectExpansionA; |
| |
| rectIxXMinL = bbs_max( rectXMinL, ( int16 ) 0 ); |
| rectIxXMaxL = bbs_max( rectXMaxL, ( int16 ) 0 ); |
| rectIxXMaxL = bbs_min( rectXMaxL, ( int16 ) imgA->widthE ); |
| rectIxYMinL = bbs_max( rectYMinL, ( int16 ) 0 ); |
| rectIxYMaxL = bbs_min( rectYMaxL, ( int16 ) 0 ); |
| rectIxYMaxL = bbs_min( rectYMaxL, ( int16 ) imgA->heightE ); |
| |
| /* avoid negative overlap */ |
| rectIxXMinL = bbs_min( rectIxXMinL, rectIxXMaxL ); |
| rectIxYMinL = bbs_min( rectIxYMinL, rectIxYMaxL ); |
| |
| /* printf( "new xmin=%d, xmax=%d, ymin=%d,ymax=%d \n", rectIxXMinL, rectIxXMaxL, rectIxYMinL, rectIxYMaxL ); */ |
| |
| /* part 1: sum up all the lines above the ROI */ |
| |
| sumL = 0; |
| ctrL = 0; |
| |
| imgPtrL = &(imgA->arrE.arrPtrE[ 0 ]); |
| ctrL += rectIxYMinL * imgA->widthE; |
| imgPtrMaxL = imgPtrL + rectIxYMinL * imgA->widthE; |
| while ( imgPtrL < imgPtrMaxL ) |
| { |
| sumL += *imgPtrL; |
| imgPtrL++; |
| } |
| |
| /* part 2: sum up all the lines below the ROI */ |
| |
| ctrL += ( imgA->heightE - rectIxYMaxL ) * imgA->widthE; |
| |
| imgPtrL = &(imgA->arrE.arrPtrE[ rectIxYMaxL * imgA->widthE ]); |
| imgPtrMaxL = &(imgA->arrE.arrPtrE[ imgA->heightE * imgA->widthE ]); |
| while ( imgPtrL < imgPtrMaxL ) |
| { |
| sumL += *imgPtrL; |
| imgPtrL++; |
| } |
| |
| /* part 3: sum over the two vertically adjacent blocks */ |
| |
| for ( jL = rectIxYMinL; jL < rectIxYMaxL; jL++ ) |
| { |
| imgPtrL = &(imgA->arrE.arrPtrE[ rectIxYMinL * imgA->widthE ]); |
| ctrL += bbs_max( 0, rectIxXMinL ); |
| |
| for ( iL = 0; iL < rectIxXMinL; iL++ ) |
| { |
| sumL += imgPtrL[ iL ]; |
| } |
| |
| if( ( int32 )imgA->widthE > ( int32 )rectIxXMaxL ) |
| { |
| ctrL += ( int32 )imgA->widthE - ( int32 )rectIxXMaxL; |
| } |
| |
| for ( iL = rectIxXMaxL; iL < ( int16 ) imgA->widthE; iL++ ) |
| { |
| sumL += imgPtrL[ iL ]; |
| } |
| } |
| |
| /* printf( "new sum = %d, new ctr = %d \n", sumL, ctrL ); */ |
| |
| /* result is bpb=[16.16] */ |
| *meanBGGrayLevelA = ( sumL << 16 ) / ( uint32 ) ctrL; |
| |
| /* result is bpb=[16.16] */ |
| *meanBGGrayLevelA = sumL / ctrL; /* integer division */ |
| sumL = sumL - *meanBGGrayLevelA * ctrL; /* result always greater than or equal to zero */ |
| *meanBGGrayLevelA = *meanBGGrayLevelA << 16; /* shift to left */ |
| *meanBGGrayLevelA = *meanBGGrayLevelA + ( sumL << 16 ) / ctrL; /* add residue */ |
| |
| } |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| void bim_ToneDownBGSupp_BGGreyLevelContour( struct bim_UInt8Image* imgA, |
| struct bts_Int16Rect* rectA, |
| uint32* meanBGGrayLevelA ) |
| { |
| /* image access */ |
| int16 iL; |
| uint8 *imgPtr0L = 0; |
| uint8 *imgPtr1L = 0; |
| |
| /* the sum is possibly a large number. e.g. for a 512x512 byte image, maximum brightness, sumL is 7x10E7 */ |
| uint32 sumL, ctrL; |
| |
| /* the rectangle vertices */ |
| int16 rectXMinL, rectXMaxL, rectYMinL, rectYMaxL; |
| int16 rectIxXMinL, rectIxXMaxL, rectIxYMinL, rectIxYMaxL; |
| int16 rectMinWidthL = 10, rectMinHeightL = 10; |
| int16 rectXMidPointL, rectYMidPointL; |
| int16 shiftXRectL, shiftYRectL; |
| |
| /* cut off the rectangle at the image bounaries |
| * when its size becomes too small |
| * the rectangle is shifted back inside the image */ |
| |
| /* cut off at image boundaries */ |
| rectXMinL = rectA->x1E; |
| rectXMaxL = rectA->x2E; |
| rectYMinL = rectA->y1E; |
| rectYMaxL = rectA->y2E; |
| |
| rectIxXMinL = bbs_max( rectXMinL, ( int16 ) 0 ); |
| rectIxXMaxL = bbs_max( rectXMaxL, ( int16 ) 0 ); |
| rectIxXMaxL = bbs_min( rectXMaxL, ( int16 ) imgA->widthE ); |
| rectIxYMinL = bbs_max( rectYMinL, ( int16 ) 0 ); |
| rectIxYMaxL = bbs_min( rectYMaxL, ( int16 ) 0 ); |
| rectIxYMaxL = bbs_min( rectYMaxL, ( int16 ) imgA->heightE ); |
| |
| /* shift back into image */ |
| shiftXRectL = 0; |
| shiftYRectL = 0; |
| if ( rectIxXMaxL - rectIxXMinL < rectMinWidthL ) |
| { |
| rectXMidPointL = ( rectIxXMaxL + rectIxXMinL ) >> 1; |
| rectIxXMinL = rectXMidPointL - ( rectMinWidthL >> 1 ); |
| rectIxXMaxL = rectXMidPointL + ( rectMinWidthL >> 1 ); |
| |
| if ( rectIxXMinL < 0 ) |
| { |
| shiftXRectL = -rectIxXMinL; |
| } |
| if ( rectIxXMaxL > ( int16 ) imgA->widthE ) |
| { |
| shiftXRectL = rectIxXMaxL - ( int16 ) imgA->widthE; |
| } |
| } |
| if ( rectIxYMaxL - rectIxYMinL < rectMinHeightL ) |
| { |
| rectYMidPointL = ( rectIxYMaxL + rectIxYMinL ) >> 1; |
| rectIxYMinL = rectYMidPointL - ( rectMinWidthL >> 1 ); |
| rectIxYMaxL = rectYMidPointL + ( rectMinWidthL >> 1 ); |
| |
| if ( rectIxYMinL < 0 ) |
| { |
| shiftXRectL = -rectIxYMinL; |
| } |
| if ( rectIxYMaxL > ( int16 ) imgA->widthE ) |
| { |
| shiftXRectL = rectIxYMaxL - ( int16 ) imgA->widthE; |
| } |
| } |
| rectIxXMinL += shiftXRectL; |
| rectIxXMaxL += shiftXRectL; |
| rectIxYMinL += shiftYRectL; |
| rectIxYMaxL += shiftYRectL; |
| |
| /* when the image is small, there is a possibility that the shifted rectangle lies outside of the image. |
| * => lop off the rectangle at image boundaries once again */ |
| rectIxXMinL = bbs_max( rectXMinL, ( int16 ) 0 ); |
| rectIxXMaxL = bbs_min( rectXMaxL, ( int16 ) imgA->widthE ); |
| rectIxYMinL = bbs_max( rectYMinL, ( int16 ) 0 ); |
| rectIxYMaxL = bbs_min( rectYMaxL, ( int16 ) imgA->heightE ); |
| |
| |
| sumL = 0; |
| ctrL = 0; |
| ctrL += ( rectIxXMaxL - rectIxXMinL ) << 1; |
| ctrL += ( rectIxYMaxL - rectIxYMinL - 2 ) << 1; |
| |
| /* loop over the contour */ |
| imgPtr0L = &(imgA->arrE.arrPtrE[ rectIxYMinL * imgA->widthE ]); |
| imgPtr1L = &(imgA->arrE.arrPtrE[ ( rectIxYMaxL - 1 ) * imgA->widthE ]); |
| for ( iL = rectIxXMinL; iL < rectIxXMaxL; iL++ ) |
| { |
| sumL += imgPtr0L[ iL ]; |
| sumL += imgPtr1L[ iL ]; |
| } |
| imgPtr0L = &(imgA->arrE.arrPtrE[ ( rectIxYMinL + 1 ) * imgA->widthE + rectIxXMinL ]); |
| imgPtr1L = &(imgA->arrE.arrPtrE[ ( rectIxYMinL + 1 ) * imgA->widthE + rectIxXMaxL - 1 ]); |
| for ( iL = rectIxYMinL + 1; iL < rectIxYMaxL - 1; iL++ ) |
| { |
| sumL += *imgPtr0L; |
| sumL += *imgPtr1L; |
| imgPtr0L += imgA->widthE; |
| imgPtr1L += imgA->widthE; |
| } |
| |
| |
| /* printf( "new sum = %d, new ctr = %d \n", sumL, ctrL ); */ |
| |
| /* result is bpb=[16.16] */ |
| *meanBGGrayLevelA = ( sumL << 16 ) / ( uint32 ) ctrL; |
| |
| /* result is bpb=[16.16] */ |
| *meanBGGrayLevelA = sumL / ctrL; /* integer division */ |
| sumL = sumL - *meanBGGrayLevelA * ctrL; /* result always greater than or equal to zero */ |
| *meanBGGrayLevelA = *meanBGGrayLevelA << 16; /* shift to left */ |
| *meanBGGrayLevelA = *meanBGGrayLevelA + ( sumL << 16 ) / ctrL; /* add residue */ |
| } |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| void bim_ToneDownBGSupp_suppress( struct bim_UInt8Image* imgA, |
| struct bts_Int16Rect* rectA, |
| int16 rectShrinkageA, |
| int32 toneDownFactorA, /* ToDo: change to int16, bpb=[0.16] */ |
| int32 cutOffAccuracyA ) |
| { |
| /* ((( variable declarations begin ))) */ |
| |
| /* the rectangle vertices */ |
| int16 rectXMinL, rectXMaxL, rectYMinL, rectYMaxL; |
| int16 rectIxXMinL, rectIxXMaxL, rectIxYMinL, rectIxYMaxL; |
| int16 rectShrinkageL; |
| |
| /* the BG mean grey value */ |
| uint8 meanBGGreyBBPL; |
| uint32 meanBGGreyLevelL; |
| uint32 meanBGGreyLevelByteL; |
| int32 meanBGGreyLevelLongL; |
| |
| /* maximum reach of the ROI */ |
| uint32 maxROIReachL; |
| int16 rOIReachXMinL, rOIReachXMaxL, rOIReachYMinL, rOIReachYMaxL; |
| int16 rOIReachIxXMinL, rOIReachIxXMaxL, rOIReachIxYMinL, rOIReachIxYMaxL; |
| int16 ridgeIxLeftL, ridgeIxRightL; |
| |
| /* tone down table */ |
| struct bbs_Int32Arr toneDownFactorsL; /* ToDo: change int32 bpb=[16.16] to uint bpb=[0.16] */ |
| int32 toneDownFactorPowA; |
| int32* toneDownFactorsPtrL; |
| int32 ctrL; |
| |
| /* image access */ |
| int16 iL, jL; |
| uint8 *imgPtrL = 0; /* welcome back to the stoneage */ |
| |
| /* weighting formula */ |
| int32 weightL, invWeightL; /* R=[0.0...1.0], bpb=[16.16] */ |
| int32 opSrcL, opBGL, sumL; /* R=[0.0...255.0], bpb=[24,8] */ |
| |
| /* ((( variable declarations end ))) */ |
| |
| /* make sure that the width is smaller than the rectangle */ |
| rectShrinkageL = rectShrinkageA; |
| rectShrinkageL = bbs_min( rectShrinkageL, ( rectA->x2E - rectA->x1E ) >> 1 ); |
| rectShrinkageL = bbs_min( rectShrinkageL, ( rectA->y2E - rectA->y1E ) >> 1 ); |
| |
| /* shrink rectangle. the result is called the ROI */ |
| rectXMinL = rectA->x1E + rectShrinkageL; |
| rectXMaxL = rectA->x2E - rectShrinkageL; |
| rectYMinL = rectA->y1E + rectShrinkageL; |
| rectYMaxL = rectA->y2E - rectShrinkageL; |
| |
| rectIxXMinL = bbs_max( rectXMinL, 0 ); |
| rectIxXMinL = bbs_min( rectIxXMinL, ( int16 ) imgA->widthE ); |
| rectIxXMaxL = bbs_min( rectXMaxL, ( int16 ) imgA->widthE ); |
| rectIxXMaxL = bbs_max( rectIxXMaxL, 0 ); |
| |
| rectIxYMinL = bbs_max( rectYMinL, 0 ); |
| rectIxYMinL = bbs_min( rectIxYMinL, ( int16 ) imgA->heightE ); |
| rectIxYMaxL = bbs_min( rectYMaxL, ( int16 ) imgA->heightE ); |
| rectIxYMaxL = bbs_max( rectIxYMaxL, 0 ); |
| |
| /* exit function at exceptional cases */ |
| if ( ( imgA->heightE == 0 ) || ( imgA->widthE == 0 ) ) return; |
| if ( rectShrinkageL == 0 ) return; |
| |
| /* compute the mean gray level aloong the rectangle contour */ |
| bim_ToneDownBGSupp_BGGreyLevelContour( imgA, rectA, &meanBGGreyLevelL ); |
| |
| /* printf( "new mean BG gray value = %f \n", ( float ) meanBGGreyLevelL / 65536.0f ); */ |
| |
| /* R=[0.0...255.0], bpb=[24.8] */ |
| meanBGGreyBBPL = 16; |
| meanBGGreyLevelL = ( 128 << meanBGGreyBBPL ); |
| meanBGGreyLevelByteL = meanBGGreyLevelL >> meanBGGreyBBPL; |
| meanBGGreyLevelLongL = ( 128 << meanBGGreyBBPL ); |
| /* ToDo ToDo ToDo ToDo ToDo ToDo ToDo ToDo ToDo ToDo ToDo ToDo ToDo ToDo ToDo ToDo ToDo ToDo ToDo ToDo ToDo */ |
| |
| /* this function computes an image that moving away from the ROI gradually fades to |
| * the background grey level BG according to the formula |
| * tonedImg = w srcImg + (1-w) BG |
| * w depends on the distance to the ROI. |
| * there is a distance maxROIReachL beyond which |
| * the importance of the source image |
| * relative to the BG in the equation |
| * falls below a small threshold. |
| * in those regions the toned image is equal to |
| * the mean BG grey value. i.e. w=0, tonedImg = BG */ |
| maxROIReachL = bbs_max( imgA->widthE, imgA->heightE ); |
| |
| /* pre-compute an array of tone down factors. R=[0.0...1.0] => bpb=[0.16] (idealy, bpb=[16.16] due to missing uInt16Arr ) */ |
| bbs_Int32Arr_init( &toneDownFactorsL ); |
| bbs_Int32Arr_size( &toneDownFactorsL, maxROIReachL ); |
| toneDownFactorPowA = toneDownFactorA; |
| toneDownFactorsPtrL = toneDownFactorsL.arrPtrE; |
| for( ctrL = 0; ctrL < ( int32 ) maxROIReachL && toneDownFactorPowA > cutOffAccuracyA; ctrL++ ) |
| { |
| toneDownFactorsPtrL[ ctrL ] = toneDownFactorPowA; |
| toneDownFactorPowA = toneDownFactorPowA * ( toneDownFactorA >> 1 ); |
| toneDownFactorPowA = toneDownFactorPowA >> 15; |
| |
| /* make active to check the error that accumulates by recursively multiplying factors */ |
| /* printf( "pow = %d, tonedown dec = %d, tonedown float = %f \n", ctrL + 2, toneDownFactorPowA, toneDownFactorPowA / 65536.0f ); */ |
| } |
| maxROIReachL = ctrL; |
| /* printf( "maxROIReachL = %d, tonedown = %d \n", maxROIReachL, toneDownFactorPowA ); */ |
| |
| /* move across the image one row at a time. |
| * (1) fill the outside frame with BG grey level |
| * (2) blend in the original image moving towards the ROI |
| */ |
| |
| rOIReachXMinL = rectXMinL - ( int32 ) maxROIReachL; |
| rOIReachXMaxL = rectXMaxL + ( int32 ) maxROIReachL; |
| rOIReachYMinL = rectYMinL - ( int32 ) maxROIReachL; |
| rOIReachYMaxL = rectYMaxL + ( int32 ) maxROIReachL; |
| |
| rOIReachIxXMinL = bbs_max( rOIReachXMinL, ( int16 ) 0 ); |
| rOIReachIxXMinL = bbs_min( rOIReachIxXMinL, ( int16 ) imgA->widthE ); |
| rOIReachIxXMaxL = bbs_min( rOIReachXMaxL, ( int16 ) imgA->widthE ); |
| rOIReachIxXMaxL = bbs_max( rOIReachIxXMaxL, ( int16 ) 0 ); |
| |
| rOIReachIxYMinL = bbs_max( rOIReachYMinL, ( int16 ) 0 ); |
| rOIReachIxYMinL = bbs_min( rOIReachIxYMinL, ( int16 ) imgA->heightE ); |
| rOIReachIxYMaxL = bbs_min( rOIReachYMaxL, ( int16 ) imgA->heightE ); |
| rOIReachIxYMaxL = bbs_max( rOIReachIxYMaxL, ( int16 ) 0 ); |
| |
| /* (1) far from the ROI the image is filled with the BG grey value */ |
| |
| imgPtrL = 0; |
| for ( jL = 0; jL < rOIReachYMinL; jL++ ) |
| { |
| imgPtrL = &( imgA->arrE.arrPtrE[ jL * imgA->widthE ] ); |
| for ( iL = 0; iL <= ( int16 ) imgA->widthE; iL++ ) |
| { |
| imgPtrL[ iL ] = meanBGGreyLevelByteL; |
| } |
| } |
| for ( jL = rOIReachYMaxL; jL < ( int16 ) imgA->heightE; jL++ ) |
| { |
| imgPtrL = &( imgA->arrE.arrPtrE[ jL * imgA->widthE ] ); |
| for ( iL = 0; iL <= ( int16 ) imgA->widthE; iL++ ) |
| { |
| imgPtrL[ iL ] = meanBGGreyLevelByteL; |
| } |
| } |
| for ( jL = rOIReachIxYMinL; jL < rOIReachIxYMaxL; jL++ ) |
| { |
| imgPtrL = &( imgA->arrE.arrPtrE[ jL * imgA->widthE ] ); |
| for ( iL = 0; iL < rOIReachXMinL; iL++ ) |
| { |
| imgPtrL[ iL ] = meanBGGreyLevelByteL; |
| } |
| for ( iL = rOIReachXMaxL; iL < ( int16 ) imgA->widthE; iL++ ) |
| { |
| imgPtrL[ iL ] = meanBGGreyLevelByteL; |
| } |
| } |
| |
| /* (2) blend from ROI to outside regions */ |
| |
| for ( jL = rOIReachIxYMinL; jL < rectIxYMinL; jL++ ) |
| { |
| /* the factor for one row is a constant */ |
| weightL = ( int32 ) toneDownFactorsPtrL[ maxROIReachL - 1 - ( jL - rOIReachYMinL ) ]; |
| invWeightL = 0x00010000 - weightL; |
| opBGL = ( meanBGGreyLevelLongL >> 9 ) * invWeightL; /* result is bpb=[8,24] */ |
| opBGL = opBGL >> 7; |
| imgPtrL = &( imgA->arrE.arrPtrE[ jL * imgA->widthE ] ); |
| |
| /* compute the ridge position */ |
| ridgeIxLeftL = bbs_max( 0, rOIReachXMinL + jL - rOIReachYMinL ); |
| ridgeIxRightL = bbs_min( ( int16 ) imgA->widthE - 1, rOIReachXMaxL - 1 - ( jL - rOIReachYMinL ) ); |
| |
| /* loop over all elements from left ridge through right ridge */ |
| for ( iL = ridgeIxLeftL; iL <= ridgeIxRightL; iL++ ) |
| { |
| opSrcL = imgPtrL[ iL ]; /* leave at byte */ |
| opSrcL = opSrcL * weightL; /* result is bpb=[16,16] */ |
| sumL = opSrcL + opBGL; /* OF impossible */ |
| imgPtrL[ iL ] = sumL >> 16; /* round to byte */ |
| } |
| } |
| for ( jL = rOIReachIxYMaxL - 1; jL >= rectIxYMaxL; jL-- ) |
| { |
| /* the factor for one row is a constant */ |
| weightL = ( int32 ) toneDownFactorsPtrL[ maxROIReachL - 1 - ( rOIReachYMaxL - 1 - jL ) ]; |
| invWeightL = 0x00010000 - weightL; |
| opBGL = ( meanBGGreyLevelLongL >> 9 ) * invWeightL; /* result is bpb=[8,24] */ |
| opBGL = opBGL >> 7; |
| imgPtrL = &( imgA->arrE.arrPtrE[ jL * imgA->widthE ] ); |
| |
| /* compute the ridge position */ |
| ridgeIxLeftL = bbs_max( 0, rOIReachXMinL + ( rOIReachYMaxL - 1 - jL ) ); |
| ridgeIxRightL = bbs_min( ( int16 ) imgA->widthE - 1, rOIReachXMaxL - 1 - ( rOIReachYMaxL - 1 - jL ) ); |
| |
| /* loop over all elements from left ridge through right ridge */ |
| for ( iL = ridgeIxLeftL; iL <= ridgeIxRightL; iL++ ) |
| { |
| opSrcL = imgPtrL[ iL ]; /* leave at byte */ |
| opSrcL = opSrcL * weightL; /* result is bpb=[16,16] */ |
| sumL = opSrcL + opBGL; /* OF impossible */ |
| imgPtrL[ iL ] = sumL >> 16; /* round to byte */ |
| } |
| } |
| for ( jL = rOIReachIxYMinL; jL < rOIReachIxYMaxL; jL++ ) |
| { |
| imgPtrL = &( imgA->arrE.arrPtrE[ jL * imgA->widthE ] ); |
| |
| ridgeIxLeftL = bbs_min( rOIReachXMinL + ( jL - rOIReachYMinL ) - 1, rectXMinL - 1 ); |
| ridgeIxLeftL = bbs_min( ridgeIxLeftL, rOIReachXMinL + ( rOIReachYMaxL - 1 - jL ) - 1 ); |
| for ( iL = rOIReachIxXMinL; iL <= ridgeIxLeftL; iL++ ) |
| { |
| weightL = ( int32 ) toneDownFactorsPtrL[ maxROIReachL - 1 - ( iL - rOIReachXMinL ) ]; |
| invWeightL = 0x00010000 - weightL; |
| opBGL = ( meanBGGreyLevelLongL >> 9 ) * invWeightL; /* result is bpb=[16,16] */ |
| opBGL = opBGL >> 7; |
| |
| opSrcL = imgPtrL[ iL ]; /* leave at byte */ |
| opSrcL = opSrcL * weightL; /* result is bpb=[16,16] */ |
| sumL = opSrcL + opBGL; /* OF impossible */ |
| imgPtrL[ iL ] = sumL >> 16; /* round to byte */ |
| } |
| |
| ridgeIxRightL = bbs_max( rOIReachXMaxL - 1 - ( jL - rOIReachYMinL ) + 1 , rectXMaxL ); |
| ridgeIxRightL = bbs_max( ridgeIxRightL, rOIReachXMaxL - 1 - ( rOIReachYMaxL - 1 - jL ) + 1 ); |
| for ( iL = ridgeIxRightL; iL < rOIReachIxXMaxL; iL++ ) |
| { |
| weightL = ( int32 ) toneDownFactorsPtrL[ iL - rectXMaxL ]; |
| invWeightL = 0x00010000 - weightL; |
| opBGL = ( meanBGGreyLevelLongL >> 9 ) * invWeightL; /* result is bpb=[16,16] */ |
| opBGL = opBGL >> 7; |
| |
| opSrcL = imgPtrL[ iL ]; /* leave at byte */ |
| opSrcL = opSrcL * weightL; /* result is bpb=[16,16] */ |
| sumL = opSrcL + opBGL; /* OF impossible */ |
| imgPtrL[ iL ] = sumL >> 16; /* round to byte */ |
| } |
| } |
| } |
| |
| /* ------------------------------------------------------------------------- */ |
| |
| /* ========================================================================= */ |