Coverage Report

Created: 2025-07-12 06:56

/src/dng_sdk/source/dng_mosaic_info.cpp
Line
Count
Source (jump to first uncovered line)
1
/*****************************************************************************/
2
// Copyright 2006-2009 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_mosaic_info.cpp#1 $ */ 
10
/* $DateTime: 2012/05/30 13:28:51 $ */
11
/* $Change: 832332 $ */
12
/* $Author: tknoll $ */
13
14
/*****************************************************************************/
15
16
#include "dng_mosaic_info.h"
17
18
#include "dng_area_task.h"
19
#include "dng_assertions.h"
20
#include "dng_bottlenecks.h"
21
#include "dng_exceptions.h"
22
#include "dng_filter_task.h"
23
#include "dng_host.h"
24
#include "dng_ifd.h"
25
#include "dng_image.h"
26
#include "dng_info.h"
27
#include "dng_negative.h"
28
#include "dng_pixel_buffer.h"
29
#include "dng_tag_types.h"
30
#include "dng_tag_values.h"
31
#include "dng_tile_iterator.h"
32
#include "dng_utils.h"
33
34
/*****************************************************************************/
35
36
// A interpolation kernel for a single pixel of a single plane.
37
38
class dng_bilinear_kernel
39
  {
40
  
41
  public:
42
  
43
    enum
44
      {
45
      kMaxCount = 8
46
      };
47
  
48
    uint32 fCount;
49
  
50
    dng_point fDelta [kMaxCount];
51
    
52
    real32 fWeight32 [kMaxCount];
53
    uint16 fWeight16 [kMaxCount];
54
    
55
    int32 fOffset [kMaxCount];
56
    
57
  public:
58
  
59
    dng_bilinear_kernel ()
60
132k
      : fCount (0)
61
132k
      {
62
132k
      }
63
    
64
    void Add (const dng_point &delta,
65
          real32 weight);
66
    
67
    void Finalize (const dng_point &scale,
68
             uint32 patRow,
69
             uint32 patCol,
70
             int32 rowStep,
71
             int32 colStep);
72
          
73
  };
74
    
75
/*****************************************************************************/
76
77
void dng_bilinear_kernel::Add (const dng_point &delta,
78
                   real32 weight)
79
4.10k
  {
80
  
81
  // Don't add zero weight elements.
82
  
83
4.10k
  if (weight <= 0.0f)
84
822
    {
85
822
    return;
86
822
    }
87
    
88
  // If the delta already matches an existing element, just combine the
89
  // weights.
90
  
91
5.99k
  for (uint32 j = 0; j < fCount; j++)
92
3.28k
    {
93
    
94
3.28k
    if (fDelta [j] == delta)
95
570
      {
96
      
97
570
      fWeight32 [j] += weight;
98
      
99
570
      return;
100
      
101
570
      }
102
      
103
3.28k
    }
104
    
105
  // Add element to list.
106
    
107
2.71k
  DNG_ASSERT (fCount < kMaxCount, "Too many kernel entries");
108
  
109
2.71k
  fDelta    [fCount] = delta;
110
2.71k
  fWeight32 [fCount] = weight;
111
  
112
2.71k
  fCount++;
113
114
2.71k
  }
115
          
116
/*****************************************************************************/
117
118
void dng_bilinear_kernel::Finalize (const dng_point &scale,
119
                  uint32 patRow,
120
                    uint32 patCol,
121
                    int32 rowStep,
122
                    int32 colStep)
123
1.33k
  {
124
  
125
1.33k
  uint32 j;
126
  
127
  // Adjust deltas to compensate for interpolation upscaling.
128
  
129
4.04k
  for (j = 0; j < fCount; j++)
130
2.71k
    {
131
    
132
2.71k
    dng_point &delta = fDelta [j];
133
    
134
2.71k
    if (scale.v == 2)
135
372
      {
136
137
372
      delta.v = (delta.v + (int32) (patRow & 1)) >> 1;
138
139
372
      }
140
      
141
2.71k
    if (scale.h == 2)
142
230
      {
143
      
144
230
      delta.h = (delta.h + (int32) (patCol & 1)) >> 1;
145
      
146
230
      }
147
      
148
2.71k
    }
149
    
150
  // Sort entries into row-column scan order.
151
  
152
1.43k
  while (true)
153
1.43k
    {
154
    
155
1.43k
    bool didSwap = false;
156
    
157
3.14k
    for (j = 1; j < fCount; j++)
158
1.71k
      {
159
      
160
1.71k
      dng_point &delta0 = fDelta [j - 1];
161
1.71k
      dng_point &delta1 = fDelta [j    ];
162
      
163
1.71k
      if (delta0.v > delta1.v ||
164
1.71k
          (delta0.v == delta1.v &&
165
1.64k
           delta0.h >  delta1.h))
166
99
        {
167
        
168
99
        didSwap = true;
169
170
99
        dng_point tempDelta = delta0;
171
        
172
99
        delta0 = delta1;
173
99
        delta1 = tempDelta;
174
        
175
99
        real32 tempWeight = fWeight32 [j - 1];
176
        
177
99
        fWeight32 [j - 1] = fWeight32 [j];
178
99
        fWeight32 [j    ] = tempWeight;
179
        
180
99
        }
181
      
182
1.71k
      }
183
      
184
1.43k
    if (!didSwap)
185
1.33k
      {
186
1.33k
      break;
187
1.33k
      }
188
    
189
1.43k
    }
190
  
191
  // Calculate offsets.
192
  
193
4.04k
  for (j = 0; j < fCount; j++)
194
2.71k
    {
195
  
196
2.71k
    fOffset [j] = rowStep * fDelta [j].v +
197
2.71k
            colStep * fDelta [j].h;
198
    
199
2.71k
    }
200
    
201
  // Calculate 16-bit weights.
202
  
203
1.33k
  uint16 total   = 0;
204
1.33k
  uint32 biggest = 0;
205
  
206
4.04k
  for (j = 0; j < fCount; j++)
207
2.71k
    {
208
    
209
    // Round weights to 8 fractional bits.
210
    
211
2.71k
    fWeight16 [j] = (uint16) Round_uint32 (fWeight32 [j] * 256.0);
212
    
213
    // Keep track of total of weights.
214
    
215
2.71k
    total += fWeight16 [j];
216
    
217
    // Keep track of which weight is biggest.
218
    
219
2.71k
    if (fWeight16 [biggest] < fWeight16 [j])
220
134
      {
221
      
222
134
      biggest = j;
223
      
224
134
      }
225
    
226
2.71k
    }
227
    
228
  // Adjust largest entry so total of weights is exactly 256.
229
    
230
1.33k
  fWeight16 [biggest] += (256 - total);
231
  
232
  // Recompute the floating point weights from the rounded integer weights
233
  // so results match more closely.
234
  
235
4.04k
  for (j = 0; j < fCount; j++)
236
2.71k
    {
237
    
238
2.71k
    fWeight32 [j] = fWeight16 [j] * (1.0f / 256.0f);
239
    
240
2.71k
    }
241
  
242
1.33k
  }
243
          
