Coverage Report

Created: 2026-08-31 06:33

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/dng_sdk/source/dng_linearization_info.cpp
Line
Count
Source
1
/*****************************************************************************/
2
// Copyright 2006-2011 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_linearization_info.cpp#1 $ */ 
10
/* $DateTime: 2012/05/30 13:28:51 $ */
11
/* $Change: 832332 $ */
12
/* $Author: tknoll $ */
13
14
/*****************************************************************************/
15
16
#include "dng_linearization_info.h"
17
18
#include "dng_area_task.h"
19
#include "dng_exceptions.h"
20
#include "dng_host.h"
21
#include "dng_image.h"
22
#include "dng_info.h"
23
#include "dng_negative.h"
24
#include "dng_pixel_buffer.h"
25
#include "dng_safe_arithmetic.h"
26
#include "dng_tag_types.h"
27
#include "dng_tile_iterator.h"
28
#include "dng_utils.h"
29
30
/*****************************************************************************/
31
32
class dng_linearize_plane
33
  {
34
  
35
  private:
36
  
37
    const dng_image & fSrcImage;
38
          dng_image & fDstImage;
39
          
40
    uint32 fPlane;
41
  
42
    dng_rect fActiveArea;
43
          
44
    uint32 fSrcPixelType;
45
    uint32 fDstPixelType;
46
    
47
    bool fReal32;
48
    
49
    real32 fScale;
50
    
51
    AutoPtr<dng_memory_block> fScale_buffer;
52
    
53
    uint32 fBlack_2D_rows;
54
    uint32 fBlack_2D_cols;
55
    
56
    AutoPtr<dng_memory_block> fBlack_2D_buffer;
57
    
58
    uint32 fBlack_1D_rows;
59
    
60
    AutoPtr<dng_memory_block> fBlack_1D_buffer;
61
    
62
  public:
63
  
64
    dng_linearize_plane (dng_host &host,
65
               dng_linearization_info &info,
66
               const dng_image &srcImage,
67
               dng_image &dstImage,
68
               uint32 plane);
69
               
70
    ~dng_linearize_plane ();
71
    
72
    void Process (const dng_rect &tile);
73
                  
74
  };
75
76
/*****************************************************************************/
77
78
dng_linearize_plane::dng_linearize_plane (dng_host &host,
79
                      dng_linearization_info &info,
80
                      const dng_image &srcImage,
81
                      dng_image &dstImage,
82
                      uint32 plane)
83
               
84
26.6k
  : fSrcImage (srcImage)
85
26.6k
  , fDstImage (dstImage)
86
26.6k
  , fPlane (plane)
87
26.6k
  , fActiveArea (info.fActiveArea)
88
26.6k
  , fSrcPixelType (srcImage.PixelType ())
89
26.6k
  , fDstPixelType (dstImage.PixelType ())
90
26.6k
  , fReal32 (false)
91
26.6k
  , fScale (0.0f)
92
26.6k
  , fScale_buffer ()
93
26.6k
  , fBlack_2D_rows (0)
94
26.6k
  , fBlack_2D_cols (0)
95
26.6k
  , fBlack_2D_buffer ()
96
26.6k
  , fBlack_1D_rows (0)
97
26.6k
  , fBlack_1D_buffer ()
98
  
