File: | home/HaikuArchives/ArtPaint/addons/AddOns/Halftone/Halftone.cpp |
Warning: | line 466, column 8 Value stored to 'target_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 <Window.h> |
12 | |
13 | #include "AddOns.h" |
14 | #include "Halftone.h" |
15 | #include "RandomNumberGenerator.h" |
16 | #include "ManipulatorInformer.h" |
17 | #include "Selection.h" |
18 | |
19 | #undef B_TRANSLATION_CONTEXT"AddOns_Halftone" |
20 | #define B_TRANSLATION_CONTEXT"AddOns_Halftone" "AddOns_Halftone" |
21 | |
22 | |
23 | #ifdef __cplusplus201402L |
24 | extern "C" { |
25 | #endif |
26 | char name[255] = B_TRANSLATE_MARK("Halftone")("Halftone"); |
27 | char menu_help_string[255] = |
28 | B_TRANSLATE_MARK("Makes a halftone-pattern with fore- and background colors.")("Makes a halftone-pattern with fore- and background colors." ); |
29 | int32 add_on_api_version = ADD_ON_API_VERSION; |
30 | add_on_types add_on_type = GENERIC_ADD_ON; |
31 | #ifdef __cplusplus201402L |
32 | } |
33 | #endif |
34 | |
35 | |
36 | Manipulator* instantiate_add_on(BBitmap*,ManipulatorInformer *i) |
37 | { |
38 | return new Halftone(i); |
39 | } |
40 | |
41 | |
42 | |
43 | Halftone::Halftone(ManipulatorInformer *i) |
44 | : Manipulator(), round_dot_size(ROUND_DOT_SIZE8), diagonal_line_size(DIAGONAL_LINE_SIZE5) |
45 | , ordered_matrix_size(ORDERED_MATRIX_SIZE4) |
46 | { |
47 | informer = i; |
48 | round_dot_pattern[0][0] = 1; |
49 | round_dot_pattern[0][1] = 8; |
50 | round_dot_pattern[0][2] = 16; |
51 | round_dot_pattern[0][3] = 29; |
52 | round_dot_pattern[0][4] = 25; |
53 | round_dot_pattern[0][5] = 22; |
54 | round_dot_pattern[0][6] = 6; |
55 | round_dot_pattern[0][7] = 2; |
56 | |
57 | round_dot_pattern[1][0] = 5; |
58 | round_dot_pattern[1][1] = 12; |
59 | round_dot_pattern[1][2] = 33; |
60 | round_dot_pattern[1][3] = 42; |
61 | round_dot_pattern[1][4] = 46; |
62 | round_dot_pattern[1][5] = 38; |
63 | round_dot_pattern[1][6] = 13; |
64 | round_dot_pattern[1][7] = 9; |
65 | |
66 | round_dot_pattern[2][0] = 21; |
67 | round_dot_pattern[2][1] = 37; |
68 | round_dot_pattern[2][2] = 49; |
69 | round_dot_pattern[2][3] = 58; |
70 | round_dot_pattern[2][4] = 54; |
71 | round_dot_pattern[2][5] = 50; |
72 | round_dot_pattern[2][6] = 34; |
73 | round_dot_pattern[2][7] = 17; |
74 | |
75 | round_dot_pattern[3][0] = 24; |
76 | round_dot_pattern[3][1] = 45; |
77 | round_dot_pattern[3][2] = 53; |
78 | round_dot_pattern[3][3] = 62; |
79 | round_dot_pattern[3][4] = 63; |
80 | round_dot_pattern[3][5] = 59; |
81 | round_dot_pattern[3][6] = 43; |
82 | round_dot_pattern[3][7] = 30; |
83 | |
84 | round_dot_pattern[4][0] = 28; |
85 | round_dot_pattern[4][1] = 41; |
86 | round_dot_pattern[4][2] = 57; |
87 | round_dot_pattern[4][3] = 61; |
88 | round_dot_pattern[4][4] = 60; |
89 | round_dot_pattern[4][5] = 55; |
90 | round_dot_pattern[4][6] = 47; |
91 | round_dot_pattern[4][7] = 26; |
92 | |
93 | round_dot_pattern[5][0] = 19; |
94 | round_dot_pattern[5][1] = 32; |
95 | round_dot_pattern[5][2] = 48; |
96 | round_dot_pattern[5][3] = 52; |
97 | round_dot_pattern[5][4] = 56; |
98 | round_dot_pattern[5][5] = 51; |
99 | round_dot_pattern[5][6] = 39; |
100 | round_dot_pattern[5][7] = 23; |
101 | |
102 | round_dot_pattern[6][0] = 11; |
103 | round_dot_pattern[6][1] = 15; |
104 | round_dot_pattern[6][2] = 36; |
105 | round_dot_pattern[6][3] = 44; |
106 | round_dot_pattern[6][4] = 40; |
107 | round_dot_pattern[6][5] = 35; |
108 | round_dot_pattern[6][6] = 14; |
109 | round_dot_pattern[6][7] = 7; |
110 | |
111 | round_dot_pattern[7][0] = 0; |
112 | round_dot_pattern[7][1] = 4; |
113 | round_dot_pattern[7][2] = 20; |
114 | round_dot_pattern[7][3] = 27; |
115 | round_dot_pattern[7][4] = 31; |
116 | round_dot_pattern[7][5] = 18; |
117 | round_dot_pattern[7][6] = 10; |
118 | round_dot_pattern[7][7] = 3; |
119 | |
120 | |
121 | diagonal_line_pattern[2][2] = 24; |
122 | diagonal_line_pattern[1][3] = 23; |
123 | diagonal_line_pattern[3][1] = 22; |
124 | diagonal_line_pattern[0][4] = 21; |
125 | diagonal_line_pattern[4][0] = 20; |
126 | |
127 | diagonal_line_pattern[1][0] = 19; |
128 | diagonal_line_pattern[0][1] = 18; |
129 | |
130 | diagonal_line_pattern[4][3] = 17; |
131 | diagonal_line_pattern[3][4] = 16; |
132 | |
133 | diagonal_line_pattern[1][1] = 15; |
134 | diagonal_line_pattern[0][2] = 14; |
135 | diagonal_line_pattern[2][0] = 13; |
136 | |
137 | diagonal_line_pattern[3][3] = 12; |
138 | diagonal_line_pattern[2][4] = 11; |
139 | diagonal_line_pattern[4][2] = 10; |
140 | |
141 | diagonal_line_pattern[2][1] = 9; |
142 | diagonal_line_pattern[1][2] = 8; |
143 | diagonal_line_pattern[3][0] = 7; |
144 | diagonal_line_pattern[0][3] = 6; |
145 | |
146 | diagonal_line_pattern[3][2] = 5; |
147 | diagonal_line_pattern[2][3] = 4; |
148 | diagonal_line_pattern[4][1] = 3; |
149 | diagonal_line_pattern[1][4] = 2; |
150 | |
151 | diagonal_line_pattern[0][0] = 1; |
152 | diagonal_line_pattern[4][4] = 0; |
153 | |
154 | ordered_matrix[0][0] = 0; |
155 | ordered_matrix[0][1] = 8; |
156 | ordered_matrix[0][2] = 2; |
157 | ordered_matrix[0][3] = 10; |
158 | |
159 | ordered_matrix[1][0] = 12; |
160 | ordered_matrix[1][1] = 4; |
161 | ordered_matrix[1][2] = 14; |
162 | ordered_matrix[1][3] = 16; |
163 | |
164 | ordered_matrix[2][0] = 3; |
165 | ordered_matrix[2][1] = 11; |
166 | ordered_matrix[2][2] = 1; |
167 | ordered_matrix[2][3] = 9; |
168 | |
169 | ordered_matrix[3][0] = 15; |
170 | ordered_matrix[3][1] = 7; |
171 | ordered_matrix[3][2] = 13; |
172 | ordered_matrix[3][3] = 5; |
173 | } |
174 | |
175 | |
176 | Halftone::~Halftone() |
177 | { |
178 | delete informer; |
179 | } |
180 | |
181 | |
182 | BBitmap* Halftone::ManipulateBitmap(BBitmap *original,Selection *selection,BStatusBar *status_bar) |
183 | { |
184 | return round_dot_halftone(original,selection,status_bar); |
185 | // return diagonal_line_halftone(original,selection,status_bar); |
186 | // return ordered_dither_halftone(original,selection,status_bar); |
187 | // return fs_dither_halftone(original,selection,status_bar); |
188 | // return ncandidate_dither_halftone(original,selection,status_bar); |
189 | } |
190 | |
191 | |
192 | const char* Halftone::ReturnHelpString() |
193 | { |
194 | return B_TRANSLATE("Makes a halftone-pattern with fore- and background colors.")BLocaleRoster::Default()->GetCatalog()->GetString(("Makes a halftone-pattern with fore- and background colors." ), "AddOns_Halftone"); |
195 | } |
196 | |
197 | |
198 | const char* Halftone::ReturnName() |
199 | { |
200 | return B_TRANSLATE("Halftone")BLocaleRoster::Default()->GetCatalog()->GetString(("Halftone" ), "AddOns_Halftone"); |
201 | } |
202 | |
203 | |
204 | BBitmap* Halftone::round_dot_halftone(BBitmap *original,Selection *selection, BStatusBar *status_bar) |
205 | { |
206 | if (original == NULL__null) |
207 | return NULL__null; |
208 | |
209 | uint32 *source_bits = (uint32*)original->Bits(); |
210 | uint32 *target_bits = (uint32*)original->Bits(); |
211 | int32 source_bpr = original->BytesPerRow()/4; |
212 | int32 target_bpr = original->BytesPerRow()/4; |
213 | int32 top,bottom,left,right; |
214 | |
215 | left = original->Bounds().left; |
216 | right = original->Bounds().right + 1; |
217 | top = original->Bounds().top; |
218 | bottom = original->Bounds().bottom + 1; |
219 | |
220 | |
221 | union { |
222 | uint8 bytes[4]; |
223 | uint32 word; |
224 | } color,c1,c2; |
225 | rgb_color c = informer->GetBackgroundColor(); |
226 | c1.bytes[0] = c.blue; |
227 | c1.bytes[1] = c.green; |
228 | c1.bytes[2] = c.red; |
229 | c1.bytes[3] = c.alpha; |
230 | |
231 | c = informer->GetForegroundColor(); |
232 | c2.bytes[0] = c.blue; |
233 | c2.bytes[1] = c.green; |
234 | c2.bytes[2] = c.red; |
235 | c2.bytes[3] = c.alpha; |
236 | |
237 | if (selection->IsEmpty()) { |
238 | // Here handle the whole image. |
239 | float normalizer = 1.0/255.0*round_dot_size*round_dot_size; |
240 | for (int32 y=top;y<bottom;y+=round_dot_size) { |
241 | for (int32 x=left;x<right;x+=round_dot_size) { |
242 | int32 r =min_c(x+round_dot_size,right)((x+round_dot_size)>(right)?(right):(x+round_dot_size)); |
243 | int32 b = min_c(y+round_dot_size,bottom)((y+round_dot_size)>(bottom)?(bottom):(y+round_dot_size)); |
244 | uint32 *s_delta_bits; |
245 | |
246 | int32 number_of_pixels = 0; |
247 | for (int32 dy=y;dy<b;dy++) { |
248 | s_delta_bits = source_bits + dy*source_bpr + x; |
249 | for (int32 dx=x;dx<r;dx++) { |
250 | color.word = *s_delta_bits; |
251 | float luminance = color.bytes[0] * .114 + color.bytes[1]*.587 + color.bytes[2]*.299; |
252 | int threshold = luminance * normalizer; |
253 | *s_delta_bits++ = (round_dot_pattern[dy-y][dx-x]>threshold?c1.word:c2.word); |
254 | } |
255 | } |
256 | } |
257 | } |
258 | } |
259 | else { |
260 | // Here handle only those pixels for which selection->ContainsPoint(x,y) is true. |
261 | float normalizer = 1.0/255.0*round_dot_size*round_dot_size; |
262 | for (int32 y=top;y<bottom;y+=round_dot_size) { |
263 | for (int32 x=left;x<right;x+=round_dot_size) { |
264 | int32 r =min_c(x+round_dot_size,right)((x+round_dot_size)>(right)?(right):(x+round_dot_size)); |
265 | int32 b = min_c(y+round_dot_size,bottom)((y+round_dot_size)>(bottom)?(bottom):(y+round_dot_size)); |
266 | uint32 *s_delta_bits; |
267 | |
268 | int32 number_of_pixels = 0; |
269 | for (int32 dy=y;dy<b;dy++) { |
270 | s_delta_bits = source_bits + dy*source_bpr + x; |
271 | for (int32 dx=x;dx<r;dx++) { |
272 | if (selection->ContainsPoint(dx,dy)) { |
273 | color.word = *s_delta_bits; |
274 | float luminance = color.bytes[0] * .114 + color.bytes[1]*.587 + color.bytes[2]*.299; |
275 | int threshold = luminance * normalizer; |
276 | *s_delta_bits = (round_dot_pattern[dy-y][dx-x]>threshold?c1.word:c2.word); |
277 | } |
278 | s_delta_bits++; |
279 | } |
280 | } |
281 | } |
282 | } |
283 | } |
284 | |
285 | return original; |
286 | } |
287 | |
288 | |
289 | BBitmap* Halftone::diagonal_line_halftone(BBitmap *original,Selection *selection, BStatusBar *status_bar) |
290 | { |
291 | if (original == NULL__null) |
292 | return NULL__null; |
293 | |
294 | uint32 *source_bits = (uint32*)original->Bits(); |
295 | uint32 *target_bits = (uint32*)original->Bits(); |
296 | int32 source_bpr = original->BytesPerRow()/4; |
297 | int32 target_bpr = original->BytesPerRow()/4; |
298 | int32 top,bottom,left,right; |
299 | |
300 | left = original->Bounds().left; |
301 | right = original->Bounds().right + 1; |
302 | top = original->Bounds().top; |
303 | bottom = original->Bounds().bottom + 1; |
304 | |
305 | |
306 | union { |
307 | uint8 bytes[4]; |
308 | uint32 word; |
309 | } color,c1,c2; |
310 | rgb_color c = informer->GetForegroundColor(); |
311 | c1.bytes[0] = c.blue; |
312 | c1.bytes[1] = c.green; |
313 | c1.bytes[2] = c.red; |
314 | c1.bytes[3] = c.alpha; |
315 | |
316 | c = informer->GetBackgroundColor(); |
317 | c2.bytes[0] = c.blue; |
318 | c2.bytes[1] = c.green; |
319 | c2.bytes[2] = c.red; |
320 | c2.bytes[3] = c.alpha; |
321 | |
322 | if (selection->IsEmpty()) { |
323 | // Here handle the whole image. |
324 | float normalizer = 1.0/255.0*diagonal_line_size*diagonal_line_size; |
325 | for (int32 y=top;y<bottom;y+=diagonal_line_size) { |
326 | for (int32 x=left;x<right;x+=diagonal_line_size) { |
327 | int32 r =min_c(x+diagonal_line_size,right)((x+diagonal_line_size)>(right)?(right):(x+diagonal_line_size )); |
328 | int32 b = min_c(y+diagonal_line_size,bottom)((y+diagonal_line_size)>(bottom)?(bottom):(y+diagonal_line_size )); |
329 | uint32 *s_delta_bits; |
330 | |
331 | int32 number_of_pixels = 0; |
332 | for (int32 dy=y;dy<b;dy++) { |
333 | s_delta_bits = source_bits + dy*source_bpr + x; |
334 | for (int32 dx=x;dx<r;dx++) { |
335 | color.word = *s_delta_bits; |
336 | float luminance = color.bytes[0] * .114 + color.bytes[1]*.587 + color.bytes[2]*.299; |
337 | int threshold = luminance * normalizer; |
338 | *s_delta_bits++ = (diagonal_line_pattern[dy-y][dx-x]>threshold?c1.word:c2.word); |
339 | } |
340 | } |
341 | } |
342 | } |
343 | } |
344 | else { |
345 | // Here handle only those pixels for which selection->ContainsPoint(x,y) is true. |
346 | float normalizer = 1.0/255.0*diagonal_line_size*diagonal_line_size; |
347 | for (int32 y=top;y<bottom;y+=diagonal_line_size) { |
348 | for (int32 x=left;x<right;x+=diagonal_line_size) { |
349 | int32 r =min_c(x+diagonal_line_size,right)((x+diagonal_line_size)>(right)?(right):(x+diagonal_line_size )); |
350 | int32 b = min_c(y+diagonal_line_size,bottom)((y+diagonal_line_size)>(bottom)?(bottom):(y+diagonal_line_size )); |
351 | uint32 *s_delta_bits; |
352 | |
353 | int32 number_of_pixels = 0; |
354 | for (int32 dy=y;dy<b;dy++) { |
355 | s_delta_bits = source_bits + dy*source_bpr + x; |
356 | for (int32 dx=x;dx<r;dx++) { |
357 | if (selection->ContainsPoint(dx,dy)) { |
358 | color.word = *s_delta_bits; |
359 | float luminance = color.bytes[0] * .114 + color.bytes[1]*.587 + color.bytes[2]*.299; |
360 | int threshold = luminance * normalizer; |
361 | *s_delta_bits = (diagonal_line_pattern[dy-y][dx-x]>threshold?c1.word:c2.word); |
362 | } |
363 | s_delta_bits++; |
364 | } |
365 | } |
366 | } |
367 | } |
368 | } |
369 | |
370 | return original; |
371 | } |
372 | |
373 | BBitmap* Halftone::ordered_dither_halftone(BBitmap *original,Selection *selection, BStatusBar *status_bar) |
374 | { |
375 | if (original == NULL__null) |
376 | return NULL__null; |
377 | |
378 | uint32 *source_bits = (uint32*)original->Bits(); |
379 | uint32 *target_bits = (uint32*)original->Bits(); |
380 | int32 source_bpr = original->BytesPerRow()/4; |
381 | int32 target_bpr = original->BytesPerRow()/4; |
382 | int32 top,bottom,left,right; |
383 | |
384 | left = original->Bounds().left; |
385 | right = original->Bounds().right + 1; |
386 | top = original->Bounds().top; |
387 | bottom = original->Bounds().bottom + 1; |
388 | |
389 | |
390 | union { |
391 | uint8 bytes[4]; |
392 | uint32 word; |
393 | } color,c1,c2; |
394 | rgb_color c = informer->GetForegroundColor(); |
395 | c1.bytes[0] = c.blue; |
396 | c1.bytes[1] = c.green; |
397 | c1.bytes[2] = c.red; |
398 | c1.bytes[3] = c.alpha; |
399 | |
400 | c = informer->GetBackgroundColor(); |
401 | c2.bytes[0] = c.blue; |
402 | c2.bytes[1] = c.green; |
403 | c2.bytes[2] = c.red; |
404 | c2.bytes[3] = c.alpha; |
405 | |
406 | if (selection->IsEmpty()) { |
407 | // Here handle the whole image. |
408 | float normalizer = 1.0/255.0*ordered_matrix_size*ordered_matrix_size; |
409 | for (int32 y=top;y<bottom;y+=ordered_matrix_size) { |
410 | for (int32 x=left;x<right;x+=ordered_matrix_size) { |
411 | int32 r =min_c(x+ordered_matrix_size,right)((x+ordered_matrix_size)>(right)?(right):(x+ordered_matrix_size )); |
412 | int32 b = min_c(y+ordered_matrix_size,bottom)((y+ordered_matrix_size)>(bottom)?(bottom):(y+ordered_matrix_size )); |
413 | uint32 *s_delta_bits; |
414 | |
415 | int32 number_of_pixels = 0; |
416 | for (int32 dy=y;dy<b;dy++) { |
417 | s_delta_bits = source_bits + dy*source_bpr + x; |
418 | for (int32 dx=x;dx<r;dx++) { |
419 | color.word = *s_delta_bits; |
420 | float luminance = color.bytes[0] * .114 + color.bytes[1]*.587 + color.bytes[2]*.299; |
421 | int threshold = luminance * normalizer; |
422 | *s_delta_bits++ = (ordered_matrix[dy-y][dx-x]>threshold?c1.word:c2.word); |
423 | } |
424 | } |
425 | } |
426 | } |
427 | } |
428 | else { |
429 | // Here handle only those pixels for which selection->ContainsPoint(x,y) is true. |
430 | float normalizer = 1.0/255.0*ordered_matrix_size*ordered_matrix_size; |
431 | for (int32 y=top;y<bottom;y+=ordered_matrix_size) { |
432 | for (int32 x=left;x<right;x+=ordered_matrix_size) { |
433 | int32 r =min_c(x+ordered_matrix_size,right)((x+ordered_matrix_size)>(right)?(right):(x+ordered_matrix_size )); |
434 | int32 b = min_c(y+ordered_matrix_size,bottom)((y+ordered_matrix_size)>(bottom)?(bottom):(y+ordered_matrix_size )); |
435 | uint32 *s_delta_bits; |
436 | |
437 | int32 number_of_pixels = 0; |
438 | for (int32 dy=y;dy<b;dy++) { |
439 | s_delta_bits = source_bits + dy*source_bpr + x; |
440 | for (int32 dx=x;dx<r;dx++) { |
441 | if (selection->ContainsPoint(dx,dy)) { |
442 | color.word = *s_delta_bits; |
443 | float luminance = color.bytes[0] * .114 + color.bytes[1]*.587 + color.bytes[2]*.299; |
444 | int threshold = luminance * normalizer; |
445 | *s_delta_bits = (ordered_matrix[dy-y][dx-x]>threshold?c1.word:c2.word); |
446 | } |
447 | s_delta_bits++; |
448 | } |
449 | } |
450 | } |
451 | } |
452 | } |
453 | |
454 | return original; |
455 | } |
456 | |
457 | |
458 | BBitmap* Halftone::fs_dither_halftone(BBitmap *original,Selection *selection, BStatusBar *status_bar) |
459 | { |
460 | if (original == NULL__null) |
461 | return NULL__null; |
462 | |
463 | uint32 *source_bits = (uint32*)original->Bits(); |
464 | uint32 *target_bits = (uint32*)original->Bits(); |
465 | int32 source_bpr = original->BytesPerRow()/4; |
466 | int32 target_bpr = original->BytesPerRow()/4; |
Value stored to 'target_bpr' during its initialization is never read | |
467 | int32 top,bottom,left,right; |
468 | |
469 | left = original->Bounds().left; |
470 | right = original->Bounds().right + 1; |
471 | top = original->Bounds().top; |
472 | bottom = original->Bounds().bottom + 1; |
473 | |
474 | float *errors = new float[right-left+3]; |
475 | for (int32 i=0;i<right-left+3;i++) |
476 | errors[i] = 0; |
477 | |
478 | float right_error = 0; |
479 | |
480 | union { |
481 | uint8 bytes[4]; |
482 | uint32 word; |
483 | } color,c1,c2; |
484 | rgb_color c = informer->GetForegroundColor(); |
485 | c1.bytes[0] = c.blue; |
486 | c1.bytes[1] = c.green; |
487 | c1.bytes[2] = c.red; |
488 | c1.bytes[3] = c.alpha; |
489 | |
490 | c = informer->GetBackgroundColor(); |
491 | c2.bytes[0] = c.blue; |
492 | c2.bytes[1] = c.green; |
493 | c2.bytes[2] = c.red; |
494 | c2.bytes[3] = c.alpha; |
495 | |
496 | if (selection->IsEmpty()) { |
497 | // Here handle the whole image. |
498 | for (int32 y=top;y<bottom;y++) { |
499 | for (int32 x=left;x<right;x++) { |
500 | color.word = *source_bits; |
501 | float threshold = color.bytes[0] * .114 + color.bytes[1]*.587 + color.bytes[2]*.299; |
502 | float value = min_c(255,max_c(threshold+right_error+errors[x+1],0))((255)>(((threshold+right_error+errors[x+1])>(0)?(threshold +right_error+errors[x+1]):(0)))?(((threshold+right_error+errors [x+1])>(0)?(threshold+right_error+errors[x+1]):(0))):(255) ); |
503 | errors[x+1] = 0; |
504 | right_error = 0; |
505 | float error; |
506 | if (value > 127) { |
507 | error = -(255 - value); |
508 | *source_bits++ = c2.word; |
509 | } |
510 | else { |
511 | error = -(0 - value); |
512 | *source_bits++ = c1.word; |
513 | } |
514 | right_error = .4375 * error; |
515 | errors[x] += .1875 * error; |
516 | errors[x+1] += .3125 * error; |
517 | errors[x+2] += .0625 * error; |
518 | } |
519 | } |
520 | } |
521 | else { |
522 | // Here handle only those pixels for which selection->ContainsPoint(x,y) is true. |
523 | float normalizer = 1.0/255.0*ordered_matrix_size*ordered_matrix_size; |
524 | for (int32 y=top;y<bottom;y+=ordered_matrix_size) { |
525 | for (int32 x=left;x<right;x+=ordered_matrix_size) { |
526 | int32 r =min_c(x+ordered_matrix_size,right)((x+ordered_matrix_size)>(right)?(right):(x+ordered_matrix_size )); |
527 | int32 b = min_c(y+ordered_matrix_size,bottom)((y+ordered_matrix_size)>(bottom)?(bottom):(y+ordered_matrix_size )); |
528 | uint32 *s_delta_bits; |
529 | |
530 | int32 number_of_pixels = 0; |
531 | for (int32 dy=y;dy<b;dy++) { |
532 | s_delta_bits = source_bits + dy*source_bpr + x; |
533 | for (int32 dx=x;dx<r;dx++) { |
534 | if (selection->ContainsPoint(dx,dy)) { |
535 | color.word = *s_delta_bits; |
536 | float luminance = color.bytes[0] * .114 + color.bytes[1]*.587 + color.bytes[2]*.299; |
537 | int threshold = luminance * normalizer; |
538 | *s_delta_bits = (ordered_matrix[dy-y][dx-x]>threshold?c1.word:c2.word); |
539 | } |
540 | s_delta_bits++; |
541 | } |
542 | } |
543 | } |
544 | } |
545 | } |
546 | |
547 | return original; |
548 | } |
549 | |
550 | |
551 | BBitmap* Halftone::ncandidate_dither_halftone(BBitmap *original,Selection *selection, BStatusBar *status_bar) |
552 | { |
553 | if (original == NULL__null) |
554 | return NULL__null; |
555 | |
556 | uint32 *source_bits = (uint32*)original->Bits(); |
557 | uint32 *target_bits = (uint32*)original->Bits(); |
558 | int32 source_bpr = original->BytesPerRow()/4; |
559 | int32 target_bpr = original->BytesPerRow()/4; |
560 | int32 top,bottom,left,right; |
561 | |
562 | left = original->Bounds().left; |
563 | right = original->Bounds().right + 1; |
564 | top = original->Bounds().top; |
565 | bottom = original->Bounds().bottom + 1; |
566 | |
567 | float *errors = new float[right-left+3]; |
568 | for (int32 i=0;i<right-left+3;i++) |
569 | errors[i] = 0; |
570 | |
571 | float right_error = 0; |
572 | |
573 | union { |
574 | uint8 bytes[4]; |
575 | uint32 word; |
576 | } color,c1,c2; |
577 | rgb_color c = informer->GetForegroundColor(); |
578 | c1.bytes[0] = c.blue; |
579 | c1.bytes[1] = c.green; |
580 | c1.bytes[2] = c.red; |
581 | c1.bytes[3] = c.alpha; |
582 | |
583 | c = informer->GetBackgroundColor(); |
584 | c2.bytes[0] = c.blue; |
585 | c2.bytes[1] = c.green; |
586 | c2.bytes[2] = c.red; |
587 | c2.bytes[3] = c.alpha; |
588 | |
589 | float probs[256]; |
590 | for (int32 i=0;i<256;i++) { |
591 | probs[i] = (float)i/256.0; // probability to get white |
592 | } |
593 | |
594 | RandomNumberGenerator *generator = new RandomNumberGenerator(1027,1000000); |
595 | if (selection->IsEmpty()) { |
596 | // Here handle the whole image. |
597 | for (int32 y=top;y<bottom;y++) { |
598 | for (int32 x=left;x<right;x++) { |
599 | color.word = *source_bits; |
600 | int32 threshold = color.bytes[0] * .114 + color.bytes[1]*.587 + color.bytes[2]*.299; |
601 | float r = generator->UniformDistribution(0.0,1.0); |
602 | if (probs[threshold] >= r) |
603 | *source_bits++ = c2.word; |
604 | else |
605 | *source_bits++ = c1.word; |
606 | } |
607 | } |
608 | } |
609 | else { |
610 | // Here handle only those pixels for which selection->ContainsPoint(x,y) is true. |
611 | float normalizer = 1.0/255.0*ordered_matrix_size*ordered_matrix_size; |
612 | for (int32 y=top;y<bottom;y+=ordered_matrix_size) { |
613 | for (int32 x=left;x<right;x+=ordered_matrix_size) { |
614 | int32 r =min_c(x+ordered_matrix_size,right)((x+ordered_matrix_size)>(right)?(right):(x+ordered_matrix_size )); |
615 | int32 b = min_c(y+ordered_matrix_size,bottom)((y+ordered_matrix_size)>(bottom)?(bottom):(y+ordered_matrix_size )); |
616 | uint32 *s_delta_bits; |
617 | |
618 | int32 number_of_pixels = 0; |
619 | for (int32 dy=y;dy<b;dy++) { |
620 | s_delta_bits = source_bits + dy*source_bpr + x; |
621 | for (int32 dx=x;dx<r;dx++) { |
622 | if (selection->ContainsPoint(dx,dy)) { |
623 | color.word = *s_delta_bits; |
624 | float luminance = color.bytes[0] * .114 + color.bytes[1]*.587 + color.bytes[2]*.299; |
625 | int threshold = luminance * normalizer; |
626 | *s_delta_bits = (ordered_matrix[dy-y][dx-x]>threshold?c1.word:c2.word); |
627 | } |
628 | s_delta_bits++; |
629 | } |
630 | } |
631 | } |
632 | } |
633 | } |
634 | delete generator; |
635 | return original; |
636 | } |
637 |