244
/*****************************************************************************/
245
246
class dng_bilinear_pattern
247
  {
248
  
249
  public:
250
  
251
    enum
252
      {
253
      kMaxPattern = kMaxCFAPattern * 2
254
      };
255
      
256
    dng_point fScale;
257
  
258
    uint32 fPatRows;
259
    uint32 fPatCols;
260
  
261
    dng_bilinear_kernel fKernel [kMaxPattern]
262
                        [kMaxPattern];
263
                        
264
    uint32 fCounts [kMaxPattern]
265
             [kMaxPattern];
266
             
267
    int32 *fOffsets [kMaxPattern]
268
            [kMaxPattern];
269
            
270
    uint16 *fWeights16 [kMaxPattern]
271
               [kMaxPattern];
272
               
273
    real32 *fWeights32 [kMaxPattern]
274
               [kMaxPattern];
275
               
276
  public:
277
    
278
    dng_bilinear_pattern ()
279
      
280
516
      : fScale ()
281
516
      , fPatRows (0)
282
516
      , fPatCols (0)
283
      
284
516
      {
285
516
      }
286
    
287
  private:
288
  
289
#if defined(__clang__) && defined(__has_attribute)
290
#if __has_attribute(no_sanitize)
291
__attribute__((no_sanitize("unsigned-integer-overflow")))
292
#endif
293
#endif
294
    uint32 DeltaRow (uint32 row, int32 delta)
295
5.80k
      {
296
      // Potential overflow in the conversion from delta to a uint32 as
297
      // well as in the subsequent addition is intentional.
298
5.80k
      return (SafeUint32Add(row, fPatRows) + (uint32) delta) % fPatRows;
299
5.80k
      }
300
      
301
#if defined(__clang__) && defined(__has_attribute)
302
#if __has_attribute(no_sanitize)
303
__attribute__((no_sanitize("unsigned-integer-overflow")))
304
#endif
305
#endif
306
    uint32 DeltaCol (uint32 col, int32 delta)
307
5.71k
      {
308
      // Potential overflow in the conversion from delta to a uint32 as
309
      // well as in the subsequent addition is intentional.
310
5.71k
      return (SafeUint32Add(col, fPatCols) + (uint32) delta) % fPatCols;
311
5.71k
      }
312
  
313
    real32 LinearWeight1 (int32 d1, int32 d2)
314
1.59k
      {
315
1.59k
      if (d1 == d2)
316
603
        return 1.0f;
317
987
      else
318
987
        return d2 / (real32) (d2 - d1);
319
1.59k
      }
320
  
321
    real32 LinearWeight2 (int32 d1, int32 d2)
322
1.59k
      {
323
1.59k
      if (d1 == d2)
324
603
        return 0.0f;
325
987
      else
326
987
        return -d1 / (real32) (d2 - d1);
327
1.59k
      }
328
      
329
  public:
330
  
331
    void Calculate (const dng_mosaic_info &info,
332
            uint32 dstPlane,
333
            int32 rowStep,
334
            int32 colStep);
335
  
336
  };
337
338
/*****************************************************************************/
339
340
void dng_bilinear_pattern::Calculate (const dng_mosaic_info &info,
341
                      uint32 dstPlane,
342
                      int32 rowStep,
343
                      int32 colStep)