99
26.6k
  {
100
  
101
26.6k
  uint32 j;
102
26.6k
  uint32 k;
103
  
104
  // Make sure the source pixel type is supported.
105
  
106
26.6k
  if (fSrcPixelType != ttByte  &&
107
15.5k
    fSrcPixelType != ttShort &&
108
7.73k
    fSrcPixelType != ttLong  &&
109
1.17k
    fSrcPixelType != ttFloat)
110
0
    {
111
    
112
0
    DNG_REPORT ("Unsupported source pixel type");
113
    
114
0
    ThrowProgramError ();
115
    
116
0
    }
117
    
118
26.6k
  if (fDstPixelType != ttShort &&
119
7.73k
    fDstPixelType != ttFloat)
120
0
    {
121
    
122
0
    DNG_REPORT ("Unsupported destination pixel type");
123
    
124
0
    ThrowProgramError ();
125
    
126
0
    }
127
  
128
26.6k
  if (fSrcPixelType == ttFloat &&
129
1.17k
    fDstPixelType != ttFloat)
130
0
    {
131
    
132
0
    DNG_REPORT ("Cannot convert floating point stage1 to non-floating stage2");
133
    
134
0
    ThrowProgramError ();
135
    
136
0
    }
137
  
138
  // Are we using floating point math?
139
  
140
26.6k
  fReal32 = (fSrcPixelType == ttLong ||
141
20.1k
         fDstPixelType == ttFloat);
142
  
143
  // Find the scale for this plane.
144
  
145
26.6k
  real64 maxBlack = info.MaxBlackLevel (plane);
146
  
147
26.6k
  real64 minRange = info.fWhiteLevel [plane] - maxBlack;
148
  
149
26.6k
  if (minRange <= 0.0)
150
66
    {
151
66
    ThrowBadFormat ();
152
66
    }
153
    
154
26.6k
  real64 scale = 1.0 / minRange;
155
  
156
26.6k
  fScale = (real32) scale;
157
    
158
  // Calculate two-dimensional black pattern, if any.
159
  
160
26.6k
  if (info.fBlackDeltaH.Get ())
161
339
    {
162
    
163
339
    fBlack_2D_rows = info.fBlackLevelRepeatRows;
164
339
    fBlack_2D_cols = info.fActiveArea.W ();
165
    
166
339
    }
167
    
168
26.3k
  else if (info.fBlackLevelRepeatCols > 1)
169
467
    {
170
    
171
467
    fBlack_2D_rows = info.fBlackLevelRepeatRows;
172
467
    fBlack_2D_cols = info.fBlackLevelRepeatCols;
173
    
174
467
    }
175
    
176
26.6k
  if (fBlack_2D_rows)
177
806
    {
178
    
179
806
    fBlack_2D_buffer.Reset (host.Allocate (
180
806
      SafeUint32Mult (fBlack_2D_rows, fBlack_2D_cols, 4)));
181
    
182
2.46k
    for (j = 0; j < fBlack_2D_rows; j++)
183
1.66k
      {
184
      
185
11.8k
      for (k = 0;  k < fBlack_2D_cols; k++)
186
10.1k
        {
187
        
188
10.1k
        real64 x = info.fBlackLevel [j]
189
10.1k
                      [k % info.fBlackLevelRepeatCols]
190
10.1k
                      [plane];
191
        
192
10.1k
        if (info.fBlackDeltaH.Get ())
193
5.52k
          {
194
          
195
5.52k
          x += info.fBlackDeltaH->Buffer_real64 () [k];
196
          
197
5.52k
          }
198
          
199
10.1k
        x *= scale;
200
          
201
10.1k
        uint32 index = j * fBlack_2D_cols + k;
202
        
203
10.1k
        if (fReal32)
204
3.33k
          {
205
          
206
3.33k
          fBlack_2D_buffer->Buffer_real32 () [index] = (real32) x;
207
          
208
3.33k
          }
209
          
210
6.85k
        else
211
6.85k
          {
212
          
213
6.85k
          x *= 0x0FFFF * 256.0;
214
          
215
6.85k
          int32 y = Round_int32 (x);
216
          
217
6.85k
          fBlack_2D_buffer->Buffer_int32 () [index] = y;
218
          
219
6.85k
          }
220
        
221
10.1k
        }
222
        
223
1.66k
      }
224
        
225
806
    }
226
    
227
  // Calculate one-dimensional (per row) black pattern, if any.
228
  
229
26.6k
  if (info.fBlackDeltaV.Get ())
230
559
    {
231
    
232
559
    fBlack_1D_rows = info.fActiveArea.H ();
233
    
234
559
    }
235
    
236
26.1k
  else if (fBlack_2D_rows == 0 &&
237
25.3k
       (info.fBlackLevelRepeatRows > 1 || fSrcPixelType != ttShort))
238
18.0k
    {
239
    
240
18.0k
    fBlack_1D_rows = info.fBlackLevelRepeatRows;
241
    
242
18.0k
    }
243
    
244
26.6k
  if (fBlack_1D_rows)
245
18.6k
    {
246
    
247
18.6k
    fBlack_1D_buffer.Reset (host.Allocate (
248
18.6k
      SafeUint32Mult(fBlack_1D_rows, 4)));
249
    
250
18.6k
    bool allZero = true;
251
    
252
121k
    for (j = 0; j < fBlack_1D_rows; j++)
253
102k
      {
254
      
255
102k
      real64 x = 0.0;
256
      
257
102k
      if (fBlack_2D_rows == 0)
258
102k
        {
259
        
260
102k
        x = info.fBlackLevel [j % info.fBlackLevelRepeatRows] 
261
102k
                   [0] 
262
102k
                   [plane];
263
        
264
102k
        }
265
      
266
102k
      if (info.fBlackDeltaV.Get ())
267
83.9k
        {
268
        
269
83.9k
        x += info.fBlackDeltaV->Buffer_real64 () [j];
270
        
271
83.9k
        }
272
        
273
102k
      allZero = allZero && (x == 0.0);
274
        
275
102k
      x *= scale;
276
      
277
102k
      if (fReal32)
278
8.11k
        {
279
        
280
8.11k
        fBlack_1D_buffer->Buffer_real32 () [j] = (real32) x;
281
        
282
8.11k
        }
283
        
284
94.6k
      else
285
94.6k
        {
286
        
287
94.6k
        x *= 0x0FFFF * 256.0;
288
        
289
94.6k
        int32 y = Round_int32 (x);
290
        
291
94.6k
        fBlack_1D_buffer->Buffer_int32 () [j] = y;
292
        
293
94.6k
        }
294
      
295
102k
      }
296
      
297
18.6k
    if (allZero)
298
16.3k
      {
299
      
300
16.3k
      fBlack_1D_rows = 0;
301
      
302
16.3k
      fBlack_1D_buffer.Reset ();
303
      
304
16.3k
      }
305
      
306
18.6k
    }
307
    
308
  // Calculate scale table, if any.
309
  
310
26.6k
  if (fSrcPixelType != ttLong &&
311
19.9k
    fSrcPixelType != ttFloat)
312
18.7k
    {
313
    
314
    // Find linearization table, if any.
315
      
316
18.7k
    uint16 *lut = NULL;
317
    
318
18.7k
    uint32 lutEntries = 0;
319
    
320
18.7k
    if (info.fLinearizationTable.Get ())
321
3.82k
      {
322
      
323
3.82k
      lut = info.fLinearizationTable->Buffer_uint16 ();
324
      
325
3.82k
      lutEntries = info.fLinearizationTable->LogicalSize () >> 1;
326
      
327
3.82k
      }
328
      
329
    // If the black level does not vary from pixel to pixel, then
330
    // the entire process can be a single LUT.
331
    
332
18.7k
    if (fBlack_1D_rows == 0 &&
333
16.9k
        fBlack_2D_rows == 0)
334
16.4k
      {
335
    
336
16.4k
      fScale_buffer.Reset (host.Allocate (0x10000 *
337
16.4k
                          TagTypeSize (fDstPixelType)));
338
                          
339
1.08G
      for (j = 0; j < 0x10000; j++)
340
1.08G
        {
341
        
342
1.08G
        uint32 x = j;
343
        
344
        // Apply linearization table, if any.
345
        
346
1.08G
        if (lut)
347
137M
          {
348
          
349
137M
          x = Min_uint32 (x, lutEntries - 1);
350
          
351
137M
          x = lut [x];
352
          
353
137M
          }
354
          
355
        // Subtract constant black level.
356
        
357
1.08G
        real64 y = x - info.fBlackLevel [0] [0] [plane];
358
        
359
        // Apply scale.
360
        
361
1.08G
        y *= scale;
362
        
363
        // We can burn in the clipping also.
364
        
365
1.08G
        y = Pin_real64 (0.0, y, 1.0);
366
        
367
        // Store output value in table.
368
        
369
1.08G
        if (fDstPixelType == ttShort)
370
1.08G
          {
371
          
372
1.08G
          uint16 z = (uint16) Round_uint32 (y * 0x0FFFF);
373
          
374
1.08G
          fScale_buffer->Buffer_uint16 () [j] = z;
375
          
376
1.08G
          }
377
          
378
0
        else
379
0
          {
380
          
381
0
          fScale_buffer->Buffer_real32 () [j] = (real32) y;
382
          
383
0
          }
384
        
385
1.08G
        }
386
        
387
16.4k
      }
388
    
389
    // Else we only do the scaling operation in the scale table.
390
    
391
2.25k
    else
392
2.25k
      {
393
    
394
2.25k
      fScale_buffer.Reset (host.Allocate (0x10000 * 4));
395
                          
396
140M
      for (j = 0; j < 0x10000; j++)
397
140M
        {
398
        
399
140M
        uint32 x = j;
400
        
401
        // Apply linearization table, if any.
402
        
403
140M
        if (lut)
404
109M
          {
405
          
406
109M
          x = Min_uint32 (x, lutEntries - 1);
407
          
408
109M
          x = lut [x];
409
          
410
109M
          }
411
          
412
        // Apply scale.
413
        
414
140M
        real64 y = x * scale;
415
          
416
        // Store output value in table.
417
        
418
140M
        if (fReal32)
419
0
          {
420
          
421
0
          fScale_buffer->Buffer_real32 () [j] = (real32) y;
422
          
423
0
          }
424
          
425
140M
        else
426
140M
          {
427
          
428
140M
          int32 z = Round_int32 (y * 0x0FFFF * 256.0);
429
          
430
140M
          fScale_buffer->Buffer_int32 () [j] = z;
431
          
432
140M
          }
433
        
434
140M
        }
435
        
436
2.25k
      }
437
    
438
18.7k
    }
439
    
440
26.6k
  }
