Bug Summary

File:home/HaikuArchives/ArtPaint/addons/AddOns/Contrast/Contrast.cpp
Warning:line 241, column 3
Value stored to 'contrast' 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 Contrast.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/Contrast -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++ Contrast.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 */
9#include <Bitmap.h>
10#include <Catalog.h>
11#include <LayoutBuilder.h>
12#include <Node.h>
13#include <StatusBar.h>
14#include <Slider.h>
15#include <string.h>
16#include <Window.h>
17
18#include "AddOns.h"
19#include "Contrast.h"
20#include "ManipulatorInformer.h"
21#include "Selection.h"
22
23#undef B_TRANSLATION_CONTEXT"AddOns_Contrast"
24#define B_TRANSLATION_CONTEXT"AddOns_Contrast" "AddOns_Contrast"
25
26
27#ifdef __cplusplus201402L
28extern "C" {
29#endif
30 char name[255] = B_TRANSLATE_MARK("Contrast" B_UTF8_ELLIPSIS)("Contrast" "\xE2\x80\xA6");
31 char menu_help_string[255] = B_TRANSLATE_MARK("Adjusts the contrast.")("Adjusts the contrast.");
32 int32 add_on_api_version = ADD_ON_API_VERSION;
33 add_on_types add_on_type = COLOR_ADD_ON;
34#ifdef __cplusplus201402L
35}
36#endif
37
38
39Manipulator* instantiate_add_on(BBitmap *bm,ManipulatorInformer *i)
40{
41 delete i;
42 return new ContrastManipulator(bm);
43}
44
45
46
47ContrastManipulator::ContrastManipulator(BBitmap *bm)
48 : WindowGUIManipulator()
49{
50 preview_bitmap = NULL__null;
51 config_view = NULL__null;
52 copy_of_the_preview_bitmap = NULL__null;
53
54 previous_settings.contrast = settings.contrast + 1;
55
56 SetPreviewBitmap(bm);
57}
58
59
60ContrastManipulator::~ContrastManipulator()
61{
62 delete copy_of_the_preview_bitmap;
63 delete config_view;
64}
65
66
67BBitmap* ContrastManipulator::ManipulateBitmap(ManipulatorSettings *set,BBitmap *original,Selection *selection,BStatusBar *status_bar)
68{
69 ContrastManipulatorSettings *new_settings = dynamic_cast<ContrastManipulatorSettings*>(set);
70
71 if (new_settings == NULL__null)
72 return NULL__null;
73
74 if (original == NULL__null)
75 return NULL__null;
76
77 if (original == preview_bitmap) {
78 if ((*new_settings == previous_settings) && (last_calculated_resolution <= 1))
79 return original;
80
81 source_bitmap = copy_of_the_preview_bitmap;
82 target_bitmap = original;
83 }
84 else {
85 source_bitmap = original;
86 target_bitmap = new BBitmap(original->Bounds(),B_RGB32,FALSE0);
87 }
88
89
90 current_resolution = 1;
91 current_selection = selection;
92 current_settings = *new_settings;
93 progress_bar = status_bar;
94 current_average_luminance = CalculateAverageLuminance(source_bitmap);
95
96 start_threads();
97
98 return target_bitmap;
99}
100
101int32 ContrastManipulator::PreviewBitmap(Selection *selection,bool full_quality,BRegion *updated_region)
102{
103 progress_bar = NULL__null;
104 current_selection = selection;
105 if (settings == previous_settings ) {
106 if ((last_calculated_resolution != highest_available_quality) && (last_calculated_resolution > 0))
107 last_calculated_resolution = max_c(highest_available_quality,floor(last_calculated_resolution/2.0))((highest_available_quality)>(floor(last_calculated_resolution
/2.0))?(highest_available_quality):(floor(last_calculated_resolution
/2.0)))
;
108 else
109 last_calculated_resolution = 0;
110 }
111 else
112 last_calculated_resolution = lowest_available_quality;
113
114 if (full_quality) {
115 last_calculated_resolution = min_c(1,last_calculated_resolution)((1)>(last_calculated_resolution)?(last_calculated_resolution
):(1))
;
116 }
117 previous_settings = settings;
118
119 if (last_calculated_resolution > 0) {
120 current_resolution = last_calculated_resolution;
121 updated_region->Set(preview_bitmap->Bounds());
122
123 target_bitmap = preview_bitmap;
124 source_bitmap = copy_of_the_preview_bitmap;
125 current_settings = settings;
126
127 start_threads();
128 }
129
130 return last_calculated_resolution;
131}
132
133
134uint8 ContrastManipulator::CalculateAverageLuminance(BBitmap *bitmap)
135{
136 uint32 *bits = (uint32*)bitmap->Bits();
137 uint32 bits_length = bitmap->BitsLength()/4;
138
139 double luminance_sum = 0;
140
141 union {
142 uint8 bytes[4];
143 uint32 word;
144 } color;
145
146 for (int32 i=0;i<bits_length;i++) {
147 color.word = *bits++;
148 luminance_sum += 0.299 * color.bytes[0] + 0.587 * color.bytes[1] + 0.144 * color.bytes[2];
149 }
150
151 luminance_sum = luminance_sum / bits_length;
152
153 uint8 sum = (uint8)luminance_sum;
154
155 return sum;
156}
157
158void ContrastManipulator::start_threads()
159{
160 number_of_threads = GetSystemCpuCount();
161
162 thread_id *threads = new thread_id[number_of_threads];
163
164 for (int32 i=0;i<number_of_threads;i++) {
165 threads[i] = spawn_thread(thread_entrythread_func,"contrast_thread",B_NORMAL_PRIORITY10,this);
166 resume_thread(threads[i]);
167 send_data(threads[i],i,NULL__null,0);
168 }
169
170 for (int32 i=0;i<number_of_threads;i++) {
171 int32 return_value;
172 wait_for_thread(threads[i],&return_value);
173 }
174
175 delete[] threads;
176}
177
178int32 ContrastManipulator::thread_entrythread_func(void *data)
179{
180 int32 thread_number;
181 thread_number = receive_data(NULL__null,NULL__null,0);
182
183 ContrastManipulator *this_pointer = (ContrastManipulator*)data;
184
185 return this_pointer->thread_function(thread_number);
186}
187
188
189int32 ContrastManipulator::thread_function(int32 thread_number)
190{
191 // This function interpolates the image with a degenerate version,
192 // which in this case is the average luminance. The luminance image is not actually
193 // used, but only implied. This function does not touch the alpha-channel.
194
195 int32 step = current_resolution;
196 uint32 contrast = settings.contrast;
197
198 BWindow *progress_bar_window = NULL__null;
199 if (progress_bar != NULL__null)
200 progress_bar_window = progress_bar->Window();
201
202
203 uint32 *source_bits = (uint32*)source_bitmap->Bits();
204 uint32 *target_bits = (uint32*)target_bitmap->Bits();
205 int32 source_bpr = source_bitmap->BytesPerRow()/4;
206 int32 target_bpr = target_bitmap->BytesPerRow()/4;
207
208 // This union must be used to guarantee endianness compatibility.
209 union {
210 uint8 bytes[4];
211 uint32 word;
212 } color;
213
214 float coeff = current_settings.contrast / 100.0;
215 float one_minus_coeff = 1.0 - coeff;
216 int32 luminance_factor = current_average_luminance*one_minus_coeff;;
217
218 uint8 luminance_values[256];
219 for (int32 i=0;i<256;i++) {
220 luminance_values[i] = max_c(0,min_c(255,i * coeff + luminance_factor))((0)>(((255)>(i * coeff + luminance_factor)?(i * coeff +
luminance_factor):(255)))?(0):(((255)>(i * coeff + luminance_factor
)?(i * coeff + luminance_factor):(255))))
;
221 }
222
223 if (current_selection->IsEmpty()) {
224 // Here handle the whole image.
225 int32 left = target_bitmap->Bounds().left;
226 int32 right = target_bitmap->Bounds().right;
227 int32 top = target_bitmap->Bounds().top;
228 int32 bottom = target_bitmap->Bounds().bottom;
229
230 float height = bottom - top;
231 top = height/number_of_threads*thread_number;
232 top = ceil(top/(float)step);
233 top *= step;
234 bottom = min_c(bottom,top + (height+1)/number_of_threads)((bottom)>(top + (height+1)/number_of_threads)?(top + (height
+1)/number_of_threads):(bottom))
;
235 int32 update_interval = 10;
236 float update_amount = 100.0/(bottom-top)*update_interval/(float)number_of_threads;
237 float missed_update = 0;
238
239 // Loop through all pixels in original.
240 uint32 sum;
241 contrast *= 3;
Value stored to 'contrast' is never read
242 for (int32 y=top;y<=bottom;y+=step) {
243 int32 y_times_source_bpr = y*source_bpr;
244 int32 y_times_target_bpr = y*target_bpr;
245 for (int32 x=left;x<=right;x+=step) {
246 color.word = *(source_bits + x + y_times_source_bpr);
247 color.bytes[0] = luminance_values[color.bytes[0]];
248 color.bytes[1] = luminance_values[color.bytes[1]];
249 color.bytes[2] = luminance_values[color.bytes[2]];
250 *(target_bits + x + y_times_target_bpr) = color.word;
251 }
252
253 // Update the status-bar
254 if ( ((y % update_interval) == 0) && (progress_bar_window != NULL__null) && (progress_bar_window->LockWithTimeout(0) == B_OK((int)0)) ) {
255 progress_bar->Update(update_amount+missed_update);
256 progress_bar_window->Unlock();
257 missed_update = 0;
258 }
259 else if ((y % update_interval) == 0) {
260 missed_update += update_amount;
261 }
262 }
263 }
264 else {
265 // Here handle only those pixels for which selection->ContainsPoint(x,y) is true.
266 BRect rect = current_selection->GetBoundingRect();
267
268 int32 left = rect.left;
269 int32 right = rect.right;
270 int32 top = rect.top;
271 int32 bottom = rect.bottom;
272
273 float height = bottom - top;
274 top += height/number_of_threads*thread_number;
275 top *= step;
276 top /= step;
277
278 bottom = min_c(bottom,top + (height+1)/number_of_threads)((bottom)>(top + (height+1)/number_of_threads)?(top + (height
+1)/number_of_threads):(bottom))
;
279
280 int32 update_interval = 10;
281 float update_amount = 100.0/(bottom-top)*update_interval/(float)number_of_threads;
282
283 // Loop through all pixels in original.
284 for (int32 y=top;y<=bottom;y+=step) {
285 int32 y_times_source_bpr = y*source_bpr;
286 int32 y_times_target_bpr = y*target_bpr;
287 for (int32 x=left;x<=right;x+=step) {
288 if (current_selection->ContainsPoint(x,y)) {
289 color.word = *(source_bits + x + y_times_source_bpr);
290 color.bytes[0] = luminance_values[color.bytes[0]];
291 color.bytes[1] = luminance_values[color.bytes[1]];
292 color.bytes[2] = luminance_values[color.bytes[2]];
293 *(target_bits + x + y_times_target_bpr) = color.word;
294 }
295 }
296
297 // Update the status-bar
298 if ( ((y % update_interval) == 0) && (progress_bar_window != NULL__null) && (progress_bar_window->LockWithTimeout(0) == B_OK((int)0)) ) {
299 progress_bar->Update(update_amount);
300 progress_bar_window->Unlock();
301 }
302 }
303 }
304
305 return B_OK((int)0);
306}
307
308
309void ContrastManipulator::MouseDown(BPoint point,uint32,BView*,bool first_click)
310{
311 // This function does nothing in ContrastManipulator.
312}
313
314
315void ContrastManipulator::SetPreviewBitmap(BBitmap *bm)
316{
317 if (preview_bitmap != bm) {
318 delete copy_of_the_preview_bitmap;
319 if (bm != NULL__null) {
320 preview_bitmap = bm;
321 copy_of_the_preview_bitmap = DuplicateBitmap(bm,0);
322 }
323 else {
324 preview_bitmap = NULL__null;
325 copy_of_the_preview_bitmap = NULL__null;
326 }
327 }
328
329 if (preview_bitmap != NULL__null) {
330 // Let's select a resolution that can handle all the pixels at least
331 // 10 times in a second while assuming that one pixel calculation takes
332 // about 50 CPU cycles.
333 double speed = GetSystemClockSpeed() / (10*50);
334 BRect bounds = preview_bitmap->Bounds();
335 float num_pixels = (bounds.Width()+1) * (bounds.Height() + 1);
336 lowest_available_quality = 1;
337 while ((num_pixels/lowest_available_quality/lowest_available_quality) > speed)
338 lowest_available_quality *= 2;
339
340 lowest_available_quality = min_c(lowest_available_quality,16)((lowest_available_quality)>(16)?(16):(lowest_available_quality
))
;
341 highest_available_quality = max_c(lowest_available_quality/2,1)((lowest_available_quality/2)>(1)?(lowest_available_quality
/2):(1))
;
342
343 current_average_luminance = CalculateAverageLuminance(preview_bitmap);
344 }
345 else {
346 lowest_available_quality = 1;
347 highest_available_quality = 1;
348 }
349 last_calculated_resolution = lowest_available_quality;
350}
351
352
353void ContrastManipulator::Reset(Selection*)
354{
355 if (copy_of_the_preview_bitmap != NULL__null) {
356 // memcpy seems to be about 10-15% faster that copying with a loop.
357 uint32 *source = (uint32*)copy_of_the_preview_bitmap->Bits();
358 uint32 *target = (uint32*)preview_bitmap->Bits();
359 uint32 bits_length = preview_bitmap->BitsLength();
360
361 memcpy(target,source,bits_length);
362 }
363}
364
365BView* ContrastManipulator::MakeConfigurationView(const BMessenger& target)
366{
367 if (config_view == NULL__null) {
368 config_view = new ContrastManipulatorView(this,target);
369 config_view->ChangeSettings(&settings);
370 }
371
372 return config_view;
373}
374
375
376ManipulatorSettings* ContrastManipulator::ReturnSettings()
377{
378 return new ContrastManipulatorSettings(settings);
379}
380
381void ContrastManipulator::ChangeSettings(ManipulatorSettings *s)
382{
383 ContrastManipulatorSettings *new_settings;
384 new_settings = dynamic_cast<ContrastManipulatorSettings*>(s);
385
386 if (new_settings != NULL__null) {
387 settings = *new_settings;
388 }
389}
390
391const char* ContrastManipulator::ReturnName()
392{
393 return B_TRANSLATE("Contrast")BLocaleRoster::Default()->GetCatalog()->GetString(("Contrast"
), "AddOns_Contrast")
;
394}
395
396const char* ContrastManipulator::ReturnHelpString()
397{
398 return B_TRANSLATE("Adjusts the contrast.")BLocaleRoster::Default()->GetCatalog()->GetString(("Adjusts the contrast."
), "AddOns_Contrast")
;
399}
400
401
402
403
404// -------------------------------------
405ContrastManipulatorView::ContrastManipulatorView(ContrastManipulator *manip,
406 const BMessenger& t)
407 : WindowGUIManipulatorView()
408{
409 target = t;
410 manipulator = manip;
411 started_adjusting = FALSE0;
412
413 contrast_slider = new BSlider("contrast_slider", B_TRANSLATE("Contrast:")BLocaleRoster::Default()->GetCatalog()->GetString(("Contrast:"
), "AddOns_Contrast")
,
414 new BMessage(CONTRAST_ADJUSTING_FINISHED'Thaf'), 0, 255, B_HORIZONTAL,
415 B_TRIANGLE_THUMB);
416 contrast_slider->SetModificationMessage(new BMessage(CONTRAST_ADJUSTED'Thad'));
417 contrast_slider->SetLimitLabels(B_TRANSLATE("Low")BLocaleRoster::Default()->GetCatalog()->GetString(("Low"
), "AddOns_Contrast")
, B_TRANSLATE("High")BLocaleRoster::Default()->GetCatalog()->GetString(("High"
), "AddOns_Contrast")
);
418 contrast_slider->SetHashMarks(B_HASH_MARKS_BOTTOM);
419 contrast_slider->SetHashMarkCount(11);
420
421 BLayoutBuilder::Group<>(this, B_VERTICAL)
422 .Add(contrast_slider)
423 .SetInsets(B_USE_SMALL_INSETS)
424 .End();
425}
426
427ContrastManipulatorView::~ContrastManipulatorView()
428{
429}
430
431void ContrastManipulatorView::AttachedToWindow()
432{
433 WindowGUIManipulatorView::AttachedToWindow();
434 contrast_slider->SetTarget(BMessenger(this));
435}
436
437void ContrastManipulatorView::AllAttached()
438{
439 contrast_slider->SetValue(settings.contrast);
440}
441
442void ContrastManipulatorView::MessageReceived(BMessage *message)
443{
444 switch (message->what) {
445 case CONTRAST_ADJUSTED'Thad':
446 settings.contrast = contrast_slider->Value();
447 manipulator->ChangeSettings(&settings);
448 if (!started_adjusting) {
449 target.SendMessage(HS_MANIPULATOR_ADJUSTING_STARTED'Mast');
450 started_adjusting = TRUE1;
451 }
452 break;
453
454 case CONTRAST_ADJUSTING_FINISHED'Thaf':
455 started_adjusting = FALSE0;
456 settings.contrast = contrast_slider->Value();
457 manipulator->ChangeSettings(&settings);
458 target.SendMessage(HS_MANIPULATOR_ADJUSTING_FINISHED'Mafi');
459 break;
460
461 default:
462 WindowGUIManipulatorView::MessageReceived(message);
463 break;
464 }
465}
466
467
468void ContrastManipulatorView::ChangeSettings(ManipulatorSettings *set)
469{
470 ContrastManipulatorSettings *new_settings = dynamic_cast<ContrastManipulatorSettings*>(set);
471
472 if (set != NULL__null) {
473 settings = *new_settings;
474
475 BWindow *window = Window();
476 if (window != NULL__null) {
477 window->Lock();
478 contrast_slider->SetValue(settings.contrast);
479 window->Unlock();
480 }
481 }
482}