344
303
  {
345
  
346
303
  uint32 j;
347
303
  uint32 k;
348
303
  uint32 patRow;
349
303
  uint32 patCol;
350
  
351
  // Find destination pattern size.
352
  
353
303
  fScale = info.FullScale ();
354
  
355
303
  fPatRows = info.fCFAPatternSize.v * fScale.v;
356
303
  fPatCols = info.fCFAPatternSize.h * fScale.h;
357
  
358
  // See if we need to scale up just while computing the kernels.
359
  
360
303
  dng_point tempScale (1, 1);
361
  
362
303
  if (info.fCFALayout >= 6)
363
23
    {
364
    
365
23
    tempScale = dng_point (2, 2);
366
    
367
23
    fPatRows *= tempScale.v;
368
23
    fPatCols *= tempScale.h;
369
370
23
    }
371
    
372
  // Find a boolean map for this plane color and layout.
373
  
374
303
  bool map [kMaxPattern]
375
303
       [kMaxPattern];
376
        
377
303
  uint8 planeColor = info.fCFAPlaneColor [dstPlane];
378
  
379
303
  switch (info.fCFALayout)
380
303
    {
381
    
382
247
    case 1:   // Rectangular (or square) layout
383
247
      {
384
      
385
845
      for (j = 0; j < fPatRows; j++)
386
598
        {
387
        
388
1.58k
        for (k = 0; k < fPatCols; k++)
389
988
          {
390
          
391
988
          map [j] [k] = (info.fCFAPattern [j] [k] == planeColor);
392
          
393
988
          }
394
          
395
598
        }
396
      
397
247
      break;
398
      
399
0
      }
400
      
401
    // Note that when the descriptions of the staggered patterns refer to even rows or
402
    // columns, this mean the second, fourth, etc. (i.e. using one-based numbering).
403
    // This needs to be clarified in the DNG specification.
404
      
405
13
    case 2:   // Staggered layout A: even (1-based) columns are offset down by 1/2 row
406
13
      {
407
      
408
69
      for (j = 0; j < fPatRows; j++)
409
56
        {
410
        
411
160
        for (k = 0; k < fPatCols; k++)
412
104
          {
413
          
414
104
          if ((j & 1) != (k & 1))
415
52
            {
416
            
417
52
            map [j] [k] = false;
418
            
419
52
            }
420
            
421
52
          else
422
52
            {
423
            
424
52
            map [j] [k] = (info.fCFAPattern [j >> 1] [k] == planeColor);
425
            
426
52
            }
427
            
428
104
          }
429
          
430
56
        }
431
        
432
13
      break;
433
      
434
0
      }
435
          
436
6
    case 3:   // Staggered layout B: even (1-based) columns are offset up by 1/2 row
437
6
      {
438
      
439
34
      for (j = 0; j < fPatRows; j++)
440
28
        {
441
        
442
76
        for (k = 0; k < fPatCols; k++)
443
48
          {
444
          
445
48
          if ((j & 1) == (k & 1))
446
24
            {
447
            
448
24
            map [j] [k] = false;
449
            
450
24
            }
451
            
452
24
          else
453
24
            {
454
            
455
24
            map [j] [k] = (info.fCFAPattern [j >> 1] [k] == planeColor);
456
            
457
24
            }
458
            
459
48
          }
460
          
461
28
        }
462
        
463
6
      break;
464
      
465
0
      }
466
          
467
6
    case 4:   // Staggered layout C: even (1-based) rows are offset right by 1/2 column
468
6
      {
469
      
470
16
      for (j = 0; j < fPatRows; j++)
471
10
        {
472
        
473
58
        for (k = 0; k < fPatCols; k++)
474
48
          {
475
          
476
48
          if ((j & 1) != (k & 1))
477
24
            {
478
            
479
24
            map [j] [k] = false;
480
            
481
24
            }
482
            
483
24
          else
484
24
            {
485
            
486
24
            map [j] [k] = (info.fCFAPattern [j] [k >> 1] == planeColor);
487
            
488
24
            }
489
            
490
48
          }
491
          
492
10
        }
493
        
494
6
      break;
495
      
496
0
      }
497
          
498
8
    case 5:   // Staggered layout D: even (1-based) rows are offset left by 1/2 column
499
8
      {
500
      
501
26
      for (j = 0; j < fPatRows; j++)
502
18
        {
503
        
504
74
        for (k = 0; k < fPatCols; k++)
505
56
          {
506
          
507
56
          if ((j & 1) == (k & 1))
508
28
            {
509
            
510
28
            map [j] [k] = false;
511
            
512
28
            }
513
            
514
28
          else
515
28
            {
516
            
517
28
            map [j] [k] = (info.fCFAPattern [j] [k >> 1] == planeColor);
518
            
519
28
            }
520
            
521
56
          }
522
          
523
18
        }
524
        
525
8
      break;
526
      
527
0
      }
528
      
529
0
    case 6:   // Staggered layout E: even rows are offset up by 1/2 row, even columns are offset left by 1/2 column
530
16
    case 7:   // Staggered layout F: even rows are offset up by 1/2 row, even columns are offset right by 1/2 column
531
21
    case 8:   // Staggered layout G: even rows are offset down by 1/2 row, even columns are offset left by 1/2 column
532
23
    case 9:   // Staggered layout H: even rows are offset down by 1/2 row, even columns are offset right by 1/2 column
533
23
      {
534
      
535
23
      uint32 eRow = (info.fCFALayout == 6 ||
536
23
               info.fCFALayout == 7) ? 1 : 3;
537
               
538
23
      uint32 eCol = (info.fCFALayout == 6 ||
539
23
               info.fCFALayout == 8) ? 1 : 3;
540
      
541
123
      for (j = 0; j < fPatRows; j++)
542
100
        {
543
        
544
452
        for (k = 0; k < fPatCols; k++)
545
352
          {
546
          
547
352
          uint32 jj = j & 3;
548
352
          uint32 kk = k & 3;
549
          
550
352
          if ((jj != 0 && jj != eRow) ||
551
352
            (kk != 0 && kk != eCol))
552
244
            {
553
            
554
244
            map [j] [k] = false;
555
            
556
244
            }
557
            
558
108
          else
559
108
            {
560
            
561
108
            map [j] [k] = (info.fCFAPattern [((j >> 1) & ~1) + Min_uint32 (jj, 1)]
562
108
                            [((k >> 1) & ~1) + Min_uint32 (kk, 1)] == planeColor);
563
            
564
108
            }
565
            
566
352
          }
567
          
568
100
        }
569
      
570
23
      break;
571
      
572
21
      }
573
          
574
0
    default:
575
0
      ThrowProgramError ();
576
    
577
303
    }
578
    
579
  // Find projections of maps.
580
  
581
303
  bool mapH [kMaxPattern];
582
303
  bool mapV [kMaxPattern];
583
  
584
5.15k
  for (j = 0; j < kMaxPattern; j++)
585
4.84k
    {
586
    
587
4.84k
    mapH [j] = false;
588
4.84k
    mapV [j] = false;
589
    
590
4.84k
    }
591
    
592
1.11k
  for (j = 0; j < fPatRows; j++)
593
810
    {
594
    
595
2.40k
    for (k = 0; k < fPatCols; k++)
596
1.59k
      {
597
      
598
1.59k
      if (map [j] [k])
599
519
        {
600
        
601
519
        mapV [j] = true;
602
519
        mapH [k] = true;
603
        
604
519
        }
605
        
606
1.59k
      }
607
      
608
810
    }
609
  
610
  // Find kernel for each patten entry.
611
  
612
1.06k
  for (patRow = 0; patRow < fPatRows; patRow += tempScale.v)
613
760
    {
614
    
615
2.09k
    for (patCol = 0; patCol < fPatCols; patCol += tempScale.h)
616
1.33k
      {
617
      
618
1.33k
      dng_bilinear_kernel &kernel = fKernel [patRow] [patCol];
619
      
620
      // Special case no interpolation case.
621
      
622
1.33k
      if (map [patRow] [patCol])
623
489
        {
624
        
625
489
        kernel.Add (dng_point (0, 0), 1.0f);
626
        
627
489
        continue;
628
        
629
489
        }
630
        
631
      // Special case common patterns in 3 by 3 neighborhood.
632
      
633
843
      uint32 n = DeltaRow (patRow, -1);
634
843
      uint32 s = DeltaRow (patRow,  1);
635
843
      uint32 w = DeltaCol (patCol, -1);
636
843
      uint32 e = DeltaCol (patCol,  1);
637
      
638
843
      bool mapNW = map [n] [w];
639
843
      bool mapN  = map [n] [patCol];
640
843
      bool mapNE = map [n] [e];
641
      
642
843
      bool mapW = map [patRow] [w];
643
843
      bool mapE = map [patRow] [e];
644
      
645
843
      bool mapSW = map [s] [w];
646
843
      bool mapS  = map [s] [patCol];
647
843
      bool mapSE = map [s] [e];
648
      
649
      // All sides.
650
      
651
843
      if (mapN && mapS && mapW && mapW)
652
71
        {
653
        
654
71
        kernel.Add (dng_point (-1,  0), 0.25f);
655
71
        kernel.Add (dng_point ( 0, -1), 0.25f);
656
71
        kernel.Add (dng_point ( 0,  1), 0.25f);
657
71
        kernel.Add (dng_point ( 1,  0), 0.25f);
658
        
659
71
        continue;
660
        
661
71
        }
662
      
663
      // N & S.
664
      
665
772
      if (mapN && mapS)
666
241
        {
667
        
668
241
        kernel.Add (dng_point (-1,  0), 0.5f);
669
241
        kernel.Add (dng_point ( 1,  0), 0.5f);
670
        
671
241
        continue;
672
        
673
241
        }
674
      
675
      // E & W.
676
      
677
531
      if (mapW && mapE)
678
165
        {
679
        
680
165
        kernel.Add (dng_point ( 0, -1), 0.5f);
681
165
        kernel.Add (dng_point ( 0,  1), 0.5f);
682
        
683
165
        continue;
684
        
685
165
        }
686
        
687
      // N & SW & SE.
688
      
689
366
      if (mapN && mapSW && mapSE)
690
0
        {
691
        
692
0
        kernel.Add (dng_point (-1,  0), 0.50f);
693
0
        kernel.Add (dng_point ( 1, -1), 0.25f);
694
0
        kernel.Add (dng_point ( 1,  1), 0.25f);
695
        
696
0
        continue;
697
        
698
0
        }
699
      
700
      // S & NW & NE.
701
      
702
366
      if (mapS && mapNW && mapNE)
703
0
        {
704
        
705
0
        kernel.Add (dng_point (-1, -1), 0.25f);
706
0
        kernel.Add (dng_point (-1,  1), 0.25f);
707
0
        kernel.Add (dng_point ( 1,  0), 0.50f);
708
        
709
0
        continue;
710
        
711
0
        }
712
      
713
      // W & NE & SE.
714
      
715
366
      if (mapW && mapNE && mapSE)
716
0
        {
717
        
718
0
        kernel.Add (dng_point (-1,  1), 0.25f);
719
0
        kernel.Add (dng_point ( 0, -1), 0.50f);
720
0
        kernel.Add (dng_point ( 1,  1), 0.25f);
721
        
722
0
        continue;
723
        
724
0
        }
725
      
726
      // E & NW & SW.
727
      
728
366
      if (mapE && mapNW && mapSW)
729
0
        {
730
        
731
0
        kernel.Add (dng_point (-1, -1), 0.25f);
732
0
        kernel.Add (dng_point ( 0,  1), 0.50f);
733
0
        kernel.Add (dng_point ( 1, -1), 0.25f);
734
        
735
0
        continue;
736
        
737
0
        }
738
        
739
      // Four corners.
740
      
741
366
      if (mapNW && mapNE && mapSE && mapSW)
742
101
        {
743
        
744
101
        kernel.Add (dng_point (-1, -1), 0.25f);
745
101
        kernel.Add (dng_point (-1,  1), 0.25f);
746
101
        kernel.Add (dng_point ( 1, -1), 0.25f);
747
101
        kernel.Add (dng_point ( 1,  1), 0.25f);
748
        
749
101
        continue;
750
        
751
101
        }
752
      
753
      // NW & SE
754
      
755
265
      if (mapNW && mapSE)
756
0
        {
757
        
758
0
        kernel.Add (dng_point (-1, -1), 0.50f);
759
0
        kernel.Add (dng_point ( 1,  1), 0.50f);
760
        
761
0
        continue;
762
        
763
0
        }
764
        
765
      // NE & SW
766
      
767
265
      if (mapNE && mapSW)
768
0
        {
769
        
770
0
        kernel.Add (dng_point (-1,  1), 0.50f);
771
0
        kernel.Add (dng_point ( 1, -1), 0.50f);
772
        
773
0
        continue;
774
        
775
0
        }
776
        
777
      // Else use double-bilinear kernel.
778
      
779
265
      int32 dv1 = 0;
780
265
      int32 dv2 = 0;
781
      
782
573
      while (!mapV [DeltaRow (patRow, dv1)])
783
308
        {
784
308
        dv1--;
785
308
        }
786
        
787
576
      while (!mapV [DeltaRow (patRow, dv2)])
788
311
        {
789
311
        dv2++;
790
311
        }
791
        
792
265
      real32 w1 = LinearWeight1 (dv1, dv2) * 0.5f;
793
265
      real32 w2 = LinearWeight2 (dv1, dv2) * 0.5f;
794
        
795
265
      int32 v1 = DeltaRow (patRow, dv1);
796
265
      int32 v2 = DeltaRow (patRow, dv2);
797
        
798
265
      int32 dh1 = 0;
799
265
      int32 dh2 = 0;
800
      
801
594
      while (!map [v1] [DeltaCol (patCol, dh1)])
802
329
        {
803
329
        dh1--;
804
329
        }
805
        
806
596
      while (!map [v1] [DeltaCol (patCol, dh2)])
807
331
        {
808
331
        dh2++;
809
331
        }
810
        
811
265
      kernel.Add (dng_point (dv1, dh1),
812
265
            LinearWeight1 (dh1, dh2) * w1);
813
            
814
265
      kernel.Add (dng_point (dv1, dh2),
815
265
            LinearWeight2 (dh1, dh2) * w1);
816
      
817
265
      dh1 = 0;
818
265
      dh2 = 0;
819
      
820
590
      while (!map [v2] [DeltaCol (patCol, dh1)])
821
325
        {
822
325
        dh1--;
823
325
        }
824
        
825
590
      while (!map [v2] [DeltaCol (patCol, dh2)])
826
325
        {
827
325
        dh2++;
828
325
        }
829
        
830
265
      kernel.Add (dng_point (dv2, dh1),
831
265
            LinearWeight1 (dh1, dh2) * w2);
832
            
833
265
      kernel.Add (dng_point (dv2, dh2),
834
265
            LinearWeight2 (dh1, dh2) * w2);
835
            
836
265
      dh1 = 0;
837
265
      dh2 = 0;
838
      
839
565
      while (!mapH [DeltaCol (patCol, dh1)])
840
300
        {
841
300
        dh1--;
842
300
        }
843
        
844
560
      while (!mapH [DeltaCol (patCol, dh2)])
845
295
        {
846
295
        dh2++;
847
295
        }
848
        
849
265
      w1 = LinearWeight1 (dh1, dh2) * 0.5f;
850
265
      w2 = LinearWeight2 (dh1, dh2) * 0.5f;
851
        
852
265
      int32 h1 = DeltaCol (patCol, dh1);
853
265
      int32 h2 = DeltaCol (patCol, dh2);
854
        
855
265
      dv1 = 0;
856
265
      dv2 = 0;
857
      
858
612
      while (!map [DeltaRow (patRow, dv1)] [h1])
859
347
        {
860
347
        dv1--;
861
347
        }
862
        
863
608
      while (!map [DeltaRow (patRow, dv2)] [h1])
864
343
        {
865
343
        dv2++;
866
343
        }
867
        
868
265
      kernel.Add (dng_point (dv1, dh1),
869
265
            LinearWeight1 (dv1, dv2) * w1);
870
            
871
265
      kernel.Add (dng_point (dv2, dh1),
872
265
            LinearWeight2 (dv1, dv2) * w1);
873
        
874
265
      dv1 = 0;
875
265
      dv2 = 0;
876
      
877
611
      while (!map [DeltaRow (patRow, dv1)] [h2])
878
346
        {
879
346
        dv1--;
880
346
        }
881
        
882
605
      while (!map [DeltaRow (patRow, dv2)] [h2])
883
340
        {
884
340
        dv2++;
885
340
        }
886
        
887
265
      kernel.Add (dng_point (dv1, dh2),
888
265
            LinearWeight1 (dv1, dv2) * w2);
889
            
890
265
      kernel.Add (dng_point (dv2, dh2),
891
265
            LinearWeight2 (dv1, dv2) * w2);
892
            
893
265
      }
894
      
895
760
    }
896
    
897
  // Deal with temp scale case.
898
  
899
303
  if (tempScale == dng_point (2, 2))
900
23
    {
901
    
902
23
    fPatRows /= tempScale.v;
903
23
    fPatCols /= tempScale.h;
904
    
905
73
    for (patRow = 0; patRow < fPatRows; patRow++)
906
50
      {
907
      
908
138
      for (patCol = 0; patCol < fPatCols; patCol++)
909
88
        {
910
        
911
88
        int32 patRow2 = patRow << 1;
912
88
        int32 patCol2 = patCol << 1;
913
        
914
88
        dng_bilinear_kernel &kernel = fKernel [patRow2] [patCol2];
915
        
916
343
        for (j = 0; j < kernel.fCount; j++)
917
255
          {
918
          
919
255
          int32 x = patRow2 + kernel.fDelta [j].v;
920
          
921
255
          if ((x & 3) != 0)
922
136
            {
923
136
            x = (x & ~3) + 2;
924
136
            }
925
            
926
255
          kernel.fDelta [j].v = ((x - patRow2) >> 1);
927
          
928
255
          x = patCol2 + kernel.fDelta [j].h;
929
          
930
255
          if ((x & 3) != 0)
931
122
            {
932
122
            x = (x & ~3) + 2;
933
122
            }
934
            
935
255
          kernel.fDelta [j].h = ((x - patCol2) >> 1);
936
          
937
255
          }
938
939
88
        kernel.Finalize (fScale,
940
88
                 patRow,
941
88
                 patCol,
942
88
                 rowStep,
943
88
                 colStep);
944
                     
945
88
        fCounts    [patRow] [patCol] = kernel.fCount;
946
88
        fOffsets   [patRow] [patCol] = kernel.fOffset;
947
88
        fWeights16 [patRow] [patCol] = kernel.fWeight16;
948
88
        fWeights32 [patRow] [patCol] = kernel.fWeight32;
949
      
950
88
        }
951
        
952
50
      }
953
      
954
23
    }
955
    
956
  // Non-temp scale case.
957
  
958
280
  else
959
280
    {
960
    
961
990
    for (patRow = 0; patRow < fPatRows; patRow++)
962
710
      {
963
      
964
1.95k
      for (patCol = 0; patCol < fPatCols; patCol++)
965
1.24k
        {
966
        
967
1.24k
        dng_bilinear_kernel &kernel = fKernel [patRow] [patCol];
968
        
969
1.24k
        kernel.Finalize (fScale,
970
1.24k
                 patRow,
971
1.24k
                 patCol,
972
1.24k
                 rowStep,
973
1.24k
                 colStep);
974
                     
975
1.24k
        fCounts    [patRow] [patCol] = kernel.fCount;
976
1.24k
        fOffsets   [patRow] [patCol] = kernel.fOffset;
977
1.24k
        fWeights16 [patRow] [patCol] = kernel.fWeight16;
978
1.24k
        fWeights32 [patRow] [patCol] = kernel.fWeight32;
979
        
980
1.24k
        }
981
        
982
710
      }
983
      
984
280
    }
985
    
986
303
  }