441
               
442
/*****************************************************************************/
443
444
dng_linearize_plane::~dng_linearize_plane ()
445
26.3k
  {
446
  
447
26.3k
  }
448
               
449
/*****************************************************************************/
450
451
void dng_linearize_plane::Process (const dng_rect &srcTile)
452
113k
  {
453
454
  // Process tile.
455
  
456
113k
  dng_rect dstTile = srcTile - fActiveArea.TL ();
457
    
458
113k
  dng_const_tile_buffer srcBuffer (fSrcImage, srcTile);
459
113k
  dng_dirty_tile_buffer dstBuffer (fDstImage, dstTile);
460
  
461
113k
  int32 sStep = srcBuffer.fColStep;
462
113k
  int32 dStep = dstBuffer.fColStep;
463
  
464
113k
  uint32 count = srcTile.W ();
465
  
466
113k
  uint32 dstCol = dstTile.l;
467
468
113k
  uint32 rows = srcTile.H ();
469
470
38.0M
  for (uint32 row = 0; row < rows; row++)
471
37.8M
    {
472
473
37.8M
    uint32 dstRow = dstTile.t + row;
474
  
475
37.8M
    const void *sPtr = srcBuffer.ConstPixel (srcTile.t + row,
476
37.8M
                           srcTile.l,
477
37.8M
                           fPlane);
478
  
479
37.8M
    void *dPtr = dstBuffer.DirtyPixel (dstRow,
480
37.8M
                       dstCol,
481
37.8M
                       fPlane);
482
                       
483
    // Floating point source case.
484
    
485
37.8M
    if (fSrcPixelType == ttFloat)
486
4.27M
      {
487
      
488
4.27M
      real32 scale = fScale;
489
      
490
4.27M
      const real32 *srcPtr = (const real32 *) sPtr;
491
      
492
4.27M
      real32 *dstPtr = (real32 *) dPtr;
493
      
494
      // Optimize scale only case, which is the most common.
495
      
496
4.27M
      if (fBlack_1D_rows == 0 &&
497
4.27M
        fBlack_2D_cols == 0)
498
3.89M
        {
499
      
500
1.05G
        for (uint32 j = 0; j < count; j++)
501
1.04G
          {
502
          
503
1.04G
          *dstPtr = (*srcPtr) * scale;
504
          
505
1.04G
          srcPtr += sStep;
506
1.04G
          dstPtr += dStep;
507
          
508
1.04G
          }
509
          
510
3.89M
        }
511
        
512
383k
      else
513
383k
        {
514
      
515
383k
        real32 b1 = 0.0f;
516
        
517
383k
        if (fBlack_1D_rows)
518
1.32k
          {
519
1.32k
          b1 = fBlack_1D_buffer->Buffer_real32 () [dstRow % fBlack_1D_rows];
520
1.32k
          }
521
          
522
383k
        const real32 *b2 = NULL;
523
        
524
383k
        uint32 b2_count = fBlack_2D_cols;
525
383k
        uint32 b2_phase = 0;
526
        
527
383k
        if (b2_count)
528
381k
          {
529
          
530
381k
          b2 = fBlack_2D_buffer->Buffer_real32 () +
531
381k
             b2_count * (dstRow % fBlack_2D_rows);
532
               
533
381k
          b2_phase = dstCol % b2_count;
534
          
535
381k
          }
536
          
537
5.37M
        for (uint32 j = 0; j < count; j++)
538
4.99M
          {
539
          
540
4.99M
          real32 x = (*srcPtr) * scale - b1;
541
          
542
4.99M
          if (b2_count)
543
4.63M
            {
544
          
545
4.63M
            x -= b2 [b2_phase];
546
            
547
4.63M
            if (++b2_phase == b2_count)
548
916k
              {
549
916k
              b2_phase = 0;
550
916k
              }
551
              
552
4.63M
            }
553
          
554
4.99M
          *dstPtr = x;
555
          
556
4.99M
          srcPtr += sStep;
557
4.99M
          dstPtr += dStep;
558
          
559
4.99M
          }
560
          
561
383k
        }
562
563
4.27M
      }
564
                       
565
    // Simple LUT case.
566
    
567
33.6M
    else if (fBlack_1D_rows == 0 &&
568
33.2M
         fBlack_2D_rows == 0 && fSrcPixelType != ttLong)
569
27.3M
      {
570
      
571
27.3M
      if (fDstPixelType == ttShort)
572
27.3M
        {
573
        
574
27.3M
        const uint16 *lut = fScale_buffer->Buffer_uint16 ();
575
        
576
27.3M
        uint16 *dstPtr = (uint16 *) dPtr;
577
        
578
27.3M
        if (fSrcPixelType == ttByte)
579
12.9M
          {
580
          
581
12.9M
          const uint8 *srcPtr = (const uint8 *) sPtr;
582
      
583
1.78G
          for (uint32 j = 0; j < count; j++)
584
1.77G
            {
585
            
586
1.77G
            *dstPtr = lut [*srcPtr];
587
            
588
1.77G
            srcPtr += sStep;
589
1.77G
            dstPtr += dStep;
590
            
591
1.77G
            }
592
            
593
12.9M
          }
594
          
595
14.4M
        else
596
14.4M
          {
597
598
14.4M
          const uint16 *srcPtr = (const uint16 *) sPtr;
599
      
600
2.49G
          for (uint32 j = 0; j < count; j++)
601
2.48G
            {
602
            
603
2.48G
            *dstPtr = lut [*srcPtr];
604
            
605
2.48G
            srcPtr += sStep;
606
2.48G
            dstPtr += dStep;
607
            
608
2.48G
            }
609
            
610
14.4M
          }
611
          
612
27.3M
        }
613
        
614
0
      else
615
0
        {
616
        
617
0
        const real32 *lut = fScale_buffer->Buffer_real32 ();
618
        
619
0
        real32 *dstPtr = (real32 *) dPtr;
620
621
0
        if (fSrcPixelType == ttByte)
622
0
          {
623
          
624
0
          const uint8 *srcPtr = (const uint8 *) sPtr;
625
      
626
0
          for (uint32 j = 0; j < count; j++)
627
0
            {
628
            
629
0
            *dstPtr = lut [*srcPtr];
630
            
631
0
            srcPtr += sStep;
632
0
            dstPtr += dStep;
633
            
634
0
            }
635
            
636
0
          }
637
          
638
0
        else
639
0
          {
640
          
641
0
          const uint16 *srcPtr = (const uint16 *) sPtr;
642
      
643
0
          for (uint32 j = 0; j < count; j++)
644
0
            {
645
            
646
0
            *dstPtr = lut [*srcPtr];
647
            
648
0
            srcPtr += sStep;
649
0
            dstPtr += dStep;
650
            
651
0
            }
652
            
653
0
          }
654
        
655
0
        }
656
      
657
27.3M
      }
658
      
659
    // Integer math case.
660
    
661
6.23M
    else if (!fReal32)
662
346k
      {
663
      
664
346k
      const int32 *lut = fScale_buffer->Buffer_int32 ();
665
      
666
346k
      int32 b1 = 0;
667
      
668
346k
      if (fBlack_1D_rows)
669
321k
        {
670
321k
        b1 = fBlack_1D_buffer->Buffer_int32 () [dstRow % fBlack_1D_rows];
671
321k
        }
672
        
673
346k
      const int32 *b2 = NULL;
674
      
675
346k
      uint32 b2_count = fBlack_2D_cols;
676
346k
      uint32 b2_phase = 0;
677
      
678
346k
      if (b2_count)
679
24.2k
        {
680
        
681
24.2k
        b2 = fBlack_2D_buffer->Buffer_int32 () +
682
24.2k
           b2_count * (dstRow % fBlack_2D_rows);
683
             
684
24.2k
        b2_phase = dstCol % b2_count;
685
        
686
24.2k
        }
687
        
688
346k
      uint16 *dstPtr = (uint16 *) dPtr;
689
690
346k
      b1 -= 128;    // Rounding for 8 bit shift
691
      
692
346k
      if (fSrcPixelType == ttByte)
693
253k
        {
694
      
695
253k
        const uint8 *srcPtr = (const uint8 *) sPtr;
696
        
697
81.8M
        for (uint32 j = 0; j < count; j++)
698
81.6M
          {
699
          
700
81.6M
          int32 x = lut [*srcPtr] - b1;
701
          
702
81.6M
          if (b2_count)
703
2.01M
            {
704
          
705
2.01M
            x -= b2 [b2_phase];
706
            
707
2.01M
            if (++b2_phase == b2_count)
708
701k
              {
709
701k
              b2_phase = 0;
710
701k
              }
711
              
712
2.01M
            }
713
            
714
81.6M
          x >>= 8;
715
            
716
81.6M
          *dstPtr = Pin_uint16 (x);
717
          
718
81.6M
          srcPtr += sStep;
719
81.6M
          dstPtr += dStep;
720
          
721
81.6M
          }
722
          
723
253k
        }
724
        
725
92.1k
      else
726
92.1k
        {
727
      
728
92.1k
        const uint16 *srcPtr = (const uint16 *) sPtr;
729
        
730
3.17M
        for (uint32 j = 0; j < count; j++)
731
3.08M
          {
732
          
733
3.08M
          int32 x = lut [*srcPtr] - b1;
734
          
735
3.08M
          if (b2_count)
736
2.33M
            {
737
          
738
2.33M
            x -= b2 [b2_phase];
739
            
740
2.33M
            if (++b2_phase == b2_count)
741
405k
              {
742
405k
              b2_phase = 0;
743
405k
              }
744
              
745
2.33M
            }
746
            
747
3.08M
          x >>= 8;
748
            
749
3.08M
          *dstPtr = Pin_uint16 (x);
750
          
751
3.08M
          srcPtr += sStep;
752
3.08M
          dstPtr += dStep;
753
          
754
3.08M
          }
755
          
756
92.1k
        }
757
          
758
346k
      }
759
      
760
    // Floating point math cases.
761
    
762
5.88M
    else
763
5.88M
      {
764
          
765
5.88M
      real32 b1 = 0.0f;
766
      
767
5.88M
      if (fBlack_1D_rows)
768
85.9k
        {
769
85.9k
        b1 = fBlack_1D_buffer->Buffer_real32 () [dstRow % fBlack_1D_rows];
770
85.9k
        }
771
        
772
5.88M
      const real32 *b2 = NULL;
773
      
774
5.88M
      uint32 b2_count = fBlack_2D_cols;
775
5.88M
      uint32 b2_phase = 0;
776
      
777
5.88M
      if (b2_count)
778
385k
        {
779
        
780
385k
        b2 = fBlack_2D_buffer->Buffer_real32 () +
781
385k
           b2_count * (dstRow % fBlack_2D_rows);
782
             
783
385k
        b2_phase = dstCol % b2_count;
784
        
785
385k
        }
786
        
787
      // Case 1: uint8/uint16 -> real32
788
        
789
5.88M
      if (fSrcPixelType != ttLong)
790
0
        {
791
        
792
0
        const real32 *lut = fScale_buffer->Buffer_real32 ();
793
        
794
0
        real32 *dstPtr = (real32 *) dPtr;
795
        
796
0
        if (fSrcPixelType == ttByte)
797
0
          {
798
        
799
0
          const uint8 *srcPtr = (const uint8 *) sPtr;
800
        
801
0
          for (uint32 j = 0; j < count; j++)
802
0
            {
803
            
804
0
            real32 x = lut [*srcPtr] - b1;
805
            
806
0
            if (b2_count)
807
0
              {
808
            
809
0
              x -= b2 [b2_phase];
810
              
811
0
              if (++b2_phase == b2_count)
812
0
                {
813
0
                b2_phase = 0;
814
0
                }
815
                
816
0
              }
817
            
818
0
            x = Pin_real32 (0.0f, x, 1.0f);
819
            
820
0
            *dstPtr = x;
821
            
822
0
            srcPtr += sStep;
823
0
            dstPtr += dStep;
824
            
825
0
            }
826
            
827
0
          }
828
          
829
0
        else
830
0
          {
831
        
832
0
          const uint16 *srcPtr = (const uint16 *) sPtr;
833
        
834
0
          for (uint32 j = 0; j < count; j++)
835
0
            {
836
            
837
0
            real32 x = lut [*srcPtr] - b1;
838
            
839
0
            if (b2_count)
840
0
              {
841
            
842
0
              x -= b2 [b2_phase];
843
              
844
0
              if (++b2_phase == b2_count)
845
0
                {
846
0
                b2_phase = 0;
847
0
                }
848
                
849
0
              }
850
            
851
0
            x = Pin_real32 (0.0f, x, 1.0f);
852
            
853
0
            *dstPtr = x;
854
            
855
0
            srcPtr += sStep;
856
0
            dstPtr += dStep;
857
            
858
0
            }
859
            
860
0
          }
861
          
862
0
        }
863
        
864
      // Otherwise source is uint32
865
      
866
5.88M
      else
867
5.88M
        {
868
        
869
5.88M
        real32 scale = fScale;
870
        
871
5.88M
        const uint32 *srcPtr = (const uint32 *) sPtr;
872
        
873
        // Case 2: uint32 -> real32
874
        
875
5.88M
        if (fDstPixelType == ttFloat)
876
5.88M
          {
877
          
878
5.88M
          real32 *dstPtr = (real32 *) dPtr;
879
          
880
714M
          for (uint32 j = 0; j < count; j++)
881
708M
            {
882
            
883
708M
            real32 x = ((real32) *srcPtr) * scale - b1;
884
            
885
708M
            if (b2_count)
886
15.6M
              {
887
            
888
15.6M
              x -= b2 [b2_phase];
889
              
890
15.6M
              if (++b2_phase == b2_count)
891
7.81M
                {
892
7.81M
                b2_phase = 0;
893
7.81M
                }
894
                
895
15.6M
              }
896
            
897
708M
            x = Pin_real32 (0.0f, x, 1.0f);
898
            
899
708M
            *dstPtr = x;
900
            
901
708M
            srcPtr += sStep;
902
708M
            dstPtr += dStep;
903
            
904
708M
            }
905
        
906
5.88M
          }
907
          
908
        // Case 3: uint32 -> uint16
909
        
910
0
        else
911
0
          {
912
          
913
0
          uint16 *dstPtr = (uint16 *) dPtr;
914
          
915
0
          real32 dstScale = (real32) 0x0FFFF;
916
          
917
0
          for (uint32 j = 0; j < count; j++)
918
0
            {
919
            
920
0
            real32 x = ((real32) *srcPtr) * scale - b1;
921
            
922
0
            if (b2_count)
923
0
              {
924
            
925
0
              x -= b2 [b2_phase];
926
              
927
0
              if (++b2_phase == b2_count)
928
0
                {
929
0
                b2_phase = 0;
930
0
                }
931
                
932
0
              }
933
            
934
0
            x = Pin_real32 (0.0f, x, 1.0f);
935
            
936
0
            *dstPtr = (uint16) (x * dstScale + 0.5f);
937
            
938
0
            srcPtr += sStep;
939
0
            dstPtr += dStep;
940
            
941
0
            }
942
        
943
0
          }
944
        
945
5.88M
        }
946
    
947
5.88M
      }
948
    
949
37.8M
    }
950
  
951
113k
  }
