Bug Summary

File:home/HaikuArchives/ArtPaint/addons/AddOns/ColorReducer/Reducer.cpp
Warning:line 107, column 14
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 Reducer.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/ColorReducer -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++ Reducer.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 <ClassInfo.h>
12#include <LayoutBuilder.h>
13#include <Menu.h>
14#include <MenuField.h>
15#include <MenuItem.h>
16#include <PopUpMenu.h>
17#include <Screen.h>
18#include <StatusBar.h>
19#include <StringView.h>
20#include <stdio.h>
21#include <string.h>
22#include <Window.h>
23
24#include "AddOns.h"
25#include "Reducer.h"
26#include "color_mapper.h"
27#include "palette_generator.h"
28#include "ManipulatorInformer.h"
29#include "Selection.h"
30
31#undef B_TRANSLATION_CONTEXT"AddOns_ColorReducer"
32#define B_TRANSLATION_CONTEXT"AddOns_ColorReducer" "AddOns_ColorReducer"
33
34
35#ifdef __cplusplus201402L
36extern "C" {
37#endif
38 char name[255] = B_TRANSLATE_MARK("Color reducer" B_UTF8_ELLIPSIS)("Color reducer" "\xE2\x80\xA6");
39 char menu_help_string[255]
40 = B_TRANSLATE_MARK("Reduces the number of used colors.")("Reduces the number of used colors.");
41 int32 add_on_api_version = ADD_ON_API_VERSION;
42 add_on_types add_on_type = COLOR_ADD_ON;
43#ifdef __cplusplus201402L
44}
45#endif
46
47
48Manipulator* instantiate_add_on(BBitmap *bm,ManipulatorInformer *i)
49{
50 delete i;
51 return new ReducerManipulator(bm);
52}
53
54
55
56ReducerManipulator::ReducerManipulator(BBitmap *bm)
57 : WindowGUIManipulator()
58{
59 preview_bitmap = NULL__null;
60 config_view = NULL__null;
61 copy_of_the_preview_bitmap = NULL__null;
62
63 previous_settings.dither_mode = settings.dither_mode + 1;
64
65 SetPreviewBitmap(bm);
66}
67
68
69ReducerManipulator::~ReducerManipulator()
70{
71 delete copy_of_the_preview_bitmap;
72 delete config_view;
73}
74
75
76BBitmap* ReducerManipulator::ManipulateBitmap(ManipulatorSettings *set,BBitmap *original,Selection *selection,BStatusBar *status_bar)
77{
78 ReducerManipulatorSettings *new_settings = cast_as(set,ReducerManipulatorSettings)(dynamic_cast<ReducerManipulatorSettings*>(set));
79
80 if (new_settings == NULL__null)
1
Assuming 'new_settings' is not equal to NULL
2
Taking false branch
81 return NULL__null;
82
83 if (original == NULL__null)
3
Assuming 'original' is not equal to NULL
4
Taking false branch
84 return NULL__null;
85
86 BBitmap *source_bitmap,*target_bitmap;
87
88 if (original == preview_bitmap) {
5
Assuming 'original' is not equal to field 'preview_bitmap'
6
Taking false branch
89 if (*new_settings == previous_settings)
90 return original;
91
92 source_bitmap = copy_of_the_preview_bitmap;
93 target_bitmap = original;
94 }
95 else {
96 source_bitmap = original;
97 target_bitmap = new BBitmap(original->Bounds(),B_RGB32,FALSE0);
98 }
99
100 BScreen screen;
101 const rgb_color *palette;
7
'palette' declared without an initial value
102 if (new_settings->palette_mode == BEOS_PALETTE)
8
Assuming field 'palette_mode' is not equal to BEOS_PALETTE
9
Taking false branch
103 palette = screen.ColorMap()->color_list;
104 else if (new_settings->palette_mode == GLA_PALETTE)
10
Assuming field 'palette_mode' is not equal to GLA_PALETTE
11
Taking false branch
105 palette = gla_palette(source_bitmap,new_settings->palette_size);
106
107 if (palette != NULL__null)
12
The left operand of '!=' is a garbage value
108 do_dither(source_bitmap,target_bitmap,palette,new_settings->palette_size,new_settings->dither_mode);
109
110 return target_bitmap;
111}
112
113int32 ReducerManipulator::PreviewBitmap(Selection *selection,bool full_quality,BRegion *updated_region)
114{
115 if (settings == previous_settings ) {
116 return 0;
117 }
118 config_view->Window()->PostMessage(REDUCER_STARTED'Rest', config_view);
119
120 previous_settings = settings;
121
122 updated_region->Set(preview_bitmap->Bounds());
123
124
125 BBitmap *source_bitmap,*target_bitmap;
126 target_bitmap = preview_bitmap;
127 source_bitmap = copy_of_the_preview_bitmap;
128
129 BScreen screen;
130 const rgb_color *palette;
131 if (previous_settings.palette_mode == BEOS_PALETTE)
132 palette = screen.ColorMap()->color_list;
133 else if (previous_settings.palette_mode == GLA_PALETTE)
134 palette = gla_palette(source_bitmap,previous_settings.palette_size);
135
136 if (palette != NULL__null)
137 do_dither(source_bitmap,target_bitmap,palette,previous_settings.palette_size,previous_settings.dither_mode);
138
139 config_view->Window()->PostMessage(REDUCER_FINISHED'Refn', config_view);
140 return 1;
141}
142
143void ReducerManipulator::MouseDown(BPoint point,uint32,BView*,bool first_click)
144{
145 // This function does nothing in ReducerManipulator.
146}
147
148
149void ReducerManipulator::SetPreviewBitmap(BBitmap *bm)
150{
151 if (preview_bitmap != bm) {
152 delete copy_of_the_preview_bitmap;
153 if (bm != NULL__null) {
154 preview_bitmap = bm;
155 copy_of_the_preview_bitmap = DuplicateBitmap(bm,0);
156 }
157 else {
158 preview_bitmap = NULL__null;
159 copy_of_the_preview_bitmap = NULL__null;
160 }
161 }
162}
163
164
165void ReducerManipulator::Reset(Selection*)
166{
167 if (copy_of_the_preview_bitmap != NULL__null) {
168 // memcpy seems to be about 10-15% faster that copying with a loop.
169 uint32 *source = (uint32*)copy_of_the_preview_bitmap->Bits();
170 uint32 *target = (uint32*)preview_bitmap->Bits();
171 uint32 bits_length = preview_bitmap->BitsLength();
172
173 memcpy(target,source,bits_length);
174 }
175}
176
177BView* ReducerManipulator::MakeConfigurationView(const BMessenger& target)
178{
179 if (config_view == NULL__null) {
180 config_view = new ReducerManipulatorView(this,target);
181 config_view->ChangeSettings(&settings);
182 }
183
184 return config_view;
185}
186
187
188ManipulatorSettings* ReducerManipulator::ReturnSettings()
189{
190 return new ReducerManipulatorSettings(settings);
191}
192
193void ReducerManipulator::ChangeSettings(ManipulatorSettings *s)
194{
195 ReducerManipulatorSettings *new_settings;
196 new_settings = cast_as(s,ReducerManipulatorSettings)(dynamic_cast<ReducerManipulatorSettings*>(s));
197 if (new_settings != NULL__null) {
198 settings = *new_settings;
199 }
200}
201
202
203const char* ReducerManipulator::ReturnName()
204{
205 return B_TRANSLATE("Color reducer")BLocaleRoster::Default()->GetCatalog()->GetString(("Color reducer"
), "AddOns_ColorReducer")
;
206}
207
208const char* ReducerManipulator::ReturnHelpString()
209{
210 return B_TRANSLATE("Reduces the number of used colors.")BLocaleRoster::Default()->GetCatalog()->GetString(("Reduces the number of used colors."
), "AddOns_ColorReducer")
;
211}
212
213
214void ReducerManipulator::do_dither(BBitmap *source,BBitmap *target,const rgb_color *palette,int palette_size,int32 dither_mode)
215{
216 BBitmap *reduced_map;
217 if (settings.dither_mode == NO_DITHER) {
218 reduced_map = nearest_color_mapper(source,palette,palette_size);
219 }
220 else if (settings.dither_mode == PRESERVE_SOLIDS_DITHER) {
221 reduced_map = preserve_solids_fs_color_mapper(source,palette,palette_size);
222 }
223 else if (settings.dither_mode == N_CANDIDATE_DITHER) {
224 reduced_map = n_candidate_color_mapper(source,palette,palette_size,2);
225 }
226 else {
227 reduced_map = floyd_steinberg_edd_color_mapper(source,palette,palette_size);
228 }
229
230 uint8 *reduced_bits = (uint8*)reduced_map->Bits();
231 uint32 reduced_bpr = reduced_map->BytesPerRow();
232
233 uint32 *destination_bits = (uint32*)target->Bits();
234 uint32 destination_bpr = target->BytesPerRow()/4;
235
236 uint32 *source_bits = (uint32*)source->Bits();
237 uint32 source_bpr = source->BytesPerRow()/4;
238
239 int32 width = target->Bounds().IntegerWidth();
240 int32 height = target->Bounds().IntegerHeight();
241
242 int32 reduced_padding = reduced_bpr - width - 1;
243 int32 destination_padding = destination_bpr - width - 1;
244 int32 source_padding = source_bpr - width - 1;
245
246 // Use this union to guarantee endianness compatibility.
247 union {
248 uint8 bytes[4];
249 uint32 word;
250 } bgra32,source_bgra32;
251
252 for (int32 y=0;y<=height;y++) {
253 for (int32 x=0;x<=width;x++) {
254 rgb_color c = palette[*reduced_bits++];
255 source_bgra32.word = *source_bits++;
256 bgra32.bytes[0] = c.blue;
257 bgra32.bytes[1] = c.green;
258 bgra32.bytes[2] = c.red;
259 bgra32.bytes[3] = source_bgra32.bytes[3];
260
261 *destination_bits++ = bgra32.word;
262 }
263 destination_bits += destination_padding;
264 reduced_bits += reduced_padding;
265 source_bits += source_padding;
266 }
267
268 delete reduced_map;
269}
270
271
272
273
274
275
276// -------------------------------------
277ReducerManipulatorView::ReducerManipulatorView(ReducerManipulator *manip,
278 const BMessenger& t)
279 : WindowGUIManipulatorView()
280{
281 target = t;
282 manipulator = manip;
283
284 BMenu *dither_menu = new BPopUpMenu("SELECT");
285
286 BMessage *message;
287 message = new BMessage(DITHER_MODE_CHANGED'Dmoc');
288 message->AddInt32("dither_mode",NO_DITHER);
289 dither_menu->AddItem(new BMenuItem(B_TRANSLATE("No dithering")BLocaleRoster::Default()->GetCatalog()->GetString(("No dithering"
), "AddOns_ColorReducer")
, message));
290
291 message = new BMessage(DITHER_MODE_CHANGED'Dmoc');
292 message->AddInt32("dither_mode",FLOYD_STEINBERG_EDD_DITHER);
293 dither_menu->AddItem(new BMenuItem(B_TRANSLATE("Floyd-Steinberg EDD")BLocaleRoster::Default()->GetCatalog()->GetString(("Floyd-Steinberg EDD"
), "AddOns_ColorReducer")
, message));
294
295 message = new BMessage(DITHER_MODE_CHANGED'Dmoc');
296 message->AddInt32("dither_mode",PRESERVE_SOLIDS_DITHER);
297 dither_menu->AddItem(new BMenuItem(B_TRANSLATE("Preserve solids FS")BLocaleRoster::Default()->GetCatalog()->GetString(("Preserve solids FS"
), "AddOns_ColorReducer")
, message));
298
299 message = new BMessage(DITHER_MODE_CHANGED'Dmoc');
300 message->AddInt32("dither_mode",N_CANDIDATE_DITHER);
301 dither_menu->AddItem(new BMenuItem(B_TRANSLATE("N-Candidate")BLocaleRoster::Default()->GetCatalog()->GetString(("N-Candidate"
), "AddOns_ColorReducer")
, message));
302
303 dither_mode_menu_field = new BMenuField(
304 "dither_mode_menu_field", B_TRANSLATE("Dither mode:")BLocaleRoster::Default()->GetCatalog()->GetString(("Dither mode:"
), "AddOns_ColorReducer")
, dither_menu);
305
306 BMenu *size_menu = new BPopUpMenu("SELECT"); // TODO: Find how initialized...
307
308 message = new BMessage(PALETTE_SIZE_CHANGED'Plsc');
309 message->AddInt32("palette_size",2);
310 size_menu->AddItem(new BMenuItem("2",message));
311
312 message = new BMessage(PALETTE_SIZE_CHANGED'Plsc');
313 message->AddInt32("palette_size",4);
314 size_menu->AddItem(new BMenuItem("4",message));
315
316 message = new BMessage(PALETTE_SIZE_CHANGED'Plsc');
317 message->AddInt32("palette_size",8);
318 size_menu->AddItem(new BMenuItem("8",message));
319
320 message = new BMessage(PALETTE_SIZE_CHANGED'Plsc');
321 message->AddInt32("palette_size",16);
322 size_menu->AddItem(new BMenuItem("16",message));
323
324 message = new BMessage(PALETTE_SIZE_CHANGED'Plsc');
325 message->AddInt32("palette_size",32);
326 size_menu->AddItem(new BMenuItem("32",message));
327
328 message = new BMessage(PALETTE_SIZE_CHANGED'Plsc');
329 message->AddInt32("palette_size",64);
330 size_menu->AddItem(new BMenuItem("64",message));
331
332 message = new BMessage(PALETTE_SIZE_CHANGED'Plsc');
333 message->AddInt32("palette_size",128);
334 size_menu->AddItem(new BMenuItem("128",message));
335
336 message = new BMessage(PALETTE_SIZE_CHANGED'Plsc');
337 message->AddInt32("palette_size",256);
338 size_menu->AddItem(new BMenuItem("256",message));
339
340 palette_size_menu_field = new BMenuField("palette_size_menu_field",
341 B_TRANSLATE("Palette size:")BLocaleRoster::Default()->GetCatalog()->GetString(("Palette size:"
), "AddOns_ColorReducer")
, size_menu);
342
343 BMenu *mode_menu = new BPopUpMenu("SELECT");
344
345 message = new BMessage(PALETTE_MODE_CHANGED'Plmc');
346 message->AddInt32("palette_mode",BEOS_PALETTE);
347 mode_menu->AddItem(new BMenuItem(B_TRANSLATE("BeOS")BLocaleRoster::Default()->GetCatalog()->GetString(("BeOS"
), "AddOns_ColorReducer")
, message));
348
349 message = new BMessage(PALETTE_MODE_CHANGED'Plmc');
350 message->AddInt32("palette_mode",GLA_PALETTE);
351 mode_menu->AddItem(new BMenuItem(B_TRANSLATE("Generalized Lloyd's Algorithm")BLocaleRoster::Default()->GetCatalog()->GetString(("Generalized Lloyd's Algorithm"
), "AddOns_ColorReducer")
, message));
352
353 palette_mode_menu_field = new BMenuField("palette_mode_menu_field",
354 B_TRANSLATE("Palette mode:")BLocaleRoster::Default()->GetCatalog()->GetString(("Palette mode:"
), "AddOns_ColorReducer")
, mode_menu);
355
356 dither_menu->ItemAt(settings.dither_mode)->SetMarked(true);
357 size_menu->ItemAt(size_menu->CountItems()-1)->SetMarked(true); // slight hack...
358 mode_menu->ItemAt(settings.palette_mode)->SetMarked(true);
359
360 busy = new BStringView("busy", B_TRANSLATE("Reducing in progress")BLocaleRoster::Default()->GetCatalog()->GetString(("Reducing in progress"
), "AddOns_ColorReducer")
);
361 busy->SetHighColor(128, 0, 0);
362 busy->SetViewColor(ViewColor());
363 busy->Hide();
364
365 BGridLayout* gridLayout =
366 BLayoutBuilder::Grid<>(B_USE_DEFAULT_SPACING, B_USE_SMALL_SPACING)
367 .Add(dither_mode_menu_field->CreateLabelLayoutItem(), 0, 0)
368 .Add(dither_mode_menu_field->CreateMenuBarLayoutItem(), 1, 0)
369 .Add(palette_size_menu_field->CreateLabelLayoutItem(), 0, 1)
370 .Add(palette_size_menu_field->CreateMenuBarLayoutItem(), 1, 1)
371 .Add(palette_mode_menu_field->CreateLabelLayoutItem(), 0, 2)
372 .Add(palette_mode_menu_field->CreateMenuBarLayoutItem(), 1, 2);
373 gridLayout->SetMinColumnWidth(1, StringWidth("-YES-THIS-IS-A-REALLY-LONG-STRING--"));
374
375 BLayoutBuilder::Group<>(this, B_VERTICAL)
376 .Add(gridLayout->View())
377 .AddGroup(B_HORIZONTAL)
378 .AddGlue()
379 .Add(busy)
380 .AddGlue()
381 .End()
382 .SetInsets(B_USE_SMALL_INSETS)
383 .End();
384
385}
386
387
388ReducerManipulatorView::~ReducerManipulatorView()
389{
390}
391
392
393void ReducerManipulatorView::AttachedToWindow()
394{
395 WindowGUIManipulatorView::AttachedToWindow();
396}
397
398void ReducerManipulatorView::AllAttached()
399{
400 dither_mode_menu_field->Menu()->SetTargetForItems(this);
401 palette_size_menu_field->Menu()->SetTargetForItems(this);
402 palette_mode_menu_field->Menu()->SetTargetForItems(this);
403}
404
405
406void ReducerManipulatorView::MessageReceived(BMessage *message)
407{
408 switch (message->what) {
409 case DITHER_MODE_CHANGED'Dmoc':
410 {
411 int32 mode;
412 if (message->FindInt32("dither_mode",&mode) == B_OK((int)0)) {
413 settings.dither_mode = mode;
414 manipulator->ChangeSettings(&settings);
415 target.SendMessage(HS_MANIPULATOR_ADJUSTING_FINISHED'Mafi');
416 }
417 break;
418 }
419
420 case PALETTE_SIZE_CHANGED'Plsc':
421 {
422 int32 size;
423 if (message->FindInt32("palette_size",&size) == B_OK((int)0)) {
424 settings.palette_size = size;
425 manipulator->ChangeSettings(&settings);
426 target.SendMessage(HS_MANIPULATOR_ADJUSTING_FINISHED'Mafi');
427 }
428 break;
429 }
430
431 case PALETTE_MODE_CHANGED'Plmc':
432 {
433 int32 mode;
434 if (message->FindInt32("palette_mode",&mode) == B_OK((int)0)) {
435 settings.palette_mode = mode;
436 manipulator->ChangeSettings(&settings);
437 target.SendMessage(HS_MANIPULATOR_ADJUSTING_FINISHED'Mafi');
438 }
439 break;
440 }
441
442 case REDUCER_STARTED'Rest':
443 {
444 busy->Show();
445 break;
446 }
447
448 case REDUCER_FINISHED'Refn':
449 {
450 busy->Hide();
451 break;
452 }
453
454 default:
455 WindowGUIManipulatorView::MessageReceived(message);
456 break;
457 }
458}
459
460
461void ReducerManipulatorView::ChangeSettings(ManipulatorSettings *set)
462{
463 ReducerManipulatorSettings *new_settings = cast_as(set,ReducerManipulatorSettings)(dynamic_cast<ReducerManipulatorSettings*>(set));
464
465 if (set != NULL__null) {
466 settings = *new_settings;
467
468 BWindow *window = Window();
469 if (window != NULL__null) {
470 window->Lock();
471 window->Unlock();
472 }
473 }
474}