Bug Summary

File:home/HaikuArchives/ArtPaint/addons/AddOns/Threshold/Threshold.cpp
Warning:line 242, column 55
The left operand of '<' is a garbage value

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