987
  
988
/*****************************************************************************/
989
990
class dng_bilinear_interpolator
991
  {
992
  
993
  private:
994
  
995
    dng_bilinear_pattern fPattern [kMaxColorPlanes];
996
    
997
  public:
998
  
999
    dng_bilinear_interpolator (const dng_mosaic_info &info,
1000
                   int32 rowStep,
1001
                   int32 colStep);
1002
    
1003
    void Interpolate (dng_pixel_buffer &srcBuffer,
1004
              dng_pixel_buffer &dstBuffer);
1005
  
1006
  };
1007
1008
/*****************************************************************************/
1009
1010
dng_bilinear_interpolator::dng_bilinear_interpolator (const dng_mosaic_info &info,
1011
                            int32 rowStep,
1012
                            int32 colStep)
1013
129
  {
1014
  
1015
432
  for (uint32 dstPlane = 0; dstPlane < info.fColorPlanes; dstPlane++)
1016
303
    {
1017
    
1018
303
    fPattern [dstPlane] . Calculate (info, 
1019
303
                     dstPlane,
1020
303
                     rowStep,
1021
303
                     colStep);
1022
        
1023
303
    }
1024
  
1025
129
  }
1026
1027
/*****************************************************************************/
1028
1029
void dng_bilinear_interpolator::Interpolate (dng_pixel_buffer &srcBuffer,
1030
                         dng_pixel_buffer &dstBuffer)