952
  
953
/*****************************************************************************/
954
955
class dng_linearize_image: public dng_area_task
956
  {
957
  
958
  private:
959
  
960
    const dng_image & fSrcImage;
961
          dng_image & fDstImage;
962
        
963
    dng_rect fActiveArea;
964
          
965
    AutoPtr<dng_linearize_plane> fPlaneTask [kMaxColorPlanes];
966
    
967
  public:
968
  
969
    dng_linearize_image (dng_host &host,
970
               dng_linearization_info &info,
971
               const dng_image &srcImage,
972
               dng_image &dstImage);
973
               
974
    virtual ~dng_linearize_image ();
975
    
976
    virtual dng_rect RepeatingTile1 () const;
977
               
978
    virtual dng_rect RepeatingTile2 () const;
979
    
980
    virtual void Process (uint32 threadIndex,
981
                const dng_rect &tile,
982
                dng_abort_sniffer *sniffer);
983
                  
984
  };
985
986
/*****************************************************************************/
987
988
dng_linearize_image::dng_linearize_image (dng_host &host,
989
                      dng_linearization_info &info,
990
                      const dng_image &srcImage,
991
                      dng_image &dstImage)
992
               
993
21.9k
  : fSrcImage   (srcImage)
994
21.9k
  , fDstImage   (dstImage)
