Coverage Report

Created: 2025-08-26 06:51

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