Bug Summary

File:home/HaikuArchives/ArtPaint/addons/AddOns/AdaptiveHistogramEqualization/../../UtilityClasses/ImageProcessingLibrary.cpp
Warning:line 503, column 9
Value stored to 'x_dist' during its initialization is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-haiku -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name ImageProcessingLibrary.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /boot/system/lib/clang/12.0.1 -iquote ./ -iquote ../../UtilityClasses/ -iquote ./ -iquote ../../../artpaint/application -iquote ../../../artpaint/controls -iquote ../../../artpaint/layers -iquote ../../../artpaint/paintwindow -iquote ../../../artpaint/tools -iquote ../../../artpaint/viewmanipulators -iquote ../../../artpaint/windows -internal-isystem /system/develop/headers/c++ -internal-isystem /system/develop/headers/c++/x86_64-unknown-haiku -internal-isystem /system/develop/headers/c++/backward -O3 -fdeprecated-macro -fdebug-compilation-dir /boot/home/HaikuArchives/ArtPaint/addons/AddOns/AdaptiveHistogramEqualization -ferror-limit 19 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -o /tmp/scan-build-2022-06-19-103017-1294-1 -x c++ ../../UtilityClasses/ImageProcessingLibrary.cpp
1/*
2 * Copyright 2003, Heikki Suhonen
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 * Heikki Suhonen <heikki.suhonen@gmail.com>
7 */
8#include <OS.h>
9#include <stdio.h>
10
11#include "ImageProcessingLibrary.h"
12
13
14status_t ImageProcessingLibrary::gaussian_blur(BBitmap *bitmap,float radius)
15{
16 int32 kernel_radius = int32(ceil(radius));
17 float *kernel_array = new float[2*kernel_radius+1];
18 float *kernel = &kernel_array[kernel_radius];
19 float sum = 0;
20 int32 *fixed_kernel_array = new int32[2*kernel_radius+1];
21 int32 *fixed_kernel = &fixed_kernel_array[kernel_radius];
22
23 // was before -log(0.002)
24 float p = -log(0.004)/(pow(radius,2)*log(2));
25 for (int32 i=-kernel_radius;i<=kernel_radius;i++) {
26 kernel[i] = pow(2,-p*i*i);
27 sum += kernel[i];
28 }
29 for (int32 i = -kernel_radius; i <= kernel_radius; i++) {
30 kernel[i] /= sum;
31 fixed_kernel[i] = kernel[i] * 32768;
32 }
33
34 BBitmap *intermediate;
35 BRect bitmap_bounds = bitmap->Bounds();
36 BRect intermediate_bounds;
37 intermediate_bounds.left = bitmap_bounds.top;
38 intermediate_bounds.top = bitmap_bounds.left;
39 intermediate_bounds.right = bitmap_bounds.bottom;
40 intermediate_bounds.bottom = bitmap_bounds.right;
41
42 intermediate = new BBitmap(intermediate_bounds,B_RGB32,false);
43
44 uint32 *b_bits = (uint32*)bitmap->Bits();
45 uint32 *i_bits = (uint32*)intermediate->Bits();
46 int32 b_bpr = bitmap->BytesPerRow()/4;
47 int32 i_bpr = intermediate->BytesPerRow()/4;
48
49 // Blur from bitmap to intermediate and rotate
50 int32 width = bitmap_bounds.IntegerWidth() + 1;
51 int32 height = bitmap_bounds.IntegerHeight() + 1;
52 uint32 *source_array = new uint32[width + kernel_radius*2];
53 uint32 *target_array = new uint32[width];
54
55
56 for (int32 y=0;y<height;y++) {
57 uint32 *source_array_position = source_array;
58 for (int32 dx = 0;dx<kernel_radius;dx++) {
59 *source_array_position++ = *b_bits;
60 }
61 for (int32 dx=0;dx<width;dx++) {
62 *source_array_position++ = *b_bits++;
63 }
64 b_bits--;
65 for (int32 dx = 0;dx<kernel_radius;dx++) {
66 *source_array_position++ = *b_bits;
67 }
68 b_bits++;
69 convolve_1d_fixed(source_array+kernel_radius,target_array,width,fixed_kernel,kernel_radius);
70
71 uint32 *target_array_position = target_array;
72 for (int32 x = 0;x<width;x++) {
73 *(i_bits + (height-y-1) + x*i_bpr) = *target_array_position++;
74 }
75
76 }
77
78
79 b_bits = (uint32*)bitmap->Bits();
80 i_bits = (uint32*)intermediate->Bits();
81
82
83 delete[] source_array;
84 delete[] target_array;
85
86
87 // Blur from intermediate to bitmap and rotate
88 width = intermediate_bounds.IntegerWidth() + 1;
89 height = intermediate_bounds.IntegerHeight() + 1;
90 source_array = new uint32[width + kernel_radius*2];
91 target_array = new uint32[width];
92
93 for (int32 y=0;y<height;y++) {
94 uint32 *source_array_position = source_array;
95 for (int32 dx = 0;dx<kernel_radius;dx++) {
96 *source_array_position++ = *i_bits;
97 }
98 for (int32 dx=0;dx<width;dx++) {
99 *source_array_position++ = *i_bits++;
100 }
101 i_bits--;
102 for (int32 dx = 0;dx<kernel_radius;dx++) {
103 *source_array_position++ = *i_bits;
104 }
105 i_bits++;
106 convolve_1d_fixed(source_array+kernel_radius,target_array,width,fixed_kernel,kernel_radius);
107
108 uint32 *target_array_position = target_array;
109 for (int32 dx = 0;dx<width;dx++) {
110 *(b_bits + y + (width-dx-1)*b_bpr) = *target_array_position++;
111 }
112
113 }
114
115 delete[] source_array;
116 delete[] target_array;
117 delete[] kernel_array;
118 delete[] fixed_kernel_array;
119 delete intermediate;
120
121 return B_OK((int)0);
122}
123
124
125status_t ImageProcessingLibrary::gaussian_blur(BBitmap *bitmap,float radius, int32 threadCount)
126{
127 int32 kernel_radius = ceil(radius);
128 float *kernel_array = new float[2*kernel_radius+1];
129 float *kernel = &kernel_array[kernel_radius];
130 float sum = 0;
131 int32 *fixed_kernel_array = new int32[2*kernel_radius+1];
132 int32 *fixed_kernel = &fixed_kernel_array[kernel_radius];
133
134 float p = -log(0.004)/(pow(radius,2)*log(2));
135 for (int32 i=-kernel_radius;i<=kernel_radius;i++) {
136 kernel[i] = pow(2,-p*i*i);
137 sum += kernel[i];
138 }
139 for (int32 i=-kernel_radius;i<=kernel_radius;i++) {
140 kernel[i] /= sum;
141 fixed_kernel[i] = kernel[i] * 32768;
142 }
143
144
145 // Use thread-count threads.
146 // First blur horizontally and rotate by 90 clockwise.
147 /*
148 Rotation changes things like this
149 *.... ..*
150 ..... ...
151 ..... ...
152 ...
153 ...
154 */
155
156
157 BRect bitmap_bounds = bitmap->Bounds();
158 BRect intermediate_bounds(0,0,bitmap_bounds.Height(),bitmap_bounds.Width());
159 BBitmap *intermediate = new BBitmap(intermediate_bounds,B_RGB32,false);
160
161 int32 *s_bits = (int32*)bitmap->Bits();
162 int32 s_bpr = bitmap->BytesPerRow()/4;
163
164 int32 *d_bits = (int32*)intermediate->Bits();
165 int32 d_bpr = intermediate->BytesPerRow()/4;
166
167 // Start the threads.
168 thread_id blur_thread_array[8]; //TODO - Was B_MAX_CPU_COUNT, find way to decide amount of threads to use based on cpu count
169 for (int32 i=0;i<threadCount;i++) {
170 int32 height = bitmap_bounds.Height() / threadCount + 1;
171 filter_thread_data *data = new filter_thread_data();
172 data->left = 0;
173 data->right = bitmap_bounds.right;
174 int32 top;
175 top = data->top = min_c(bitmap_bounds.bottom,bitmap_bounds.top + i*height)((bitmap_bounds.bottom)>(bitmap_bounds.top + i*height)?(bitmap_bounds
.top + i*height):(bitmap_bounds.bottom))
;
176 data->bottom = min_c(bitmap_bounds.bottom,top+height-1)((bitmap_bounds.bottom)>(top+height-1)?(top+height-1):(bitmap_bounds
.bottom))
;
177
178 data->s_bpr = s_bpr;
179 data->s_bits = s_bits + top*s_bpr;
180 data->d_bpr = d_bpr;
181 data->d_bits = d_bits;
182
183 data->kernel = fixed_kernel;
184 data->kernel_radius = kernel_radius;
185
186 blur_thread_array[i] = spawn_thread(start_filter_1d_thread_clockwise,"filter_1d_thread",B_NORMAL_PRIORITY10,data);
187 resume_thread(blur_thread_array[i]);
188 }
189
190 for (int32 i=0;i<threadCount;i++) {
191 int32 return_value;
192 wait_for_thread(blur_thread_array[i],&return_value);
193 }
194
195 s_bits = (int32*)intermediate->Bits();
196 s_bpr = intermediate->BytesPerRow() / 4;
197
198 d_bits = (int32*)bitmap->Bits();
199 d_bpr = bitmap->BytesPerRow()/4;
200
201 // Here blur from intermediate to bitmap horizontally and rotate
202 // by 90 degrees counterclockwise
203 // Start the threads.
204 for (int32 i=0;i<threadCount;i++) {
205 int32 height = intermediate_bounds.Height() / threadCount + 1;
206 filter_thread_data *data = new filter_thread_data();
207 data->left = 0;
208 data->right = intermediate_bounds.right;
209 int32 top;
210 top = data->top = min_c(intermediate_bounds.bottom,intermediate_bounds.top + i*height)((intermediate_bounds.bottom)>(intermediate_bounds.top + i
*height)?(intermediate_bounds.top + i*height):(intermediate_bounds
.bottom))
;
211 data->bottom = min_c(intermediate_bounds.bottom,top+height-1)((intermediate_bounds.bottom)>(top+height-1)?(top+height-1
):(intermediate_bounds.bottom))
;
212
213 data->s_bpr = s_bpr;
214 data->s_bits = s_bits + top*s_bpr;
215 data->d_bpr = d_bpr;
216 data->d_bits = d_bits;
217
218 data->kernel = fixed_kernel;
219 data->kernel_radius = kernel_radius;
220
221 blur_thread_array[i] = spawn_thread(start_filter_1d_thread_counterclockwise,"filter_1d_thread",B_NORMAL_PRIORITY10,data);
222 resume_thread(blur_thread_array[i]);
223 }
224
225 for (int32 i=0;i<threadCount;i++) {
226 int32 return_value;
227 wait_for_thread(blur_thread_array[i],&return_value);
228 }
229
230 delete[] kernel_array;
231 delete[] fixed_kernel_array;
232 delete intermediate;
233
234 return B_OK((int)0);
235}
236
237int32 ImageProcessingLibrary::start_filter_1d_thread_clockwise(void *d)
238{
239 filter_thread_data *data = (filter_thread_data*)d;
240
241 filter_1d_and_rotate_clockwise(data->s_bits,data->s_bpr,data->d_bits,data->d_bpr,
242 data->left,data->right,data->top,data->bottom,data->kernel,data->kernel_radius);
243
244 delete data;
245
246 return B_OK((int)0);
247}
248
249
250int32 ImageProcessingLibrary::start_filter_1d_thread_counterclockwise(void *d)
251{
252 filter_thread_data *data = (filter_thread_data*)d;
253
254 filter_1d_and_rotate_counterclockwise(data->s_bits,data->s_bpr,data->d_bits,data->d_bpr,
255 data->left,data->right,data->top,data->bottom,data->kernel,data->kernel_radius);
256
257 delete data;
258
259 return B_OK((int)0);
260}
261
262
263void ImageProcessingLibrary::filter_1d_and_rotate_clockwise(int32 *s_bits,int32 s_bpr,int32 *d_bits,int32 d_bpr,int32 left,int32 right,int32 top,int32 bottom,int32 *kernel,int32 kernel_radius)
264{
265 int32 width = right - left + 1;
266 uint32 *source_array = new uint32[width + kernel_radius*2];
267 uint32 *target_array = new uint32[width];
268
269 for (int32 y=top;y<=bottom;++y) {
270 uint32 *source_array_position = source_array;
271 for (int32 dx = 0;dx<kernel_radius;++dx) {
272 *source_array_position++ = *s_bits;
273 }
274 for (int32 dx=left;dx<=right;++dx) {
275 *source_array_position++ = *s_bits++;
276 }
277 s_bits--;
278 for (int32 dx = 0;dx<kernel_radius;++dx) {
279 *source_array_position++ = *s_bits;
280 }
281 s_bits++;
282
283 convolve_1d_fixed(source_array+kernel_radius,target_array,width,kernel,kernel_radius);
284
285 uint32 *target_array_position = target_array;
286 for (int32 x = left;x<=right;x++) {
287 *(d_bits + (d_bpr-1-y) + x*d_bpr) = *target_array_position++;
288 }
289 }
290
291 delete[] source_array;
292 delete[] target_array;
293}
294
295
296void ImageProcessingLibrary::filter_1d_and_rotate_counterclockwise(int32 *s_bits,int32 s_bpr,int32 *d_bits,int32 d_bpr,int32 left,int32 right,int32 top,int32 bottom,int32 *kernel,int32 kernel_radius)
297{
298 int32 width = right - left + 1;
299 uint32 *source_array = new uint32[width + kernel_radius*2];
300 uint32 *target_array = new uint32[width];
301
302
303 for (int32 y=top;y<=bottom;++y) {
304 uint32 *source_array_position = source_array;
305 for (int32 dx = 0;dx<kernel_radius;++dx) {
306 *source_array_position++ = *s_bits;
307 }
308 for (int32 dx=left;dx<=right;++dx) {
309 *source_array_position++ = *s_bits++;
310 }
311 s_bits--;
312 for (int32 dx = 0;dx<kernel_radius;++dx) {
313 *source_array_position++ = *s_bits;
314 }
315 s_bits++;
316
317 convolve_1d_fixed(source_array+kernel_radius,target_array,width,kernel,kernel_radius);
318
319 uint32 *target_array_position = target_array;
320 for (int32 x = left;x<=right;x++) {
321 *(d_bits + y + (right-x)*d_bpr) = *target_array_position++;
322 }
323 }
324
325 delete[] source_array;
326 delete[] target_array;
327}
328
329
330void ImageProcessingLibrary::convolve_1d(uint32 *s, uint32 *t,int32 length,float *kernel,int32 kernel_radius)
331{
332 union {
333 uint8 bytes[4];
334 uint32 word;
335 } c;
336
337 for (int32 x=0;x<length;x++) {
338 float red=0;
339 float green=0;
340 float blue=0;
341 float alpha=0;
342 for (int32 index = -kernel_radius;index<=kernel_radius;index++) {
343 c.word = *(s + index);
344 red += c.bytes[2] * kernel[index];
345 green += c.bytes[1] * kernel[index];
346 blue += c.bytes[0] * kernel[index];
347 alpha += c.bytes[3] * kernel[index];
348 }
349
350 c.bytes[0] = blue;
351 c.bytes[1] = green;
352 c.bytes[2] = red;
353 c.bytes[3] = alpha;
354
355 *t++ = c.word;
356 s++;
357 }
358}
359
360
361void ImageProcessingLibrary::convolve_1d_fixed(uint32 *s, uint32 *t,int32 length,int32 *kernel,int32 kernel_radius)
362{
363 union {
364 uint8 bytes[4];
365 uint32 word;
366 } c;
367
368 for (int32 x=0;x<length;++x) {
369 int32 red=0;
370 int32 green=0;
371 int32 blue=0;
372 int32 alpha=0;
373 uint32 *tmp = s-kernel_radius;
374 int32 *kernel_tmp = kernel-kernel_radius;
375 for (int32 index = -kernel_radius;index<=kernel_radius;++index) {
376 c.word = *tmp++;
377 if (c.bytes[3] != 0) {
378 blue += (c.bytes[0] * *kernel_tmp);
379 green += (c.bytes[1] * *kernel_tmp);
380 red += (c.bytes[2] * *kernel_tmp);
381 }
382 alpha += (c.bytes[3] * *kernel_tmp++);
383 }
384
385 c.bytes[0] = blue >> 15;
386 c.bytes[1] = green >> 15;
387 c.bytes[2] = red >> 15;
388 c.bytes[3] = alpha >> 15;
389
390 *t++ = c.word;
391 s++;
392 }
393}
394
395
396
397
398
399
400
401
402/*
403
404Grayscale AHE
405
406*/
407
408status_t ImageProcessingLibrary::grayscale_ahe(BBitmap *bitmap, int32 regionSize)
409{
410 int32 right,bottom;
411 right = bitmap->Bounds().right;
412 bottom = bitmap->Bounds().bottom;
413
414 int32 region_half = regionSize / 2;
415
416 uint8 **prev_histograms;
417 uint8 **next_histograms;
418
419 int32 histogram_count_per_row = right / regionSize + 1 + 2; // extras at the edges
420
421 prev_histograms = new uint8*[histogram_count_per_row];
422 next_histograms = new uint8*[histogram_count_per_row];
423
424 for (int32 i=0;i<histogram_count_per_row;i++) {
425 prev_histograms[i] = new uint8[256];
426 next_histograms[i] = new uint8[256];
427 }
428
429 int32 corner_y = 0;
430 int32 corner_x = 0;
431 // calculate the initial row of histograms
432 for (int32 i=0;i<histogram_count_per_row;i++) {
433 if (i == 1) {
434 for (int32 j=0;j<256;j++) {
435 next_histograms[1][j] = next_histograms[0][j];
436 }
437 }
438 else if(i == histogram_count_per_row-1) {
439 for (int32 j=0;j<256;j++) {
440 next_histograms[i][j] = next_histograms[i][j];
441 }
442 }
443 else {
444 calculate_local_mapping_function(bitmap,corner_x,corner_y,regionSize,next_histograms[i]);
445 corner_x = corner_x + regionSize;
446 }
447 }
448
449 // make a copy of it
450 for (int32 i=0;i<histogram_count_per_row;i++) {
451 for (int32 j=0;j<256;j++) {
452 prev_histograms[i][j] = next_histograms[i][j];
453 }
454 }
455
456
457 // loop through the picture
458 uint32 *bits = (uint32*)bitmap->Bits();
459 union {
460 uint8 bytes[4];
461 uint32 word;
462 } c;
463
464 for (int32 y=0;y<=bottom;y++) {
465 if (y % regionSize == region_half) {
466 corner_y += regionSize;
467 if (corner_y > bottom) {
468 for (int32 i=0;i<histogram_count_per_row;i++) {
469 for (int32 j=0;j<256;j++) {
470 prev_histograms[i][j] = next_histograms[i][j];
471 }
472 }
473 }
474 else {
475 uint8 **spare = prev_histograms;
476 prev_histograms = next_histograms;
477
478 next_histograms = spare;
479
480 corner_x = 0;
481
482 // calculate the next row of histograms
483 for (int32 i=0;i<histogram_count_per_row;i++) {
484 if (i == 1) {
485 for (int32 j=0;j<256;j++) {
486 next_histograms[1][j] = next_histograms[0][j];
487 }
488 }
489 else if(i == histogram_count_per_row-1) {
490 for (int32 j=0;j<256;j++) {
491 next_histograms[i][j] = next_histograms[i][j];
492 }
493 }
494 else {
495 calculate_local_mapping_function(bitmap,corner_x,corner_y,regionSize,next_histograms[i]);
496 corner_x = corner_x + regionSize;
497 }
498 }
499 }
500 }
501
502 int32 current_bin = 1;
503 int32 x_dist = region_half;
Value stored to 'x_dist' during its initialization is never read
504 int32 y_dist = region_half; // distance to the previous center
505 uint8 hist_index;
506 uint8 map_value;
507
508 float left_coeff,right_coeff,top_coeff,bottom_coeff;
509
510 for (int32 x=0;x<=right;x++) {
511 if (x % regionSize == region_half)
512 current_bin++;
513
514 if (x % regionSize < region_half) {
515 x_dist = x % regionSize + region_half;
516 }
517 else {
518 x_dist = x % regionSize - region_half;
519 }
520
521 if (y % regionSize < region_half) {
522 y_dist = y % regionSize + region_half;
523 }
524 else {
525 y_dist = y % regionSize - region_half;
526 }
527
528 // the bins are prev...[current_bin], prev...[current_bin-1] and the same for next
529
530 c.word = *bits;
531 hist_index = c.bytes[0];
532
533 right_coeff = (float)x_dist / (float)regionSize;
534 bottom_coeff = (float)y_dist / (float)regionSize;
535 left_coeff = 1.0 - right_coeff;
536 top_coeff = 1.0 - bottom_coeff;
537
538 map_value = left_coeff*(top_coeff*prev_histograms[current_bin-1][hist_index] +
539 bottom_coeff*next_histograms[current_bin-1][hist_index]) +
540 right_coeff*(top_coeff*prev_histograms[current_bin][hist_index] +
541 bottom_coeff*next_histograms[current_bin][hist_index]);
542
543 c.bytes[0] = c.bytes[1] = c.bytes[2] = map_value;
544 *bits++ = c.word;
545 }
546 }
547
548 // clean up...
549 for (int32 i=0;i<histogram_count_per_row;i++) {
550 delete[] prev_histograms[i];
551 delete[] next_histograms[i];
552 prev_histograms[i] = NULL__null;
553 next_histograms[i] = NULL__null;
554 }
555
556 delete[] prev_histograms;
557 delete[] next_histograms;
558
559 return B_OK((int)0);
560}
561
562
563
564
565status_t ImageProcessingLibrary::grayscale_clahe(BBitmap *bitmap, int32 regionSize,int32 clipLimit)
566{
567 int32 right,bottom;
568 right = bitmap->Bounds().right;
569 bottom = bitmap->Bounds().bottom;
570
571 int32 region_half = regionSize / 2;
572
573 uint8 **prev_histograms;
574 uint8 **next_histograms;
575
576 int32 histogram_count_per_row = right / regionSize + 1 + 2; // extras at the edges
577
578 prev_histograms = new uint8*[histogram_count_per_row];
579 next_histograms = new uint8*[histogram_count_per_row];
580
581 for (int32 i=0;i<histogram_count_per_row;i++) {
582 prev_histograms[i] = new uint8[256];
583 next_histograms[i] = new uint8[256];
584 }
585
586 int32 corner_y = 0;
587 int32 corner_x = 0;
588 // calculate the initial row of histograms
589 for (int32 i=0;i<histogram_count_per_row;i++) {
590 if (i == 1) {
591 for (int32 j=0;j<256;j++) {
592 next_histograms[1][j] = next_histograms[0][j];
593 }
594 }
595 else if(i == histogram_count_per_row-1) {
596 for (int32 j=0;j<256;j++) {
597 next_histograms[i][j] = next_histograms[i][j];
598 }
599 }
600 else {
601 calculate_local_mapping_function_clip(bitmap,corner_x,corner_y,regionSize,clipLimit,next_histograms[i]);
602 corner_x = corner_x + regionSize;
603 }
604 }
605
606 // make a copy of it
607 for (int32 i=0;i<histogram_count_per_row;i++) {
608 for (int32 j=0;j<256;j++) {
609 prev_histograms[i][j] = next_histograms[i][j];
610 }
611 }
612
613
614 // loop through the picture
615 uint32 *bits = (uint32*)bitmap->Bits();
616 union {
617 uint8 bytes[4];
618 uint32 word;
619 } c;
620
621 for (int32 y=0;y<=bottom;y++) {
622 if (y % regionSize == region_half) {
623 corner_y += regionSize;
624 if (corner_y > bottom) {
625 for (int32 i=0;i<histogram_count_per_row;i++) {
626 for (int32 j=0;j<256;j++) {
627 prev_histograms[i][j] = next_histograms[i][j];
628 }
629 }
630 }
631 else {
632 uint8 **spare = prev_histograms;
633 prev_histograms = next_histograms;
634
635 next_histograms = spare;
636
637 corner_x = 0;
638
639 // calculate the next row of histograms
640 for (int32 i=0;i<histogram_count_per_row;i++) {
641 if (i == 1) {
642 for (int32 j=0;j<256;j++) {
643 next_histograms[1][j] = next_histograms[0][j];
644 }
645 }
646 else if(i == histogram_count_per_row-1) {
647 for (int32 j=0;j<256;j++) {
648 next_histograms[i][j] = next_histograms[i][j];
649 }
650 }
651 else {
652 calculate_local_mapping_function_clip(bitmap,corner_x,corner_y,regionSize,clipLimit,next_histograms[i]);
653 corner_x = corner_x + regionSize;
654 }
655 }
656 }
657 }
658
659 int32 current_bin = 1;
660 int32 x_dist = region_half;
661 int32 y_dist = region_half; // distance to the previous center
662 uint8 hist_index;
663 uint8 map_value;
664
665 float left_coeff,right_coeff,top_coeff,bottom_coeff;
666
667 for (int32 x=0;x<=right;x++) {
668 if (x % regionSize == region_half)
669 current_bin++;
670
671 if (x % regionSize < region_half) {
672 x_dist = x % regionSize + region_half;
673 }
674 else {
675 x_dist = x % regionSize - region_half;
676 }
677
678 if (y % regionSize < region_half) {
679 y_dist = y % regionSize + region_half;
680 }
681 else {
682 y_dist = y % regionSize - region_half;
683 }
684
685 // the bins are prev...[current_bin], prev...[current_bin-1] and the same for next
686
687 c.word = *bits;
688 hist_index = c.bytes[0];
689
690 right_coeff = (float)x_dist / (float)regionSize;
691 bottom_coeff = (float)y_dist / (float)regionSize;
692 left_coeff = 1.0 - right_coeff;
693 top_coeff = 1.0 - bottom_coeff;
694
695 map_value = left_coeff*(top_coeff*prev_histograms[current_bin-1][hist_index] +
696 bottom_coeff*next_histograms[current_bin-1][hist_index]) +
697 right_coeff*(top_coeff*prev_histograms[current_bin][hist_index] +
698 bottom_coeff*next_histograms[current_bin][hist_index]);
699
700 c.bytes[0] = c.bytes[1] = c.bytes[2] = map_value;
701 *bits++ = c.word;
702 }
703 }
704
705 // clean up...
706 for (int32 i=0;i<histogram_count_per_row;i++) {
707 delete[] prev_histograms[i];
708 delete[] next_histograms[i];
709 prev_histograms[i] = NULL__null;
710 next_histograms[i] = NULL__null;
711 }
712
713 delete[] prev_histograms;
714 delete[] next_histograms;
715
716 return B_OK((int)0);
717}
718
719
720
721
722void ImageProcessingLibrary::calculate_local_mapping_function(BBitmap *bitmap,int32 cx, int32 cy,int32 regionSize,uint8 *mapFunction)
723{
724 int32 left,right,top,bottom;
725 left = cx;
726 top = cy;
727 right = min_c(left+regionSize-1,bitmap->Bounds().right)((left+regionSize-1)>(bitmap->Bounds().right)?(bitmap->
Bounds().right):(left+regionSize-1))
;
728 bottom = min_c(top+regionSize-1,bitmap->Bounds().bottom)((top+regionSize-1)>(bitmap->Bounds().bottom)?(bitmap->
Bounds().bottom):(top+regionSize-1))
;
729
730
731 uint32 *bits = (uint32*)bitmap->Bits();
732 int32 bpr = bitmap->BytesPerRow()/4;
733
734 union {
735 uint8 bytes[4];
736 uint32 word;
737 } c;
738
739 // calculate the histogram
740 int32 histogram[256];
741 for (int32 i=0;i<256;i++) {
742 histogram[i] = 0;
743 }
744
745 for (int32 y=top;y<=bottom;y++) {
746 for (int32 x=left;x<=right;x++) {
747 c.word = *(bits + x + y*bpr);
748 histogram[c.bytes[0]]++;
749 }
750 }
751
752 // make the histogram cumulative
753 for (int32 i=1;i<256;i++) {
754 histogram[i] = histogram[i] + histogram[i-1];
755 }
756
757
758 // normalize cumulative histogram to create mapping function
759 float multiplier = 255.0 / (float)histogram[255];
760
761 for (int32 i=0;i<256;i++) {
762 mapFunction[i] = floor(histogram[i]*multiplier);
763 }
764}
765
766
767
768void ImageProcessingLibrary::calculate_local_mapping_function_clip(BBitmap *bitmap,int32 cx, int32 cy,int32 regionSize,int32 clipLimit,uint8 *mapFunction)
769{
770 int32 left,right,top,bottom;
771 left = cx;
772 top = cy;
773 right = min_c(left+regionSize-1,bitmap->Bounds().right)((left+regionSize-1)>(bitmap->Bounds().right)?(bitmap->
Bounds().right):(left+regionSize-1))
;
774 bottom = min_c(top+regionSize-1,bitmap->Bounds().bottom)((top+regionSize-1)>(bitmap->Bounds().bottom)?(bitmap->
Bounds().bottom):(top+regionSize-1))
;
775
776 uint32 *bits = (uint32*)bitmap->Bits();
777 int32 bpr = bitmap->BytesPerRow()/4;
778
779 union {
780 uint8 bytes[4];
781 uint32 word;
782 } c;
783
784 // calculate the histogram
785 int32 histogram[256];
786 for (int32 i=0;i<256;i++) {
787 histogram[i] = 0;
788 }
789
790 for (int32 y=top;y<=bottom;y++) {
791 for (int32 x=left;x<=right;x++) {
792 c.word = *(bits + x + y*bpr);
793 histogram[c.bytes[0]]++;
794 }
795 }
796
797
798 // clip the histogram
799 int32 actual_clip_limit;
800
801 top = clipLimit;
802 bottom = 0;
803 int32 middle;
804 int32 S;
805 while ((top - bottom) > 1) {
806 middle = (top + bottom) / 2;
807 S = 0;
808 for (int32 i=0;i<256;i++) {
809 if (histogram[i] > middle)
810 S += histogram[i] - middle;
811 }
812 if (S > (clipLimit-middle)*256) {
813 top = middle;
814 }
815 else {
816 bottom = middle;
817 }
818 }
819
820 actual_clip_limit = bottom + S/256;
821 int32 L = clipLimit - actual_clip_limit;
822
823 for (int32 i=0;i<256;i++) {
824 if (histogram[i] >= actual_clip_limit)
825 histogram[i] = clipLimit;
826 else
827 histogram[i] += L;
828 }
829
830
831
832 // make the histogram cumulative
833 for (int32 i=1;i<256;i++) {
834 histogram[i] = histogram[i] + histogram[i-1];
835 }
836
837
838 // normalize cumulative histogram to create mapping function
839 float multiplier = 255.0 / (float)histogram[255];
840
841 for (int32 i=0;i<256;i++) {
842 mapFunction[i] = floor(histogram[i]*multiplier);
843 }
844
845}