995
21.9k
  , fActiveArea (info.fActiveArea)
996
  
997
21.9k
  {
998
  
999
  // Build linearization table for each plane.
1000
  
1001
48.6k
  for (uint32 plane = 0; plane < srcImage.Planes (); plane++)
1002
26.6k
    {
1003
    
1004
26.6k
    fPlaneTask [plane].Reset (new dng_linearize_plane (host,
1005
26.6k
                               info,
1006
26.6k
                               srcImage,
1007
26.6k
                               dstImage,
1008
26.6k
                               plane));
1009
                               
1010
26.6k
    }
1011
1012
  // Adjust maximum tile size.
1013
    
1014
21.9k
  fMaxTileSize = dng_point (1024, 1024);
1015
    
1016
21.9k
  }
1017
               
1018
/*****************************************************************************/
1019
1020
dng_linearize_image::~dng_linearize_image ()
1021
21.5k
  {
1022
  
1023
21.5k
  }
1024
               
1025
/*****************************************************************************/
1026
1027
dng_rect dng_linearize_image::RepeatingTile1 () const
1028
43.1k
  {
1029
  
1030
43.1k
  return fSrcImage.RepeatingTile ();
1031
  
1032
43.1k
  }
1033
               
1034
/*****************************************************************************/
1035
1036
dng_rect dng_linearize_image::RepeatingTile2 () const
1037
43.1k
  {
1038
  
1039
43.1k
  return fDstImage.RepeatingTile () + fActiveArea.TL ();
1040
  
1041
43.1k
  }
