File: | home/HaikuArchives/ArtPaint/addons/AddOns/Interference/Interference.cpp |
Warning: | line 238, column 9 Value stored to 'num_pixels' during its initialization is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 <Box.h> |
11 | #include <Catalog.h> |
12 | #include <GroupLayoutBuilder.h> |
13 | #include <LayoutBuilder.h> |
14 | #include <StatusBar.h> |
15 | #include <StopWatch.h> |
16 | #include <Window.h> |
17 | |
18 | |
19 | #include "AddOns.h" |
20 | #include "Interference.h" |
21 | #include "ManipulatorInformer.h" |
22 | #include "PixelOperations.h" |
23 | #include "Selection.h" |
24 | #include "UtilityClasses.h" |
25 | |
26 | #include <math.h> |
27 | |
28 | |
29 | #define PI3.14159265358979323846 M_PI3.14159265358979323846 |
30 | |
31 | #undef B_TRANSLATION_CONTEXT"AddOns_Interference" |
32 | #define B_TRANSLATION_CONTEXT"AddOns_Interference" "AddOns_Interference" |
33 | |
34 | |
35 | #define WAVE_LENGTH_A_CHANGED'WvAc' 'WvAc' |
36 | #define WAVE_LENGTH_B_CHANGED'WvBc' 'WvBc' |
37 | #define WAVE_LENGTH_ADJUSTING_STARTED'WLAs' 'WLAs' |
38 | #define CENTER_A_X_CHANGED'CaXc' 'CaXc' |
39 | #define CENTER_A_Y_CHANGED'CaYc' 'CaYc' |
40 | #define CENTER_B_X_CHANGED'CbXc' 'CbXc' |
41 | #define CENTER_B_Y_CHANGED'CbYc' 'CbYc' |
42 | #define GRAYSCALE_CHANGED'gScd' 'gScd' |
43 | |
44 | |
45 | #ifdef __cplusplus201402L |
46 | extern "C" { |
47 | #endif |
48 | char name[255] = B_TRANSLATE_MARK("Interference" B_UTF8_ELLIPSIS)("Interference" "\xE2\x80\xA6"); |
49 | char menu_help_string[255] = B_TRANSLATE_MARK("Creates an interference-pattern.")("Creates an interference-pattern."); |
50 | int32 add_on_api_version = ADD_ON_API_VERSION; |
51 | add_on_types add_on_type = DISTORT_ADD_ON; |
52 | #ifdef __cplusplus201402L |
53 | } |
54 | #endif |
55 | |
56 | |
57 | Manipulator* |
58 | instantiate_add_on(BBitmap* bm, ManipulatorInformer* i) |
59 | { |
60 | // Here create a view-manipulator. The class should inherit |
61 | // from the WindowGuiManipulator base-class. It will be deleted |
62 | // in the application program. |
63 | return new InterferenceManipulator(bm, i); |
64 | } |
65 | |
66 | |
67 | InterferenceManipulator::InterferenceManipulator(BBitmap* bm, ManipulatorInformer* i) |
68 | : WindowGUIManipulator() |
69 | { |
70 | copy_of_the_preview_bitmap = NULL__null; |
71 | preview_bitmap = NULL__null; |
72 | config_view = NULL__null; |
73 | informer = i; |
74 | |
75 | SetPreviewBitmap(bm); |
76 | |
77 | sin_table = new float[720]; |
78 | for (int32 i=0;i<720;i++) |
79 | sin_table[i] = sin((float)i/720.0*2*PI3.14159265358979323846); |
80 | } |
81 | |
82 | |
83 | InterferenceManipulator::~InterferenceManipulator() |
84 | { |
85 | delete[] sin_table; |
86 | delete copy_of_the_preview_bitmap; |
87 | delete informer; |
88 | |
89 | if (config_view != NULL__null) { |
90 | config_view->RemoveSelf(); |
91 | delete config_view; |
92 | config_view = NULL__null; |
93 | } |
94 | } |
95 | |
96 | |
97 | BBitmap* |
98 | InterferenceManipulator::ManipulateBitmap(ManipulatorSettings *set,BBitmap *original,Selection *selection,BStatusBar *status_bar) |
99 | { |
100 | InterferenceManipulatorSettings *new_settings = dynamic_cast<InterferenceManipulatorSettings*>(set); |
101 | |
102 | if (new_settings == NULL__null) |
103 | return NULL__null; |
104 | |
105 | if (original == NULL__null) |
106 | return NULL__null; |
107 | |
108 | MakeInterference(original,new_settings,selection); |
109 | |
110 | return original; |
111 | } |
112 | |
113 | |
114 | int32 |
115 | InterferenceManipulator::PreviewBitmap(Selection *selection,bool full_quality,BRegion *updated_region) |
116 | { |
117 | if ((settings == previous_settings) == FALSE0) { |
118 | previous_settings = settings; |
119 | MakeInterference(preview_bitmap,&previous_settings,selection); |
120 | updated_region->Set(selection->GetBoundingRect()); |
121 | return 1; |
122 | } |
123 | |
124 | return DRAW_ONLY_GUI; |
125 | } |
126 | |
127 | |
128 | void |
129 | InterferenceManipulator::MouseDown(BPoint point,uint32 buttons,BView*,bool first_click) |
130 | { |
131 | if (first_click == TRUE1) |
132 | previous_settings = settings; |
133 | |
134 | if (buttons & B_PRIMARY_MOUSE_BUTTON) |
135 | settings.centerA = point; |
136 | else |
137 | settings.centerB = point; |
138 | |
139 | if (config_view != NULL__null) |
140 | config_view->ChangeSettings(&settings); |
141 | } |
142 | |
143 | |
144 | void |
145 | InterferenceManipulator::MakeInterference(BBitmap *target, InterferenceManipulatorSettings *set, Selection *sel) |
146 | { |
147 | BStopWatch watch("Making an interference"); |
148 | uint32 *target_bits = (uint32*)target->Bits(); |
149 | uint32 target_bpr = target->BytesPerRow()/4; |
150 | |
151 | BRect b = sel->GetBoundingRect(); |
152 | |
153 | // the wave lengths are taken as inverse numbers |
154 | float wl_A = 1.0/set->waveLengthA; |
155 | float wl_B = 1.0/set->waveLengthB; |
156 | |
157 | // the centers |
158 | BPoint c_A = set->centerA; |
159 | BPoint c_B = set->centerB; |
160 | |
161 | union { |
162 | uint8 bytes[4]; |
163 | uint32 word; |
164 | } c, fg, bg; |
165 | |
166 | c.bytes[3] = 255; |
167 | |
168 | float max_dist = 500; |
169 | |
170 | rgb_color fgColor; |
171 | rgb_color bgColor; |
172 | |
173 | if (set->grayscale == B_CONTROL_ON) { |
174 | fgColor.set_to(255, 255, 255, 255); |
175 | bgColor.set_to(0, 0, 0, 255); |
176 | } else { |
177 | fgColor = informer->GetForegroundColor(); |
178 | bgColor = informer->GetBackgroundColor(); |
179 | } |
180 | |
181 | fg.word = RGBColorToBGRA(fgColor); |
182 | bg.word = RGBColorToBGRA(bgColor); |
183 | |
184 | for (int32 y=b.top;y<=b.bottom;y++) { |
185 | for (int32 x=b.left;x<=b.right;x++) { |
186 | if (sel->ContainsPoint(x,y)) { |
187 | float dist_A = sqrt(pow(fabs(x-c_A.x),2) + pow(fabs(y-c_A.y),2)); |
188 | float dist_B = sqrt(pow(fabs(x-c_B.x),2) + pow(fabs(y-c_B.y),2)); |
189 | |
190 | float contrib_A = sin(((dist_A*wl_A)-floor(dist_A*wl_A))*2*PI3.14159265358979323846) * max_c(0,(max_dist-dist_A))((0)>((max_dist-dist_A))?(0):((max_dist-dist_A)))/max_dist; |
191 | float contrib_B = sin(((dist_B*wl_B)-floor(dist_B*wl_B))*2*PI3.14159265358979323846) * max_c(0,(max_dist-dist_B))((0)>((max_dist-dist_B))?(0):((max_dist-dist_B)))/max_dist; |
192 | // float contrib_A = sin_table[(int32)(((dist_A*wl_A)-floor(dist_A*wl_A))*720)]; |
193 | // float contrib_B = sin_table[(int32)(((dist_B*wl_B)-floor(dist_B*wl_B))*720)]; |
194 | |
195 | float contrib = (contrib_A + contrib_B + 2) / 4; |
196 | float contrib_opposite = 1.0 - contrib; |
197 | |
198 | c.bytes[0] = bg.bytes[0] * contrib_opposite + fg.bytes[0] * contrib; |
199 | c.bytes[1] = bg.bytes[1] * contrib_opposite + fg.bytes[1] * contrib; |
200 | c.bytes[2] = bg.bytes[2] * contrib_opposite + fg.bytes[2] * contrib; |
201 | c.bytes[3] = bg.bytes[3] * contrib_opposite + fg.bytes[3] * contrib; |
202 | |
203 | |
204 | // if (contrib_A*contrib_B > 0) { |
205 | // // partially constructive |
206 | // c.bytes[0] = c.bytes[1] = c.bytes[2] = 255; |
207 | // } |
208 | // else { |
209 | // // destructive |
210 | // c.bytes[0] = c.bytes[1] = c.bytes[2] = 0; |
211 | // } |
212 | |
213 | *(target_bits + x + y*target_bpr) = c.word; |
214 | } |
215 | } |
216 | } |
217 | } |
218 | |
219 | |
220 | void |
221 | InterferenceManipulator::SetPreviewBitmap(BBitmap *bm) |
222 | { |
223 | if (preview_bitmap != bm) { |
224 | delete copy_of_the_preview_bitmap; |
225 | if (bm != NULL__null) { |
226 | preview_bitmap = bm; |
227 | copy_of_the_preview_bitmap = DuplicateBitmap(bm,0); |
228 | } |
229 | else { |
230 | preview_bitmap = NULL__null; |
231 | copy_of_the_preview_bitmap = NULL__null; |
232 | } |
233 | } |
234 | if (preview_bitmap != NULL__null) { |
235 | double speed = GetSystemClockSpeed() / 15000; |
236 | |
237 | BRect bounds = preview_bitmap->Bounds(); |
238 | float num_pixels = (bounds.Width()+1) * (bounds.Height() + 1); |
Value stored to 'num_pixels' during its initialization is never read | |
239 | |
240 | if ((settings.centerA == BPoint(0,0)) && (settings.centerB == BPoint(0,0))) { |
241 | settings.centerA.x = bounds.Width()/2; |
242 | settings.centerB.x = bounds.Width()/2; |
243 | settings.centerA.y = bounds.Height()/2-50; |
244 | settings.centerB.y = bounds.Height()/2+50; |
245 | } |
246 | } |
247 | } |
248 | |
249 | |
250 | const char* |
251 | InterferenceManipulator::ReturnHelpString() |
252 | { |
253 | return B_TRANSLATE("Left-click to move Center A, right-click to move Center B.")BLocaleRoster::Default()->GetCatalog()->GetString(("Left-click to move Center A, right-click to move Center B." ), "AddOns_Interference"); |
254 | } |
255 | |
256 | |
257 | const char* |
258 | InterferenceManipulator::ReturnName() |
259 | { |
260 | return B_TRANSLATE("Interference")BLocaleRoster::Default()->GetCatalog()->GetString(("Interference" ), "AddOns_Interference"); |
261 | } |
262 | |
263 | |
264 | void |
265 | InterferenceManipulator::Reset(Selection*) |
266 | { |
267 | if (preview_bitmap != NULL__null) { |
268 | uint32 *source_bits = (uint32*)copy_of_the_preview_bitmap->Bits(); |
269 | uint32 *target_bits = (uint32*)preview_bitmap->Bits(); |
270 | |
271 | int32 bits_length = preview_bitmap->BitsLength()/4; |
272 | |
273 | for (int32 i=0;i<bits_length;i++) |
274 | *target_bits++ = *source_bits++; |
275 | } |
276 | } |
277 | |
278 | |
279 | BView* |
280 | InterferenceManipulator::MakeConfigurationView(const BMessenger& target) |
281 | { |
282 | config_view = new InterferenceManipulatorView(BRect(0,0,0,0),this,target); |
283 | config_view->ChangeSettings(&settings); |
284 | return config_view; |
285 | } |
286 | |
287 | |
288 | ManipulatorSettings* |
289 | InterferenceManipulator::ReturnSettings() |
290 | { |
291 | return new InterferenceManipulatorSettings(settings); |
292 | } |
293 | |
294 | |
295 | void |
296 | InterferenceManipulator::ChangeSettings(ManipulatorSettings *s) |
297 | { |
298 | InterferenceManipulatorSettings *new_settings = dynamic_cast<InterferenceManipulatorSettings*>(s); |
299 | if (new_settings != NULL__null) { |
300 | previous_settings = settings; |
301 | settings = *new_settings; |
302 | } |
303 | } |
304 | |
305 | |
306 | //------------- |
307 | |
308 | |
309 | InterferenceManipulatorView::InterferenceManipulatorView(BRect rect, |
310 | InterferenceManipulator *manip, const BMessenger& t) |
311 | : WindowGUIManipulatorView() |
312 | , target(NULL__null) |
313 | { |
314 | manipulator = manip; |
315 | target = new BMessenger(t); |
316 | preview_started = FALSE0; |
317 | |
318 | centerAX = new BSpinner("centerAx", "X:", new BMessage(CENTER_A_X_CHANGED'CaXc')); |
319 | centerAX->SetMaxValue(9999); |
320 | centerAX->SetMinValue(-9999); |
321 | centerAY = new BSpinner("centerAy", "Y:", new BMessage(CENTER_A_Y_CHANGED'CaYc')); |
322 | centerAY->SetMaxValue(9999); |
323 | centerAY->SetMinValue(-9999); |
324 | centerBX = new BSpinner("centerBx", "X:", new BMessage(CENTER_B_X_CHANGED'CbXc')); |
325 | centerBX->SetMaxValue(9999); |
326 | centerBX->SetMinValue(-9999); |
327 | centerBY = new BSpinner("centerBy", "Y:", new BMessage(CENTER_B_Y_CHANGED'CbYc')); |
328 | centerBY->SetMaxValue(9999); |
329 | centerBY->SetMinValue(-9999); |
330 | |
331 | waveLengthSliderA = new BSlider("waveLengthSliderA", |
332 | B_TRANSLATE("Wavelength:")BLocaleRoster::Default()->GetCatalog()->GetString(("Wavelength:" ), "AddOns_Interference"), |
333 | new BMessage(WAVE_LENGTH_A_CHANGED'WvAc'), |
334 | (int32)MIN_WAVE_LENGTH2, (int32)MAX_WAVE_LENGTH100, |
335 | B_HORIZONTAL, B_TRIANGLE_THUMB); |
336 | waveLengthSliderA->SetLimitLabels(B_TRANSLATE("Short")BLocaleRoster::Default()->GetCatalog()->GetString(("Short" ), "AddOns_Interference"), |
337 | B_TRANSLATE("Long")BLocaleRoster::Default()->GetCatalog()->GetString(("Long" ), "AddOns_Interference")); |
338 | waveLengthSliderA->SetModificationMessage( |
339 | new BMessage(WAVE_LENGTH_ADJUSTING_STARTED'WLAs')); |
340 | |
341 | waveLengthSliderB = new BSlider("waveLengthSliderB", |
342 | B_TRANSLATE("Wavelength:")BLocaleRoster::Default()->GetCatalog()->GetString(("Wavelength:" ), "AddOns_Interference"), |
343 | new BMessage(WAVE_LENGTH_B_CHANGED'WvBc'), |
344 | (int32)MIN_WAVE_LENGTH2, (int32)MAX_WAVE_LENGTH100, |
345 | B_HORIZONTAL, B_TRIANGLE_THUMB); |
346 | waveLengthSliderB->SetLimitLabels(B_TRANSLATE("Short")BLocaleRoster::Default()->GetCatalog()->GetString(("Short" ), "AddOns_Interference"), |
347 | B_TRANSLATE("Long")BLocaleRoster::Default()->GetCatalog()->GetString(("Long" ), "AddOns_Interference")); |
348 | waveLengthSliderB->SetModificationMessage( |
349 | new BMessage(WAVE_LENGTH_ADJUSTING_STARTED'WLAs')); |
350 | |
351 | BBox *frameA = new BBox(B_FANCY_BORDER, BGroupLayoutBuilder(B_VERTICAL) |
352 | .AddGroup(B_HORIZONTAL) |
353 | .Add(centerAX) |
354 | .Add(centerAY) |
355 | .End() |
356 | .Add(waveLengthSliderA) |
357 | .SetInsets(5.0, 5.0, 5.0, 5.0) |
358 | .TopView()); |
359 | |
360 | frameA->SetLabel(B_TRANSLATE("Center A")BLocaleRoster::Default()->GetCatalog()->GetString(("Center A" ), "AddOns_Interference")); |
361 | |
362 | BBox *frameB = new BBox(B_FANCY_BORDER, BGroupLayoutBuilder(B_VERTICAL) |
363 | .AddGroup(B_HORIZONTAL) |
364 | .Add(centerBX) |
365 | .Add(centerBY) |
366 | .End() |
367 | .Add(waveLengthSliderB) |
368 | .SetInsets(5.0, 5.0, 5.0, 5.0) |
369 | .TopView()); |
370 | |
371 | frameB->SetLabel(B_TRANSLATE("Center B")BLocaleRoster::Default()->GetCatalog()->GetString(("Center B" ), "AddOns_Interference")); |
372 | |
373 | grayScale = new BCheckBox(B_TRANSLATE("Grayscale")BLocaleRoster::Default()->GetCatalog()->GetString(("Grayscale" ), "AddOns_Interference"), new BMessage(GRAYSCALE_CHANGED'gScd')); |
374 | |
375 | SetLayout(BLayoutBuilder::Group<>(this, B_VERTICAL) |
376 | .Add(frameA) |
377 | .Add(frameB) |
378 | .Add(grayScale) |
379 | ); |
380 | |
381 | } |
382 | |
383 | |
384 | void |
385 | InterferenceManipulatorView::AttachedToWindow() |
386 | { |
387 | WindowGUIManipulatorView::AttachedToWindow(); |
388 | |
389 | waveLengthSliderA->SetTarget(BMessenger(this)); |
390 | waveLengthSliderB->SetTarget(BMessenger(this)); |
391 | centerAX->SetTarget(BMessenger(this)); |
392 | centerAY->SetTarget(BMessenger(this)); |
393 | centerBX->SetTarget(BMessenger(this)); |
394 | centerBY->SetTarget(BMessenger(this)); |
395 | grayScale->SetTarget(BMessenger(this)); |
396 | } |
397 | |
398 | |
399 | void |
400 | InterferenceManipulatorView::AllAttached() |
401 | { |
402 | waveLengthSliderA->SetValue(settings.waveLengthA); |
403 | waveLengthSliderB->SetValue(settings.waveLengthB); |
404 | |
405 | centerAX->SetValue(settings.centerA.x); |
406 | centerAY->SetValue(settings.centerA.y); |
407 | centerBX->SetValue(settings.centerB.x); |
408 | centerBY->SetValue(settings.centerB.y); |
409 | grayScale->SetValue(settings.grayscale); |
410 | } |
411 | |
412 | |
413 | void |
414 | InterferenceManipulatorView::MessageReceived(BMessage *message) |
415 | { |
416 | switch (message->what) { |
417 | case WAVE_LENGTH_ADJUSTING_STARTED'WLAs': |
418 | if (preview_started == FALSE0) { |
419 | preview_started = TRUE1; |
420 | target->SendMessage(HS_MANIPULATOR_ADJUSTING_STARTED'Mast'); |
421 | } |
422 | settings.waveLengthA = waveLengthSliderA->Value(); |
423 | settings.waveLengthB = waveLengthSliderB->Value(); |
424 | manipulator->ChangeSettings(&settings); |
425 | break; |
426 | |
427 | case WAVE_LENGTH_A_CHANGED'WvAc': |
428 | preview_started = FALSE0; |
429 | settings.waveLengthA = waveLengthSliderA->Value(); |
430 | manipulator->ChangeSettings(&settings); |
431 | target->SendMessage(HS_MANIPULATOR_ADJUSTING_FINISHED'Mafi'); |
432 | break; |
433 | |
434 | case WAVE_LENGTH_B_CHANGED'WvBc': |
435 | preview_started = FALSE0; |
436 | settings.waveLengthB = waveLengthSliderB->Value(); |
437 | manipulator->ChangeSettings(&settings); |
438 | target->SendMessage(HS_MANIPULATOR_ADJUSTING_FINISHED'Mafi'); |
439 | break; |
440 | |
441 | case CENTER_A_X_CHANGED'CaXc': |
442 | preview_started = FALSE0; |
443 | settings.centerA.x = centerAX->Value(); |
444 | manipulator->ChangeSettings(&settings); |
445 | target->SendMessage(HS_MANIPULATOR_ADJUSTING_FINISHED'Mafi'); |
446 | break; |
447 | |
448 | case CENTER_A_Y_CHANGED'CaYc': |
449 | preview_started = FALSE0; |
450 | settings.centerA.y = centerAY->Value(); |
451 | manipulator->ChangeSettings(&settings); |
452 | target->SendMessage(HS_MANIPULATOR_ADJUSTING_FINISHED'Mafi'); |
453 | break; |
454 | |
455 | case CENTER_B_X_CHANGED'CbXc': |
456 | preview_started = FALSE0; |
457 | settings.centerB.x = centerBX->Value(); |
458 | manipulator->ChangeSettings(&settings); |
459 | target->SendMessage(HS_MANIPULATOR_ADJUSTING_FINISHED'Mafi'); |
460 | break; |
461 | |
462 | case CENTER_B_Y_CHANGED'CbYc': |
463 | preview_started = FALSE0; |
464 | settings.centerB.y = centerBY->Value(); |
465 | manipulator->ChangeSettings(&settings); |
466 | target->SendMessage(HS_MANIPULATOR_ADJUSTING_FINISHED'Mafi'); |
467 | break; |
468 | |
469 | case GRAYSCALE_CHANGED'gScd': |
470 | preview_started = FALSE0; |
471 | settings.grayscale = grayScale->Value(); |
472 | manipulator->ChangeSettings(&settings); |
473 | target->SendMessage(HS_MANIPULATOR_ADJUSTING_FINISHED'Mafi'); |
474 | break; |
475 | |
476 | default: |
477 | WindowGUIManipulatorView::MessageReceived(message); |
478 | break; |
479 | } |
480 | } |
481 | |
482 | |
483 | void |
484 | InterferenceManipulatorView::ChangeSettings(InterferenceManipulatorSettings *s) |
485 | { |
486 | settings = *s; |
487 | BWindow *window = Window(); |
488 | |
489 | if (window != NULL__null) { |
490 | window->Lock(); |
491 | |
492 | waveLengthSliderA->SetValue(settings.waveLengthA); |
493 | waveLengthSliderB->SetValue(settings.waveLengthB); |
494 | centerAX->SetValue(settings.centerA.x); |
495 | centerAY->SetValue(settings.centerA.y); |
496 | centerBX->SetValue(settings.centerB.x); |
497 | centerBY->SetValue(settings.centerB.y); |
498 | grayScale->SetValue(settings.grayscale); |
499 | |
500 | window->Unlock(); |
501 | } |
502 | } |