File: | home/HaikuArchives/ArtPaint/addons/AddOns/MarbleTexturer/Marble.cpp |
Warning: | line 155, column 10 Value stored to 'y_times_bpr' 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 <Catalog.h> |
11 | #include <StatusBar.h> |
12 | #include <StopWatch.h> |
13 | #include <Window.h> |
14 | |
15 | #include "AddOns.h" |
16 | #include "Marble.h" |
17 | #include "ManipulatorInformer.h" |
18 | #include "PixelOperations.h" |
19 | #include "PerlinNoiseGenerator.h" |
20 | #include "Selection.h" |
21 | #include "SplineGenerator.h" |
22 | |
23 | #undef B_TRANSLATION_CONTEXT"AddOns_Marble" |
24 | #define B_TRANSLATION_CONTEXT"AddOns_Marble" "AddOns_Marble" |
25 | |
26 | |
27 | #ifdef __cplusplus201402L |
28 | extern "C" { |
29 | #endif |
30 | char name[255] = B_TRANSLATE_MARK("Marble")("Marble"); |
31 | char menu_help_string[255] = B_TRANSLATE_MARK("Puts a marble-like texture over the image.")("Puts a marble-like texture over the image."); |
32 | int32 add_on_api_version = ADD_ON_API_VERSION; |
33 | add_on_types add_on_type = EFFECT_FILTER_ADD_ON; |
34 | #ifdef __cplusplus201402L |
35 | } |
36 | #endif |
37 | |
38 | |
39 | Manipulator* instantiate_add_on(BBitmap*,ManipulatorInformer *i) |
40 | { |
41 | return new MarbleManipulator(i); |
42 | } |
43 | |
44 | |
45 | |
46 | MarbleManipulator::MarbleManipulator(ManipulatorInformer *i) |
47 | : Manipulator() |
48 | { |
49 | informer = i; |
50 | processor_count = GetSystemCpuCount(); |
51 | } |
52 | |
53 | |
54 | MarbleManipulator::~MarbleManipulator() |
55 | { |
56 | delete informer; |
57 | } |
58 | |
59 | |
60 | BBitmap* MarbleManipulator::ManipulateBitmap(BBitmap *original,Selection *selection,BStatusBar *status_bar) |
61 | { |
62 | BStopWatch watch("PerlinMarble"); |
63 | |
64 | source_bitmap = original; |
65 | target_bitmap = original; |
66 | the_selection = selection; |
67 | progress_bar = status_bar; |
68 | |
69 | thread_id *threads = new thread_id[processor_count]; |
70 | |
71 | spare_copy_bitmap = DuplicateBitmap(original,-1); |
72 | |
73 | for (int32 i = 0;i < processor_count;i++) { |
74 | threads[i] = spawn_thread(thread_entrythread_func,"perlin_fade_thread",B_NORMAL_PRIORITY10,this); |
75 | resume_thread(threads[i]); |
76 | send_data(threads[i],i,NULL__null,0); |
77 | } |
78 | |
79 | for (int32 i = 0;i < processor_count;i++) { |
80 | int32 return_value; |
81 | wait_for_thread(threads[i],&return_value); |
82 | } |
83 | |
84 | delete[] threads; |
85 | |
86 | delete spare_copy_bitmap; |
87 | |
88 | // Return the original. |
89 | return original; |
90 | } |
91 | |
92 | |
93 | const char* MarbleManipulator::ReturnHelpString() |
94 | { |
95 | return B_TRANSLATE("Puts a marble-like texture over the image.")BLocaleRoster::Default()->GetCatalog()->GetString(("Puts a marble-like texture over the image." ), "AddOns_Marble"); |
96 | } |
97 | |
98 | |
99 | const char* MarbleManipulator::ReturnName() |
100 | { |
101 | return B_TRANSLATE("Marble")BLocaleRoster::Default()->GetCatalog()->GetString(("Marble" ), "AddOns_Marble"); |
102 | } |
103 | |
104 | |
105 | int32 MarbleManipulator::thread_entrythread_func(void *data) |
106 | { |
107 | int32 thread_number; |
108 | thread_number = receive_data(NULL__null,NULL__null,0); |
109 | |
110 | MarbleManipulator *this_pointer = (MarbleManipulator*)data; |
111 | |
112 | return this_pointer->thread_function(thread_number); |
113 | } |
114 | |
115 | |
116 | int32 MarbleManipulator::thread_function(int32 thread_number) |
117 | { |
118 | BWindow *progress_bar_window = NULL__null; |
119 | if (progress_bar != NULL__null) |
120 | progress_bar_window = progress_bar->Window(); |
121 | |
122 | uint32 *source = (uint32*)source_bitmap->Bits(); |
123 | int32 source_bpr = source_bitmap->BytesPerRow()/4; |
124 | |
125 | PerlinNoiseGenerator generator(0.5,7); |
126 | |
127 | // This union must be used to guarantee endianness compatibility. |
128 | union { |
129 | uint8 bytes[4]; |
130 | uint32 word; |
131 | } color; |
132 | |
133 | if (the_selection->IsEmpty()) { |
134 | // Here handle the whole image. |
135 | float left = target_bitmap->Bounds().left; |
136 | float right = target_bitmap->Bounds().right; |
137 | float top = target_bitmap->Bounds().top; |
138 | float bottom = target_bitmap->Bounds().bottom; |
139 | |
140 | int32 height = (bottom - top+1)/processor_count; |
141 | top = min_c(bottom,top+thread_number*height)((bottom)>(top+thread_number*height)?(top+thread_number*height ):(bottom)); |
142 | bottom = min_c(bottom,top + height-1)((bottom)>(top + height-1)?(top + height-1):(bottom)); |
143 | |
144 | int32 update_interval = 10; |
145 | float update_amount = 100.0/(bottom-top)*update_interval/(float)processor_count; |
146 | float missed_update = 0; |
147 | |
148 | // Loop through all pixels in original. |
149 | float one_per_width = 1.0/128; |
150 | float one_per_height = 1.0/128; |
151 | float one_per_depth = 1.0/1024; |
152 | source += (int32)top*source_bpr; |
153 | |
154 | for (float y=top;y<=bottom;++y) { |
155 | int32 y_times_bpr = y*source_bpr; |
Value stored to 'y_times_bpr' during its initialization is never read | |
156 | for (float x=left;x<=right;++x) { |
157 | color.word = *source; |
158 | float noise = generator.PerlinNoise2D(x*one_per_width,y*one_per_height); |
159 | |
160 | if (noise > 0) { |
161 | rgb_color c = informer->GetForegroundColor(); |
162 | color.bytes[0] = c.blue; |
163 | color.bytes[1] = c.green; |
164 | color.bytes[2] = c.red; |
165 | color.bytes[3] = c.alpha; |
166 | *source = mix_2_pixels_fixed(*source,color.word,32768*(1.0-noise)); |
167 | } |
168 | ++source; |
169 | } |
170 | // Update the status-bar |
171 | if ( (((int32)y % update_interval) == 0) && (progress_bar_window != NULL__null) && (progress_bar_window->LockWithTimeout(0) == B_OK((int)0)) ) { |
172 | progress_bar->Update(update_amount+missed_update); |
173 | progress_bar_window->Unlock(); |
174 | missed_update = 0; |
175 | } |
176 | else if (((int32)y % update_interval) == 0) { |
177 | missed_update += update_amount; |
178 | } |
179 | } |
180 | } |
181 | else { |
182 | // Here handle only those pixels for which selection->ContainsPoint(x,y) is true. |
183 | BRect rect = the_selection->GetBoundingRect(); |
184 | |
185 | int32 left = rect.left; |
186 | int32 right = rect.right; |
187 | int32 top = rect.top; |
188 | int32 bottom = rect.bottom; |
189 | |
190 | int32 height = (bottom - top+1)/processor_count; |
191 | top = min_c(bottom,top+thread_number*height)((bottom)>(top+thread_number*height)?(top+thread_number*height ):(bottom)); |
192 | bottom = min_c(bottom,top + height-1)((bottom)>(top + height-1)?(top + height-1):(bottom)); |
193 | |
194 | int32 update_interval = 10; |
195 | float update_amount = 100.0/(bottom-top)*update_interval/(float)processor_count; |
196 | float missed_update = 0; |
197 | |
198 | // Loop through all pixels in original. |
199 | float one_per_width = 1.0/8; |
200 | float one_per_height = 1.0/256; |
201 | float one_per_depth = 1.0/1024; |
202 | source += (int32)left + (int32)top*source_bpr; |
203 | |
204 | // Loop through all pixels in original. |
205 | for (int32 y=top;y<=bottom;++y) { |
206 | for (int32 x=left;x<=right;++x) { |
207 | if (the_selection->ContainsPoint(x,y)) { |
208 | |
209 | } |
210 | else { |
211 | ++source; |
212 | } |
213 | } |
214 | source += (source_bpr - (int32)(right-left)-1); |
215 | |
216 | // Update the status-bar |
217 | if ( (((int32)y % update_interval) == 0) && (progress_bar_window != NULL__null) && (progress_bar_window->LockWithTimeout(0) == B_OK((int)0)) ) { |
218 | progress_bar->Update(update_amount+missed_update); |
219 | progress_bar_window->Unlock(); |
220 | missed_update = 0; |
221 | } |
222 | else if (((int32)y % update_interval) == 0) { |
223 | missed_update += update_amount; |
224 | } |
225 | } |
226 | } |
227 | |
228 | return B_OK((int)0); |
229 | } |
230 | |
231 | |
232 | |
233 | float MarbleManipulator::marble_amount(float x) |
234 | { |
235 | x = fabs(x); |
236 | // Select the four value and proper u |
237 | float v1 = 0; |
238 | float v2 = 127; |
239 | float v3 = -128; |
240 | float v4 = 0; |
241 | |
242 | float u; |
243 | |
244 | if (x<0.33) { |
245 | v2 = v1; |
246 | v3 = v2; |
247 | v4 = v3; |
248 | u = (0.33-x)/0.33; |
249 | } |
250 | else if (x < 0.66) { |
251 | u = (0.66-x)/0.66; |
252 | } |
253 | else { |
254 | v1 = v2; |
255 | v2 = v3; |
256 | v3 = v4; |
257 | u = (1-x)/0.33; |
258 | } |
259 | |
260 | return SplineGenerator::CardinalSpline(v1,v2,v3,v4,u); |
261 | } |