1042
               
1043
/*****************************************************************************/
1044
1045
void dng_linearize_image::Process (uint32 /* threadIndex */,
1046
                     const dng_rect &srcTile,
1047
                     dng_abort_sniffer * /* sniffer */)
1048
89.0k
  {
1049
1050
  // Process each plane.
1051
  
1052
202k
  for (uint32 plane = 0; plane < fSrcImage.Planes (); plane++)
1053
113k
    {
1054
    
1055
113k
    fPlaneTask [plane]->Process (srcTile);
1056
                               
1057
113k
    }
1058
    
1059
89.0k
  }
1060
  
1061
/*****************************************************************************/
1062
1063
dng_linearization_info::dng_linearization_info ()
1064
1065
48.5k
  : fActiveArea ()
1066
48.5k
  , fMaskedAreaCount (0)
1067
48.5k
  , fLinearizationTable ()
1068
48.5k
  , fBlackLevelRepeatRows (1)
1069
48.5k
  , fBlackLevelRepeatCols (1)
1070
48.5k
  , fBlackDeltaH ()
1071
48.5k
  , fBlackDeltaV ()
1072
48.5k
  , fBlackDenom (256)
1073
  
1074
48.5k
  {
1075
  
1076
48.5k
  uint32 j;
1077
48.5k
  uint32 k;
1078
48.5k
  uint32 n;
1079
  
1080
437k
  for (j = 0; j < kMaxBlackPattern; j++)
1081
3.49M
    for (k = 0; k < kMaxBlackPattern; k++)
1082
15.5M
      for (n = 0; n < kMaxSamplesPerPixel; n++)
1083
12.4M
        {
1084
12.4M
        fBlackLevel [j] [k] [n] = 0.0;
1085
12.4M
        }
1086
        
1087
242k
  for (n = 0; n < kMaxSamplesPerPixel; n++)
1088
194k
    {
1089
194k
    fWhiteLevel [n] = 65535.0;
1090
194k
    }
1091
      
1092
48.5k
  }
1093
  
1094
/*****************************************************************************/
1095
1096
dng_linearization_info::~dng_linearization_info ()
1097
48.5k
  {
1098
  
1099
48.5k
  }
1100
    
1101
/*****************************************************************************/
1102
1103
void dng_linearization_info::RoundBlacks ()
1104
40.4k
  {
1105
  
1106
40.4k
  uint32 j;
1107
40.4k
  uint32 k;
1108
40.4k
  uint32 n;
1109
  
1110
40.4k
  real64 maxAbs = 0.0;
1111
  
1112
82.3k
  for (j = 0; j < fBlackLevelRepeatRows; j++)
1113
88.7k
    for (k = 0; k < fBlackLevelRepeatCols; k++)
1114
233k
      for (n = 0; n < kMaxSamplesPerPixel; n++)
1115
187k
        {
1116
        
1117
187k
        maxAbs = Max_real64 (maxAbs,
1118
187k
                   Abs_real64 (fBlackLevel [j] [k] [n]));
1119
        
1120
187k
        }
1121
        
1122
40.4k
  uint32 count = RowBlackCount ();
1123
        
1124
213k
  for (j = 0; j < count; j++)
1125
172k
    {
1126
    
1127
172k
    maxAbs = Max_real64 (maxAbs,
1128
172k
               Abs_real64 (fBlackDeltaV->Buffer_real64 () [j]));
1129
        
1130
172k
    }
1131
    
1132
40.4k
  count = ColumnBlackCount ();
1133
        
1134
84.2k
  for (j = 0; j < count; j++)
1135
43.8k
    {
1136
    
1137
43.8k
    maxAbs = Max_real64 (maxAbs,
1138
43.8k
               Abs_real64 (fBlackDeltaH->Buffer_real64 () [j]));
1139
        
1140
    
1141
43.8k
    }
1142
    
1143
40.4k
  fBlackDenom = 256;
1144
  
1145
42.3k
  while (fBlackDenom > 1 && (maxAbs * fBlackDenom) >= 30000.0 * 65536.0)
1146
1.95k
    {
1147
1.95k
    fBlackDenom >>= 1;
1148
1.95k
    }
1149
  
1150
82.3k
  for (j = 0; j < fBlackLevelRepeatRows; j++)
1151
88.5k
    for (k = 0; k < fBlackLevelRepeatCols; k++)
1152
233k
      for (n = 0; n < kMaxSamplesPerPixel; n++)
1153
186k
        {
1154
        
1155
186k
        fBlackLevel [j] [k] [n] = BlackLevel (j, k, n).As_real64 ();
1156
        
1157
186k
        }
1158
        
1159
40.4k
  count = RowBlackCount ();
1160
        
1161
212k
  for (j = 0; j < count; j++)
1162
171k
    {
1163
    
1164
171k
    fBlackDeltaV->Buffer_real64 () [j] = RowBlack (j).As_real64 ();
1165
    
1166
171k
    }
1167
    
1168
40.4k
  count = ColumnBlackCount ();
1169
        
1170
81.7k
  for (j = 0; j < count; j++)
1171
41.3k
    {
1172
    
1173
41.3k
    fBlackDeltaH->Buffer_real64 () [j] = ColumnBlack (j).As_real64 ();
1174
    
1175
41.3k
    }
1176
  
1177
40.4k
  }
1178
    
1179
/*****************************************************************************/
1180
1181
void dng_linearization_info::Parse (dng_host &host,
1182
                    dng_stream &stream,
1183
                    dng_info &info)