1031
7.10k
  {
1032
  
1033
7.10k
  uint32 patCols = fPattern [0] . fPatCols;
1034
7.10k
  uint32 patRows = fPattern [0] . fPatRows;
1035
  
1036
7.10k
  dng_point scale = fPattern [0] . fScale;
1037
  
1038
7.10k
  uint32 sRowShift = scale.v - 1;
1039
7.10k
  uint32 sColShift = scale.h - 1;
1040
  
1041
7.10k
  int32 dstCol = dstBuffer.fArea.l;
1042
  
1043
7.10k
  int32 srcCol = dstCol >> sColShift;
1044
  
1045
7.10k
  uint32 patPhase = dstCol % patCols;
1046
  
1047
7.10k
  for (int32 dstRow = dstBuffer.fArea.t; 
1048
226k
     dstRow < dstBuffer.fArea.b;
1049
219k
     dstRow++)
1050
219k
    {
1051
    
1052
219k
    int32 srcRow = dstRow >> sRowShift;
1053
    
1054
219k
    uint32 patRow = dstRow % patRows;
1055
    
1056
219k
    for (uint32 dstPlane = 0;
1057
751k
       dstPlane < dstBuffer.fPlanes;
1058
532k
       dstPlane++)
1059
532k
      {
1060
      
1061
532k
      const void *sPtr = srcBuffer.ConstPixel (srcRow,
1062
532k
                            srcCol,
1063
532k
                            srcBuffer.fPlane);
1064
                          
1065
532k
      void *dPtr = dstBuffer.DirtyPixel (dstRow,
1066
532k
                           dstCol,
1067
532k
                           dstPlane);
1068
                      
1069
532k
      if (dstBuffer.fPixelType == ttShort)
1070
263k
        {
1071
        
1072
263k
        DoBilinearRow16 ((const uint16 *) sPtr,
1073
263k
                   (uint16 *) dPtr,
1074
263k
                   dstBuffer.fArea.W (),
1075
263k
                   patPhase,
1076
263k
                   patCols,
1077
263k
                   fPattern [dstPlane].fCounts    [patRow],
1078
263k
                   fPattern [dstPlane].fOffsets   [patRow],
1079
263k
                   fPattern [dstPlane].fWeights16 [patRow],
1080
263k
                   sColShift);
1081
        
1082
263k
        }
1083
        
1084
268k
      else
1085
268k
        {
1086
        
1087
268k
        DoBilinearRow32 ((const real32 *) sPtr,
1088
268k
                   (real32 *) dPtr,
1089
268k
                   dstBuffer.fArea.W (),
1090
268k
                   patPhase,
1091
268k
                   patCols,
1092
268k
                   fPattern [dstPlane].fCounts    [patRow],
1093
268k
                   fPattern [dstPlane].fOffsets   [patRow],
1094
268k
                   fPattern [dstPlane].fWeights32 [patRow],
1095
268k
                   sColShift);
1096
        
1097
268k
        }
1098
                      
1099
532k
      }
1100
    
1101
219k
    }
1102
  
1103
7.10k
  }
1104
  
1105
/*****************************************************************************/
1106
1107
class dng_fast_interpolator: public dng_filter_task
1108
  {
1109
  
1110
  protected:
1111
  
1112
    const dng_mosaic_info &fInfo;
1113
  
1114
    dng_point fDownScale;
1115
    
1116
    uint32 fFilterColor [kMaxCFAPattern] [kMaxCFAPattern];
1117
    
1118
  public:
1119
  
1120
    dng_fast_interpolator (const dng_mosaic_info &info,
1121
                 const dng_image &srcImage,
1122
                 dng_image &dstImage,
1123
                 const dng_point &downScale,
1124
                 uint32 srcPlane);
1125
                 
1126
    virtual dng_rect SrcArea (const dng_rect &dstArea);
1127
      
1128
    virtual void ProcessArea (uint32 threadIndex,
1129
                  dng_pixel_buffer &srcBuffer,
1130
                  dng_pixel_buffer &dstBuffer);
1131
    
1132
  };
1133
1134
/*****************************************************************************/
1135
1136
dng_fast_interpolator::dng_fast_interpolator (const dng_mosaic_info &info,
1137
                        const dng_image &srcImage,
1138
                        dng_image &dstImage,
1139
                        const dng_point &downScale,
1140
                        uint32 srcPlane)
1141
  
1142
2
  : dng_filter_task (srcImage,
1143
2
             dstImage)
1144
  
1145
2
  , fInfo       (info     )
1146
2
  , fDownScale  (downScale)
1147
  
1148
2
  {
1149
  
1150
2
  fSrcPlane  = srcPlane;
1151
2
  fSrcPlanes = 1;
1152
  
1153
2
  fSrcPixelType = ttShort;
1154
2
  fDstPixelType = ttShort;
1155
  
1156
2
  fSrcRepeat = fInfo.fCFAPatternSize;
1157
  
1158
2
  fUnitCell = fInfo.fCFAPatternSize;
1159
  
1160
2
  fMaxTileSize = dng_point (256 / fDownScale.v,
1161
2
                  256 / fDownScale.h);
1162
                
1163
2
  fMaxTileSize.h = Max_int32 (fMaxTileSize.h, fUnitCell.h);
1164
2
  fMaxTileSize.v = Max_int32 (fMaxTileSize.v, fUnitCell.v);
1165
                  
1166
  // Find color map.
1167
  
1168
2
    {
1169
    
1170
6
    for (int32 r = 0; r < fInfo.fCFAPatternSize.v; r++)
1171
4
      {
1172
      
1173
12
      for (int32 c = 0; c < fInfo.fCFAPatternSize.h; c++)
1174
8
        {
1175
        
1176
8
        uint8 key = fInfo.fCFAPattern [r] [c];
1177
        
1178
17
        for (uint32 index = 0; index < fInfo.fColorPlanes; index++)
1179
17
          {
1180
          
1181
17
          if (key == fInfo.fCFAPlaneColor [index])
1182
8
            {
1183
            
1184
8
            fFilterColor [r] [c] = index;
1185
            
1186
8
            break;
1187
            
1188
8
            }
1189
            
1190
17
          }
1191
        
1192
8
        }
1193
        
1194
4
      }
1195
        
1196
2
    }
1197
1198
2
  }
1199
1200
/*****************************************************************************/
1201
1202
dng_rect dng_fast_interpolator::SrcArea (const dng_rect &dstArea)
1203
13
  {
1204
  
1205
13
  return dng_rect (dstArea.t * fDownScale.v,
1206
13
           dstArea.l * fDownScale.h,
1207
13
           dstArea.b * fDownScale.v,
1208
13
           dstArea.r * fDownScale.h);
1209
  
1210
13
  }
1211
      
1212
/*****************************************************************************/
1213
1214
void dng_fast_interpolator::ProcessArea (uint32 /* threadIndex */,
1215
                         dng_pixel_buffer &srcBuffer,
1216
                         dng_pixel_buffer &dstBuffer)
1217
11
  {
1218
  
1219
11
  dng_rect srcArea = srcBuffer.fArea;
1220
11
  dng_rect dstArea = dstBuffer.fArea;
1221
            
1222
  // Downsample buffer.
1223
  
1224
11
  int32 srcRow = srcArea.t;
1225
  
1226
11
  uint32 srcRowPhase1 = 0;
1227
11
  uint32 srcRowPhase2 = 0;
1228
  
1229
11
  uint32 patRows = fInfo.fCFAPatternSize.v;
1230
11
  uint32 patCols = fInfo.fCFAPatternSize.h;
1231
  
1232
11
  uint32 cellRows = fDownScale.v;
1233
11
  uint32 cellCols = fDownScale.h;
1234
  
1235
11
  uint32 plane;
1236
11
  uint32 planes = fInfo.fColorPlanes;
1237
  
1238
11
  int32 dstPlaneStep = dstBuffer.fPlaneStep;
1239
  
1240
11
  uint32 total [kMaxColorPlanes];
1241
11
  uint32 count [kMaxColorPlanes];
1242
  
1243
54
  for (plane = 0; plane < planes; plane++)
1244
43
    {
1245
43
    total [plane] = 0;
1246
43
    count [plane] = 0;
1247
43
    }
1248
      
1249
25
  for (int32 dstRow = dstArea.t; dstRow < dstArea.b; dstRow++)
1250
14
    {
1251
    
1252
14
    const uint16 *sPtr = srcBuffer.ConstPixel_uint16 (srcRow,
1253
14
                              srcArea.l,
1254
14
                              fSrcPlane);
1255
                                  
1256
14
    uint16 *dPtr = dstBuffer.DirtyPixel_uint16 (dstRow,
1257
14
                          dstArea.l,
1258
14
                          0);
1259
                         
1260
14
    uint32 srcColPhase1 = 0;
1261
14
    uint32 srcColPhase2 = 0;
1262
    
1263
55
    for (int32 dstCol = dstArea.l; dstCol < dstArea.r; dstCol++)
1264
41
      {
1265
      
1266
41
      const uint16 *ssPtr = sPtr;
1267
      
1268
41
      srcRowPhase2 = srcRowPhase1;
1269
      
1270
2.43k
      for (uint32 cellRow = 0; cellRow < cellRows; cellRow++)
1271
2.39k
        {
1272
        
1273
2.39k
        const uint32 *filterRow = fFilterColor [srcRowPhase2];
1274
      
1275
2.39k
        if (++srcRowPhase2 == patRows)
1276
1.19k
          {
1277
1.19k
          srcRowPhase2 = 0;
1278
1.19k
          }
1279
          
1280
2.39k
        srcColPhase2 = srcColPhase1;
1281
        
1282
154k
        for (uint32 cellCol = 0; cellCol < cellCols; cellCol++)
1283
151k
          {
1284
        
1285
151k
          uint32 color = filterRow [srcColPhase2];
1286
          
1287
151k
          if (++srcColPhase2 == patCols)
1288
75.8k
            {
1289
75.8k
            srcColPhase2 = 0;
1290
75.8k
            }
1291
          
1292
151k
          total [color] += (uint32) ssPtr [cellCol];
1293
151k
          count [color] ++;
1294
          
1295
151k
          }
1296
          
1297
2.39k
        ssPtr += srcBuffer.fRowStep;
1298
        
1299
2.39k
        }
1300
        
1301
201
      for (plane = 0; plane < planes; plane++)
1302
160
        {
1303
        
1304
160
        uint32 t = total [plane];
1305
160
        uint32 c = count [plane];
1306
        
1307
160
        dPtr [plane * dstPlaneStep] = (uint16) ((t + (c >> 1)) / c);
1308
        
1309
160
        total [plane] = 0;
1310
160
        count [plane] = 0;
1311
        
1312
160
        }
1313
        
1314
41
      srcColPhase1 = srcColPhase2;
1315
        
1316
41
      sPtr += cellCols;
1317
        
1318
41
      dPtr ++;
1319
1320
41
      }
1321
      
1322
14
    srcRowPhase1 = srcRowPhase2;
1323
      
1324
14
    srcRow += cellRows;
1325
    
1326
14
    }
1327
           
1328
11
  }
