/src/skia/third_party/externals/dng_sdk/source/dng_bad_pixels.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /*****************************************************************************/ |
2 | | // Copyright 2008 Adobe Systems Incorporated |
3 | | // All Rights Reserved. |
4 | | // |
5 | | // NOTICE: Adobe permits you to use, modify, and distribute this file in |
6 | | // accordance with the terms of the Adobe license agreement accompanying it. |
7 | | /*****************************************************************************/ |
8 | | |
9 | | /* $Id: //mondo/dng_sdk_1_4/dng_sdk/source/dng_bad_pixels.cpp#1 $ */ |
10 | | /* $DateTime: 2012/05/30 13:28:51 $ */ |
11 | | /* $Change: 832332 $ */ |
12 | | /* $Author: tknoll $ */ |
13 | | |
14 | | /*****************************************************************************/ |
15 | | |
16 | | #include "dng_bad_pixels.h" |
17 | | |
18 | | #include "dng_filter_task.h" |
19 | | #include "dng_globals.h" |
20 | | #include "dng_host.h" |
21 | | #include "dng_image.h" |
22 | | #include "dng_negative.h" |
23 | | #include "dng_safe_arithmetic.h" |
24 | | |
25 | | #include <algorithm> |
26 | | |
27 | | /*****************************************************************************/ |
28 | | |
29 | | dng_opcode_FixBadPixelsConstant::dng_opcode_FixBadPixelsConstant |
30 | | (uint32 constant, |
31 | | uint32 bayerPhase) |
32 | | |
33 | | : dng_filter_opcode (dngOpcode_FixBadPixelsConstant, |
34 | | dngVersion_1_3_0_0, |
35 | | 0) |
36 | | |
37 | | , fConstant (constant) |
38 | | , fBayerPhase (bayerPhase) |
39 | | |
40 | 0 | { |
41 | | |
42 | 0 | } |
43 | | |
44 | | /*****************************************************************************/ |
45 | | |
46 | | dng_opcode_FixBadPixelsConstant::dng_opcode_FixBadPixelsConstant |
47 | | (dng_stream &stream) |
48 | | |
49 | | : dng_filter_opcode (dngOpcode_FixBadPixelsConstant, |
50 | | stream, |
51 | | "FixBadPixelsConstant") |
52 | | |
53 | | , fConstant (0) |
54 | | , fBayerPhase (0) |
55 | | |
56 | 0 | { |
57 | | |
58 | 0 | if (stream.Get_uint32 () != 8) |
59 | 0 | { |
60 | 0 | ThrowBadFormat (); |
61 | 0 | } |
62 | | |
63 | 0 | fConstant = stream.Get_uint32 (); |
64 | 0 | fBayerPhase = stream.Get_uint32 (); |
65 | | |
66 | | #if qDNGValidate |
67 | | |
68 | | if (gVerbose) |
69 | | { |
70 | | |
71 | | printf ("Constant: %u\n", (unsigned) fConstant); |
72 | | |
73 | | printf ("Bayer Phase: %u\n", (unsigned) fBayerPhase); |
74 | | |
75 | | } |
76 | | |
77 | | #endif |
78 | | |
79 | 0 | } |
80 | | |
81 | | /*****************************************************************************/ |
82 | | |
83 | | void dng_opcode_FixBadPixelsConstant::PutData (dng_stream &stream) const |
84 | 0 | { |
85 | | |
86 | 0 | stream.Put_uint32 (8); |
87 | | |
88 | 0 | stream.Put_uint32 (fConstant ); |
89 | 0 | stream.Put_uint32 (fBayerPhase); |
90 | | |
91 | 0 | } |
92 | | |
93 | | /*****************************************************************************/ |
94 | | |
95 | | dng_point dng_opcode_FixBadPixelsConstant::SrcRepeat () |
96 | 0 | { |
97 | | |
98 | 0 | return dng_point (2, 2); |
99 | | |
100 | 0 | } |
101 | | |
102 | | /*****************************************************************************/ |
103 | | |
104 | | dng_rect dng_opcode_FixBadPixelsConstant::SrcArea (const dng_rect &dstArea, |
105 | | const dng_rect & /* imageBounds */) |
106 | 0 | { |
107 | | |
108 | 0 | dng_rect srcArea = dstArea; |
109 | | |
110 | 0 | srcArea.t -= 2; |
111 | 0 | srcArea.l -= 2; |
112 | | |
113 | 0 | srcArea.b += 2; |
114 | 0 | srcArea.r += 2; |
115 | | |
116 | 0 | return srcArea; |
117 | | |
118 | 0 | } |
119 | | |
120 | | /*****************************************************************************/ |
121 | | |
122 | | void dng_opcode_FixBadPixelsConstant::Prepare (dng_negative & /* negative */, |
123 | | uint32 /* threadCount */, |
124 | | const dng_point & /* tileSize */, |
125 | | const dng_rect & /* imageBounds */, |
126 | | uint32 imagePlanes, |
127 | | uint32 bufferPixelType, |
128 | | dng_memory_allocator & /* allocator */) |
129 | 0 | { |
130 | | |
131 | | // This opcode is restricted to single channel images. |
132 | | |
133 | 0 | if (imagePlanes != 1) |
134 | 0 | { |
135 | | |
136 | 0 | ThrowBadFormat (); |
137 | | |
138 | 0 | } |
139 | | |
140 | | // This opcode is restricted to 16-bit images. |
141 | | |
142 | 0 | if (bufferPixelType != ttShort) |
143 | 0 | { |
144 | | |
145 | 0 | ThrowBadFormat (); |
146 | | |
147 | 0 | } |
148 | | |
149 | 0 | } |
150 | | |
151 | | /*****************************************************************************/ |
152 | | |
153 | | void dng_opcode_FixBadPixelsConstant::ProcessArea (dng_negative & /* negative */, |
154 | | uint32 /* threadIndex */, |
155 | | dng_pixel_buffer &srcBuffer, |
156 | | dng_pixel_buffer &dstBuffer, |
157 | | const dng_rect &dstArea, |
158 | | const dng_rect & /* imageBounds */) |
159 | 0 | { |
160 | | |
161 | 0 | dstBuffer.CopyArea (srcBuffer, |
162 | 0 | dstArea, |
163 | 0 | 0, |
164 | 0 | dstBuffer.fPlanes); |
165 | | |
166 | 0 | uint16 badPixel = (uint16) fConstant; |
167 | | |
168 | 0 | for (int32 dstRow = dstArea.t; dstRow < dstArea.b; dstRow++) |
169 | 0 | { |
170 | | |
171 | 0 | const uint16 *sPtr = srcBuffer.ConstPixel_uint16 (dstRow, dstArea.l, 0); |
172 | 0 | uint16 *dPtr = dstBuffer.DirtyPixel_uint16 (dstRow, dstArea.l, 0); |
173 | | |
174 | 0 | for (int32 dstCol = dstArea.l; dstCol < dstArea.r; dstCol++) |
175 | 0 | { |
176 | | |
177 | 0 | if (*sPtr == badPixel) |
178 | 0 | { |
179 | | |
180 | 0 | uint32 count = 0; |
181 | 0 | uint32 total = 0; |
182 | | |
183 | 0 | uint16 value; |
184 | | |
185 | 0 | if (IsGreen (dstRow, dstCol)) // Green pixel |
186 | 0 | { |
187 | | |
188 | 0 | value = sPtr [-srcBuffer.fRowStep - 1]; |
189 | | |
190 | 0 | if (value != badPixel) |
191 | 0 | { |
192 | 0 | count += 1; |
193 | 0 | total += value; |
194 | 0 | } |
195 | | |
196 | 0 | value = sPtr [-srcBuffer.fRowStep + 1]; |
197 | | |
198 | 0 | if (value != badPixel) |
199 | 0 | { |
200 | 0 | count += 1; |
201 | 0 | total += value; |
202 | 0 | } |
203 | | |
204 | 0 | value = sPtr [srcBuffer.fRowStep - 1]; |
205 | | |
206 | 0 | if (value != badPixel) |
207 | 0 | { |
208 | 0 | count += 1; |
209 | 0 | total += value; |
210 | 0 | } |
211 | | |
212 | 0 | value = sPtr [srcBuffer.fRowStep + 1]; |
213 | | |
214 | 0 | if (value != badPixel) |
215 | 0 | { |
216 | 0 | count += 1; |
217 | 0 | total += value; |
218 | 0 | } |
219 | | |
220 | 0 | } |
221 | | |
222 | 0 | else // Red/blue pixel. |
223 | 0 | { |
224 | | |
225 | 0 | value = sPtr [-srcBuffer.fRowStep * 2]; |
226 | | |
227 | 0 | if (value != badPixel) |
228 | 0 | { |
229 | 0 | count += 1; |
230 | 0 | total += value; |
231 | 0 | } |
232 | | |
233 | 0 | value = sPtr [srcBuffer.fRowStep * 2]; |
234 | | |
235 | 0 | if (value != badPixel) |
236 | 0 | { |
237 | 0 | count += 1; |
238 | 0 | total += value; |
239 | 0 | } |
240 | | |
241 | 0 | value = sPtr [-2]; |
242 | | |
243 | 0 | if (value != badPixel) |
244 | 0 | { |
245 | 0 | count += 1; |
246 | 0 | total += value; |
247 | 0 | } |
248 | | |
249 | 0 | value = sPtr [2]; |
250 | | |
251 | 0 | if (value != badPixel) |
252 | 0 | { |
253 | 0 | count += 1; |
254 | 0 | total += value; |
255 | 0 | } |
256 | | |
257 | 0 | } |
258 | | |
259 | 0 | if (count == 4) // Most common case. |
260 | 0 | { |
261 | | |
262 | 0 | *dPtr = (uint16) ((total + 2) >> 2); |
263 | | |
264 | 0 | } |
265 | | |
266 | 0 | else if (count > 0) |
267 | 0 | { |
268 | | |
269 | 0 | *dPtr = (uint16) ((total + (count >> 1)) / count); |
270 | | |
271 | 0 | } |
272 | | |
273 | 0 | } |
274 | | |
275 | 0 | sPtr++; |
276 | 0 | dPtr++; |
277 | | |
278 | 0 | } |
279 | | |
280 | 0 | } |
281 | | |
282 | 0 | } |
283 | | |
284 | | /*****************************************************************************/ |
285 | | |
286 | | dng_bad_pixel_list::dng_bad_pixel_list () |
287 | | |
288 | | : fBadPoints () |
289 | | , fBadRects () |
290 | | |
291 | 0 | { |
292 | | |
293 | 0 | } |
294 | | |
295 | | /*****************************************************************************/ |
296 | | |
297 | | void dng_bad_pixel_list::AddPoint (const dng_point &pt) |
298 | 0 | { |
299 | | |
300 | 0 | fBadPoints.push_back (pt); |
301 | | |
302 | 0 | } |
303 | | |
304 | | /*****************************************************************************/ |
305 | | |
306 | | void dng_bad_pixel_list::AddRect (const dng_rect &r) |
307 | 0 | { |
308 | | |
309 | 0 | fBadRects.push_back (r); |
310 | | |
311 | 0 | } |
312 | | |
313 | | /*****************************************************************************/ |
314 | | |
315 | | static bool SortBadPoints (const dng_point &a, |
316 | | const dng_point &b) |
317 | 0 | { |
318 | | |
319 | 0 | if (a.v < b.v) |
320 | 0 | return true; |
321 | | |
322 | 0 | if (a.v > b.v) |
323 | 0 | return false; |
324 | | |
325 | 0 | return a.h < b.h; |
326 | | |
327 | 0 | } |
328 | | |
329 | | /*****************************************************************************/ |
330 | | |
331 | | static bool SortBadRects (const dng_rect &a, |
332 | | const dng_rect &b) |
333 | 0 | { |
334 | | |
335 | 0 | if (a.t < b.t) |
336 | 0 | return true; |
337 | | |
338 | 0 | if (a.t > b.t) |
339 | 0 | return false; |
340 | | |
341 | 0 | if (a.l < b.l) |
342 | 0 | return true; |
343 | | |
344 | 0 | if (a.l > b.l) |
345 | 0 | return false; |
346 | | |
347 | 0 | if (a.b < b.b) |
348 | 0 | return true; |
349 | | |
350 | 0 | if (a.b > b.b) |
351 | 0 | return false; |
352 | | |
353 | 0 | return a.r < b.r; |
354 | | |
355 | 0 | } |
356 | | |
357 | | /*****************************************************************************/ |
358 | | |
359 | | void dng_bad_pixel_list::Sort () |
360 | 0 | { |
361 | | |
362 | 0 | if (PointCount () > 1) |
363 | 0 | { |
364 | | |
365 | 0 | std::sort (fBadPoints.begin (), |
366 | 0 | fBadPoints.end (), |
367 | 0 | SortBadPoints); |
368 | | |
369 | 0 | } |
370 | | |
371 | 0 | if (RectCount () > 1) |
372 | 0 | { |
373 | | |
374 | 0 | std::sort (fBadRects.begin (), |
375 | 0 | fBadRects.end (), |
376 | 0 | SortBadRects); |
377 | | |
378 | 0 | } |
379 | | |
380 | 0 | } |
381 | | |
382 | | /*****************************************************************************/ |
383 | | |
384 | | bool dng_bad_pixel_list::IsPointIsolated (uint32 index, |
385 | | uint32 radius) const |
386 | 0 | { |
387 | | |
388 | 0 | dng_point pt = Point (index); |
389 | | |
390 | | // Search backward through bad point list. |
391 | | |
392 | 0 | for (int32 j = index - 1; j >= 0; j--) |
393 | 0 | { |
394 | | |
395 | 0 | const dng_point &pt2 = Point (j); |
396 | | |
397 | 0 | if (pt2.v < pt.v - (int32) radius) |
398 | 0 | { |
399 | 0 | break; |
400 | 0 | } |
401 | | |
402 | 0 | if (Abs_int32 (pt2.h - pt.h) <= radius) |
403 | 0 | { |
404 | 0 | return false; |
405 | 0 | } |
406 | | |
407 | 0 | } |
408 | | |
409 | | // Search forward through bad point list. |
410 | | |
411 | 0 | for (uint32 k = index + 1; k < PointCount (); k++) |
412 | 0 | { |
413 | | |
414 | 0 | const dng_point &pt2 = Point (k); |
415 | | |
416 | 0 | if (pt2.v > pt.v + (int32) radius) |
417 | 0 | { |
418 | 0 | break; |
419 | 0 | } |
420 | | |
421 | 0 | if (Abs_int32 (pt2.h - pt.h) <= radius) |
422 | 0 | { |
423 | 0 | return false; |
424 | 0 | } |
425 | | |
426 | 0 | } |
427 | | |
428 | | // Search through bad rectangle list. |
429 | | |
430 | 0 | dng_rect testRect (pt.v - radius, |
431 | 0 | pt.h - radius, |
432 | 0 | pt.v + radius + 1, |
433 | 0 | pt.h + radius + 1); |
434 | | |
435 | 0 | for (uint32 n = 0; n < RectCount (); n++) |
436 | 0 | { |
437 | | |
438 | 0 | if ((testRect & Rect (n)).NotEmpty ()) |
439 | 0 | { |
440 | 0 | return false; |
441 | 0 | } |
442 | | |
443 | 0 | } |
444 | | |
445 | | // Did not find point anywhere, so bad pixel is isolated. |
446 | | |
447 | 0 | return true; |
448 | | |
449 | 0 | } |
450 | | |
451 | | /*****************************************************************************/ |
452 | | |
453 | | bool dng_bad_pixel_list::IsRectIsolated (uint32 index, |
454 | | uint32 radius) const |
455 | 0 | { |
456 | | |
457 | 0 | dng_rect testRect = Rect (index); |
458 | | |
459 | 0 | testRect.t -= radius; |
460 | 0 | testRect.l -= radius; |
461 | 0 | testRect.b += radius; |
462 | 0 | testRect.r += radius; |
463 | | |
464 | 0 | for (uint32 n = 0; n < RectCount (); n++) |
465 | 0 | { |
466 | | |
467 | 0 | if (n != index) |
468 | 0 | { |
469 | | |
470 | 0 | if ((testRect & Rect (n)).NotEmpty ()) |
471 | 0 | { |
472 | 0 | return false; |
473 | 0 | } |
474 | | |
475 | 0 | } |
476 | | |
477 | 0 | } |
478 | | |
479 | 0 | return true; |
480 | | |
481 | 0 | } |
482 | | |
483 | | /*****************************************************************************/ |
484 | | |
485 | | bool dng_bad_pixel_list::IsPointValid (const dng_point &pt, |
486 | | const dng_rect &imageBounds, |
487 | | uint32 index) const |
488 | 0 | { |
489 | | |
490 | | // The point must be in the image bounds to be valid. |
491 | | |
492 | 0 | if (pt.v < imageBounds.t || |
493 | 0 | pt.h < imageBounds.l || |
494 | 0 | pt.v >= imageBounds.b || |
495 | 0 | pt.h >= imageBounds.r) |
496 | 0 | { |
497 | 0 | return false; |
498 | 0 | } |
499 | | |
500 | | // Only search the bad point list if we have a starting search index. |
501 | | |
502 | 0 | if (index != kNoIndex) |
503 | 0 | { |
504 | | |
505 | | // Search backward through bad point list. |
506 | | |
507 | 0 | for (int32 j = index - 1; j >= 0; j--) |
508 | 0 | { |
509 | | |
510 | 0 | const dng_point &pt2 = Point (j); |
511 | | |
512 | 0 | if (pt2.v < pt.v) |
513 | 0 | { |
514 | 0 | break; |
515 | 0 | } |
516 | | |
517 | 0 | if (pt2 == pt) |
518 | 0 | { |
519 | 0 | return false; |
520 | 0 | } |
521 | | |
522 | 0 | } |
523 | | |
524 | | // Search forward through bad point list. |
525 | | |
526 | 0 | for (uint32 k = index + 1; k < PointCount (); k++) |
527 | 0 | { |
528 | | |
529 | 0 | const dng_point &pt2 = Point (k); |
530 | | |
531 | 0 | if (pt2.v > pt.v) |
532 | 0 | { |
533 | 0 | break; |
534 | 0 | } |
535 | | |
536 | 0 | if (pt2 == pt) |
537 | 0 | { |
538 | 0 | return false; |
539 | 0 | } |
540 | | |
541 | 0 | } |
542 | | |
543 | 0 | } |
544 | | |
545 | | // Search through bad rectangle list. |
546 | | |
547 | 0 | for (uint32 n = 0; n < RectCount (); n++) |
548 | 0 | { |
549 | | |
550 | 0 | const dng_rect &r = Rect (n); |
551 | | |
552 | 0 | if (pt.v >= r.t && |
553 | 0 | pt.h >= r.l && |
554 | 0 | pt.v < r.b && |
555 | 0 | pt.h < r.r) |
556 | 0 | { |
557 | 0 | return false; |
558 | 0 | } |
559 | | |
560 | 0 | } |
561 | | |
562 | | // Did not find point anywhere, so pixel is valid. |
563 | | |
564 | 0 | return true; |
565 | | |
566 | 0 | } |
567 | | |
568 | | /*****************************************************************************/ |
569 | | |
570 | | dng_opcode_FixBadPixelsList::dng_opcode_FixBadPixelsList |
571 | | (AutoPtr<dng_bad_pixel_list> &list, |
572 | | uint32 bayerPhase) |
573 | | |
574 | | |
575 | | : dng_filter_opcode (dngOpcode_FixBadPixelsList, |
576 | | dngVersion_1_3_0_0, |
577 | | 0) |
578 | | |
579 | | , fList () |
580 | | |
581 | | , fBayerPhase (bayerPhase) |
582 | | |
583 | 0 | { |
584 | | |
585 | 0 | fList.Reset (list.Release ()); |
586 | | |
587 | 0 | fList->Sort (); |
588 | | |
589 | 0 | } |
590 | | |
591 | | /*****************************************************************************/ |
592 | | |
593 | | dng_opcode_FixBadPixelsList::dng_opcode_FixBadPixelsList (dng_stream &stream) |
594 | | |
595 | | : dng_filter_opcode (dngOpcode_FixBadPixelsList, |
596 | | stream, |
597 | | "FixBadPixelsList") |
598 | | |
599 | | , fList () |
600 | | |
601 | | , fBayerPhase (0) |
602 | | |
603 | 0 | { |
604 | | |
605 | 0 | uint32 size = stream.Get_uint32 (); |
606 | | |
607 | 0 | fBayerPhase = stream.Get_uint32 (); |
608 | | |
609 | 0 | uint32 pCount = stream.Get_uint32 (); |
610 | 0 | uint32 rCount = stream.Get_uint32 (); |
611 | 0 | uint32 expectedSize = |
612 | 0 | SafeUint32Add(12, SafeUint32Add(SafeUint32Mult(pCount, 8), SafeUint32Mult(rCount, 16))); |
613 | 0 | if (size != expectedSize) |
614 | 0 | { |
615 | 0 | ThrowBadFormat (); |
616 | 0 | } |
617 | | |
618 | 0 | fList.Reset (new dng_bad_pixel_list); |
619 | | |
620 | 0 | uint32 index; |
621 | | |
622 | 0 | for (index = 0; index < pCount; index++) |
623 | 0 | { |
624 | | |
625 | 0 | dng_point pt; |
626 | | |
627 | 0 | pt.v = stream.Get_int32 (); |
628 | 0 | pt.h = stream.Get_int32 (); |
629 | | |
630 | 0 | fList->AddPoint (pt); |
631 | | |
632 | 0 | } |
633 | | |
634 | 0 | for (index = 0; index < rCount; index++) |
635 | 0 | { |
636 | | |
637 | 0 | dng_rect r; |
638 | | |
639 | 0 | r.t = stream.Get_int32 (); |
640 | 0 | r.l = stream.Get_int32 (); |
641 | 0 | r.b = stream.Get_int32 (); |
642 | 0 | r.r = stream.Get_int32 (); |
643 | | |
644 | 0 | fList->AddRect (r); |
645 | | |
646 | 0 | } |
647 | | |
648 | 0 | fList->Sort (); |
649 | | |
650 | | #if qDNGValidate |
651 | | |
652 | | if (gVerbose) |
653 | | { |
654 | | |
655 | | printf ("Bayer Phase: %u\n", (unsigned) fBayerPhase); |
656 | | |
657 | | printf ("Bad Pixels: %u\n", (unsigned) pCount); |
658 | | |
659 | | for (index = 0; index < pCount && index < gDumpLineLimit; index++) |
660 | | { |
661 | | printf (" Pixel [%u]: v=%d, h=%d\n", |
662 | | (unsigned) index, |
663 | | (int) fList->Point (index).v, |
664 | | (int) fList->Point (index).h); |
665 | | } |
666 | | |
667 | | if (pCount > gDumpLineLimit) |
668 | | { |
669 | | printf (" ... %u bad pixels skipped\n", (unsigned) (pCount - gDumpLineLimit)); |
670 | | } |
671 | | |
672 | | printf ("Bad Rects: %u\n", (unsigned) rCount); |
673 | | |
674 | | for (index = 0; index < rCount && index < gDumpLineLimit; index++) |
675 | | { |
676 | | printf (" Rect [%u]: t=%d, l=%d, b=%d, r=%d\n", |
677 | | (unsigned) index, |
678 | | (int) fList->Rect (index).t, |
679 | | (int) fList->Rect (index).l, |
680 | | (int) fList->Rect (index).b, |
681 | | (int) fList->Rect (index).r); |
682 | | } |
683 | | |
684 | | if (rCount > gDumpLineLimit) |
685 | | { |
686 | | printf (" ... %u bad rects skipped\n", (unsigned) (rCount - gDumpLineLimit)); |
687 | | } |
688 | | |
689 | | } |
690 | | |
691 | | #endif |
692 | | |
693 | 0 | } |
694 | | |
695 | | /*****************************************************************************/ |
696 | | |
697 | | void dng_opcode_FixBadPixelsList::PutData (dng_stream &stream) const |
698 | 0 | { |
699 | | |
700 | 0 | uint32 pCount = fList->PointCount (); |
701 | 0 | uint32 rCount = fList->RectCount (); |
702 | | |
703 | 0 | stream.Put_uint32 (12 + pCount * 8 + rCount * 16); |
704 | | |
705 | 0 | stream.Put_uint32 (fBayerPhase); |
706 | | |
707 | 0 | stream.Put_uint32 (pCount); |
708 | 0 | stream.Put_uint32 (rCount); |
709 | | |
710 | 0 | uint32 index; |
711 | | |
712 | 0 | for (index = 0; index < pCount; index++) |
713 | 0 | { |
714 | | |
715 | 0 | const dng_point &pt (fList->Point (index)); |
716 | | |
717 | 0 | stream.Put_int32 (pt.v); |
718 | 0 | stream.Put_int32 (pt.h); |
719 | | |
720 | 0 | } |
721 | | |
722 | 0 | for (index = 0; index < rCount; index++) |
723 | 0 | { |
724 | | |
725 | 0 | const dng_rect &r (fList->Rect (index)); |
726 | | |
727 | 0 | stream.Put_int32 (r.t); |
728 | 0 | stream.Put_int32 (r.l); |
729 | 0 | stream.Put_int32 (r.b); |
730 | 0 | stream.Put_int32 (r.r); |
731 | | |
732 | 0 | } |
733 | | |
734 | 0 | } |
735 | | |
736 | | /*****************************************************************************/ |
737 | | |
738 | | dng_rect dng_opcode_FixBadPixelsList::SrcArea (const dng_rect &dstArea, |
739 | | const dng_rect & /* imageBounds */) |
740 | 0 | { |
741 | | |
742 | 0 | int32 padding = 0; |
743 | | |
744 | 0 | if (fList->PointCount ()) |
745 | 0 | { |
746 | 0 | padding += kBadPointPadding; |
747 | 0 | } |
748 | | |
749 | 0 | if (fList->RectCount ()) |
750 | 0 | { |
751 | 0 | padding += kBadRectPadding; |
752 | 0 | } |
753 | | |
754 | 0 | dng_rect srcArea = dstArea; |
755 | | |
756 | 0 | srcArea.t -= padding; |
757 | 0 | srcArea.l -= padding; |
758 | | |
759 | 0 | srcArea.b += padding; |
760 | 0 | srcArea.r += padding; |
761 | | |
762 | 0 | return srcArea; |
763 | | |
764 | 0 | } |
765 | | |
766 | | /*****************************************************************************/ |
767 | | |
768 | | dng_point dng_opcode_FixBadPixelsList::SrcRepeat () |
769 | 0 | { |
770 | | |
771 | 0 | return dng_point (2, 2); |
772 | | |
773 | 0 | } |
774 | | |
775 | | /*****************************************************************************/ |
776 | | |
777 | | void dng_opcode_FixBadPixelsList::Prepare (dng_negative & /* negative */, |
778 | | uint32 /* threadCount */, |
779 | | const dng_point & /* tileSize */, |
780 | | const dng_rect & /* imageBounds */, |
781 | | uint32 imagePlanes, |
782 | | uint32 bufferPixelType, |
783 | | dng_memory_allocator & /* allocator */) |
784 | 0 | { |
785 | | |
786 | | // This opcode is restricted to single channel images. |
787 | | |
788 | 0 | if (imagePlanes != 1) |
789 | 0 | { |
790 | | |
791 | 0 | ThrowBadFormat (); |
792 | | |
793 | 0 | } |
794 | | |
795 | | // This opcode is restricted to 16-bit images. |
796 | | |
797 | 0 | if (bufferPixelType != ttShort) |
798 | 0 | { |
799 | | |
800 | 0 | ThrowBadFormat (); |
801 | | |
802 | 0 | } |
803 | | |
804 | 0 | } |
805 | | |
806 | | /*****************************************************************************/ |
807 | | |
808 | | void dng_opcode_FixBadPixelsList::FixIsolatedPixel (dng_pixel_buffer &buffer, |
809 | | dng_point &badPoint) |
810 | 0 | { |
811 | | |
812 | 0 | uint16 *p0 = buffer.DirtyPixel_uint16 (badPoint.v - 2, badPoint.h - 2, 0); |
813 | 0 | uint16 *p1 = buffer.DirtyPixel_uint16 (badPoint.v - 1, badPoint.h - 2, 0); |
814 | 0 | uint16 *p2 = buffer.DirtyPixel_uint16 (badPoint.v , badPoint.h - 2, 0); |
815 | 0 | uint16 *p3 = buffer.DirtyPixel_uint16 (badPoint.v + 1, badPoint.h - 2, 0); |
816 | 0 | uint16 *p4 = buffer.DirtyPixel_uint16 (badPoint.v + 2, badPoint.h - 2, 0); |
817 | |
|
818 | 0 | uint32 est0; |
819 | 0 | uint32 est1; |
820 | 0 | uint32 est2; |
821 | 0 | uint32 est3; |
822 | |
|
823 | 0 | uint32 grad0; |
824 | 0 | uint32 grad1; |
825 | 0 | uint32 grad2; |
826 | 0 | uint32 grad3; |
827 | |
|
828 | 0 | if (IsGreen (badPoint.v, badPoint.h)) // Green pixel |
829 | 0 | { |
830 | | |
831 | | // g00 b01 g02 b03 g04 |
832 | | // r10 g11 r12 g13 r14 |
833 | | // g20 b21 g22 b23 g24 |
834 | | // r30 g31 r32 g33 r34 |
835 | | // g40 b41 g42 b43 g44 |
836 | | |
837 | 0 | int32 b01 = p0 [1]; |
838 | 0 | int32 g02 = p0 [2]; |
839 | 0 | int32 b03 = p0 [3]; |
840 | | |
841 | 0 | int32 r10 = p1 [0]; |
842 | 0 | int32 g11 = p1 [1]; |
843 | 0 | int32 r12 = p1 [2]; |
844 | 0 | int32 g13 = p1 [3]; |
845 | 0 | int32 r14 = p1 [4]; |
846 | | |
847 | 0 | int32 g20 = p2 [0]; |
848 | 0 | int32 b21 = p2 [1]; |
849 | 0 | int32 b23 = p2 [3]; |
850 | 0 | int32 g24 = p2 [4]; |
851 | | |
852 | 0 | int32 r30 = p3 [0]; |
853 | 0 | int32 g31 = p3 [1]; |
854 | 0 | int32 r32 = p3 [2]; |
855 | 0 | int32 g33 = p3 [3]; |
856 | 0 | int32 r34 = p3 [4]; |
857 | | |
858 | 0 | int32 b41 = p4 [1]; |
859 | 0 | int32 g42 = p4 [2]; |
860 | 0 | int32 b43 = p4 [3]; |
861 | | |
862 | 0 | est0 = g02 + g42; |
863 | | |
864 | 0 | grad0 = Abs_int32 (g02 - g42) + |
865 | 0 | Abs_int32 (g11 - g31) + |
866 | 0 | Abs_int32 (g13 - g33) + |
867 | 0 | Abs_int32 (b01 - b21) + |
868 | 0 | Abs_int32 (b03 - b23) + |
869 | 0 | Abs_int32 (b21 - b41) + |
870 | 0 | Abs_int32 (b23 - b43); |
871 | | |
872 | 0 | est1 = g11 + g33; |
873 | | |
874 | 0 | grad1 = Abs_int32 (g11 - g33) + |
875 | 0 | Abs_int32 (g02 - g24) + |
876 | 0 | Abs_int32 (g20 - g42) + |
877 | 0 | Abs_int32 (b01 - b23) + |
878 | 0 | Abs_int32 (r10 - r32) + |
879 | 0 | Abs_int32 (r12 - r34) + |
880 | 0 | Abs_int32 (b21 - b43); |
881 | | |
882 | 0 | est2 = g20 + g24; |
883 | | |
884 | 0 | grad2 = Abs_int32 (g20 - g24) + |
885 | 0 | Abs_int32 (g11 - g13) + |
886 | 0 | Abs_int32 (g31 - g33) + |
887 | 0 | Abs_int32 (r10 - r12) + |
888 | 0 | Abs_int32 (r30 - r32) + |
889 | 0 | Abs_int32 (r12 - r14) + |
890 | 0 | Abs_int32 (r32 - r34); |
891 | | |
892 | 0 | est3 = g13 + g31; |
893 | | |
894 | 0 | grad3 = Abs_int32 (g13 - g31) + |
895 | 0 | Abs_int32 (g02 - g20) + |
896 | 0 | Abs_int32 (g24 - g42) + |
897 | 0 | Abs_int32 (b03 - b21) + |
898 | 0 | Abs_int32 (r14 - r32) + |
899 | 0 | Abs_int32 (r12 - r30) + |
900 | 0 | Abs_int32 (b23 - b41); |
901 | | |
902 | 0 | } |
903 | | |
904 | 0 | else // Red/blue pixel |
905 | 0 | { |
906 | | |
907 | | // b00 g01 b02 g03 b04 |
908 | | // g10 r11 g12 r13 g14 |
909 | | // b20 g21 b22 g23 b24 |
910 | | // g30 r31 g32 r33 g34 |
911 | | // b40 g41 b42 g43 b44 |
912 | | |
913 | 0 | int32 b00 = p0 [0]; |
914 | 0 | int32 g01 = p0 [1]; |
915 | 0 | int32 b02 = p0 [2]; |
916 | 0 | int32 g03 = p0 [3]; |
917 | 0 | int32 b04 = p0 [4]; |
918 | | |
919 | 0 | int32 g10 = p1 [0]; |
920 | 0 | int32 r11 = p1 [1]; |
921 | 0 | int32 g12 = p1 [2]; |
922 | 0 | int32 r13 = p1 [3]; |
923 | 0 | int32 g14 = p1 [4]; |
924 | | |
925 | 0 | int32 b20 = p2 [0]; |
926 | 0 | int32 g21 = p2 [1]; |
927 | 0 | int32 g23 = p2 [3]; |
928 | 0 | int32 b24 = p2 [4]; |
929 | | |
930 | 0 | int32 g30 = p3 [0]; |
931 | 0 | int32 r31 = p3 [1]; |
932 | 0 | int32 g32 = p3 [2]; |
933 | 0 | int32 r33 = p3 [3]; |
934 | 0 | int32 g34 = p3 [4]; |
935 | | |
936 | 0 | int32 b40 = p4 [0]; |
937 | 0 | int32 g41 = p4 [1]; |
938 | 0 | int32 b42 = p4 [2]; |
939 | 0 | int32 g43 = p4 [3]; |
940 | 0 | int32 b44 = p4 [4]; |
941 | |
|
942 | 0 | est0 = b02 + b42; |
943 | |
|
944 | 0 | grad0 = Abs_int32 (b02 - b42) + |
945 | 0 | Abs_int32 (g12 - g32) + |
946 | 0 | Abs_int32 (g01 - g21) + |
947 | 0 | Abs_int32 (g21 - g41) + |
948 | 0 | Abs_int32 (g03 - g23) + |
949 | 0 | Abs_int32 (g23 - g43) + |
950 | 0 | Abs_int32 (r11 - r31) + |
951 | 0 | Abs_int32 (r13 - r33); |
952 | | |
953 | 0 | est1 = b00 + b44; |
954 | | |
955 | 0 | grad1 = Abs_int32 (b00 - b44) + |
956 | 0 | Abs_int32 (r11 - r33) + |
957 | 0 | Abs_int32 (g01 - g23) + |
958 | 0 | Abs_int32 (g10 - g32) + |
959 | 0 | Abs_int32 (g12 - g34) + |
960 | 0 | Abs_int32 (g21 - g43) + |
961 | 0 | Abs_int32 (b02 - b24) + |
962 | 0 | Abs_int32 (b20 - b42); |
963 | | |
964 | 0 | est2 = b20 + b24; |
965 | |
|
966 | 0 | grad2 = Abs_int32 (b20 - b24) + |
967 | 0 | Abs_int32 (g21 - g23) + |
968 | 0 | Abs_int32 (g10 - g12) + |
969 | 0 | Abs_int32 (g12 - g14) + |
970 | 0 | Abs_int32 (g30 - g32) + |
971 | 0 | Abs_int32 (g32 - g34) + |
972 | 0 | Abs_int32 (r11 - r13) + |
973 | 0 | Abs_int32 (r31 - r33); |
974 | | |
975 | 0 | est3 = b04 + b40; |
976 | | |
977 | 0 | grad3 = Abs_int32 (b04 - b40) + |
978 | 0 | Abs_int32 (r13 - r31) + |
979 | 0 | Abs_int32 (g03 - g21) + |
980 | 0 | Abs_int32 (g14 - g32) + |
981 | 0 | Abs_int32 (g12 - g30) + |
982 | 0 | Abs_int32 (g23 - g41) + |
983 | 0 | Abs_int32 (b02 - b20) + |
984 | 0 | Abs_int32 (b24 - b42); |
985 | | |
986 | 0 | } |
987 | | |
988 | 0 | uint32 minGrad = Min_uint32 (grad0, grad1); |
989 | | |
990 | 0 | minGrad = Min_uint32 (minGrad, grad2); |
991 | 0 | minGrad = Min_uint32 (minGrad, grad3); |
992 | |
|
993 | 0 | uint32 limit = (minGrad * 3) >> 1; |
994 | | |
995 | 0 | uint32 total = 0; |
996 | 0 | uint32 count = 0; |
997 | | |
998 | 0 | if (grad0 <= limit) |
999 | 0 | { |
1000 | 0 | total += est0; |
1001 | 0 | count += 2; |
1002 | 0 | } |
1003 | | |
1004 | 0 | if (grad1 <= limit) |
1005 | 0 | { |
1006 | 0 | total += est1; |
1007 | 0 | count += 2; |
1008 | 0 | } |
1009 | | |
1010 | 0 | if (grad2 <= limit) |
1011 | 0 | { |
1012 | 0 | total += est2; |
1013 | 0 | count += 2; |
1014 | 0 | } |
1015 | |
|
1016 | 0 | if (grad3 <= limit) |
1017 | 0 | { |
1018 | 0 | total += est3; |
1019 | 0 | count += 2; |
1020 | 0 | } |
1021 | |
|
1022 | 0 | uint32 estimate = (total + (count >> 1)) / count; |
1023 | | |
1024 | 0 | p2 [2] = (uint16) estimate; |
1025 | |
|
1026 | 0 | } |
1027 | | |
1028 | | /*****************************************************************************/ |
1029 | | |
1030 | | void dng_opcode_FixBadPixelsList::FixClusteredPixel (dng_pixel_buffer &buffer, |
1031 | | uint32 pointIndex, |
1032 | | const dng_rect &imageBounds) |
1033 | 0 | { |
1034 | | |
1035 | 0 | const uint32 kNumSets = 3; |
1036 | 0 | const uint32 kSetSize = 4; |
1037 | | |
1038 | 0 | static const int32 kOffset [kNumSets] [kSetSize] [2] = |
1039 | 0 | { |
1040 | 0 | { |
1041 | 0 | { -1, 1 }, |
1042 | 0 | { -1, -1 }, |
1043 | 0 | { 1, -1 }, |
1044 | 0 | { 1, 1 } |
1045 | 0 | }, |
1046 | 0 | { |
1047 | 0 | { -2, 0 }, |
1048 | 0 | { 2, 0 }, |
1049 | 0 | { 0, -2 }, |
1050 | 0 | { 0, 2 } |
1051 | 0 | }, |
1052 | 0 | { |
1053 | 0 | { -2, -2 }, |
1054 | 0 | { -2, 2 }, |
1055 | 0 | { 2, -2 }, |
1056 | 0 | { 2, 2 } |
1057 | 0 | } |
1058 | 0 | }; |
1059 | | |
1060 | 0 | dng_point badPoint = fList->Point (pointIndex); |
1061 | | |
1062 | 0 | bool isGreen = IsGreen (badPoint.v, badPoint.h); |
1063 | | |
1064 | 0 | uint16 *p = buffer.DirtyPixel_uint16 (badPoint.v, badPoint.h, 0); |
1065 | | |
1066 | 0 | for (uint32 set = 0; set < kNumSets; set++) |
1067 | 0 | { |
1068 | | |
1069 | 0 | if (!isGreen && (kOffset [set] [0] [0] & 1) == 1) |
1070 | 0 | { |
1071 | 0 | continue; |
1072 | 0 | } |
1073 | | |
1074 | 0 | uint32 total = 0; |
1075 | 0 | uint32 count = 0; |
1076 | | |
1077 | 0 | for (uint32 entry = 0; entry < kSetSize; entry++) |
1078 | 0 | { |
1079 | | |
1080 | 0 | dng_point offset (kOffset [set] [entry] [0], |
1081 | 0 | kOffset [set] [entry] [1]); |
1082 | | |
1083 | 0 | if (fList->IsPointValid (badPoint + offset, |
1084 | 0 | imageBounds, |
1085 | 0 | pointIndex)) |
1086 | 0 | { |
1087 | | |
1088 | 0 | total += p [offset.v * buffer.fRowStep + |
1089 | 0 | offset.h * buffer.fColStep]; |
1090 | | |
1091 | 0 | count++; |
1092 | | |
1093 | 0 | } |
1094 | | |
1095 | 0 | } |
1096 | | |
1097 | 0 | if (count) |
1098 | 0 | { |
1099 | | |
1100 | 0 | uint32 estimate = (total + (count >> 1)) / count; |
1101 | | |
1102 | 0 | p [0] = (uint16) estimate; |
1103 | | |
1104 | 0 | return; |
1105 | | |
1106 | 0 | } |
1107 | |
|
1108 | 0 | } |
1109 | | |
1110 | | // Unable to patch bad pixel. Leave pixel as is. |
1111 | | |
1112 | | #if qDNGValidate |
1113 | | |
1114 | | char s [256]; |
1115 | | |
1116 | | sprintf (s, "Unable to repair bad pixel, row %d, column %d", |
1117 | | (int) badPoint.v, |
1118 | | (int) badPoint.h); |
1119 | | |
1120 | | ReportWarning (s); |
1121 | | |
1122 | | #endif |
1123 | | |
1124 | 0 | } |
1125 | | |
1126 | | /*****************************************************************************/ |
1127 | | |
1128 | | void dng_opcode_FixBadPixelsList::FixSingleColumn (dng_pixel_buffer &buffer, |
1129 | | const dng_rect &badRect) |
1130 | 0 | { |
1131 | | |
1132 | 0 | int32 cs = buffer.fColStep; |
1133 | | |
1134 | 0 | for (int32 row = badRect.t; row < badRect.b; row++) |
1135 | 0 | { |
1136 | | |
1137 | 0 | uint16 *p0 = buffer.DirtyPixel_uint16 (row - 4, badRect.l - 4, 0); |
1138 | 0 | uint16 *p1 = buffer.DirtyPixel_uint16 (row - 3, badRect.l - 4, 0); |
1139 | 0 | uint16 *p2 = buffer.DirtyPixel_uint16 (row - 2, badRect.l - 4, 0); |
1140 | 0 | uint16 *p3 = buffer.DirtyPixel_uint16 (row - 1, badRect.l - 4, 0); |
1141 | 0 | uint16 *p4 = buffer.DirtyPixel_uint16 (row , badRect.l - 4, 0); |
1142 | 0 | uint16 *p5 = buffer.DirtyPixel_uint16 (row + 1, badRect.l - 4, 0); |
1143 | 0 | uint16 *p6 = buffer.DirtyPixel_uint16 (row + 2, badRect.l - 4, 0); |
1144 | 0 | uint16 *p7 = buffer.DirtyPixel_uint16 (row + 3, badRect.l - 4, 0); |
1145 | 0 | uint16 *p8 = buffer.DirtyPixel_uint16 (row + 4, badRect.l - 4, 0); |
1146 | | |
1147 | 0 | uint32 est0; |
1148 | 0 | uint32 est1; |
1149 | 0 | uint32 est2; |
1150 | 0 | uint32 est3; |
1151 | 0 | uint32 est4; |
1152 | 0 | uint32 est5; |
1153 | 0 | uint32 est6; |
1154 | | |
1155 | 0 | uint32 grad0; |
1156 | 0 | uint32 grad1; |
1157 | 0 | uint32 grad2; |
1158 | 0 | uint32 grad3; |
1159 | 0 | uint32 grad4; |
1160 | 0 | uint32 grad5; |
1161 | 0 | uint32 grad6; |
1162 | | |
1163 | 0 | uint32 lower = 0; |
1164 | 0 | uint32 upper = 0x0FFFF; |
1165 | | |
1166 | 0 | if (IsGreen (row, badRect.l)) // Green pixel |
1167 | 0 | { |
1168 | | |
1169 | | // g00 b01 g02 b03 g04 b05 g06 b07 g08 |
1170 | | // r10 g11 r12 g13 r14 g15 r16 g17 r18 |
1171 | | // g20 b21 g22 b23 g24 b25 g26 b27 g28 |
1172 | | // r30 g31 r32 g33 r34 g35 r36 g37 r38 |
1173 | | // g40 b41 g42 b43 g44 b45 g46 b47 g48 |
1174 | | // r50 g51 r52 g53 r54 g55 r56 g57 r58 |
1175 | | // g60 b61 g62 b63 g64 b65 g66 b67 g68 |
1176 | | // r70 g71 r72 g73 r74 g75 r76 g77 r78 |
1177 | | // g80 b81 g82 b83 g84 b85 g86 b87 g88 |
1178 | | |
1179 | 0 | int32 b03 = p0 [3 * cs]; |
1180 | 0 | int32 b05 = p0 [5 * cs]; |
1181 | | |
1182 | 0 | int32 g11 = p1 [1 * cs]; |
1183 | 0 | int32 g13 = p1 [3 * cs]; |
1184 | 0 | int32 g15 = p1 [5 * cs]; |
1185 | 0 | int32 g17 = p1 [7 * cs]; |
1186 | | |
1187 | 0 | int32 g22 = p2 [2 * cs]; |
1188 | 0 | int32 b23 = p2 [3 * cs]; |
1189 | 0 | int32 b25 = p2 [5 * cs]; |
1190 | 0 | int32 g26 = p2 [6 * cs]; |
1191 | | |
1192 | 0 | int32 r30 = p3 [0 * cs]; |
1193 | 0 | int32 g31 = p3 [1 * cs]; |
1194 | 0 | int32 r32 = p3 [2 * cs]; |
1195 | 0 | int32 g33 = p3 [3 * cs]; |
1196 | 0 | int32 g35 = p3 [5 * cs]; |
1197 | 0 | int32 r36 = p3 [6 * cs]; |
1198 | 0 | int32 g37 = p3 [7 * cs]; |
1199 | 0 | int32 r38 = p3 [8 * cs]; |
1200 | | |
1201 | 0 | int32 g40 = p4 [0 * cs]; |
1202 | 0 | int32 g42 = p4 [2 * cs]; |
1203 | 0 | int32 b43 = p4 [3 * cs]; |
1204 | 0 | int32 b45 = p4 [5 * cs]; |
1205 | 0 | int32 g46 = p4 [6 * cs]; |
1206 | 0 | int32 g48 = p4 [8 * cs]; |
1207 | | |
1208 | 0 | int32 r50 = p5 [0 * cs]; |
1209 | 0 | int32 g51 = p5 [1 * cs]; |
1210 | 0 | int32 r52 = p5 [2 * cs]; |
1211 | 0 | int32 g53 = p5 [3 * cs]; |
1212 | 0 | int32 g55 = p5 [5 * cs]; |
1213 | 0 | int32 r56 = p5 [6 * cs]; |
1214 | 0 | int32 g57 = p5 [7 * cs]; |
1215 | 0 | int32 r58 = p5 [8 * cs]; |
1216 | | |
1217 | 0 | int32 g62 = p6 [2 * cs]; |
1218 | 0 | int32 b63 = p6 [3 * cs]; |
1219 | 0 | int32 b65 = p6 [5 * cs]; |
1220 | 0 | int32 g66 = p6 [6 * cs]; |
1221 | | |
1222 | 0 | int32 g71 = p7 [1 * cs]; |
1223 | 0 | int32 g73 = p7 [3 * cs]; |
1224 | 0 | int32 g75 = p7 [5 * cs]; |
1225 | 0 | int32 g77 = p7 [7 * cs]; |
1226 | | |
1227 | 0 | int32 b83 = p8 [3 * cs]; |
1228 | 0 | int32 b85 = p8 [5 * cs]; |
1229 | | |
1230 | | // In case there is some green split, make an estimate of |
1231 | | // of the local difference between the greens, and adjust |
1232 | | // the estimated green values for the difference |
1233 | | // between the two types of green pixels when estimating |
1234 | | // across green types. |
1235 | | |
1236 | 0 | int32 split = ((g22 + g62 + g26 + g66) * 4 + |
1237 | 0 | (g42 + g46 ) * 8 - |
1238 | 0 | (g11 + g13 + g15 + g17) - |
1239 | 0 | (g31 + g33 + g35 + g37) * 3 - |
1240 | 0 | (g51 + g53 + g55 + g57) * 3 - |
1241 | 0 | (g71 + g73 + g75 + g77) + 16) >> 5; |
1242 | | |
1243 | 0 | est0 = g13 + g75 + split * 2; |
1244 | | |
1245 | 0 | grad0 = Abs_int32 (g13 - g75) + |
1246 | 0 | Abs_int32 (g15 - g46) + |
1247 | 0 | Abs_int32 (g22 - g53) + |
1248 | 0 | Abs_int32 (g35 - g66) + |
1249 | 0 | Abs_int32 (g42 - g73) + |
1250 | 0 | Abs_int32 (b03 - b65) + |
1251 | 0 | Abs_int32 (b23 - b85); |
1252 | | |
1253 | 0 | est1 = g33 + g55 + split * 2; |
1254 | | |
1255 | 0 | grad1 = Abs_int32 (g33 - g55) + |
1256 | 0 | Abs_int32 (g22 - g55) + |
1257 | 0 | Abs_int32 (g33 - g66) + |
1258 | 0 | Abs_int32 (g13 - g35) + |
1259 | 0 | Abs_int32 (g53 - g75) + |
1260 | 0 | Abs_int32 (b23 - b45) + |
1261 | 0 | Abs_int32 (b43 - b65); |
1262 | | |
1263 | 0 | est2 = g31 + g57 + split * 2; |
1264 | | |
1265 | 0 | grad2 = Abs_int32 (g31 - g57) + |
1266 | 0 | Abs_int32 (g33 - g46) + |
1267 | 0 | Abs_int32 (g35 - g48) + |
1268 | 0 | Abs_int32 (g40 - g53) + |
1269 | 0 | Abs_int32 (g42 - g55) + |
1270 | 0 | Abs_int32 (r30 - r56) + |
1271 | 0 | Abs_int32 (r32 - r58); |
1272 | | |
1273 | 0 | est3 = g42 + g46; |
1274 | | |
1275 | 0 | grad3 = Abs_int32 (g42 - g46) * 2 + |
1276 | 0 | Abs_int32 (g33 - g35) + |
1277 | 0 | Abs_int32 (g53 - g55) + |
1278 | 0 | Abs_int32 (b23 - b25) + |
1279 | 0 | Abs_int32 (b43 - b45) + |
1280 | 0 | Abs_int32 (b63 - b65); |
1281 | | |
1282 | 0 | est4 = g37 + g51 + split * 2; |
1283 | |
|
1284 | 0 | grad4 = Abs_int32 (g37 - g51) + |
1285 | 0 | Abs_int32 (g35 - g42) + |
1286 | 0 | Abs_int32 (g33 - g40) + |
1287 | 0 | Abs_int32 (g48 - g55) + |
1288 | 0 | Abs_int32 (g46 - g53) + |
1289 | 0 | Abs_int32 (r38 - r52) + |
1290 | 0 | Abs_int32 (r36 - r50); |
1291 | | |
1292 | 0 | est5 = g35 + g53 + split * 2; |
1293 | | |
1294 | 0 | grad5 = Abs_int32 (g35 - g53) + |
1295 | 0 | Abs_int32 (g26 - g53) + |
1296 | 0 | Abs_int32 (g35 - g62) + |
1297 | 0 | Abs_int32 (g15 - g33) + |
1298 | 0 | Abs_int32 (g55 - g73) + |
1299 | 0 | Abs_int32 (b25 - b43) + |
1300 | 0 | Abs_int32 (b45 - b63); |
1301 | | |
1302 | 0 | est6 = g15 + g73 + split * 2; |
1303 | | |
1304 | 0 | grad6 = Abs_int32 (g15 - g73) + |
1305 | 0 | Abs_int32 (g13 - g42) + |
1306 | 0 | Abs_int32 (g26 - g55) + |
1307 | 0 | Abs_int32 (g33 - g62) + |
1308 | 0 | Abs_int32 (g46 - g75) + |
1309 | 0 | Abs_int32 (b05 - b63) + |
1310 | 0 | Abs_int32 (b25 - b83); |
1311 | | |
1312 | 0 | lower = Min_uint32 (Min_uint32 (g33, g35), |
1313 | 0 | Min_uint32 (g53, g55)); |
1314 | |
|
1315 | 0 | upper = Max_uint32 (Max_uint32 (g33, g35), |
1316 | 0 | Max_uint32 (g53, g55)); |
1317 | | |
1318 | 0 | lower = Pin_int32 (0, lower + split, 65535); |
1319 | 0 | upper = Pin_int32 (0, upper + split, 65535); |
1320 | | |
1321 | 0 | } |
1322 | | |
1323 | 0 | else // Red/blue pixel |
1324 | 0 | { |
1325 | | |
1326 | | // b00 g01 b02 g03 b04 g05 b06 g07 b08 |
1327 | | // g10 r11 g12 r13 g14 r15 g16 r17 g18 |
1328 | | // b20 g21 b22 g23 b24 g25 b26 g27 b28 |
1329 | | // g30 r31 g32 r33 g34 r35 g36 r37 g38 |
1330 | | // b40 g41 b42 g43 b44 g45 b46 g47 b48 |
1331 | | // g50 r51 g52 r53 g54 r55 g56 r57 g58 |
1332 | | // b60 g61 b62 g63 b64 g65 b66 g67 b68 |
1333 | | // g70 r71 g72 r73 g74 r75 g76 r77 g78 |
1334 | | // b80 g81 b82 g83 b84 g85 b86 g87 b88 |
1335 | | |
1336 | 0 | int32 b02 = p0 [2 * cs]; |
1337 | 0 | int32 g03 = p0 [3 * cs]; |
1338 | 0 | int32 g05 = p0 [5 * cs]; |
1339 | 0 | int32 b06 = p0 [6 * cs]; |
1340 | | |
1341 | 0 | int32 r13 = p1 [3 * cs]; |
1342 | 0 | int32 r15 = p1 [5 * cs]; |
1343 | | |
1344 | 0 | int32 b20 = p2 [0 * cs]; |
1345 | 0 | int32 b22 = p2 [2 * cs]; |
1346 | 0 | int32 g23 = p2 [3 * cs]; |
1347 | 0 | int32 g25 = p2 [5 * cs]; |
1348 | 0 | int32 b26 = p2 [6 * cs]; |
1349 | 0 | int32 b28 = p2 [8 * cs]; |
1350 | | |
1351 | 0 | int32 r31 = p3 [1 * cs]; |
1352 | 0 | int32 g32 = p3 [2 * cs]; |
1353 | 0 | int32 r33 = p3 [3 * cs]; |
1354 | 0 | int32 r35 = p3 [5 * cs]; |
1355 | 0 | int32 g36 = p3 [6 * cs]; |
1356 | 0 | int32 r37 = p3 [7 * cs]; |
1357 | | |
1358 | 0 | int32 g41 = p4 [1 * cs]; |
1359 | 0 | int32 b42 = p4 [2 * cs]; |
1360 | 0 | int32 g43 = p4 [3 * cs]; |
1361 | 0 | int32 g45 = p4 [5 * cs]; |
1362 | 0 | int32 b46 = p4 [6 * cs]; |
1363 | 0 | int32 g47 = p4 [7 * cs]; |
1364 | |
|
1365 | 0 | int32 r51 = p5 [1 * cs]; |
1366 | 0 | int32 g52 = p5 [2 * cs]; |
1367 | 0 | int32 r53 = p5 [3 * cs]; |
1368 | 0 | int32 r55 = p5 [5 * cs]; |
1369 | 0 | int32 g56 = p5 [6 * cs]; |
1370 | 0 | int32 r57 = p5 [7 * cs]; |
1371 | | |
1372 | 0 | int32 b60 = p6 [0 * cs]; |
1373 | 0 | int32 b62 = p6 [2 * cs]; |
1374 | 0 | int32 g63 = p6 [3 * cs]; |
1375 | 0 | int32 g65 = p6 [5 * cs]; |
1376 | 0 | int32 b66 = p6 [6 * cs]; |
1377 | 0 | int32 b68 = p6 [8 * cs]; |
1378 | | |
1379 | 0 | int32 r73 = p7 [3 * cs]; |
1380 | 0 | int32 r75 = p7 [5 * cs]; |
1381 | |
|
1382 | 0 | int32 b82 = p8 [2 * cs]; |
1383 | 0 | int32 g83 = p8 [3 * cs]; |
1384 | 0 | int32 g85 = p8 [5 * cs]; |
1385 | 0 | int32 b86 = p8 [6 * cs]; |
1386 | | |
1387 | 0 | est0 = b02 + b86; |
1388 | | |
1389 | 0 | grad0 = Abs_int32 (b02 - b86) + |
1390 | 0 | Abs_int32 (r13 - r55) + |
1391 | 0 | Abs_int32 (r33 - r75) + |
1392 | 0 | Abs_int32 (g03 - g45) + |
1393 | 0 | Abs_int32 (g23 - g65) + |
1394 | 0 | Abs_int32 (g43 - g85); |
1395 | |
|
1396 | 0 | est1 = b22 + b66; |
1397 | | |
1398 | 0 | grad1 = Abs_int32 (b22 - b66) + |
1399 | 0 | Abs_int32 (r13 - r35) + |
1400 | 0 | Abs_int32 (r33 - r55) + |
1401 | 0 | Abs_int32 (r53 - r75) + |
1402 | 0 | Abs_int32 (g23 - g45) + |
1403 | 0 | Abs_int32 (g43 - g65); |
1404 | | |
1405 | 0 | est2 = b20 + b68; |
1406 | | |
1407 | 0 | grad2 = Abs_int32 (b20 - b68) + |
1408 | 0 | Abs_int32 (r31 - r55) + |
1409 | 0 | Abs_int32 (r33 - r57) + |
1410 | 0 | Abs_int32 (g23 - g47) + |
1411 | 0 | Abs_int32 (g32 - g56) + |
1412 | 0 | Abs_int32 (g41 - g65); |
1413 | | |
1414 | 0 | est3 = b42 + b46; |
1415 | | |
1416 | 0 | grad3 = Abs_int32 (b42 - b46) + |
1417 | 0 | Abs_int32 (r33 - r35) + |
1418 | 0 | Abs_int32 (r53 - r55) + |
1419 | 0 | Abs_int32 (g32 - g36) + |
1420 | 0 | Abs_int32 (g43 - g43) + |
1421 | 0 | Abs_int32 (g52 - g56); |
1422 | | |
1423 | 0 | est4 = b28 + b60; |
1424 | | |
1425 | 0 | grad4 = Abs_int32 (b28 - b60) + |
1426 | 0 | Abs_int32 (r37 - r53) + |
1427 | 0 | Abs_int32 (r35 - r51) + |
1428 | 0 | Abs_int32 (g25 - g41) + |
1429 | 0 | Abs_int32 (g36 - g52) + |
1430 | 0 | Abs_int32 (g47 - g63); |
1431 | | |
1432 | 0 | est5 = b26 + b62; |
1433 | | |
1434 | 0 | grad5 = Abs_int32 (b26 - b62) + |
1435 | 0 | Abs_int32 (r15 - r33) + |
1436 | 0 | Abs_int32 (r35 - r53) + |
1437 | 0 | Abs_int32 (r55 - r73) + |
1438 | 0 | Abs_int32 (g25 - g43) + |
1439 | 0 | Abs_int32 (g45 - g63); |
1440 | | |
1441 | 0 | est6 = b06 + b82; |
1442 | | |
1443 | 0 | grad6 = Abs_int32 (b06 - b82) + |
1444 | 0 | Abs_int32 (r15 - r53) + |
1445 | 0 | Abs_int32 (r35 - r73) + |
1446 | 0 | Abs_int32 (g05 - g43) + |
1447 | 0 | Abs_int32 (g25 - g63) + |
1448 | 0 | Abs_int32 (g45 - g83); |
1449 | | |
1450 | 0 | lower = Min_uint32 (b42, b46); |
1451 | 0 | upper = Max_uint32 (b42, b46); |
1452 | | |
1453 | 0 | } |
1454 | | |
1455 | 0 | uint32 minGrad = Min_uint32 (grad0, grad1); |
1456 | | |
1457 | 0 | minGrad = Min_uint32 (minGrad, grad2); |
1458 | 0 | minGrad = Min_uint32 (minGrad, grad3); |
1459 | 0 | minGrad = Min_uint32 (minGrad, grad4); |
1460 | 0 | minGrad = Min_uint32 (minGrad, grad5); |
1461 | 0 | minGrad = Min_uint32 (minGrad, grad6); |
1462 | | |
1463 | 0 | uint32 limit = (minGrad * 3) >> 1; |
1464 | | |
1465 | 0 | uint32 total = 0; |
1466 | 0 | uint32 count = 0; |
1467 | | |
1468 | 0 | if (grad0 <= limit) |
1469 | 0 | { |
1470 | 0 | total += est0; |
1471 | 0 | count += 2; |
1472 | 0 | } |
1473 | | |
1474 | 0 | if (grad1 <= limit) |
1475 | 0 | { |
1476 | 0 | total += est1; |
1477 | 0 | count += 2; |
1478 | 0 | } |
1479 | | |
1480 | 0 | if (grad2 <= limit) |
1481 | 0 | { |
1482 | 0 | total += est2; |
1483 | 0 | count += 2; |
1484 | 0 | } |
1485 | |
|
1486 | 0 | if (grad3 <= limit) |
1487 | 0 | { |
1488 | 0 | total += est3; |
1489 | 0 | count += 2; |
1490 | 0 | } |
1491 | |
|
1492 | 0 | if (grad4 <= limit) |
1493 | 0 | { |
1494 | 0 | total += est4; |
1495 | 0 | count += 2; |
1496 | 0 | } |
1497 | |
|
1498 | 0 | if (grad5 <= limit) |
1499 | 0 | { |
1500 | 0 | total += est5; |
1501 | 0 | count += 2; |
1502 | 0 | } |
1503 | |
|
1504 | 0 | if (grad6 <= limit) |
1505 | 0 | { |
1506 | 0 | total += est6; |
1507 | 0 | count += 2; |
1508 | 0 | } |
1509 | |
|
1510 | 0 | uint32 estimate = (total + (count >> 1)) / count; |
1511 | | |
1512 | 0 | p4 [4] = (uint16) Pin_uint32 (lower, estimate, upper); |
1513 | |
|
1514 | 0 | } |
1515 | | |
1516 | 0 | } |
1517 | | |
1518 | | /*****************************************************************************/ |
1519 | | |
1520 | | void dng_opcode_FixBadPixelsList::FixSingleRow (dng_pixel_buffer &buffer, |
1521 | | const dng_rect &badRect) |
1522 | 0 | { |
1523 | | |
1524 | 0 | dng_pixel_buffer tBuffer = buffer; |
1525 | | |
1526 | 0 | tBuffer.fArea = Transpose (buffer.fArea); |
1527 | | |
1528 | 0 | tBuffer.fRowStep = buffer.fColStep; |
1529 | 0 | tBuffer.fColStep = buffer.fRowStep; |
1530 | | |
1531 | 0 | dng_rect tBadRect = Transpose (badRect); |
1532 | | |
1533 | 0 | FixSingleColumn (tBuffer, tBadRect); |
1534 | | |
1535 | 0 | } |
1536 | | |
1537 | | /*****************************************************************************/ |
1538 | | |
1539 | | void dng_opcode_FixBadPixelsList::FixClusteredRect (dng_pixel_buffer &buffer, |
1540 | | const dng_rect &badRect, |
1541 | | const dng_rect &imageBounds) |
1542 | 0 | { |
1543 | | |
1544 | 0 | const uint32 kNumSets = 8; |
1545 | 0 | const uint32 kSetSize = 8; |
1546 | | |
1547 | 0 | static const int32 kOffset [kNumSets] [kSetSize] [2] = |
1548 | 0 | { |
1549 | 0 | { |
1550 | 0 | { -1, 1 }, |
1551 | 0 | { -1, -1 }, |
1552 | 0 | { 1, -1 }, |
1553 | 0 | { 1, 1 }, |
1554 | 0 | { 0, 0 }, |
1555 | 0 | { 0, 0 }, |
1556 | 0 | { 0, 0 }, |
1557 | 0 | { 0, 0 } |
1558 | 0 | }, |
1559 | 0 | { |
1560 | 0 | { -2, 0 }, |
1561 | 0 | { 2, 0 }, |
1562 | 0 | { 0, -2 }, |
1563 | 0 | { 0, 2 }, |
1564 | 0 | { 0, 0 }, |
1565 | 0 | { 0, 0 }, |
1566 | 0 | { 0, 0 }, |
1567 | 0 | { 0, 0 } |
1568 | 0 | }, |
1569 | 0 | { |
1570 | 0 | { -2, -2 }, |
1571 | 0 | { -2, 2 }, |
1572 | 0 | { 2, -2 }, |
1573 | 0 | { 2, 2 }, |
1574 | 0 | { 0, 0 }, |
1575 | 0 | { 0, 0 }, |
1576 | 0 | { 0, 0 }, |
1577 | 0 | { 0, 0 } |
1578 | 0 | }, |
1579 | 0 | { |
1580 | 0 | { -1, -3 }, |
1581 | 0 | { -3, -1 }, |
1582 | 0 | { 1, -3 }, |
1583 | 0 | { 3, -1 }, |
1584 | 0 | { -1, 3 }, |
1585 | 0 | { -3, 1 }, |
1586 | 0 | { 1, 3 }, |
1587 | 0 | { 3, 1 } |
1588 | 0 | }, |
1589 | 0 | { |
1590 | 0 | { -4, 0 }, |
1591 | 0 | { 4, 0 }, |
1592 | 0 | { 0, -4 }, |
1593 | 0 | { 0, 4 }, |
1594 | 0 | { 0, 0 }, |
1595 | 0 | { 0, 0 }, |
1596 | 0 | { 0, 0 }, |
1597 | 0 | { 0, 0 } |
1598 | 0 | }, |
1599 | 0 | { |
1600 | 0 | { -3, -3 }, |
1601 | 0 | { -3, 3 }, |
1602 | 0 | { 3, -3 }, |
1603 | 0 | { 3, 3 }, |
1604 | 0 | { 0, 0 }, |
1605 | 0 | { 0, 0 }, |
1606 | 0 | { 0, 0 }, |
1607 | 0 | { 0, 0 } |
1608 | 0 | }, |
1609 | 0 | { |
1610 | 0 | { -2, -4 }, |
1611 | 0 | { -4, -2 }, |
1612 | 0 | { 2, -4 }, |
1613 | 0 | { 4, -2 }, |
1614 | 0 | { -2, 4 }, |
1615 | 0 | { -4, 2 }, |
1616 | 0 | { 2, 4 }, |
1617 | 0 | { 4, 2 } |
1618 | 0 | }, |
1619 | 0 | { |
1620 | 0 | { -4, -4 }, |
1621 | 0 | { -4, 4 }, |
1622 | 0 | { 4, -4 }, |
1623 | 0 | { 4, 4 }, |
1624 | 0 | { 0, 0 }, |
1625 | 0 | { 0, 0 }, |
1626 | 0 | { 0, 0 }, |
1627 | 0 | { 0, 0 } |
1628 | 0 | } |
1629 | 0 | }; |
1630 | | |
1631 | 0 | bool didFail = false; |
1632 | | |
1633 | 0 | for (int32 row = badRect.t; row < badRect.b; row++) |
1634 | 0 | { |
1635 | | |
1636 | 0 | for (int32 col = badRect.l; col < badRect.r; col++) |
1637 | 0 | { |
1638 | | |
1639 | 0 | uint16 *p = buffer.DirtyPixel_uint16 (row, col, 0); |
1640 | | |
1641 | 0 | bool isGreen = IsGreen (row, col); |
1642 | | |
1643 | 0 | bool didFixPixel = false; |
1644 | | |
1645 | 0 | for (uint32 set = 0; set < kNumSets && !didFixPixel; set++) |
1646 | 0 | { |
1647 | | |
1648 | 0 | if (!isGreen && (kOffset [set] [0] [0] & 1) == 1) |
1649 | 0 | { |
1650 | 0 | continue; |
1651 | 0 | } |
1652 | | |
1653 | 0 | uint32 total = 0; |
1654 | 0 | uint32 count = 0; |
1655 | | |
1656 | 0 | for (uint32 entry = 0; entry < kSetSize; entry++) |
1657 | 0 | { |
1658 | | |
1659 | 0 | dng_point offset (kOffset [set] [entry] [0], |
1660 | 0 | kOffset [set] [entry] [1]); |
1661 | | |
1662 | 0 | if (offset.v == 0 && |
1663 | 0 | offset.h == 0) |
1664 | 0 | { |
1665 | 0 | break; |
1666 | 0 | } |
1667 | | |
1668 | 0 | if (fList->IsPointValid (dng_point (row, col) + offset, |
1669 | 0 | imageBounds)) |
1670 | 0 | { |
1671 | | |
1672 | 0 | total += p [offset.v * buffer.fRowStep + |
1673 | 0 | offset.h * buffer.fColStep]; |
1674 | | |
1675 | 0 | count++; |
1676 | | |
1677 | 0 | } |
1678 | | |
1679 | 0 | } |
1680 | | |
1681 | 0 | if (count) |
1682 | 0 | { |
1683 | | |
1684 | 0 | uint32 estimate = (total + (count >> 1)) / count; |
1685 | | |
1686 | 0 | p [0] = (uint16) estimate; |
1687 | | |
1688 | 0 | didFixPixel = true; |
1689 | | |
1690 | 0 | } |
1691 | |
|
1692 | 0 | } |
1693 | | |
1694 | 0 | if (!didFixPixel) |
1695 | 0 | { |
1696 | | |
1697 | 0 | didFail = true; |
1698 | | |
1699 | 0 | } |
1700 | | |
1701 | 0 | } |
1702 | | |
1703 | 0 | } |
1704 | | |
1705 | | #if qDNGValidate |
1706 | | |
1707 | | if (didFail) |
1708 | | { |
1709 | | |
1710 | | ReportWarning ("Unable to repair bad rectangle"); |
1711 | | |
1712 | | } |
1713 | | |
1714 | | #endif |
1715 | | |
1716 | 0 | } |
1717 | | |
1718 | | /*****************************************************************************/ |
1719 | | |
1720 | | void dng_opcode_FixBadPixelsList::ProcessArea (dng_negative & /* negative */, |
1721 | | uint32 /* threadIndex */, |
1722 | | dng_pixel_buffer &srcBuffer, |
1723 | | dng_pixel_buffer &dstBuffer, |
1724 | | const dng_rect &dstArea, |
1725 | | const dng_rect &imageBounds) |
1726 | 0 | { |
1727 | | |
1728 | 0 | uint32 pointCount = fList->PointCount (); |
1729 | 0 | uint32 rectCount = fList->RectCount (); |
1730 | | |
1731 | 0 | dng_rect fixArea = dstArea; |
1732 | | |
1733 | 0 | if (rectCount) |
1734 | 0 | { |
1735 | 0 | fixArea.t -= kBadRectPadding; |
1736 | 0 | fixArea.l -= kBadRectPadding; |
1737 | 0 | fixArea.b += kBadRectPadding; |
1738 | 0 | fixArea.r += kBadRectPadding; |
1739 | 0 | } |
1740 | | |
1741 | 0 | bool didFixPoint = false; |
1742 | | |
1743 | 0 | if (pointCount) |
1744 | 0 | { |
1745 | | |
1746 | 0 | for (uint32 pointIndex = 0; pointIndex < pointCount; pointIndex++) |
1747 | 0 | { |
1748 | | |
1749 | 0 | dng_point badPoint = fList->Point (pointIndex); |
1750 | | |
1751 | 0 | if (badPoint.v >= fixArea.t && |
1752 | 0 | badPoint.h >= fixArea.l && |
1753 | 0 | badPoint.v < fixArea.b && |
1754 | 0 | badPoint.h < fixArea.r) |
1755 | 0 | { |
1756 | | |
1757 | 0 | bool isIsolated = fList->IsPointIsolated (pointIndex, |
1758 | 0 | kBadPointPadding); |
1759 | | |
1760 | 0 | if (isIsolated && |
1761 | 0 | badPoint.v >= imageBounds.t + kBadPointPadding && |
1762 | 0 | badPoint.h >= imageBounds.l + kBadPointPadding && |
1763 | 0 | badPoint.v < imageBounds.b - kBadPointPadding && |
1764 | 0 | badPoint.h < imageBounds.r - kBadPointPadding) |
1765 | 0 | { |
1766 | | |
1767 | 0 | FixIsolatedPixel (srcBuffer, |
1768 | 0 | badPoint); |
1769 | | |
1770 | 0 | } |
1771 | | |
1772 | 0 | else |
1773 | 0 | { |
1774 | | |
1775 | 0 | FixClusteredPixel (srcBuffer, |
1776 | 0 | pointIndex, |
1777 | 0 | imageBounds); |
1778 | | |
1779 | 0 | } |
1780 | | |
1781 | 0 | didFixPoint = true; |
1782 | | |
1783 | 0 | } |
1784 | | |
1785 | 0 | } |
1786 | |
|
1787 | 0 | } |
1788 | | |
1789 | 0 | if (rectCount) |
1790 | 0 | { |
1791 | | |
1792 | 0 | if (didFixPoint) |
1793 | 0 | { |
1794 | | |
1795 | 0 | srcBuffer.RepeatSubArea (imageBounds, |
1796 | 0 | SrcRepeat ().v, |
1797 | 0 | SrcRepeat ().h); |
1798 | | |
1799 | 0 | } |
1800 | | |
1801 | 0 | for (uint32 rectIndex = 0; rectIndex < rectCount; rectIndex++) |
1802 | 0 | { |
1803 | | |
1804 | 0 | dng_rect badRect = fList->Rect (rectIndex); |
1805 | | |
1806 | 0 | dng_rect overlap = dstArea & badRect; |
1807 | |
|
1808 | 0 | if (overlap.NotEmpty ()) |
1809 | 0 | { |
1810 | | |
1811 | 0 | bool isIsolated = fList->IsRectIsolated (rectIndex, |
1812 | 0 | kBadRectPadding); |
1813 | | |
1814 | 0 | if (isIsolated && |
1815 | 0 | badRect.r == badRect.l + 1 && |
1816 | 0 | badRect.l >= imageBounds.l + SrcRepeat ().h && |
1817 | 0 | badRect.r <= imageBounds.r - SrcRepeat ().v) |
1818 | 0 | { |
1819 | | |
1820 | 0 | FixSingleColumn (srcBuffer, |
1821 | 0 | overlap); |
1822 | | |
1823 | 0 | } |
1824 | | |
1825 | 0 | else if (isIsolated && |
1826 | 0 | badRect.b == badRect.t + 1 && |
1827 | 0 | badRect.t >= imageBounds.t + SrcRepeat ().h && |
1828 | 0 | badRect.b <= imageBounds.b - SrcRepeat ().v) |
1829 | 0 | { |
1830 | | |
1831 | 0 | FixSingleRow (srcBuffer, |
1832 | 0 | overlap); |
1833 | | |
1834 | 0 | } |
1835 | | |
1836 | 0 | else |
1837 | 0 | { |
1838 | | |
1839 | 0 | FixClusteredRect (srcBuffer, |
1840 | 0 | overlap, |
1841 | 0 | imageBounds); |
1842 | | |
1843 | 0 | } |
1844 | | |
1845 | 0 | } |
1846 | | |
1847 | 0 | } |
1848 | | |
1849 | 0 | } |
1850 | | |
1851 | 0 | dstBuffer.CopyArea (srcBuffer, |
1852 | 0 | dstArea, |
1853 | 0 | 0, |
1854 | 0 | dstBuffer.fPlanes); |
1855 | | |
1856 | 0 | } |
1857 | | |
1858 | | /*****************************************************************************/ |