File: | home/HaikuArchives/ArtPaint/addons/AddOns/Halftone/Halftone.cpp |
Warning: | line 523, column 22 Potential leak of memory pointed to by 'errors' |
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; | |||
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 |