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