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
bim_ToneDownBGSupp_BGGreyLevelOutside(struct bim_UInt8Image * imgA,struct bts_Int16Rect * rectA,int16 rectExpansionA,uint32 * meanBGGrayLevelA)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
bim_ToneDownBGSupp_BGGreyLevelContour(struct bim_UInt8Image * imgA,struct bts_Int16Rect * rectA,uint32 * meanBGGrayLevelA)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
bim_ToneDownBGSupp_suppress(struct bim_UInt8Image * imgA,struct bts_Int16Rect * rectA,int16 rectShrinkageA,int32 toneDownFactorA,int32 cutOffAccuracyA)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