Coverage Report

Created: 2021-08-22 09:07

/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
/*****************************************************************************/