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/Math.h" 20 #include "b_BasicEM/Memory.h" 21 #include "b_BasicEM/Int16Arr.h" 22 #include "b_BasicEM/Int32Arr.h" 23 24 #include "b_ImageEM/ToneDownBGSupp.h" 25 26 /* ------------------------------------------------------------------------- */ 27 28 /* ========================================================================= */ 29 /* */ 30 /* ---- \ghd{ auxiliary functions } ---------------------------------------- */ 31 /* */ 32 /* ========================================================================= */ 33 34 /* ------------------------------------------------------------------------- */ 35 36 /* ========================================================================= */ 37 /* */ 38 /* ---- \ghd{ constructor / destructor } ----------------------------------- */ 39 /* */ 40 /* ========================================================================= */ 41 42 /* ------------------------------------------------------------------------- */ 43 44 /* ========================================================================= */ 45 /* */ 46 /* ---- \ghd{ operators } -------------------------------------------------- */ 47 /* */ 48 /* ========================================================================= */ 49 50 /* ------------------------------------------------------------------------- */ 51 52 /* ========================================================================= */ 53 /* */ 54 /* ---- \ghd{ query functions } -------------------------------------------- */ 55 /* */ 56 /* ========================================================================= */ 57 58 /* ------------------------------------------------------------------------- */ 59 60 /* ========================================================================= */ 61 /* */ 62 /* ---- \ghd{ modify functions } ------------------------------------------- */ 63 /* */ 64 /* ========================================================================= */ 65 66 /* ------------------------------------------------------------------------- */ 67 68 /* ------------------------------------------------------------------------- */ 69 70 /* ========================================================================= */ 71 /* */ 72 /* ---- \ghd{ I/O } -------------------------------------------------------- */ 73 /* */ 74 /* ========================================================================= */ 75 76 /* ------------------------------------------------------------------------- */ 77 78 /* ========================================================================= */ 79 /* */ 80 /* ---- \ghd{ exec functions } --------------------------------------------- */ 81 /* */ 82 /* ========================================================================= */ 83 84 /* ------------------------------------------------------------------------- */ 85 86 void bim_ToneDownBGSupp_BGGreyLevelOutside( struct bim_UInt8Image* imgA, 87 struct bts_Int16Rect* rectA, 88 int16 rectExpansionA, 89 uint32* meanBGGrayLevelA ) 90 { 91 /* image access */ 92 int16 iL, jL; 93 uint8 *imgPtrL = 0; 94 uint8 *imgPtrMaxL = 0; 95 96 /* the sum is possibly a large number. e.g. for a 512x512 byte image, maximum brightness, sumL is 7x10E7 */ 97 uint32 sumL, ctrL; 98 99 /* the rectangle vertices */ 100 int16 rectXMinL, rectXMaxL, rectYMinL, rectYMaxL; 101 int16 rectIxXMinL, rectIxXMaxL, rectIxYMinL, rectIxYMaxL; 102 103 /* expand the rectangle */ 104 105 /* expand rectangle. the result is called the ROI */ 106 rectXMinL = rectA->x1E + rectExpansionA; 107 rectXMaxL = rectA->x2E - rectExpansionA; 108 rectYMinL = rectA->y1E + rectExpansionA; 109 rectYMaxL = rectA->y2E - rectExpansionA; 110 111 rectIxXMinL = bbs_max( rectXMinL, ( int16 ) 0 ); 112 rectIxXMaxL = bbs_max( rectXMaxL, ( int16 ) 0 ); 113 rectIxXMaxL = bbs_min( rectXMaxL, ( int16 ) imgA->widthE ); 114 rectIxYMinL = bbs_max( rectYMinL, ( int16 ) 0 ); 115 rectIxYMaxL = bbs_min( rectYMaxL, ( int16 ) 0 ); 116 rectIxYMaxL = bbs_min( rectYMaxL, ( int16 ) imgA->heightE ); 117 118 /* avoid negative overlap */ 119 rectIxXMinL = bbs_min( rectIxXMinL, rectIxXMaxL ); 120 rectIxYMinL = bbs_min( rectIxYMinL, rectIxYMaxL ); 121 122 /* printf( "new xmin=%d, xmax=%d, ymin=%d,ymax=%d \n", rectIxXMinL, rectIxXMaxL, rectIxYMinL, rectIxYMaxL ); */ 123 124 /* part 1: sum up all the lines above the ROI */ 125 126 sumL = 0; 127 ctrL = 0; 128 129 imgPtrL = &(imgA->arrE.arrPtrE[ 0 ]); 130 ctrL += rectIxYMinL * imgA->widthE; 131 imgPtrMaxL = imgPtrL + rectIxYMinL * imgA->widthE; 132 while ( imgPtrL < imgPtrMaxL ) 133 { 134 sumL += *imgPtrL; 135 imgPtrL++; 136 } 137 138 /* part 2: sum up all the lines below the ROI */ 139 140 ctrL += ( imgA->heightE - rectIxYMaxL ) * imgA->widthE; 141 142 imgPtrL = &(imgA->arrE.arrPtrE[ rectIxYMaxL * imgA->widthE ]); 143 imgPtrMaxL = &(imgA->arrE.arrPtrE[ imgA->heightE * imgA->widthE ]); 144 while ( imgPtrL < imgPtrMaxL ) 145 { 146 sumL += *imgPtrL; 147 imgPtrL++; 148 } 149 150 /* part 3: sum over the two vertically adjacent blocks */ 151 152 for ( jL = rectIxYMinL; jL < rectIxYMaxL; jL++ ) 153 { 154 imgPtrL = &(imgA->arrE.arrPtrE[ rectIxYMinL * imgA->widthE ]); 155 ctrL += bbs_max( 0, rectIxXMinL ); 156 157 for ( iL = 0; iL < rectIxXMinL; iL++ ) 158 { 159 sumL += imgPtrL[ iL ]; 160 } 161 162 if( ( int32 )imgA->widthE > ( int32 )rectIxXMaxL ) 163 { 164 ctrL += ( int32 )imgA->widthE - ( int32 )rectIxXMaxL; 165 } 166 167 for ( iL = rectIxXMaxL; iL < ( int16 ) imgA->widthE; iL++ ) 168 { 169 sumL += imgPtrL[ iL ]; 170 } 171 } 172 173 /* printf( "new sum = %d, new ctr = %d \n", sumL, ctrL ); */ 174 175 /* result is bpb=[16.16] */ 176 *meanBGGrayLevelA = ( sumL << 16 ) / ( uint32 ) ctrL; 177 178 /* result is bpb=[16.16] */ 179 *meanBGGrayLevelA = sumL / ctrL; /* integer division */ 180 sumL = sumL - *meanBGGrayLevelA * ctrL; /* result always greater than or equal to zero */ 181 *meanBGGrayLevelA = *meanBGGrayLevelA << 16; /* shift to left */ 182 *meanBGGrayLevelA = *meanBGGrayLevelA + ( sumL << 16 ) / ctrL; /* add residue */ 183 184 } 185 186 /* ------------------------------------------------------------------------- */ 187 188 void bim_ToneDownBGSupp_BGGreyLevelContour( struct bim_UInt8Image* imgA, 189 struct bts_Int16Rect* rectA, 190 uint32* meanBGGrayLevelA ) 191 { 192 /* image access */ 193 int16 iL; 194 uint8 *imgPtr0L = 0; 195 uint8 *imgPtr1L = 0; 196 197 /* the sum is possibly a large number. e.g. for a 512x512 byte image, maximum brightness, sumL is 7x10E7 */ 198 uint32 sumL, ctrL; 199 200 /* the rectangle vertices */ 201 int16 rectXMinL, rectXMaxL, rectYMinL, rectYMaxL; 202 int16 rectIxXMinL, rectIxXMaxL, rectIxYMinL, rectIxYMaxL; 203 int16 rectMinWidthL = 10, rectMinHeightL = 10; 204 int16 rectXMidPointL, rectYMidPointL; 205 int16 shiftXRectL, shiftYRectL; 206 207 /* cut off the rectangle at the image bounaries 208 * when its size becomes too small 209 * the rectangle is shifted back inside the image */ 210 211 /* cut off at image boundaries */ 212 rectXMinL = rectA->x1E; 213 rectXMaxL = rectA->x2E; 214 rectYMinL = rectA->y1E; 215 rectYMaxL = rectA->y2E; 216 217 rectIxXMinL = bbs_max( rectXMinL, ( int16 ) 0 ); 218 rectIxXMaxL = bbs_max( rectXMaxL, ( int16 ) 0 ); 219 rectIxXMaxL = bbs_min( rectXMaxL, ( int16 ) imgA->widthE ); 220 rectIxYMinL = bbs_max( rectYMinL, ( int16 ) 0 ); 221 rectIxYMaxL = bbs_min( rectYMaxL, ( int16 ) 0 ); 222 rectIxYMaxL = bbs_min( rectYMaxL, ( int16 ) imgA->heightE ); 223 224 /* shift back into image */ 225 shiftXRectL = 0; 226 shiftYRectL = 0; 227 if ( rectIxXMaxL - rectIxXMinL < rectMinWidthL ) 228 { 229 rectXMidPointL = ( rectIxXMaxL + rectIxXMinL ) >> 1; 230 rectIxXMinL = rectXMidPointL - ( rectMinWidthL >> 1 ); 231 rectIxXMaxL = rectXMidPointL + ( rectMinWidthL >> 1 ); 232 233 if ( rectIxXMinL < 0 ) 234 { 235 shiftXRectL = -rectIxXMinL; 236 } 237 if ( rectIxXMaxL > ( int16 ) imgA->widthE ) 238 { 239 shiftXRectL = rectIxXMaxL - ( int16 ) imgA->widthE; 240 } 241 } 242 if ( rectIxYMaxL - rectIxYMinL < rectMinHeightL ) 243 { 244 rectYMidPointL = ( rectIxYMaxL + rectIxYMinL ) >> 1; 245 rectIxYMinL = rectYMidPointL - ( rectMinWidthL >> 1 ); 246 rectIxYMaxL = rectYMidPointL + ( rectMinWidthL >> 1 ); 247 248 if ( rectIxYMinL < 0 ) 249 { 250 shiftXRectL = -rectIxYMinL; 251 } 252 if ( rectIxYMaxL > ( int16 ) imgA->widthE ) 253 { 254 shiftXRectL = rectIxYMaxL - ( int16 ) imgA->widthE; 255 } 256 } 257 rectIxXMinL += shiftXRectL; 258 rectIxXMaxL += shiftXRectL; 259 rectIxYMinL += shiftYRectL; 260 rectIxYMaxL += shiftYRectL; 261 262 /* when the image is small, there is a possibility that the shifted rectangle lies outside of the image. 263 * => lop off the rectangle at image boundaries once again */ 264 rectIxXMinL = bbs_max( rectXMinL, ( int16 ) 0 ); 265 rectIxXMaxL = bbs_min( rectXMaxL, ( int16 ) imgA->widthE ); 266 rectIxYMinL = bbs_max( rectYMinL, ( int16 ) 0 ); 267 rectIxYMaxL = bbs_min( rectYMaxL, ( int16 ) imgA->heightE ); 268 269 270 sumL = 0; 271 ctrL = 0; 272 ctrL += ( rectIxXMaxL - rectIxXMinL ) << 1; 273 ctrL += ( rectIxYMaxL - rectIxYMinL - 2 ) << 1; 274 275 /* loop over the contour */ 276 imgPtr0L = &(imgA->arrE.arrPtrE[ rectIxYMinL * imgA->widthE ]); 277 imgPtr1L = &(imgA->arrE.arrPtrE[ ( rectIxYMaxL - 1 ) * imgA->widthE ]); 278 for ( iL = rectIxXMinL; iL < rectIxXMaxL; iL++ ) 279 { 280 sumL += imgPtr0L[ iL ]; 281 sumL += imgPtr1L[ iL ]; 282 } 283 imgPtr0L = &(imgA->arrE.arrPtrE[ ( rectIxYMinL + 1 ) * imgA->widthE + rectIxXMinL ]); 284 imgPtr1L = &(imgA->arrE.arrPtrE[ ( rectIxYMinL + 1 ) * imgA->widthE + rectIxXMaxL - 1 ]); 285 for ( iL = rectIxYMinL + 1; iL < rectIxYMaxL - 1; iL++ ) 286 { 287 sumL += *imgPtr0L; 288 sumL += *imgPtr1L; 289 imgPtr0L += imgA->widthE; 290 imgPtr1L += imgA->widthE; 291 } 292 293 294 /* printf( "new sum = %d, new ctr = %d \n", sumL, ctrL ); */ 295 296 /* result is bpb=[16.16] */ 297 *meanBGGrayLevelA = ( sumL << 16 ) / ( uint32 ) ctrL; 298 299 /* result is bpb=[16.16] */ 300 *meanBGGrayLevelA = sumL / ctrL; /* integer division */ 301 sumL = sumL - *meanBGGrayLevelA * ctrL; /* result always greater than or equal to zero */ 302 *meanBGGrayLevelA = *meanBGGrayLevelA << 16; /* shift to left */ 303 *meanBGGrayLevelA = *meanBGGrayLevelA + ( sumL << 16 ) / ctrL; /* add residue */ 304 } 305 306 /* ------------------------------------------------------------------------- */ 307 308 void bim_ToneDownBGSupp_suppress( struct bim_UInt8Image* imgA, 309 struct bts_Int16Rect* rectA, 310 int16 rectShrinkageA, 311 int32 toneDownFactorA, /* ToDo: change to int16, bpb=[0.16] */ 312 int32 cutOffAccuracyA ) 313 { 314 /* ((( variable declarations begin ))) */ 315 316 /* the rectangle vertices */ 317 int16 rectXMinL, rectXMaxL, rectYMinL, rectYMaxL; 318 int16 rectIxXMinL, rectIxXMaxL, rectIxYMinL, rectIxYMaxL; 319 int16 rectShrinkageL; 320 321 /* the BG mean grey value */ 322 uint8 meanBGGreyBBPL; 323 uint32 meanBGGreyLevelL; 324 uint32 meanBGGreyLevelByteL; 325 int32 meanBGGreyLevelLongL; 326 327 /* maximum reach of the ROI */ 328 uint32 maxROIReachL; 329 int16 rOIReachXMinL, rOIReachXMaxL, rOIReachYMinL, rOIReachYMaxL; 330 int16 rOIReachIxXMinL, rOIReachIxXMaxL, rOIReachIxYMinL, rOIReachIxYMaxL; 331 int16 ridgeIxLeftL, ridgeIxRightL; 332 333 /* tone down table */ 334 struct bbs_Int32Arr toneDownFactorsL; /* ToDo: change int32 bpb=[16.16] to uint bpb=[0.16] */ 335 int32 toneDownFactorPowA; 336 int32* toneDownFactorsPtrL; 337 int32 ctrL; 338 339 /* image access */ 340 int16 iL, jL; 341 uint8 *imgPtrL = 0; /* welcome back to the stoneage */ 342 343 /* weighting formula */ 344 int32 weightL, invWeightL; /* R=[0.0...1.0], bpb=[16.16] */ 345 int32 opSrcL, opBGL, sumL; /* R=[0.0...255.0], bpb=[24,8] */ 346 347 /* ((( variable declarations end ))) */ 348 349 /* make sure that the width is smaller than the rectangle */ 350 rectShrinkageL = rectShrinkageA; 351 rectShrinkageL = bbs_min( rectShrinkageL, ( rectA->x2E - rectA->x1E ) >> 1 ); 352 rectShrinkageL = bbs_min( rectShrinkageL, ( rectA->y2E - rectA->y1E ) >> 1 ); 353 354 /* shrink rectangle. the result is called the ROI */ 355 rectXMinL = rectA->x1E + rectShrinkageL; 356 rectXMaxL = rectA->x2E - rectShrinkageL; 357 rectYMinL = rectA->y1E + rectShrinkageL; 358 rectYMaxL = rectA->y2E - rectShrinkageL; 359 360 rectIxXMinL = bbs_max( rectXMinL, 0 ); 361 rectIxXMinL = bbs_min( rectIxXMinL, ( int16 ) imgA->widthE ); 362 rectIxXMaxL = bbs_min( rectXMaxL, ( int16 ) imgA->widthE ); 363 rectIxXMaxL = bbs_max( rectIxXMaxL, 0 ); 364 365 rectIxYMinL = bbs_max( rectYMinL, 0 ); 366 rectIxYMinL = bbs_min( rectIxYMinL, ( int16 ) imgA->heightE ); 367 rectIxYMaxL = bbs_min( rectYMaxL, ( int16 ) imgA->heightE ); 368 rectIxYMaxL = bbs_max( rectIxYMaxL, 0 ); 369 370 /* exit function at exceptional cases */ 371 if ( ( imgA->heightE == 0 ) || ( imgA->widthE == 0 ) ) return; 372 if ( rectShrinkageL == 0 ) return; 373 374 /* compute the mean gray level aloong the rectangle contour */ 375 bim_ToneDownBGSupp_BGGreyLevelContour( imgA, rectA, &meanBGGreyLevelL ); 376 377 /* printf( "new mean BG gray value = %f \n", ( float ) meanBGGreyLevelL / 65536.0f ); */ 378 379 /* R=[0.0...255.0], bpb=[24.8] */ 380 meanBGGreyBBPL = 16; 381 meanBGGreyLevelL = ( 128 << meanBGGreyBBPL ); 382 meanBGGreyLevelByteL = meanBGGreyLevelL >> meanBGGreyBBPL; 383 meanBGGreyLevelLongL = ( 128 << meanBGGreyBBPL ); 384 /* ToDo ToDo ToDo ToDo ToDo ToDo ToDo ToDo ToDo ToDo ToDo ToDo ToDo ToDo ToDo ToDo ToDo ToDo ToDo ToDo ToDo */ 385 386 /* this function computes an image that moving away from the ROI gradually fades to 387 * the background grey level BG according to the formula 388 * tonedImg = w srcImg + (1-w) BG 389 * w depends on the distance to the ROI. 390 * there is a distance maxROIReachL beyond which 391 * the importance of the source image 392 * relative to the BG in the equation 393 * falls below a small threshold. 394 * in those regions the toned image is equal to 395 * the mean BG grey value. i.e. w=0, tonedImg = BG */ 396 maxROIReachL = bbs_max( imgA->widthE, imgA->heightE ); 397 398 /* pre-compute an array of tone down factors. R=[0.0...1.0] => bpb=[0.16] (idealy, bpb=[16.16] due to missing uInt16Arr ) */ 399 bbs_Int32Arr_init( &toneDownFactorsL ); 400 bbs_Int32Arr_size( &toneDownFactorsL, maxROIReachL ); 401 toneDownFactorPowA = toneDownFactorA; 402 toneDownFactorsPtrL = toneDownFactorsL.arrPtrE; 403 for( ctrL = 0; ctrL < ( int32 ) maxROIReachL && toneDownFactorPowA > cutOffAccuracyA; ctrL++ ) 404 { 405 toneDownFactorsPtrL[ ctrL ] = toneDownFactorPowA; 406 toneDownFactorPowA = toneDownFactorPowA * ( toneDownFactorA >> 1 ); 407 toneDownFactorPowA = toneDownFactorPowA >> 15; 408 409 /* make active to check the error that accumulates by recursively multiplying factors */ 410 /* printf( "pow = %d, tonedown dec = %d, tonedown float = %f \n", ctrL + 2, toneDownFactorPowA, toneDownFactorPowA / 65536.0f ); */ 411 } 412 maxROIReachL = ctrL; 413 /* printf( "maxROIReachL = %d, tonedown = %d \n", maxROIReachL, toneDownFactorPowA ); */ 414 415 /* move across the image one row at a time. 416 * (1) fill the outside frame with BG grey level 417 * (2) blend in the original image moving towards the ROI 418 */ 419 420 rOIReachXMinL = rectXMinL - ( int32 ) maxROIReachL; 421 rOIReachXMaxL = rectXMaxL + ( int32 ) maxROIReachL; 422 rOIReachYMinL = rectYMinL - ( int32 ) maxROIReachL; 423 rOIReachYMaxL = rectYMaxL + ( int32 ) maxROIReachL; 424 425 rOIReachIxXMinL = bbs_max( rOIReachXMinL, ( int16 ) 0 ); 426 rOIReachIxXMinL = bbs_min( rOIReachIxXMinL, ( int16 ) imgA->widthE ); 427 rOIReachIxXMaxL = bbs_min( rOIReachXMaxL, ( int16 ) imgA->widthE ); 428 rOIReachIxXMaxL = bbs_max( rOIReachIxXMaxL, ( int16 ) 0 ); 429 430 rOIReachIxYMinL = bbs_max( rOIReachYMinL, ( int16 ) 0 ); 431 rOIReachIxYMinL = bbs_min( rOIReachIxYMinL, ( int16 ) imgA->heightE ); 432 rOIReachIxYMaxL = bbs_min( rOIReachYMaxL, ( int16 ) imgA->heightE ); 433 rOIReachIxYMaxL = bbs_max( rOIReachIxYMaxL, ( int16 ) 0 ); 434 435 /* (1) far from the ROI the image is filled with the BG grey value */ 436 437 imgPtrL = 0; 438 for ( jL = 0; jL < rOIReachYMinL; jL++ ) 439 { 440 imgPtrL = &( imgA->arrE.arrPtrE[ jL * imgA->widthE ] ); 441 for ( iL = 0; iL <= ( int16 ) imgA->widthE; iL++ ) 442 { 443 imgPtrL[ iL ] = meanBGGreyLevelByteL; 444 } 445 } 446 for ( jL = rOIReachYMaxL; jL < ( int16 ) imgA->heightE; jL++ ) 447 { 448 imgPtrL = &( imgA->arrE.arrPtrE[ jL * imgA->widthE ] ); 449 for ( iL = 0; iL <= ( int16 ) imgA->widthE; iL++ ) 450 { 451 imgPtrL[ iL ] = meanBGGreyLevelByteL; 452 } 453 } 454 for ( jL = rOIReachIxYMinL; jL < rOIReachIxYMaxL; jL++ ) 455 { 456 imgPtrL = &( imgA->arrE.arrPtrE[ jL * imgA->widthE ] ); 457 for ( iL = 0; iL < rOIReachXMinL; iL++ ) 458 { 459 imgPtrL[ iL ] = meanBGGreyLevelByteL; 460 } 461 for ( iL = rOIReachXMaxL; iL < ( int16 ) imgA->widthE; iL++ ) 462 { 463 imgPtrL[ iL ] = meanBGGreyLevelByteL; 464 } 465 } 466 467 /* (2) blend from ROI to outside regions */ 468 469 for ( jL = rOIReachIxYMinL; jL < rectIxYMinL; jL++ ) 470 { 471 /* the factor for one row is a constant */ 472 weightL = ( int32 ) toneDownFactorsPtrL[ maxROIReachL - 1 - ( jL - rOIReachYMinL ) ]; 473 invWeightL = 0x00010000 - weightL; 474 opBGL = ( meanBGGreyLevelLongL >> 9 ) * invWeightL; /* result is bpb=[8,24] */ 475 opBGL = opBGL >> 7; 476 imgPtrL = &( imgA->arrE.arrPtrE[ jL * imgA->widthE ] ); 477 478 /* compute the ridge position */ 479 ridgeIxLeftL = bbs_max( 0, rOIReachXMinL + jL - rOIReachYMinL ); 480 ridgeIxRightL = bbs_min( ( int16 ) imgA->widthE - 1, rOIReachXMaxL - 1 - ( jL - rOIReachYMinL ) ); 481 482 /* loop over all elements from left ridge through right ridge */ 483 for ( iL = ridgeIxLeftL; iL <= ridgeIxRightL; iL++ ) 484 { 485 opSrcL = imgPtrL[ iL ]; /* leave at byte */ 486 opSrcL = opSrcL * weightL; /* result is bpb=[16,16] */ 487 sumL = opSrcL + opBGL; /* OF impossible */ 488 imgPtrL[ iL ] = sumL >> 16; /* round to byte */ 489 } 490 } 491 for ( jL = rOIReachIxYMaxL - 1; jL >= rectIxYMaxL; jL-- ) 492 { 493 /* the factor for one row is a constant */ 494 weightL = ( int32 ) toneDownFactorsPtrL[ maxROIReachL - 1 - ( rOIReachYMaxL - 1 - jL ) ]; 495 invWeightL = 0x00010000 - weightL; 496 opBGL = ( meanBGGreyLevelLongL >> 9 ) * invWeightL; /* result is bpb=[8,24] */ 497 opBGL = opBGL >> 7; 498 imgPtrL = &( imgA->arrE.arrPtrE[ jL * imgA->widthE ] ); 499 500 /* compute the ridge position */ 501 ridgeIxLeftL = bbs_max( 0, rOIReachXMinL + ( rOIReachYMaxL - 1 - jL ) ); 502 ridgeIxRightL = bbs_min( ( int16 ) imgA->widthE - 1, rOIReachXMaxL - 1 - ( rOIReachYMaxL - 1 - jL ) ); 503 504 /* loop over all elements from left ridge through right ridge */ 505 for ( iL = ridgeIxLeftL; iL <= ridgeIxRightL; iL++ ) 506 { 507 opSrcL = imgPtrL[ iL ]; /* leave at byte */ 508 opSrcL = opSrcL * weightL; /* result is bpb=[16,16] */ 509 sumL = opSrcL + opBGL; /* OF impossible */ 510 imgPtrL[ iL ] = sumL >> 16; /* round to byte */ 511 } 512 } 513 for ( jL = rOIReachIxYMinL; jL < rOIReachIxYMaxL; jL++ ) 514 { 515 imgPtrL = &( imgA->arrE.arrPtrE[ jL * imgA->widthE ] ); 516 517 ridgeIxLeftL = bbs_min( rOIReachXMinL + ( jL - rOIReachYMinL ) - 1, rectXMinL - 1 ); 518 ridgeIxLeftL = bbs_min( ridgeIxLeftL, rOIReachXMinL + ( rOIReachYMaxL - 1 - jL ) - 1 ); 519 for ( iL = rOIReachIxXMinL; iL <= ridgeIxLeftL; iL++ ) 520 { 521 weightL = ( int32 ) toneDownFactorsPtrL[ maxROIReachL - 1 - ( iL - rOIReachXMinL ) ]; 522 invWeightL = 0x00010000 - weightL; 523 opBGL = ( meanBGGreyLevelLongL >> 9 ) * invWeightL; /* result is bpb=[16,16] */ 524 opBGL = opBGL >> 7; 525 526 opSrcL = imgPtrL[ iL ]; /* leave at byte */ 527 opSrcL = opSrcL * weightL; /* result is bpb=[16,16] */ 528 sumL = opSrcL + opBGL; /* OF impossible */ 529 imgPtrL[ iL ] = sumL >> 16; /* round to byte */ 530 } 531 532 ridgeIxRightL = bbs_max( rOIReachXMaxL - 1 - ( jL - rOIReachYMinL ) + 1 , rectXMaxL ); 533 ridgeIxRightL = bbs_max( ridgeIxRightL, rOIReachXMaxL - 1 - ( rOIReachYMaxL - 1 - jL ) + 1 ); 534 for ( iL = ridgeIxRightL; iL < rOIReachIxXMaxL; iL++ ) 535 { 536 weightL = ( int32 ) toneDownFactorsPtrL[ iL - rectXMaxL ]; 537 invWeightL = 0x00010000 - weightL; 538 opBGL = ( meanBGGreyLevelLongL >> 9 ) * invWeightL; /* result is bpb=[16,16] */ 539 opBGL = opBGL >> 7; 540 541 opSrcL = imgPtrL[ iL ]; /* leave at byte */ 542 opSrcL = opSrcL * weightL; /* result is bpb=[16,16] */ 543 sumL = opSrcL + opBGL; /* OF impossible */ 544 imgPtrL[ iL ] = sumL >> 16; /* round to byte */ 545 } 546 } 547 } 548 549 /* ------------------------------------------------------------------------- */ 550 551 /* ========================================================================= */ 552