Coverage Report

Created: 2026-01-10 07:04

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
20.0k
  : fSrcImage (srcImage)
85
20.0k
  , fDstImage (dstImage)
86
20.0k
  , fPlane (plane)
87
20.0k
  , fActiveArea (info.fActiveArea)
88
20.0k
  , fSrcPixelType (srcImage.PixelType ())
89
20.0k
  , fDstPixelType (dstImage.PixelType ())
90
20.0k
  , fReal32 (false)
91
20.0k
  , fScale (0.0f)
92
20.0k
  , fScale_buffer ()
93
20.0k
  , fBlack_2D_rows (0)
94
20.0k
  , fBlack_2D_cols (0)
95
20.0k
  , fBlack_2D_buffer ()
96
20.0k
  , fBlack_1D_rows (0)
97
20.0k
  , fBlack_1D_buffer ()
98
  
99
20.0k
  {
100
  
101
20.0k
  uint32 j;
102
20.0k
  uint32 k;
103
  
104
  // Make sure the source pixel type is supported.
105
  
106
20.0k
  if (fSrcPixelType != ttByte  &&
107
12.5k
    fSrcPixelType != ttShort &&
108
6.19k
    fSrcPixelType != ttLong  &&
109
1.01k
    fSrcPixelType != ttFloat)
110
0
    {
111
    
112
0
    DNG_REPORT ("Unsupported source pixel type");
113
    
114
0
    ThrowProgramError ();
115
    
116
0
    }
117
    
118
20.0k
  if (fDstPixelType != ttShort &&
119
6.19k
    fDstPixelType != ttFloat)
120
0
    {
121
    
122
0
    DNG_REPORT ("Unsupported destination pixel type");
123
    
124
0
    ThrowProgramError ();
125
    
126
0
    }
127
  
128
20.0k
  if (fSrcPixelType == ttFloat &&
129
1.01k
    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
20.0k
  fReal32 = (fSrcPixelType == ttLong ||
141
14.8k
         fDstPixelType == ttFloat);
142
  
143
  // Find the scale for this plane.
144
  
145
20.0k
  real64 maxBlack = info.MaxBlackLevel (plane);
146
  
147
20.0k
  real64 minRange = info.fWhiteLevel [plane] - maxBlack;
148
  
149
20.0k
  if (minRange <= 0.0)
150
27
    {
151
27
    ThrowBadFormat ();
152
27
    }
153
    
154
20.0k
  real64 scale = 1.0 / minRange;
155
  
156
20.0k
  fScale = (real32) scale;
157
    
158
  // Calculate two-dimensional black pattern, if any.
159
  
160
20.0k
  if (info.fBlackDeltaH.Get ())
161
223
    {
162
    
163
223
    fBlack_2D_rows = info.fBlackLevelRepeatRows;
164
223
    fBlack_2D_cols = info.fActiveArea.W ();
165
    
166
223
    }
167
    
168
19.8k
  else if (info.fBlackLevelRepeatCols > 1)
169
396
    {
170
    
171
396
    fBlack_2D_rows = info.fBlackLevelRepeatRows;
172
396
    fBlack_2D_cols = info.fBlackLevelRepeatCols;
173
    
174
396
    }
175
    
176
20.0k
  if (fBlack_2D_rows)
177
619
    {
178
    
179
619
    fBlack_2D_buffer.Reset (host.Allocate (
180
619
      SafeUint32Mult (fBlack_2D_rows, fBlack_2D_cols, 4)));
181
    
182
1.94k
    for (j = 0; j < fBlack_2D_rows; j++)
183
1.33k
      {
184
      
185
9.73k
      for (k = 0;  k < fBlack_2D_cols; k++)
186
8.40k
        {
187
        
188
8.40k
        real64 x = info.fBlackLevel [j]
189
8.40k
                      [k % info.fBlackLevelRepeatCols]
190
8.40k
                      [plane];
191
        
192
8.40k
        if (info.fBlackDeltaH.Get ())
193
4.01k
          {
194
          
195
4.01k
          x += info.fBlackDeltaH->Buffer_real64 () [k];
196
          
197
4.01k
          }
198
          
199
8.40k
        x *= scale;
200
          
201
8.40k
        uint32 index = j * fBlack_2D_cols + k;
202
        
203
8.40k
        if (fReal32)
204
2.61k
          {
205
          
206
2.61k
          fBlack_2D_buffer->Buffer_real32 () [index] = (real32) x;
207
          
208
2.61k
          }
209
          
210
5.79k
        else
211
5.79k
          {
212
          
213
5.79k
          x *= 0x0FFFF * 256.0;
214
          
215
5.79k
          int32 y = Round_int32 (x);
216
          
217
5.79k
          fBlack_2D_buffer->Buffer_int32 () [index] = y;
218
          
219
5.79k
          }
220
        
221
8.40k
        }
222
        
223
1.33k
      }
224
        
225
619
    }
226
    
227
  // Calculate one-dimensional (per row) black pattern, if any.
228
  
229
20.0k
  if (info.fBlackDeltaV.Get ())
230
396
    {
231
    
232
396
    fBlack_1D_rows = info.fActiveArea.H ();
233
    
234
396
    }
235
    
236
19.6k
  else if (fBlack_2D_rows == 0 &&
237
19.0k
       (info.fBlackLevelRepeatRows > 1 || fSrcPixelType != ttShort))
238
13.0k
    {
239
    
240
13.0k
    fBlack_1D_rows = info.fBlackLevelRepeatRows;
241
    
242
13.0k
    }
243
    
244
20.0k
  if (fBlack_1D_rows)
245
13.4k
    {
246
    
247
13.4k
    fBlack_1D_buffer.Reset (host.Allocate (
248
13.4k
      SafeUint32Mult(fBlack_1D_rows, 4)));
249
    
250
13.4k
    bool allZero = true;
251
    
252
144k
    for (j = 0; j < fBlack_1D_rows; j++)
253
131k
      {
254
      
255
131k
      real64 x = 0.0;
256
      
257
131k
      if (fBlack_2D_rows == 0)
258
131k
        {
259
        
260
131k
        x = info.fBlackLevel [j % info.fBlackLevelRepeatRows] 
261
131k
                   [0] 
262
131k
                   [plane];
263
        
264
131k
        }
265
      
266
131k
      if (info.fBlackDeltaV.Get ())
267
117k
        {
268
        
269
117k
        x += info.fBlackDeltaV->Buffer_real64 () [j];
270
        
271
117k
        }
272
        
273
131k
      allZero = allZero && (x == 0.0);
274
        
275
131k
      x *= scale;
276
      
277
131k
      if (fReal32)
278
7.30k
        {
279
        
280
7.30k
        fBlack_1D_buffer->Buffer_real32 () [j] = (real32) x;
281
        
282
7.30k
        }
283
        
284
124k
      else
285
124k
        {
286
        
287
124k
        x *= 0x0FFFF * 256.0;
288
        
289
124k
        int32 y = Round_int32 (x);
290
        
291
124k
        fBlack_1D_buffer->Buffer_int32 () [j] = y;
292
        
293
124k
        }
294
      
295
131k
      }
296
      
297
13.4k
    if (allZero)
298
11.8k
      {
299
      
300
11.8k
      fBlack_1D_rows = 0;
301
      
302
11.8k
      fBlack_1D_buffer.Reset ();
303
      
304
11.8k
      }
305
      
306
13.4k
    }
307
    
308
  // Calculate scale table, if any.
309
  
310
20.0k
  if (fSrcPixelType != ttLong &&
311
14.7k
    fSrcPixelType != ttFloat)
312
13.7k
    {
313
    
314
    // Find linearization table, if any.
315
      
316
13.7k
    uint16 *lut = NULL;
317
    
318
13.7k
    uint32 lutEntries = 0;
319
    
320
13.7k
    if (info.fLinearizationTable.Get ())
321
2.51k
      {
322
      
323
2.51k
      lut = info.fLinearizationTable->Buffer_uint16 ();
324
      
325
2.51k
      lutEntries = info.fLinearizationTable->LogicalSize () >> 1;
326
      
327
2.51k
      }
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
13.7k
    if (fBlack_1D_rows == 0 &&
333
12.4k
        fBlack_2D_rows == 0)
334
12.0k
      {
335
    
336
12.0k
      fScale_buffer.Reset (host.Allocate (0x10000 *
337
12.0k
                          TagTypeSize (fDstPixelType)));
338
                          
339
792M
      for (j = 0; j < 0x10000; j++)
340
792M
        {
341
        
342
792M
        uint32 x = j;
343
        
344
        // Apply linearization table, if any.
345
        
346
792M
        if (lut)
347
80.2M
          {
348
          
349
80.2M
          x = Min_uint32 (x, lutEntries - 1);
350
          
351
80.2M
          x = lut [x];
352
          
353
80.2M
          }
354
          
355
        // Subtract constant black level.
356
        
357
792M
        real64 y = x - info.fBlackLevel [0] [0] [plane];
358
        
359
        // Apply scale.
360
        
361
792M
        y *= scale;
362
        
363
        // We can burn in the clipping also.
364
        
365
792M
        y = Pin_real64 (0.0, y, 1.0);
366
        
367
        // Store output value in table.
368
        
369
792M
        if (fDstPixelType == ttShort)
370
792M
          {
371
          
372
792M
          uint16 z = (uint16) Round_uint32 (y * 0x0FFFF);
373
          
374
792M
          fScale_buffer->Buffer_uint16 () [j] = z;
375
          
376
792M
          }
377
          
378
0
        else
379
0
          {
380
          
381
0
          fScale_buffer->Buffer_real32 () [j] = (real32) y;
382
          
383
0
          }
384
        
385
792M
        }
386
        
387
12.0k
      }
388
    
389
    // Else we only do the scaling operation in the scale table.
390
    
391
1.66k
    else
392
1.66k
      {
393
    
394
1.66k
      fScale_buffer.Reset (host.Allocate (0x10000 * 4));
395
                          
396
103M
      for (j = 0; j < 0x10000; j++)
397
103M
        {
398
        
399
103M
        uint32 x = j;
400
        
401
        // Apply linearization table, if any.
402
        
403
103M
        if (lut)
404
80.0M
          {
405
          
406
80.0M
          x = Min_uint32 (x, lutEntries - 1);
407
          
408
80.0M
          x = lut [x];
409
          
410
80.0M
          }
411
          
412
        // Apply scale.
413
        
414
103M
        real64 y = x * scale;
415
          
416
        // Store output value in table.
417
        
418
103M
        if (fReal32)
419
0
          {
420
          
421
0
          fScale_buffer->Buffer_real32 () [j] = (real32) y;
422
          
423
0
          }
424
          
425
103M
        else
426
103M
          {
427
          
428
103M
          int32 z = Round_int32 (y * 0x0FFFF * 256.0);
429
          
430
103M
          fScale_buffer->Buffer_int32 () [j] = z;
431
          
432
103M
          }
433
        
434
103M
        }
435
        
436
1.66k
      }
437
    
438
13.7k
    }
439
    
440
20.0k
  }
441
               
442
/*****************************************************************************/
443
444
dng_linearize_plane::~dng_linearize_plane ()
445
19.8k
  {
446
  
447
19.8k
  }
448
               
449
/*****************************************************************************/
450
451
void dng_linearize_plane::Process (const dng_rect &srcTile)
452
91.4k
  {
453
454
  // Process tile.
455
  
456
91.4k
  dng_rect dstTile = srcTile - fActiveArea.TL ();
457
    
458
91.4k
  dng_const_tile_buffer srcBuffer (fSrcImage, srcTile);
459
91.4k
  dng_dirty_tile_buffer dstBuffer (fDstImage, dstTile);
460
  
461
91.4k
  int32 sStep = srcBuffer.fColStep;
462
91.4k
  int32 dStep = dstBuffer.fColStep;
463
  
464
91.4k
  uint32 count = srcTile.W ();
465
  
466
91.4k
  uint32 dstCol = dstTile.l;
467
468
91.4k
  uint32 rows = srcTile.H ();
469
470
33.4M
  for (uint32 row = 0; row < rows; row++)
471
33.4M
    {
472
473
33.4M
    uint32 dstRow = dstTile.t + row;
474
  
475
33.4M
    const void *sPtr = srcBuffer.ConstPixel (srcTile.t + row,
476
33.4M
                           srcTile.l,
477
33.4M
                           fPlane);
478
  
479
33.4M
    void *dPtr = dstBuffer.DirtyPixel (dstRow,
480
33.4M
                       dstCol,
481
33.4M
                       fPlane);
482
                       
483
    // Floating point source case.
484
    
485
33.4M
    if (fSrcPixelType == ttFloat)
486
2.43M
      {
487
      
488
2.43M
      real32 scale = fScale;
489
      
490
2.43M
      const real32 *srcPtr = (const real32 *) sPtr;
491
      
492
2.43M
      real32 *dstPtr = (real32 *) dPtr;
493
      
494
      // Optimize scale only case, which is the most common.
495
      
496
2.43M
      if (fBlack_1D_rows == 0 &&
497
2.42M
        fBlack_2D_cols == 0)
498
2.14M
        {
499
      
500
691M
        for (uint32 j = 0; j < count; j++)
501
689M
          {
502
          
503
689M
          *dstPtr = (*srcPtr) * scale;
504
          
505
689M
          srcPtr += sStep;
506
689M
          dstPtr += dStep;
507
          
508
689M
          }
509
          
510
2.14M
        }
511
        
512
293k
      else
513
293k
        {
514
      
515
293k
        real32 b1 = 0.0f;
516
        
517
293k
        if (fBlack_1D_rows)
518
8.16k
          {
519
8.16k
          b1 = fBlack_1D_buffer->Buffer_real32 () [dstRow % fBlack_1D_rows];
520
8.16k
          }
521
          
522
293k
        const real32 *b2 = NULL;
523
        
524
293k
        uint32 b2_count = fBlack_2D_cols;
525
293k
        uint32 b2_phase = 0;
526
        
527
293k
        if (b2_count)
528
285k
          {
529
          
530
285k
          b2 = fBlack_2D_buffer->Buffer_real32 () +
531
285k
             b2_count * (dstRow % fBlack_2D_rows);
532
               
533
285k
          b2_phase = dstCol % b2_count;
534
          
535
285k
          }
536
          
537
1.43M
        for (uint32 j = 0; j < count; j++)
538
1.14M
          {
539
          
540
1.14M
          real32 x = (*srcPtr) * scale - b1;
541
          
542
1.14M
          if (b2_count)
543
943k
            {
544
          
545
943k
            x -= b2 [b2_phase];
546
            
547
943k
            if (++b2_phase == b2_count)
548
330k
              {
549
330k
              b2_phase = 0;
550
330k
              }
551
              
552
943k
            }
553
          
554
1.14M
          *dstPtr = x;
555
          
556
1.14M
          srcPtr += sStep;
557
1.14M
          dstPtr += dStep;
558
          
559
1.14M
          }
560
          
561
293k
        }
562
563
2.43M
      }
564
                       
565
    // Simple LUT case.
566
    
567
30.9M
    else if (fBlack_1D_rows == 0 &&
568
30.6M
         fBlack_2D_rows == 0 && fSrcPixelType != ttLong)
569
24.4M
      {
570
      
571
24.4M
      if (fDstPixelType == ttShort)
572
24.4M
        {
573
        
574
24.4M
        const uint16 *lut = fScale_buffer->Buffer_uint16 ();
575
        
576
24.4M
        uint16 *dstPtr = (uint16 *) dPtr;
577
        
578
24.4M
        if (fSrcPixelType == ttByte)
579
10.9M
          {
580
          
581
10.9M
          const uint8 *srcPtr = (const uint8 *) sPtr;
582
      
583
2.40G
          for (uint32 j = 0; j < count; j++)
584
2.39G
            {
585
            
586
2.39G
            *dstPtr = lut [*srcPtr];
587
            
588
2.39G
            srcPtr += sStep;
589
2.39G
            dstPtr += dStep;
590
            
591
2.39G
            }
592
            
593
10.9M
          }
594
          
595
13.4M
        else
596
13.4M
          {
597
598
13.4M
          const uint16 *srcPtr = (const uint16 *) sPtr;
599
      
600
3.71G
          for (uint32 j = 0; j < count; j++)
601
3.70G
            {
602
            
603
3.70G
            *dstPtr = lut [*srcPtr];
604
            
605
3.70G
            srcPtr += sStep;
606
3.70G
            dstPtr += dStep;
607
            
608
3.70G
            }
609
            
610
13.4M
          }
611
          
612
24.4M
        }
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
24.4M
      }
658
      
659
    // Integer math case.
660
    
661
6.54M
    else if (!fReal32)
662
347k
      {
663
      
664
347k
      const int32 *lut = fScale_buffer->Buffer_int32 ();
665
      
666
347k
      int32 b1 = 0;
667
      
668
347k
      if (fBlack_1D_rows)
669
278k
        {
670
278k
        b1 = fBlack_1D_buffer->Buffer_int32 () [dstRow % fBlack_1D_rows];
671
278k
        }
672
        
673
347k
      const int32 *b2 = NULL;
674
      
675
347k
      uint32 b2_count = fBlack_2D_cols;
676
347k
      uint32 b2_phase = 0;
677
      
678
347k
      if (b2_count)
679
69.1k
        {
680
        
681
69.1k
        b2 = fBlack_2D_buffer->Buffer_int32 () +
682
69.1k
           b2_count * (dstRow % fBlack_2D_rows);
683
             
684
69.1k
        b2_phase = dstCol % b2_count;
685
        
686
69.1k
        }
687
        
688
347k
      uint16 *dstPtr = (uint16 *) dPtr;
689
690
347k
      b1 -= 128;    // Rounding for 8 bit shift
691
      
692
347k
      if (fSrcPixelType == ttByte)
693
188k
        {
694
      
695
188k
        const uint8 *srcPtr = (const uint8 *) sPtr;
696
        
697
56.3M
        for (uint32 j = 0; j < count; j++)
698
56.1M
          {
699
          
700
56.1M
          int32 x = lut [*srcPtr] - b1;
701
          
702
56.1M
          if (b2_count)
703
6.27M
            {
704
          
705
6.27M
            x -= b2 [b2_phase];
706
            
707
6.27M
            if (++b2_phase == b2_count)
708
2.29M
              {
709
2.29M
              b2_phase = 0;
710
2.29M
              }
711
              
712
6.27M
            }
713
            
714
56.1M
          x >>= 8;
715
            
716
56.1M
          *dstPtr = Pin_uint16 (x);
717
          
718
56.1M
          srcPtr += sStep;
719
56.1M
          dstPtr += dStep;
720
          
721
56.1M
          }
722
          
723
188k
        }
724
        
725
159k
      else
726
159k
        {
727
      
728
159k
        const uint16 *srcPtr = (const uint16 *) sPtr;
729
        
730
844k
        for (uint32 j = 0; j < count; j++)
731
684k
          {
732
          
733
684k
          int32 x = lut [*srcPtr] - b1;
734
          
735
684k
          if (b2_count)
736
112k
            {
737
          
738
112k
            x -= b2 [b2_phase];
739
            
740
112k
            if (++b2_phase == b2_count)
741
9.59k
              {
742
9.59k
              b2_phase = 0;
743
9.59k
              }
744
              
745
112k
            }
746
            
747
684k
          x >>= 8;
748
            
749
684k
          *dstPtr = Pin_uint16 (x);
750
          
751
684k
          srcPtr += sStep;
752
684k
          dstPtr += dStep;
753
          
754
684k
          }
755
          
756
159k
        }
757
          
758
347k
      }
759
      
760
    // Floating point math cases.
761
    
762
6.19M
    else
763
6.19M
      {
764
          
765
6.19M
      real32 b1 = 0.0f;
766
      
767
6.19M
      if (fBlack_1D_rows)
768
33.1k
        {
769
33.1k
        b1 = fBlack_1D_buffer->Buffer_real32 () [dstRow % fBlack_1D_rows];
770
33.1k
        }
771
        
772
6.19M
      const real32 *b2 = NULL;
773
      
774
6.19M
      uint32 b2_count = fBlack_2D_cols;
775
6.19M
      uint32 b2_phase = 0;
776
      
777
6.19M
      if (b2_count)
778
6.53k
        {
779
        
780
6.53k
        b2 = fBlack_2D_buffer->Buffer_real32 () +
781
6.53k
           b2_count * (dstRow % fBlack_2D_rows);
782
             
783
6.53k
        b2_phase = dstCol % b2_count;
784
        
785
6.53k
        }
786
        
787
      // Case 1: uint8/uint16 -> real32
788
        
789
6.19M
      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
6.19M
      else
867
6.19M
        {
868
        
869
6.19M
        real32 scale = fScale;
870
        
871
6.19M
        const uint32 *srcPtr = (const uint32 *) sPtr;
872
        
873
        // Case 2: uint32 -> real32
874
        
875
6.19M
        if (fDstPixelType == ttFloat)
876
6.19M
          {
877
          
878
6.19M
          real32 *dstPtr = (real32 *) dPtr;
879
          
880
1.33G
          for (uint32 j = 0; j < count; j++)
881
1.32G
            {
882
            
883
1.32G
            real32 x = ((real32) *srcPtr) * scale - b1;
884
            
885
1.32G
            if (b2_count)
886
15.5k
              {
887
            
888
15.5k
              x -= b2 [b2_phase];
889
              
890
15.5k
              if (++b2_phase == b2_count)
891
4.68k
                {
892
4.68k
                b2_phase = 0;
893
4.68k
                }
894
                
895
15.5k
              }
896
            
897
1.32G
            x = Pin_real32 (0.0f, x, 1.0f);
898
            
899
1.32G
            *dstPtr = x;
900
            
901
1.32G
            srcPtr += sStep;
902
1.32G
            dstPtr += dStep;
903
            
904
1.32G
            }
905
        
906
6.19M
          }
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
6.19M
        }
946
    
947
6.19M
      }
948
    
949
33.4M
    }
950
  
951
91.4k
  }
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
16.7k
  : fSrcImage   (srcImage)
994
16.7k
  , fDstImage   (dstImage)
995
16.7k
  , fActiveArea (info.fActiveArea)
996
  
997
16.7k
  {
998
  
999
  // Build linearization table for each plane.
1000
  
1001
36.8k
  for (uint32 plane = 0; plane < srcImage.Planes (); plane++)
1002
20.0k
    {
1003
    
1004
20.0k
    fPlaneTask [plane].Reset (new dng_linearize_plane (host,
1005
20.0k
                               info,
1006
20.0k
                               srcImage,
1007
20.0k
                               dstImage,
1008
20.0k
                               plane));
1009
                               
1010
20.0k
    }
1011
1012
  // Adjust maximum tile size.
1013
    
1014
16.7k
  fMaxTileSize = dng_point (1024, 1024);
1015
    
1016
16.7k
  }
1017
               
1018
/*****************************************************************************/
1019
1020
dng_linearize_image::~dng_linearize_image ()
1021
16.5k
  {
1022
  
1023
16.5k
  }
1024
               
1025
/*****************************************************************************/
1026
1027
dng_rect dng_linearize_image::RepeatingTile1 () const
1028
33.0k
  {
1029
  
1030
33.0k
  return fSrcImage.RepeatingTile ();
1031
  
1032
33.0k
  }
1033
               
1034
/*****************************************************************************/
1035
1036
dng_rect dng_linearize_image::RepeatingTile2 () const
1037
33.0k
  {
1038
  
1039
33.0k
  return fDstImage.RepeatingTile () + fActiveArea.TL ();
1040
  
1041
33.0k
  }
1042
               
1043
/*****************************************************************************/
1044
1045
void dng_linearize_image::Process (uint32 /* threadIndex */,
1046
                     const dng_rect &srcTile,
1047
                     dng_abort_sniffer * /* sniffer */)
1048
70.4k
  {
1049
1050
  // Process each plane.
1051
  
1052
161k
  for (uint32 plane = 0; plane < fSrcImage.Planes (); plane++)
1053
91.4k
    {
1054
    
1055
91.4k
    fPlaneTask [plane]->Process (srcTile);
1056
                               
1057
91.4k
    }
1058
    
1059
70.4k
  }
1060
  
1061
/*****************************************************************************/
1062
1063
dng_linearization_info::dng_linearization_info ()
1064
1065
39.1k
  : fActiveArea ()
1066
39.1k
  , fMaskedAreaCount (0)
1067
39.1k
  , fLinearizationTable ()
1068
39.1k
  , fBlackLevelRepeatRows (1)
1069
39.1k
  , fBlackLevelRepeatCols (1)
1070
39.1k
  , fBlackDeltaH ()
1071
39.1k
  , fBlackDeltaV ()
1072
39.1k
  , fBlackDenom (256)
1073
  
1074
39.1k
  {
1075
  
1076
39.1k
  uint32 j;
1077
39.1k
  uint32 k;
1078
39.1k
  uint32 n;
1079
  
1080
352k
  for (j = 0; j < kMaxBlackPattern; j++)
1081
2.81M
    for (k = 0; k < kMaxBlackPattern; k++)
1082
12.5M
      for (n = 0; n < kMaxSamplesPerPixel; n++)
1083
10.0M
        {
1084
10.0M
        fBlackLevel [j] [k] [n] = 0.0;
1085
10.0M
        }
1086
        
1087
195k
  for (n = 0; n < kMaxSamplesPerPixel; n++)
1088
156k
    {
1089
156k
    fWhiteLevel [n] = 65535.0;
1090
156k
    }
1091
      
1092
39.1k
  }
1093
  
1094
/*****************************************************************************/
1095
1096
dng_linearization_info::~dng_linearization_info ()
1097
39.1k
  {
1098
  
1099
39.1k
  }
1100
    
1101
/*****************************************************************************/
1102
1103
void dng_linearization_info::RoundBlacks ()
1104
30.6k
  {
1105
  
1106
30.6k
  uint32 j;
1107
30.6k
  uint32 k;
1108
30.6k
  uint32 n;
1109
  
1110
30.6k
  real64 maxAbs = 0.0;
1111
  
1112
62.4k
  for (j = 0; j < fBlackLevelRepeatRows; j++)
1113
67.5k
    for (k = 0; k < fBlackLevelRepeatCols; k++)
1114
178k
      for (n = 0; n < kMaxSamplesPerPixel; n++)
1115
142k
        {
1116
        
1117
142k
        maxAbs = Max_real64 (maxAbs,
1118
142k
                   Abs_real64 (fBlackLevel [j] [k] [n]));
1119
        
1120
142k
        }
1121
        
1122
30.6k
  uint32 count = RowBlackCount ();
1123
        
1124
230k
  for (j = 0; j < count; j++)
1125
200k
    {
1126
    
1127
200k
    maxAbs = Max_real64 (maxAbs,
1128
200k
               Abs_real64 (fBlackDeltaV->Buffer_real64 () [j]));
1129
        
1130
200k
    }
1131
    
1132
30.6k
  count = ColumnBlackCount ();
1133
        
1134
39.1k
  for (j = 0; j < count; j++)
1135
8.53k
    {
1136
    
1137
8.53k
    maxAbs = Max_real64 (maxAbs,
1138
8.53k
               Abs_real64 (fBlackDeltaH->Buffer_real64 () [j]));
1139
        
1140
    
1141
8.53k
    }
1142
    
1143
30.6k
  fBlackDenom = 256;
1144
  
1145
32.1k
  while (fBlackDenom > 1 && (maxAbs * fBlackDenom) >= 30000.0 * 65536.0)
1146
1.52k
    {
1147
1.52k
    fBlackDenom >>= 1;
1148
1.52k
    }
1149
  
1150
62.4k
  for (j = 0; j < fBlackLevelRepeatRows; j++)
1151
67.5k
    for (k = 0; k < fBlackLevelRepeatCols; k++)
1152
178k
      for (n = 0; n < kMaxSamplesPerPixel; n++)
1153
142k
        {
1154
        
1155
142k
        fBlackLevel [j] [k] [n] = BlackLevel (j, k, n).As_real64 ();
1156
        
1157
142k
        }
1158
        
1159
30.6k
  count = RowBlackCount ();
1160
        
1161
230k
  for (j = 0; j < count; j++)
1162
200k
    {
1163
    
1164
200k
    fBlackDeltaV->Buffer_real64 () [j] = RowBlack (j).As_real64 ();
1165
    
1166
200k
    }
1167
    
1168
30.6k
  count = ColumnBlackCount ();
1169
        
1170
36.9k
  for (j = 0; j < count; j++)
1171
6.35k
    {
1172
    
1173
6.35k
    fBlackDeltaH->Buffer_real64 () [j] = ColumnBlack (j).As_real64 ();
1174
    
1175
6.35k
    }
1176
  
1177
30.6k
  }
1178
    
1179
/*****************************************************************************/
1180
1181
void dng_linearization_info::Parse (dng_host &host,
1182
                    dng_stream &stream,
1183
                    dng_info &info)
1184
30.7k
  {
1185
  
1186
30.7k
  uint32 j;
1187
30.7k
  uint32 k;
1188
30.7k
  uint32 n;
1189
  
1190
  // Find main image IFD.
1191
  
1192
30.7k
  dng_ifd &rawIFD = *info.fIFD [info.fMainIndex].Get ();
1193
  
1194
  // Copy active area.
1195
  
1196
30.7k
  fActiveArea = rawIFD.fActiveArea;
1197
  
1198
  // Copy masked areas.
1199
  
1200
30.7k
  fMaskedAreaCount = rawIFD.fMaskedAreaCount;
1201
  
1202
30.7k
  for (j = 0; j < fMaskedAreaCount; j++)
1203
0
    {
1204
0
    fMaskedArea [j] = rawIFD.fMaskedArea [j];
1205
0
    }
1206
    
1207
  // Read linearization LUT.
1208
  
1209
30.7k
  if (rawIFD.fLinearizationTableCount)
1210
2.68k
    {
1211
    
1212
2.68k
    uint32 size = SafeUint32Mult (rawIFD.fLinearizationTableCount,
1213
2.68k
                    static_cast<uint32> (sizeof (uint16)));
1214
    
1215
2.68k
    fLinearizationTable.Reset (host.Allocate (size));
1216
                              
1217
2.68k
    uint16 *table = fLinearizationTable->Buffer_uint16 ();
1218
    
1219
2.68k
    stream.SetReadPosition (rawIFD.fLinearizationTableOffset);
1220
    
1221
1.21M
    for (j = 0; j < rawIFD.fLinearizationTableCount; j++)
1222
1.21M
      {
1223
1.21M
      table [j] = stream.Get_uint16 ();
1224
1.21M
      }
1225
          
1226
2.68k
    }
1227
    
1228
  // Copy black level pattern.
1229
  
1230
30.7k
  fBlackLevelRepeatRows = rawIFD.fBlackLevelRepeatRows;
1231
30.7k
  fBlackLevelRepeatCols = rawIFD.fBlackLevelRepeatCols;
1232
  
1233
276k
  for (j = 0; j < kMaxBlackPattern; j++)
1234
2.20M
    for (k = 0; k < kMaxBlackPattern; k++)
1235
9.81M
      for (n = 0; n < kMaxSamplesPerPixel; n++)
1236
7.85M
        {
1237
7.85M
        fBlackLevel [j] [k] [n] = rawIFD.fBlackLevel [j] [k] [n];
1238
7.85M
        }
1239
  
1240
  // Read BlackDeltaH.
1241
                 
1242
30.7k
  if (rawIFD.fBlackLevelDeltaHCount)
1243
374
    {
1244
    
1245
374
    uint32 size = SafeUint32Mult (rawIFD.fBlackLevelDeltaHCount,
1246
374
                    static_cast<uint32> (sizeof (real64)));
1247
    
1248
374
    fBlackDeltaH.Reset (host.Allocate (size));
1249
    
1250
374
    real64 *blacks = fBlackDeltaH->Buffer_real64 ();
1251
    
1252
374
    stream.SetReadPosition (rawIFD.fBlackLevelDeltaHOffset);
1253
    
1254
9.13k
    for (j = 0; j < rawIFD.fBlackLevelDeltaHCount; j++)
1255
8.76k
      {
1256
8.76k
      blacks [j] = stream.TagValue_real64 (rawIFD.fBlackLevelDeltaHType);
1257
8.76k
      }
1258
      
1259
374
    }
1260
    
1261
  // Read BlackDeltaV.
1262
                 
1263
30.7k
  if (rawIFD.fBlackLevelDeltaVCount)
1264
494
    {
1265
    
1266
494
    uint32 size = SafeUint32Mult (rawIFD.fBlackLevelDeltaVCount,
1267
494
                    static_cast<uint32> (sizeof (real64)));
1268
    
1269
494
    fBlackDeltaV.Reset (host.Allocate (size));
1270
    
1271
494
    real64 *blacks = fBlackDeltaV->Buffer_real64 ();
1272
    
1273
494
    stream.SetReadPosition (rawIFD.fBlackLevelDeltaVOffset);
1274
    
1275
234k
    for (j = 0; j < rawIFD.fBlackLevelDeltaVCount; j++)
1276
234k
      {
1277
234k
      blacks [j] = stream.TagValue_real64 (rawIFD.fBlackLevelDeltaVType);
1278
234k
      }
1279
      
1280
494
    }
1281
    
1282
  // Copy white level.
1283
    
1284
153k
  for (n = 0; n < kMaxSamplesPerPixel; n++)
1285
122k
    {
1286
122k
    fWhiteLevel [n] = rawIFD.fWhiteLevel [n];
1287
122k
    }
1288
    
1289
  // Round off black levels.
1290
    
1291
30.7k
  RoundBlacks ();
1292
1293
30.7k
  }
1294
        
1295
/*****************************************************************************/
1296
1297
void dng_linearization_info::PostParse (dng_host & /* host */,
1298
                    dng_negative &negative)
1299
16.7k
  {
1300
  
1301
16.7k
  if (fActiveArea.IsEmpty ())
1302
0
    {
1303
    
1304
0
    fActiveArea = negative.Stage1Image ()->Bounds ();
1305
    
1306
0
    }
1307
  
1308
16.7k
  }
1309
1310
/*****************************************************************************/
1311
1312
real64 dng_linearization_info::MaxBlackLevel (uint32 plane) const
1313
20.0k
  {
1314
  
1315
20.0k
  uint32 j;
1316
20.0k
  uint32 k;
1317
  
1318
  // Find maximum value of fBlackDeltaH for each phase of black pattern.
1319
  
1320
20.0k
  real64 maxDeltaH [kMaxBlackPattern];
1321
  
1322
41.5k
  for (j = 0; j < fBlackLevelRepeatCols; j++)
1323
21.5k
    {
1324
21.5k
    maxDeltaH [j] = 0.0;
1325
21.5k
    }
1326
    
1327
20.0k
  if (fBlackDeltaH.Get ())
1328
245
    {
1329
    
1330
245
    real64 *table = fBlackDeltaH->Buffer_real64 ();
1331
    
1332
245
    uint32 entries = fBlackDeltaH->LogicalSize () / (uint32) sizeof (table [0]);
1333
    
1334
4.44k
    for (j = 0; j < entries; j++)
1335
4.20k
      {
1336
      
1337
4.20k
      real64 &entry = maxDeltaH [j % fBlackLevelRepeatCols];
1338
      
1339
4.20k
      if (j < fBlackLevelRepeatCols)
1340
277
        {
1341
277
        entry = table [j];
1342
277
        }
1343
3.92k
      else
1344
3.92k
        {
1345
3.92k
        entry = Max_real64 (entry, table [j]);
1346
3.92k
        }
1347
      
1348
4.20k
      }
1349
    
1350
245
    }
1351
    
1352
  // Find maximum value of fBlackDeltaV for each phase of black pattern.
1353
    
1354
20.0k
  real64 maxDeltaV [kMaxBlackPattern];
1355
  
1356
41.5k
  for (j = 0; j < fBlackLevelRepeatRows; j++)
1357
21.5k
    {
1358
21.5k
    maxDeltaV [j] = 0.0;
1359
21.5k
    }
1360
    
1361
20.0k
  if (fBlackDeltaV.Get ())
1362
401
    {
1363
    
1364
401
    real64 *table = fBlackDeltaV->Buffer_real64 ();
1365
    
1366
401
    uint32 entries = fBlackDeltaV->LogicalSize () / (uint32) sizeof (table [0]);
1367
    
1368
118k
    for (j = 0; j < entries; j++)
1369
118k
      {
1370
      
1371
118k
      real64 &entry = maxDeltaV [j % fBlackLevelRepeatRows];
1372
      
1373
118k
      if (j < fBlackLevelRepeatRows)
1374
490
        {
1375
490
        entry = table [j];
1376
490
        }
1377
117k
      else
1378
117k
        {
1379
117k
        entry = Max_real64 (entry, table [j]);
1380
117k
        }
1381
      
1382
118k
      }
1383
    
1384
401
    }
1385
    
1386
  // Now scan the pattern and find the maximum value after row and column
1387
  // deltas.
1388
    
1389
20.0k
  real64 maxBlack = 0.0;
1390
  
1391
41.5k
  for (j = 0; j < fBlackLevelRepeatRows; j++)
1392
21.5k
    {
1393
    
1394
47.0k
    for (k = 0; k < fBlackLevelRepeatCols; k++)
1395
25.5k
      {
1396
      
1397
25.5k
      real64 black = fBlackLevel [j] [k] [plane];
1398
      
1399
25.5k
      black += maxDeltaH [k];
1400
25.5k
      black += maxDeltaV [j];
1401
               
1402
25.5k
      if (j == 0 && k == 0)
1403
20.0k
        {
1404
20.0k
        maxBlack = black;
1405
20.0k
        }
1406
5.42k
      else
1407
5.42k
        {
1408
5.42k
        maxBlack = Max_real64 (maxBlack, black);
1409
5.42k
        }
1410
      
1411
25.5k
      }
1412
      
1413
21.5k
    }
1414
    
1415
20.0k
  return maxBlack;
1416
    
1417
20.0k
  }
1418
        
1419
/*****************************************************************************/
1420
1421
void dng_linearization_info::Linearize (dng_host &host,
1422
                    const dng_image &srcImage,
1423
                    dng_image &dstImage)
1424
16.7k
  {
1425
  
1426
16.7k
  dng_linearize_image processor (host,
1427
16.7k
                   *this,
1428
16.7k
                   srcImage,
1429
16.7k
                   dstImage);
1430
                   
1431
16.7k
  host.PerformAreaTask (processor,
1432
16.7k
              fActiveArea);
1433
            
1434
16.7k
  }
1435
        
1436
/*****************************************************************************/
1437
1438
dng_urational dng_linearization_info::BlackLevel (uint32 row,
1439
                          uint32 col,
1440
                          uint32 plane) const
1441
153k
  {
1442
  
1443
153k
  dng_urational r;
1444
  
1445
153k
  r.Set_real64 (fBlackLevel [row] [col] [plane], fBlackDenom);
1446
  
1447
153k
  return r;
1448
  
1449
153k
  }
1450
        
1451
/*****************************************************************************/
1452
1453
uint32 dng_linearization_info::RowBlackCount () const
1454
68.4k
  {
1455
  
1456
68.4k
  if (fBlackDeltaV.Get ())
1457
1.01k
    {
1458
    
1459
1.01k
    return fBlackDeltaV->LogicalSize () >> 3;
1460
    
1461
1.01k
    }
1462
    
1463
67.4k
  return 0;
1464
    
1465
68.4k
  }
1466
        
1467
/*****************************************************************************/
1468
1469
dng_srational dng_linearization_info::RowBlack (uint32 row) const
1470
200k
  {
1471
  
1472
200k
  if (fBlackDeltaV.Get ())
1473
200k
    {
1474
    
1475
200k
    dng_srational r;
1476
    
1477
200k
    r.Set_real64 (fBlackDeltaV->Buffer_real64 () [row], fBlackDenom);
1478
    
1479
200k
    return r;
1480
    
1481
200k
    }
1482
    
1483
0
  return dng_srational (0, 1);
1484
  
1485
200k
  }
1486
    
1487
/*****************************************************************************/
1488
1489
uint32 dng_linearization_info::ColumnBlackCount () const
1490
68.4k
  {
1491
  
1492
68.4k
  if (fBlackDeltaH.Get ())
1493
802
    {
1494
    
1495
802
    return fBlackDeltaH->LogicalSize () >> 3;
1496
    
1497
802
    }
1498
    
1499
67.6k
  return 0;
1500
    
1501
68.4k
  }
1502
        
1503
/*****************************************************************************/
1504
1505
dng_srational dng_linearization_info::ColumnBlack (uint32 col) const
1506
6.69k
  {
1507
  
1508
6.69k
  if (fBlackDeltaH.Get ())
1509
6.69k
    {
1510
    
1511
6.69k
    dng_srational r;
1512
    
1513
6.69k
    r.Set_real64 (fBlackDeltaH->Buffer_real64 () [col], fBlackDenom);
1514
    
1515
6.69k
    return r;
1516
    
1517
6.69k
    }
1518
    
1519
0
  return dng_srational (0, 1);
1520
  
1521
6.69k
  }
1522
    
1523
/*****************************************************************************/