1329
  
1330
/*****************************************************************************/
1331
1332
dng_mosaic_info::dng_mosaic_info ()
1333
1334
24.7k
  : fCFAPatternSize  ()
1335
24.7k
  , fColorPlanes     (0)
1336
24.7k
  , fCFALayout     (1)
1337
24.7k
  , fBayerGreenSplit (0)
1338
24.7k
  , fSrcSize     ()
1339
24.7k
  , fCroppedSize     ()
1340
24.7k
  , fAspectRatio     (1.0)
1341
  
1342
24.7k
  {
1343
  
1344
24.7k
  }
1345
1346
/*****************************************************************************/
1347
1348
dng_mosaic_info::~dng_mosaic_info ()
1349
24.7k
  {
1350
  
1351
24.7k
  }
1352
    
1353
/*****************************************************************************/
1354
1355
void dng_mosaic_info::Parse (dng_host & /* host */,
1356
               dng_stream & /* stream */,
1357
               dng_info &info)
1358
218
  {
1359
  
1360
  // Find main image IFD.
1361
  
1362
218
  dng_ifd &rawIFD = *info.fIFD [info.fMainIndex].Get ();
1363
  
1364
  // This information only applies to CFA images.
1365
  
1366
218
  if (rawIFD.fPhotometricInterpretation != piCFA)
1367
0
    {
1368
0
    return;
1369
0
    }
1370
  
1371
  // Copy CFA pattern.
1372
  
1373
218
  fCFAPatternSize.v = rawIFD.fCFARepeatPatternRows;
1374
218
  fCFAPatternSize.h = rawIFD.fCFARepeatPatternCols;
1375
  
1376
755
  for (int32 j = 0; j < fCFAPatternSize.v; j++)
1377
537
    {
1378
1.40k
    for (int32 k = 0; k < fCFAPatternSize.h; k++)
1379
868
      {
1380
868
      fCFAPattern [j] [k] = rawIFD.fCFAPattern [j] [k];
1381
868
      }
1382
537
    }
1383
    
1384
  // Copy CFA plane information.
1385
  
1386
218
  fColorPlanes = info.fShared->fCameraProfile.fColorPlanes;
1387
  
1388
695
  for (uint32 n = 0; n < fColorPlanes; n++)
1389
477
    {
1390
477
    fCFAPlaneColor [n] = rawIFD.fCFAPlaneColor [n];
1391
477
    }
1392
    
1393
  // Copy CFA layout information.
1394
  
1395
218
  fCFALayout = rawIFD.fCFALayout;
1396
  
1397
  // Green split value for Bayer patterns.
1398
  
1399
218
  fBayerGreenSplit = rawIFD.fBayerGreenSplit;
1400
  
1401
218
  }
1402
    
1403
/*****************************************************************************/
1404
1405
void dng_mosaic_info::PostParse (dng_host & /* host */,
1406
                 dng_negative &negative)
1407
9.32k
  {
1408
  
1409
  // Keep track of source image size.
1410
  
1411
9.32k
  fSrcSize = negative.Stage2Image ()->Size ();
1412
  
1413
  // Default cropped size.
1414
  
1415
9.32k
  fCroppedSize.v = Round_int32 (negative.DefaultCropSizeV ().As_real64 ());
1416
9.32k
  fCroppedSize.h = Round_int32 (negative.DefaultCropSizeH ().As_real64 ());
1417
  
1418
  // Pixel aspect ratio.
1419
  
1420
9.32k
  fAspectRatio = negative.DefaultScaleH ().As_real64 () /
1421
9.32k
           negative.DefaultScaleV ().As_real64 ();
1422
  
1423
9.32k
  }
1424
                
1425
/*****************************************************************************/
1426
1427
bool dng_mosaic_info::SetFourColorBayer ()
1428
13
  {
1429
  
1430
13
  if (fCFAPatternSize != dng_point (2, 2))
1431
0
    {
1432
0
    return false;
1433
0
    }
1434
    
1435
13
  if (fColorPlanes != 3)
1436
0
    {
1437
0
    return false;
1438
0
    }
1439
    
1440
13
  uint8 color0 = fCFAPlaneColor [0];
1441
13
  uint8 color1 = fCFAPlaneColor [1];
1442
13
  uint8 color2 = fCFAPlaneColor [2];
1443
  
1444
  // Look for color 1 repeated twice in a diagonal.
1445
  
1446
13
  if ((fCFAPattern [0] [0] == color1 && fCFAPattern [1] [1] == color1) ||
1447
13
    (fCFAPattern [0] [1] == color1 && fCFAPattern [1] [0] == color1))
1448
11
    {
1449
    
1450
    // OK, this looks like a Bayer pattern. 
1451
    
1452
    // Find unused color code.
1453
    
1454
11
    uint8 color3 = 0;
1455
    
1456
44
    while (color3 == color0 ||
1457
44
         color3 == color1 ||
1458
44
         color3 == color2)
1459
33
      {
1460
33
      color3++;
1461
33
      }
1462
      
1463
    // Switch the four color mosaic.
1464
    
1465
11
    fColorPlanes = 4;
1466
    
1467
11
    fCFAPlaneColor [3] = color3;
1468
    
1469
    // Replace the "green" in the "blue" rows with the new color.
1470
    
1471
11
    if (fCFAPattern [0] [0] == color0)
1472
11
      {
1473
11
      fCFAPattern [1] [0] = color3;
1474
11
      }
1475
      
1476
0
    else if (fCFAPattern [0] [1] == color0)
1477
0
      {
1478
0
      fCFAPattern [1] [1] = color3;
1479
0
      }
1480
      
1481
0
    else if (fCFAPattern [1] [0] == color0)
1482
0
      {
1483
0
      fCFAPattern [0] [0] = color3;
1484
0
      }
1485
      
1486
0
    else
1487
0
      {
1488
0
      fCFAPattern [0] [1] = color3;
1489
0
      }
1490
      
1491
11
    return true;
1492
1493
11
    }
1494
  
1495
2
  return false;
1496
  
1497
13
  }
1498
                