1184
40.5k
  {
1185
  
1186
40.5k
  uint32 j;
1187
40.5k
  uint32 k;
1188
40.5k
  uint32 n;
1189
  
1190
  // Find main image IFD.
1191
  
1192
40.5k
  dng_ifd &rawIFD = *info.fIFD [info.fMainIndex].Get ();
1193
  
1194
  // Copy active area.
1195
  
1196
40.5k
  fActiveArea = rawIFD.fActiveArea;
1197
  
1198
  // Copy masked areas.
1199
  
1200
40.5k
  fMaskedAreaCount = rawIFD.fMaskedAreaCount;
1201
  
1202
40.5k
  for (j = 0; j < fMaskedAreaCount; j++)
1203
0
    {
1204
0
    fMaskedArea [j] = rawIFD.fMaskedArea [j];
1205
0
    }
1206
    
1207
  // Read linearization LUT.
1208
  
1209
40.5k
  if (rawIFD.fLinearizationTableCount)
1210
4.33k
    {
1211
    
1212
4.33k
    uint32 size = SafeUint32Mult (rawIFD.fLinearizationTableCount,
1213
4.33k
                    static_cast<uint32> (sizeof (uint16)));
1214
    
1215
4.33k
    fLinearizationTable.Reset (host.Allocate (size));
1216
                              
1217
4.33k
    uint16 *table = fLinearizationTable->Buffer_uint16 ();
1218
    
1219
4.33k
    stream.SetReadPosition (rawIFD.fLinearizationTableOffset);
1220
    
1221
3.17M
    for (j = 0; j < rawIFD.fLinearizationTableCount; j++)
1222
3.17M
      {
1223
3.17M
      table [j] = stream.Get_uint16 ();
1224
3.17M
      }
1225
          
1226
4.33k
    }
1227
    
1228
  // Copy black level pattern.
1229
  
1230
40.5k
  fBlackLevelRepeatRows = rawIFD.fBlackLevelRepeatRows;
1231
40.5k
  fBlackLevelRepeatCols = rawIFD.fBlackLevelRepeatCols;
1232
  
1233
364k
  for (j = 0; j < kMaxBlackPattern; j++)
1234
2.91M
    for (k = 0; k < kMaxBlackPattern; k++)
1235
12.9M
      for (n = 0; n < kMaxSamplesPerPixel; n++)
1236
10.3M
        {
1237
10.3M
        fBlackLevel [j] [k] [n] = rawIFD.fBlackLevel [j] [k] [n];
1238
10.3M
        }
1239
  
1240
  // Read BlackDeltaH.
1241
                 
1242
40.5k
  if (rawIFD.fBlackLevelDeltaHCount)
1243
544
    {
1244
    
1245
544
    uint32 size = SafeUint32Mult (rawIFD.fBlackLevelDeltaHCount,
1246
544
                    static_cast<uint32> (sizeof (real64)));
1247
    
1248
544
    fBlackDeltaH.Reset (host.Allocate (size));
1249
    
1250
544
    real64 *blacks = fBlackDeltaH->Buffer_real64 ();
1251
    
1252
544
    stream.SetReadPosition (rawIFD.fBlackLevelDeltaHOffset);
1253
    
1254
44.6k
    for (j = 0; j < rawIFD.fBlackLevelDeltaHCount; j++)
1255
44.1k
      {
1256
44.1k
      blacks [j] = stream.TagValue_real64 (rawIFD.fBlackLevelDeltaHType);
1257
44.1k
      }
1258
      
1259
544
    }
1260
    
1261
  // Read BlackDeltaV.
1262
                 
1263
40.5k
  if (rawIFD.fBlackLevelDeltaVCount)
1264
702
    {
1265
    
1266
702
    uint32 size = SafeUint32Mult (rawIFD.fBlackLevelDeltaVCount,
1267
702
                    static_cast<uint32> (sizeof (real64)));
1268
    
1269
702
    fBlackDeltaV.Reset (host.Allocate (size));
1270
    
1271
702
    real64 *blacks = fBlackDeltaV->Buffer_real64 ();
1272
    
1273
702
    stream.SetReadPosition (rawIFD.fBlackLevelDeltaVOffset);
1274
    
1275
181k
    for (j = 0; j < rawIFD.fBlackLevelDeltaVCount; j++)
1276
181k
      {
1277
181k
      blacks [j] = stream.TagValue_real64 (rawIFD.fBlackLevelDeltaVType);
1278
181k
      }
1279
      
1280
702
    }
1281
    
1282
  // Copy white level.
1283
    
1284
202k
  for (n = 0; n < kMaxSamplesPerPixel; n++)
1285
161k
    {
1286
161k
    fWhiteLevel [n] = rawIFD.fWhiteLevel [n];
1287
161k
    }
1288
    
1289
  // Round off black levels.
1290
    
1291
40.5k
  RoundBlacks ();
1292
1293
40.5k
  }
1294
        
1295
/*****************************************************************************/
1296
1297
void dng_linearization_info::PostParse (dng_host & /* host */,
1298
                    dng_negative &negative)
1299
21.9k
  {
1300
  
1301
21.9k
  if (fActiveArea.IsEmpty ())
1302
0
    {
1303
    
1304
0
    fActiveArea = negative.Stage1Image ()->Bounds ();
1305
    
1306
0
    }
1307
  
1308
21.9k
  }
