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