1499
/*****************************************************************************/
1500
1501
dng_point dng_mosaic_info::FullScale () const
1502
561
  {
1503
  
1504
561
  switch (fCFALayout)
1505
561
    {
1506
    
1507
    // Staggered layouts with offset columns double the row count
1508
    // during interpolation.
1509
    
1510
25
    case 2:
1511
37
    case 3:
1512
37
      return dng_point (2, 1);
1513
      
1514
    // Staggered layouts with offset rows double the column count
1515
    // during interpolation.
1516
      
1517
12
    case 4:
1518
28
    case 5:
1519
28
      return dng_point (1, 2);
1520
      
1521
    // Otherwise there is no size change during interpolation.
1522
    
1523
496
    default:
1524
496
      break;
1525
    
1526
561
    }
1527
    
1528
496
  return dng_point (1, 1);
1529
  
1530
561
  }
1531
  
1532
/*****************************************************************************/
1533
1534
bool dng_mosaic_info::IsSafeDownScale (const dng_point &downScale) const
1535
92
  {
1536
  
1537
92
  if (downScale.v >= fCFAPatternSize.v &&
1538
92
    downScale.h >= fCFAPatternSize.h)
1539
80
    {
1540
    
1541
80
    return true;
1542
    
1543
80
    }
1544
    
1545
12
  dng_point test;
1546
  
1547
12
  test.v = Min_int32 (downScale.v, fCFAPatternSize.v);
1548
12
  test.h = Min_int32 (downScale.h, fCFAPatternSize.h);
1549
    
1550
13
  for (int32 phaseV = 0; phaseV <= fCFAPatternSize.v - test.v; phaseV++)
1551
12
    {
1552
    
1553
15
    for (int32 phaseH = 0; phaseH <= fCFAPatternSize.h - test.h; phaseH++)
1554
14
      {
1555
      
1556
14
      uint32 plane;
1557
      
1558
14
      bool contains [kMaxColorPlanes];
1559
      
1560
55
      for (plane = 0; plane < fColorPlanes; plane++)
1561
41
        {
1562
        
1563
41
        contains [plane] = false;
1564
        
1565
41
        }
1566
      
1567
28
      for (int32 srcRow = 0; srcRow < test.v; srcRow++)
1568
14
        {
1569
        
1570
31
        for (int32 srcCol = 0; srcCol < test.h; srcCol++)
1571
17
          {
1572
          
1573
17
          uint8 srcKey = fCFAPattern [srcRow + phaseV]
1574
17
                         [srcCol + phaseH];
1575
                         
1576
64
          for (plane = 0; plane < fColorPlanes; plane++)
1577
47
            {
1578
            
1579
47
            if (srcKey == fCFAPlaneColor [plane])
1580
17
              {
1581
              
1582
17
              contains [plane] = true;
1583
              
1584
17
              }
1585
              
1586
47
            }
1587
          
1588
          
1589
17
          }
1590
          
1591
14
        }
1592
        
1593
28
      for (plane = 0; plane < fColorPlanes; plane++)
1594
25
        {
1595
        
1596
25
        if (!contains [plane])
1597
11
          {
1598
          
1599
11
          return false;
1600
          
1601
11
          }
1602
          
1603
25
        }
1604
      
1605
14
      }
1606
    
1607
12
    }
1608
    
1609
1
  return true;
1610
  
1611
12
  }
1612
  
1613
/*****************************************************************************/
1614
1615
uint32 dng_mosaic_info::SizeForDownScale (const dng_point &downScale) const
1616
162
  {
1617
  
1618
162
  uint32 sizeV = Max_uint32 (1, (fCroppedSize.v + (downScale.v >> 1)) / downScale.v);
1619
162
  uint32 sizeH = Max_uint32 (1, (fCroppedSize.h + (downScale.h >> 1)) / downScale.h);
1620
  
1621
162
  return Max_int32 (sizeV, sizeH);
1622
  
1623
162
  }
1624
  
1625
/*****************************************************************************/
1626
1627
bool dng_mosaic_info::ValidSizeDownScale (const dng_point &downScale,
1628
                      uint32 minSize) const
1629
81
  {
1630
  
1631
81
  const int32 kMaxDownScale = 64;
1632
  
1633
81
  if (downScale.h > kMaxDownScale ||
1634
81
    downScale.v > kMaxDownScale)
1635
1
    {
1636
    
1637
1
    return false;
1638
    
1639
1
    }
1640
    
1641
80
  return SizeForDownScale (downScale) >= minSize;
1642
      
1643
81
  }
1644
1645
/*****************************************************************************/
1646
1647
dng_point dng_mosaic_info::DownScale (uint32 minSize,
1648
                    uint32 prefSize,
1649
                    real64 cropFactor) const
1650
132
  {
1651
  
1652
132
  dng_point bestScale (1, 1);
1653
  
1654
132
  if (prefSize && IsColorFilterArray ())
1655
13
    {
1656
    
1657
    // Adjust sizes for crop factor.
1658
    
1659
13
    minSize  = Round_uint32 (minSize  / cropFactor);
1660
13
    prefSize = Round_uint32 (prefSize / cropFactor);
1661
    
1662
13
    prefSize = Max_uint32 (prefSize, minSize);
1663
    
1664
    // Start by assuming we need the full size image.
1665
    
1666
13
    int32 bestSize = SizeForDownScale (bestScale);
1667
    
1668
    // Find size of nearly square cell.
1669
    
1670
13
    dng_point squareCell (1, 1);
1671
    
1672
13
    if (fAspectRatio < 1.0 / 1.8)
1673
1
      {
1674
      
1675
1
      squareCell.h = Min_int32 (4, Round_int32 (1.0 / fAspectRatio));
1676
      
1677
1
      }
1678
    
1679
13
    if (fAspectRatio > 1.8)
1680
1
      {
1681
      
1682
1
      squareCell.v = Min_int32 (4, Round_int32 (fAspectRatio));
1683
      
1684
1
      }
1685
  
1686
    // Find minimum safe cell size.
1687
    
1688
13
    dng_point testScale = squareCell;
1689
    
1690
24
    while (!IsSafeDownScale (testScale))
1691
11
      {
1692
      
1693
11
      testScale.v += squareCell.v;
1694
11
      testScale.h += squareCell.h;
1695
      
1696
11
      }
1697
    
1698
    // See if this scale is usable.
1699
    
1700
13
    if (!ValidSizeDownScale (testScale, minSize))
1701
10
      {
1702
      
1703
      // We cannot downsample at all...
1704
      
1705
10
      return bestScale;
1706
      
1707
10
      }
1708
      
1709
    // See if this is closer to the preferred size.
1710
    
1711
3
    int32 testSize = SizeForDownScale (testScale);
1712
    
1713
3
    if (Abs_int32 (testSize - (int32) prefSize) <=
1714
3
        Abs_int32 (bestSize - (int32) prefSize))
1715
2
      {
1716
2
      bestScale = testScale;
1717
2
      bestSize  = testSize;
1718
2
      }
1719
      
1720
1
    else
1721
1
      {
1722
1
      return bestScale;
1723
1
      }
1724
    
1725
    // Now keep adding square cells as long as possible.
1726
    
1727
69
    while (true)
1728
69
      {
1729
      
1730
69
      testScale.v += squareCell.v;
1731
69
      testScale.h += squareCell.h;
1732
      
1733
69
      if (IsSafeDownScale (testScale))
1734
69
        {
1735
        
1736
69
        if (!ValidSizeDownScale (testScale, minSize))
1737
2
          {
1738
2
          return bestScale;
1739
2
          }
1740
        
1741
        // See if this is closer to the preferred size.
1742
        
1743
67
        testSize = SizeForDownScale (testScale);
1744
        
1745
67
        if (Abs_int32 (testSize - (int32) prefSize) <=
1746
67
          Abs_int32 (bestSize - (int32) prefSize))
1747
67
          {
1748
67
          bestScale = testScale;
1749
67
          bestSize  = testSize;
1750
67
          }
1751
          
1752
0
        else
1753
0
          {
1754
0
          return bestScale;
1755
0
          }
1756
            
1757
67
        }
1758
        
1759
69
      }
1760
    
1761
2
    }
1762
  
1763
119
  return bestScale;
1764
  
1765
132
  }