1309
1310
/*****************************************************************************/
1311
1312
real64 dng_linearization_info::MaxBlackLevel (uint32 plane) const
1313
26.6k
  {
1314
  
1315
26.6k
  uint32 j;
1316
26.6k
  uint32 k;
1317
  
1318
  // Find maximum value of fBlackDeltaH for each phase of black pattern.
1319
  
1320
26.6k
  real64 maxDeltaH [kMaxBlackPattern];
1321
  
1322
54.7k
  for (j = 0; j < fBlackLevelRepeatCols; j++)
1323
28.0k
    {
1324
28.0k
    maxDeltaH [j] = 0.0;
1325
28.0k
    }
1326
    
1327
26.6k
  if (fBlackDeltaH.Get ())
1328
399
    {
1329
    
1330
399
    real64 *table = fBlackDeltaH->Buffer_real64 ();
1331
    
1332
399
    uint32 entries = fBlackDeltaH->LogicalSize () / (uint32) sizeof (table [0]);
1333
    
1334
7.40k
    for (j = 0; j < entries; j++)
1335
7.00k
      {
1336
      
1337
7.00k
      real64 &entry = maxDeltaH [j % fBlackLevelRepeatCols];
1338
      
1339
7.00k
      if (j < fBlackLevelRepeatCols)
1340
446
        {
1341
446
        entry = table [j];
1342
446
        }
1343
6.56k
      else
1344
6.56k
        {
1345
6.56k
        entry = Max_real64 (entry, table [j]);
1346
6.56k
        }
1347
      
1348
7.00k
      }
1349
    
1350
399
    }
1351
    
1352
  // Find maximum value of fBlackDeltaV for each phase of black pattern.
1353
    
1354
26.6k
  real64 maxDeltaV [kMaxBlackPattern];
1355
  
1356
55.0k
  for (j = 0; j < fBlackLevelRepeatRows; j++)
1357
28.3k
    {
1358
28.3k
    maxDeltaV [j] = 0.0;
1359
28.3k
    }
1360
    
1361
26.6k
  if (fBlackDeltaV.Get ())
1362
575
    {
1363
    
1364
575
    real64 *table = fBlackDeltaV->Buffer_real64 ();
1365
    
1366
575
    uint32 entries = fBlackDeltaV->LogicalSize () / (uint32) sizeof (table [0]);
1367
    
1368
84.6k
    for (j = 0; j < entries; j++)
1369
84.1k
      {
1370
      
1371
84.1k
      real64 &entry = maxDeltaV [j % fBlackLevelRepeatRows];
1372
      
1373
84.1k
      if (j < fBlackLevelRepeatRows)
1374
676
        {
1375
676
        entry = table [j];
1376
676
        }
1377
83.4k
      else
1378
83.4k
        {
1379
83.4k
        entry = Max_real64 (entry, table [j]);
1380
83.4k
        }
1381
      
1382
84.1k
      }
1383
    
1384
575
    }
1385
    
1386
  // Now scan the pattern and find the maximum value after row and column
1387
  // deltas.
1388
    
1389
26.6k
  real64 maxBlack = 0.0;
1390
  
1391
55.0k
  for (j = 0; j < fBlackLevelRepeatRows; j++)
1392
28.3k
    {
1393
    
1394
60.8k
    for (k = 0; k < fBlackLevelRepeatCols; k++)
1395
32.4k
      {
1396
      
1397
32.4k
      real64 black = fBlackLevel [j] [k] [plane];
1398
      
1399
32.4k
      black += maxDeltaH [k];
1400
32.4k
      black += maxDeltaV [j];
1401
               
1402
32.4k
      if (j == 0 && k == 0)
1403
26.6k
        {
1404
26.6k
        maxBlack = black;
1405
26.6k
        }
1406
5.80k
      else
1407
5.80k
        {
1408
5.80k
        maxBlack = Max_real64 (maxBlack, black);
1409
5.80k
        }
1410
      
1411
32.4k
      }
1412
      
1413
28.3k
    }
1414
    
1415
26.6k
  return maxBlack;
1416
    
1417
26.6k
  }
1418
        
1419
/*****************************************************************************/
1420
1421
void dng_linearization_info::Linearize (dng_host &host,
1422
                    const dng_image &srcImage,
1423
                    dng_image &dstImage)
1424
21.9k
  {
1425
  
1426
21.9k
  dng_linearize_image processor (host,
1427
21.9k
                   *this,
1428
21.9k
                   srcImage,
1429
21.9k
                   dstImage);
1430
                   
1431
21.9k
  host.PerformAreaTask (processor,
1432
21.9k
              fActiveArea);
1433
            
1434
21.9k
  }
1435
        
1436
/*****************************************************************************/
1437
1438
dng_urational dng_linearization_info::BlackLevel (uint32 row,
1439
                          uint32 col,
1440
                          uint32 plane) const
1441
196k
  {
1442
  
1443
196k
  dng_urational r;
1444
  
1445
196k
  r.Set_real64 (fBlackLevel [row] [col] [plane], fBlackDenom);
1446
  
1447
196k
  return r;
1448
  
1449
196k
  }
1450
        
1451
/*****************************************************************************/
1452
1453
uint32 dng_linearization_info::RowBlackCount () const
1454
88.1k
  {
1455
  
1456
88.1k
  if (fBlackDeltaV.Get ())
1457
1.41k
    {
1458
    
1459
1.41k
    return fBlackDeltaV->LogicalSize () >> 3;
1460
    
1461
1.41k
    }
1462
    
1463
86.7k
  return 0;
1464
    
1465
88.1k
  }
1466
        
1467
/*****************************************************************************/
1468
1469
dng_srational dng_linearization_info::RowBlack (uint32 row) const
1470
171k
  {
1471
  
1472
171k
  if (fBlackDeltaV.Get ())
1473
171k
    {
1474
    
1475
171k
    dng_srational r;
1476
    
1477
171k
    r.Set_real64 (fBlackDeltaV->Buffer_real64 () [row], fBlackDenom);
1478
    
1479
171k
    return r;
1480
    
1481
171k
    }
1482
    
1483
0
  return dng_srational (0, 1);
1484
  
1485
171k
  }
1486
    
1487
/*****************************************************************************/
1488
1489
uint32 dng_linearization_info::ColumnBlackCount () const
1490
88.0k
  {
1491
  
1492
88.0k
  if (fBlackDeltaH.Get ())
1493
1.12k
    {
1494
    
1495
1.12k
    return fBlackDeltaH->LogicalSize () >> 3;
1496
    
1497
1.12k
    }
1498
    
1499
86.9k
  return 0;
1500
    
1501
88.0k
  }
1502
        
1503
/*****************************************************************************/
1504
1505
dng_srational dng_linearization_info::ColumnBlack (uint32 col) const
1506
41.6k
  {
1507
  
1508
41.6k
  if (fBlackDeltaH.Get ())
1509
41.6k
    {
1510
    
1511
41.6k
    dng_srational r;
1512
    
1513
41.6k
    r.Set_real64 (fBlackDeltaH->Buffer_real64 () [col], fBlackDenom);
1514
    
1515
41.6k
    return r;
1516
    
1517
41.6k
    }
1518
    
1519
0
  return dng_srational (0, 1);
1520
  
1521
41.6k
  }
1522
    
1523
/*****************************************************************************/