1766
1767
/*****************************************************************************/
1768
1769
dng_point dng_mosaic_info::DstSize (const dng_point &downScale) const
1770
131
  {
1771
  
1772
131
  if (downScale == dng_point (1, 1))
1773
129
    {
1774
  
1775
129
    dng_point scale = FullScale ();
1776
    
1777
129
    return dng_point (fSrcSize.v * scale.v,
1778
129
              fSrcSize.h * scale.h);
1779
              
1780
129
    }
1781
    
1782
2
  const int32 kMaxDownScale = 64;
1783
  
1784
2
  if (downScale.h > kMaxDownScale ||
1785
2
    downScale.v > kMaxDownScale)
1786
0
    {
1787
    
1788
0
    return dng_point (0, 0);
1789
    
1790
0
    }
1791
    
1792
2
  dng_point size;
1793
  
1794
2
  size.v = Max_int32 (1, (fSrcSize.v + (downScale.v >> 1)) / downScale.v);
1795
2
  size.h = Max_int32 (1, (fSrcSize.h + (downScale.h >> 1)) / downScale.h);
1796
  
1797
2
  return size;
1798
      
1799
2
  }
1800
1801
/*****************************************************************************/
1802
1803
void dng_mosaic_info::InterpolateGeneric (dng_host &host,
1804
                      dng_negative & /* negative */,
1805
                        const dng_image &srcImage,
1806
                        dng_image &dstImage,
1807
                        uint32 srcPlane) const
1808
129
  {
1809
  
1810
  // Find destination to source bit shifts.
1811
  
1812
129
  dng_point scale = FullScale ();
1813
  
1814
129
  uint32 srcShiftV = scale.v - 1;
1815
129
  uint32 srcShiftH = scale.h - 1;
1816
  
1817
  // Find tile sizes.
1818
  
1819
129
  const uint32 kMaxDstTileRows = 128;
1820
129
  const uint32 kMaxDstTileCols = 128;
1821
  
1822
129
  dng_point dstTileSize = dstImage.RepeatingTile ().Size ();
1823
  
1824
129
  dstTileSize.v = Min_int32 (dstTileSize.v, kMaxDstTileRows);
1825
129
  dstTileSize.h = Min_int32 (dstTileSize.h, kMaxDstTileCols);
1826
  
1827
129
  dng_point srcTileSize = dstTileSize;
1828
  
1829
129
  srcTileSize.v >>= srcShiftV;
1830
129
  srcTileSize.h >>= srcShiftH;
1831
  
1832
129
  srcTileSize.v += fCFAPatternSize.v * 2;
1833
129
  srcTileSize.h += fCFAPatternSize.h * 2;
1834
  
1835
  // Allocate source buffer.
1836
  
1837
129
  dng_pixel_buffer srcBuffer (dng_rect (srcTileSize), srcPlane, 1,
1838
129
     srcImage.PixelType (), pcInterleaved, NULL);
1839
  
1840
129
  uint32 srcBufferSize = ComputeBufferSize (srcBuffer.fPixelType,
1841
129
                        srcTileSize, srcBuffer.fPlanes,
1842
129
                        padNone);
1843
  
1844
129
  AutoPtr<dng_memory_block> srcData (host.Allocate (srcBufferSize));
1845
  
1846
129
  srcBuffer.fData = srcData->Buffer ();
1847
  
1848
  // Allocate destination buffer.
1849
  
1850
129
  dng_pixel_buffer dstBuffer (dng_rect (dstTileSize), 0, fColorPlanes,
1851
129
     dstImage.PixelType (), pcRowInterleaved, NULL);
1852
  
1853
129
  uint32 dstBufferSize = ComputeBufferSize (dstBuffer.fPixelType,
1854
129
                        dstTileSize, dstBuffer.fPlanes,
1855
129
                        padNone);
1856
  
1857
129
  AutoPtr<dng_memory_block> dstData (host.Allocate (dstBufferSize));
1858
  
1859
129
  dstBuffer.fData = dstData->Buffer ();
1860
  
1861
  // Create interpolator.
1862
1863
129
  AutoPtr<dng_bilinear_interpolator> interpolator (new dng_bilinear_interpolator (*this,
1864
129
                                          srcBuffer.fRowStep,
1865
129
                                          srcBuffer.fColStep));
1866
1867
  // Iterate over destination tiles.
1868
  
1869
129
  dng_rect dstArea;
1870
  
1871
129
  dng_tile_iterator iter1 (dstImage, dstImage.Bounds ());
1872
  
1873
258
  while (iter1.GetOneTile (dstArea))
1874
129
    {
1875
    
1876
    // Break into buffer sized tiles.
1877
    
1878
129
    dng_rect dstTile;
1879
    
1880
129
    dng_tile_iterator iter2 (dstTileSize, dstArea);
1881
    
1882
7.22k
    while (iter2.GetOneTile (dstTile))
1883
7.10k
      {
1884
      
1885
7.10k
      host.SniffForAbort ();
1886
      
1887
      // Setup buffers for this tile.
1888
      
1889
7.10k
      dng_rect srcTile (dstTile);
1890
      
1891
7.10k
      srcTile.t >>= srcShiftV;
1892
7.10k
      srcTile.b >>= srcShiftV;
1893
      
1894
7.10k
      srcTile.l >>= srcShiftH;
1895
7.10k
      srcTile.r >>= srcShiftH;
1896
      
1897
7.10k
      srcTile.t -= fCFAPatternSize.v;
1898
7.10k
      srcTile.b += fCFAPatternSize.v;
1899
      
1900
7.10k
      srcTile.l -= fCFAPatternSize.h;
1901
7.10k
      srcTile.r += fCFAPatternSize.h;
1902
      
1903
7.10k
      srcBuffer.fArea = srcTile;
1904
7.10k
      dstBuffer.fArea = dstTile;
1905
      
1906
      // Get source data.
1907
      
1908
7.10k
      srcImage.Get (srcBuffer,
1909
7.10k
              dng_image::edge_repeat,
1910
7.10k
              fCFAPatternSize.v,
1911
7.10k
              fCFAPatternSize.h);
1912
              
1913
      // Process data.
1914
      
1915
7.10k
      interpolator->Interpolate (srcBuffer,
1916
7.10k
                     dstBuffer);
1917
                    
1918
      // Save results.
1919
      
1920
7.10k
      dstImage.Put (dstBuffer);
1921
                
1922
7.10k
      }
1923
      
1924
129
    }
1925
    
1926
129
  }
1927
1928
/*****************************************************************************/
1929
1930
void dng_mosaic_info::InterpolateFast (dng_host &host,
1931
                     dng_negative & /* negative */,
1932
                         const dng_image &srcImage,
1933
                       dng_image &dstImage,
1934
                       const dng_point &downScale,
1935
                       uint32 srcPlane) const
1936
2
  {
1937
  
1938
  // Create fast interpolator task.
1939
  
1940
2
  dng_fast_interpolator interpolator (*this,
1941
2
                    srcImage,
1942
2
                    dstImage,
1943
2
                    downScale,
1944
2
                    srcPlane);
1945
  
1946
  // Find area to process.
1947
  
1948
2
  dng_rect bounds = dstImage.Bounds ();
1949
  
1950
  // Do the interpolation.
1951
  
1952
2
  host.PerformAreaTask (interpolator,
1953
2
              bounds);
1954
  
1955
2
  }
1956
  
1957
/*****************************************************************************/
1958
1959
void dng_mosaic_info::Interpolate (dng_host &host,
1960
                   dng_negative &negative,
1961
                     const dng_image &srcImage,
1962
                   dng_image &dstImage,
1963
                   const dng_point &downScale,
1964
                   uint32 srcPlane) const
1965
131
  {
1966
  
1967
131
  if (downScale == dng_point (1, 1))
1968
129
    {
1969
  
1970
129
    InterpolateGeneric (host,
1971
129
              negative,
1972
129
              srcImage,
1973
129
              dstImage,
1974
129
              srcPlane);
1975
              
1976
129
    }
1977
    
1978
2
  else
1979
2
    {
1980
    
1981
2
    InterpolateFast (host,
1982
2
             negative,
1983
2
             srcImage,
1984
2
             dstImage,
1985
2
             downScale,
1986
2
             srcPlane);
1987
    
1988
2
    }
1989
  
1990
131
  }
1991
1992
/*****************************************************************************/