Coverage Report

Created: 2021-08-22 09:07

/src/skia/third_party/externals/dng_sdk/source/dng_camera_profile.cpp
Line
Count
Source (jump to first uncovered line)
1
/*****************************************************************************/
2
// Copyright 2006-2008 Adobe Systems Incorporated
3
// All Rights Reserved.
4
//
5
// NOTICE:  Adobe permits you to use, modify, and distribute this file in
6
// accordance with the terms of the Adobe license agreement accompanying it.
7
/*****************************************************************************/
8
9
/* $Id: //mondo/dng_sdk_1_4/dng_sdk/source/dng_camera_profile.cpp#1 $ */ 
10
/* $DateTime: 2012/05/30 13:28:51 $ */
11
/* $Change: 832332 $ */
12
/* $Author: tknoll $ */
13
14
#include "dng_camera_profile.h"
15
16
#include "dng_1d_table.h"
17
#include "dng_assertions.h"
18
#include "dng_color_space.h"
19
#include "dng_host.h"
20
#include "dng_exceptions.h"
21
#include "dng_image_writer.h"
22
#include "dng_info.h"
23
#include "dng_parse_utils.h"
24
#include "dng_safe_arithmetic.h"
25
#include "dng_tag_codes.h"
26
#include "dng_tag_types.h"
27
#include "dng_temperature.h"
28
#include "dng_xy_coord.h"
29
30
/*****************************************************************************/
31
32
const char * kProfileName_Embedded = "Embedded";
33
34
const char * kAdobeCalibrationSignature = "com.adobe";
35
36
/*****************************************************************************/
37
38
dng_camera_profile::dng_camera_profile ()
39
40
  : fName ()
41
  , fCalibrationIlluminant1 (lsUnknown)
42
  , fCalibrationIlluminant2 (lsUnknown)
43
  , fColorMatrix1 ()
44
  , fColorMatrix2 ()
45
  , fForwardMatrix1 ()
46
  , fForwardMatrix2 ()
47
  , fReductionMatrix1 ()
48
  , fReductionMatrix2 ()
49
  , fFingerprint ()
50
  , fCopyright ()
51
  , fEmbedPolicy (pepAllowCopying)
52
  , fHueSatDeltas1 ()
53
  , fHueSatDeltas2 ()
54
  , fHueSatMapEncoding (encoding_Linear)
55
  , fLookTable ()
56
  , fLookTableEncoding (encoding_Linear)
57
  , fBaselineExposureOffset (0, 100)
58
  , fDefaultBlackRender (defaultBlackRender_Auto)
59
  , fToneCurve ()
60
  , fProfileCalibrationSignature ()
61
  , fUniqueCameraModelRestriction ()
62
  , fWasReadFromDNG (false)
63
  , fWasReadFromDisk (false)
64
  , fWasBuiltinMatrix (false)
65
  , fWasStubbed (false)
66
  
67
0
  {
68
69
0
  fToneCurve.SetInvalid ();
70
71
0
  }
72
73
/*****************************************************************************/
74
75
dng_camera_profile::~dng_camera_profile ()
76
0
  {
77
  
78
0
  }
79
80
/*****************************************************************************/
81
82
real64 dng_camera_profile::IlluminantToTemperature (uint32 light)
83
0
  {
84
  
85
0
  switch (light)
86
0
    {
87
    
88
0
    case lsStandardLightA:
89
0
    case lsTungsten:
90
0
      {
91
0
      return 2850.0;
92
0
      }
93
      
94
0
    case lsISOStudioTungsten:
95
0
      {
96
0
      return 3200.0;
97
0
      }
98
      
99
0
    case lsD50:
100
0
      {
101
0
      return 5000.0;
102
0
      }
103
      
104
0
    case lsD55:
105
0
    case lsDaylight:
106
0
    case lsFineWeather:
107
0
    case lsFlash:
108
0
    case lsStandardLightB:
109
0
      {
110
0
      return 5500.0;
111
0
      }
112
      
113
0
    case lsD65:
114
0
    case lsStandardLightC:
115
0
    case lsCloudyWeather:
116
0
      {
117
0
      return 6500.0;
118
0
      }
119
      
120
0
    case lsD75:
121
0
    case lsShade:
122
0
      {
123
0
      return 7500.0;
124
0
      }
125
      
126
0
    case lsDaylightFluorescent:
127
0
      {
128
0
      return (5700.0 + 7100.0) * 0.5;
129
0
      }
130
      
131
0
    case lsDayWhiteFluorescent:
132
0
      {
133
0
      return (4600.0 + 5500.0) * 0.5;
134
0
      }
135
      
136
0
    case lsCoolWhiteFluorescent:
137
0
    case lsFluorescent:
138
0
      {
139
0
      return (3800.0 + 4500.0) * 0.5;
140
0
      }
141
      
142
0
    case lsWhiteFluorescent:
143
0
      {
144
0
      return (3250.0 + 3800.0) * 0.5;
145
0
      }
146
      
147
0
    case lsWarmWhiteFluorescent:
148
0
      {
149
0
      return (2600.0 + 3250.0) * 0.5;
150
0
      }
151
      
152
0
    default:
153
0
      {
154
0
      return 0.0;
155
0
      }
156
      
157
0
    }
158
  
159
0
  }
160
161
/******************************************************************************/
162
163
void dng_camera_profile::NormalizeColorMatrix (dng_matrix &m)
164
0
  {
165
  
166
0
  if (m.NotEmpty ())
167
0
    {
168
  
169
    // Find scale factor to normalize the matrix.
170
    
171
0
    dng_vector coord = m * PCStoXYZ ();
172
    
173
0
    real64 maxCoord = coord.MaxEntry ();
174
    
175
0
    if (maxCoord > 0.0 && (maxCoord < 0.99 || maxCoord > 1.01))
176
0
      {
177
      
178
0
      m.Scale (1.0 / maxCoord);
179
      
180
0
      }
181
      
182
    // Round to four decimal places.
183
    
184
0
    m.Round (10000);
185
    
186
0
    }
187
      
188
0
  }
189
190
/******************************************************************************/
191
192
void dng_camera_profile::SetColorMatrix1 (const dng_matrix &m)
193
0
  {
194
  
195
0
  fColorMatrix1 = m;
196
  
197
0
  NormalizeColorMatrix (fColorMatrix1);
198
199
0
  ClearFingerprint ();
200
  
201
0
  }
202
203
/******************************************************************************/
204
205
void dng_camera_profile::SetColorMatrix2 (const dng_matrix &m)
206
0
  {
207
  
208
0
  fColorMatrix2 = m;
209
  
210
0
  NormalizeColorMatrix (fColorMatrix2);
211
  
212
0
  ClearFingerprint ();
213
214
0
  }
215
    
216
/******************************************************************************/
217
218
// Make sure the forward matrix maps to exactly the PCS.
219
220
void dng_camera_profile::NormalizeForwardMatrix (dng_matrix &m)
221
0
  {
222
  
223
0
  if (m.NotEmpty ())
224
0
    {
225
    
226
0
    dng_vector cameraOne;
227
    
228
0
    cameraOne.SetIdentity (m.Cols ());
229
    
230
0
    dng_vector xyz = m * cameraOne;
231
    
232
0
    m = PCStoXYZ ().AsDiagonal () *
233
0
      Invert (xyz.AsDiagonal ()) *
234
0
      m;
235
    
236
0
    }
237
  
238
0
  }
239
240
/******************************************************************************/
241
242
void dng_camera_profile::SetForwardMatrix1 (const dng_matrix &m)
243
0
  {
244
  
245
0
  fForwardMatrix1 = m;
246
  
247
0
  fForwardMatrix1.Round (10000);
248
  
249
0
  ClearFingerprint ();
250
  
251
0
  }
252
253
/******************************************************************************/
254
255
void dng_camera_profile::SetForwardMatrix2 (const dng_matrix &m)
256
0
  {
257
  
258
0
  fForwardMatrix2 = m;
259
  
260
0
  fForwardMatrix2.Round (10000);
261
  
262
0
  ClearFingerprint ();
263
  
264
0
  }
265
266
/*****************************************************************************/
267
268
void dng_camera_profile::SetReductionMatrix1 (const dng_matrix &m)
269
0
  {
270
  
271
0
  fReductionMatrix1 = m;
272
  
273
0
  fReductionMatrix1.Round (10000);
274
  
275
0
  ClearFingerprint ();
276
277
0
  }
278
279
/******************************************************************************/
280
281
void dng_camera_profile::SetReductionMatrix2 (const dng_matrix &m)
282
0
  {
283
  
284
0
  fReductionMatrix2 = m;
285
  
286
0
  fReductionMatrix2.Round (10000);
287
  
288
0
  ClearFingerprint ();
289
290
0
  }
291
292
/*****************************************************************************/
293
294
bool dng_camera_profile::HasColorMatrix1 () const
295
0
  {
296
  
297
0
  return fColorMatrix1.Cols () == 3 &&
298
0
       fColorMatrix1.Rows ()  > 1;
299
  
300
0
  }
301
    
302
/*****************************************************************************/
303
304
bool dng_camera_profile::HasColorMatrix2 () const
305
0
  {
306
307
0
  return fColorMatrix2.Cols () == 3 &&
308
0
       fColorMatrix2.Rows () == fColorMatrix1.Rows ();
309
  
310
0
  }
311
    
312
/*****************************************************************************/
313
314
void dng_camera_profile::SetHueSatDeltas1 (const dng_hue_sat_map &deltas1)
315
0
  {
316
317
0
  fHueSatDeltas1 = deltas1;
318
319
0
  ClearFingerprint ();
320
321
0
  }
322
323
/*****************************************************************************/
324
325
void dng_camera_profile::SetHueSatDeltas2 (const dng_hue_sat_map &deltas2)
326
0
  {
327
328
0
  fHueSatDeltas2 = deltas2;
329
330
0
  ClearFingerprint ();
331
332
0
  }
333
334
/*****************************************************************************/
335
336
void dng_camera_profile::SetLookTable (const dng_hue_sat_map &table)
337
0
  {
338
339
0
  fLookTable = table;
340
341
0
  ClearFingerprint ();
342
343
0
  }
344
345
/*****************************************************************************/
346
347
static void FingerprintMatrix (dng_md5_printer_stream &printer,
348
                 const dng_matrix &matrix)
349
0
  {
350
351
0
  tag_matrix tag (0, matrix);
352
  
353
  // Tag's Put routine doesn't write the header, only the data
354
355
0
  tag.Put (printer);
356
357
0
  }
358
359
/*****************************************************************************/
360
361
static void FingerprintHueSatMap (dng_md5_printer_stream &printer,
362
                  const dng_hue_sat_map &map)
363
0
  {
364
365
0
  if (map.IsNull ())
366
0
    return;
367
368
0
  uint32 hues;
369
0
  uint32 sats;
370
0
  uint32 vals;
371
372
0
  map.GetDivisions (hues, sats, vals);
373
374
0
  printer.Put_uint32 (hues);
375
0
  printer.Put_uint32 (sats);
376
0
  printer.Put_uint32 (vals);
377
378
0
  for (uint32 val = 0; val < vals; val++)
379
0
    for (uint32 hue = 0; hue < hues; hue++)
380
0
      for (uint32 sat = 0; sat < sats; sat++)
381
0
        {
382
383
0
        dng_hue_sat_map::HSBModify modify;
384
385
0
        map.GetDelta (hue, sat, val, modify);
386
387
0
        printer.Put_real32 (modify.fHueShift);
388
0
        printer.Put_real32 (modify.fSatScale);
389
0
        printer.Put_real32 (modify.fValScale);
390
391
0
        }
392
393
0
  }
394
395
/*****************************************************************************/
396
397
void dng_camera_profile::CalculateFingerprint () const
398
0
  {
399
  
400
0
  DNG_ASSERT (!fWasStubbed, "CalculateFingerprint on stubbed profile");
401
402
0
  dng_md5_printer_stream printer;
403
404
  // MD5 hash is always calculated on little endian data.
405
406
0
  printer.SetLittleEndian ();
407
  
408
  // The data that we fingerprint closely matches that saved
409
  // by the profile_tag_set class in dng_image_writer.cpp, with
410
  // the exception of the fingerprint itself.
411
  
412
0
  if (HasColorMatrix1 ())
413
0
    {
414
415
0
    uint32 colorChannels = ColorMatrix1 ().Rows ();
416
    
417
0
    printer.Put_uint16 ((uint16) fCalibrationIlluminant1);
418
419
0
    FingerprintMatrix (printer, fColorMatrix1);
420
    
421
0
    if (fForwardMatrix1.Rows () == fColorMatrix1.Cols () &&
422
0
      fForwardMatrix1.Cols () == fColorMatrix1.Rows ())
423
0
      {
424
      
425
0
      FingerprintMatrix (printer, fForwardMatrix1);
426
      
427
0
      }
428
    
429
0
    if (colorChannels > 3 && fReductionMatrix1.Rows () *
430
0
                 fReductionMatrix1.Cols () == colorChannels * 3)
431
0
      {
432
      
433
0
      FingerprintMatrix (printer, fReductionMatrix1);
434
      
435
0
      }
436
    
437
0
    if (HasColorMatrix2 ())
438
0
      {
439
      
440
0
      printer.Put_uint16 ((uint16) fCalibrationIlluminant2);
441
      
442
0
      FingerprintMatrix (printer, fColorMatrix2);
443
    
444
0
      if (fForwardMatrix2.Rows () == fColorMatrix2.Cols () &&
445
0
        fForwardMatrix2.Cols () == fColorMatrix2.Rows ())
446
0
        {
447
        
448
0
        FingerprintMatrix (printer, fForwardMatrix2);
449
        
450
0
        }
451
    
452
0
      if (colorChannels > 3 && fReductionMatrix2.Rows () *
453
0
                   fReductionMatrix2.Cols () == colorChannels * 3)
454
0
        {
455
        
456
0
        FingerprintMatrix (printer, fReductionMatrix2);
457
        
458
0
        }
459
        
460
0
      }
461
    
462
0
    printer.Put (fName.Get    (),
463
0
           fName.Length ());
464
465
0
    printer.Put (fProfileCalibrationSignature.Get    (),
466
0
           fProfileCalibrationSignature.Length ());
467
468
0
    printer.Put_uint32 (fEmbedPolicy);
469
    
470
0
    printer.Put (fCopyright.Get    (),
471
0
           fCopyright.Length ());
472
           
473
0
    bool haveHueSat1 = HueSatDeltas1 ().IsValid ();
474
    
475
0
    bool haveHueSat2 = HueSatDeltas2 ().IsValid () &&
476
0
               HasColorMatrix2 ();
477
478
0
    if (haveHueSat1)
479
0
      {
480
      
481
0
      FingerprintHueSatMap (printer, fHueSatDeltas1);
482
      
483
0
      }
484
      
485
0
    if (haveHueSat2)
486
0
      {
487
      
488
0
      FingerprintHueSatMap (printer, fHueSatDeltas2);
489
      
490
0
      }
491
492
0
    if (haveHueSat1 || haveHueSat2)
493
0
      {
494
495
0
      if (fHueSatMapEncoding != 0)
496
0
        {
497
498
0
        printer.Put_uint32 (fHueSatMapEncoding);
499
500
0
        }
501
      
502
0
      }
503
      
504
0
    if (fLookTable.IsValid ())
505
0
      {
506
      
507
0
      FingerprintHueSatMap (printer, fLookTable);
508
509
0
      if (fLookTableEncoding != 0)
510
0
        {
511
512
0
        printer.Put_uint32 (fLookTableEncoding);
513
514
0
        }
515
      
516
0
      }
517
518
0
    if (fBaselineExposureOffset.IsValid ())
519
0
      {
520
      
521
0
      if (fBaselineExposureOffset.As_real64 () != 0.0)
522
0
        {
523
524
0
        printer.Put_real64 (fBaselineExposureOffset.As_real64 ());
525
526
0
        }
527
      
528
0
      }
529
530
0
    if (fDefaultBlackRender != 0)
531
0
      {
532
      
533
0
      printer.Put_int32 (fDefaultBlackRender);
534
      
535
0
      }
536
      
537
0
    if (fToneCurve.IsValid ())
538
0
      {
539
      
540
0
      for (uint32 i = 0; i < fToneCurve.fCoord.size (); i++)
541
0
        {
542
        
543
0
        printer.Put_real32 ((real32) fToneCurve.fCoord [i].h);
544
0
        printer.Put_real32 ((real32) fToneCurve.fCoord [i].v);
545
        
546
0
        }
547
        
548
0
      }
549
      
550
0
    }
551
552
0
  fFingerprint = printer.Result ();
553
554
0
  }
555
556
/******************************************************************************/
557
558
bool dng_camera_profile::ValidForwardMatrix (const dng_matrix &m)
559
0
  {
560
  
561
0
  const real64 kThreshold = 0.01;
562
  
563
0
  if (m.NotEmpty ())
564
0
    {
565
    
566
0
    dng_vector cameraOne;
567
    
568
0
    cameraOne.SetIdentity (m.Cols ());
569
    
570
0
    dng_vector xyz = m * cameraOne;
571
    
572
0
    dng_vector pcs = PCStoXYZ ();
573
    
574
0
    if (Abs_real64 (xyz [0] - pcs [0]) > kThreshold ||
575
0
      Abs_real64 (xyz [1] - pcs [1]) > kThreshold ||
576
0
      Abs_real64 (xyz [2] - pcs [2]) > kThreshold)
577
0
      {
578
      
579
0
      return false;
580
      
581
0
      }
582
      
583
0
    }
584
    
585
0
  return true;
586
  
587
0
  }
588
589
/******************************************************************************/
590
591
bool dng_camera_profile::IsValid (uint32 channels) const
592
0
  {
593
  
594
  // For Monochrome images, we ignore the camera profile.
595
    
596
0
  if (channels == 1)
597
0
    {
598
    
599
0
    return true;
600
    
601
0
    }
602
    
603
  // ColorMatrix1 is required for all color images.
604
    
605
0
  if (fColorMatrix1.Cols () != 3 ||
606
0
    fColorMatrix1.Rows () != channels)
607
0
    {
608
    
609
    #if qDNGValidate
610
  
611
    ReportError ("ColorMatrix1 is wrong size");
612
           
613
    #endif
614
           
615
0
    return false;
616
    
617
0
    }
618
    
619
  // ColorMatrix2 is optional, but it must be valid if present.
620
  
621
0
  if (fColorMatrix2.Cols () != 0 ||
622
0
    fColorMatrix2.Rows () != 0)
623
0
    {
624
    
625
0
    if (fColorMatrix2.Cols () != 3 ||
626
0
      fColorMatrix2.Rows () != channels)
627
0
      {
628
      
629
      #if qDNGValidate
630
    
631
      ReportError ("ColorMatrix2 is wrong size");
632
             
633
      #endif
634
           
635
0
      return false;
636
      
637
0
      }
638
    
639
0
    }
640
    
641
  // ForwardMatrix1 is optional, but it must be valid if present.
642
  
643
0
  if (fForwardMatrix1.Cols () != 0 ||
644
0
    fForwardMatrix1.Rows () != 0)
645
0
    {
646
    
647
0
    if (fForwardMatrix1.Rows () != 3 ||
648
0
      fForwardMatrix1.Cols () != channels)
649
0
      {
650
      
651
      #if qDNGValidate
652
    
653
      ReportError ("ForwardMatrix1 is wrong size");
654
             
655
      #endif
656
             
657
0
      return false;
658
      
659
0
      }
660
661
    // Make sure ForwardMatrix1 does a valid mapping.
662
    
663
0
    if (!ValidForwardMatrix (fForwardMatrix1))
664
0
      {
665
      
666
      #if qDNGValidate
667
    
668
      ReportError ("ForwardMatrix1 does not map equal camera values to XYZ D50");
669
             
670
      #endif
671
             
672
0
      return false;
673
    
674
0
      }
675
        
676
0
    }
677
678
  // ForwardMatrix2 is optional, but it must be valid if present.
679
  
680
0
  if (fForwardMatrix2.Cols () != 0 ||
681
0
    fForwardMatrix2.Rows () != 0)
682
0
    {
683
    
684
0
    if (fForwardMatrix2.Rows () != 3 ||
685
0
      fForwardMatrix2.Cols () != channels)
686
0
      {
687
      
688
      #if qDNGValidate
689
    
690
      ReportError ("ForwardMatrix2 is wrong size");
691
             
692
      #endif
693
             
694
0
      return false;
695
      
696
0
      }
697
698
    // Make sure ForwardMatrix2 does a valid mapping.
699
    
700
0
    if (!ValidForwardMatrix (fForwardMatrix2))
701
0
      {
702
      
703
      #if qDNGValidate
704
    
705
      ReportError ("ForwardMatrix2 does not map equal camera values to XYZ D50");
706
             
707
      #endif
708
             
709
0
      return false;
710
    
711
0
      }
712
        
713
0
    }
714
715
  // ReductionMatrix1 is optional, but it must be valid if present.
716
  
717
0
  if (fReductionMatrix1.Cols () != 0 ||
718
0
    fReductionMatrix1.Rows () != 0)
719
0
    {
720
    
721
0
    if (fReductionMatrix1.Cols () != channels ||
722
0
      fReductionMatrix1.Rows () != 3)
723
0
      {
724
      
725
      #if qDNGValidate
726
    
727
      ReportError ("ReductionMatrix1 is wrong size");
728
             
729
      #endif
730
           
731
0
      return false;
732
      
733
0
      }
734
    
735
0
    }
736
  
737
  // ReductionMatrix2 is optional, but it must be valid if present.
738
  
739
0
  if (fReductionMatrix2.Cols () != 0 ||
740
0
    fReductionMatrix2.Rows () != 0)
741
0
    {
742
    
743
0
    if (fReductionMatrix2.Cols () != channels ||
744
0
      fReductionMatrix2.Rows () != 3)
745
0
      {
746
      
747
      #if qDNGValidate
748
    
749
      ReportError ("ReductionMatrix2 is wrong size");
750
             
751
      #endif
752
           
753
0
      return false;
754
      
755
0
      }
756
    
757
0
    }
758
    
759
  // Make sure ColorMatrix1 is invertable.
760
  
761
0
  try
762
0
    {
763
    
764
0
    if (fReductionMatrix1.NotEmpty ())
765
0
      {
766
      
767
0
      (void) Invert (fColorMatrix1,
768
0
               fReductionMatrix1);
769
      
770
0
      }
771
      
772
0
    else
773
0
      {
774
    
775
0
      (void) Invert (fColorMatrix1);
776
      
777
0
      }
778
    
779
0
    }
780
    
781
0
  catch (...)
782
0
    {
783
      
784
    #if qDNGValidate
785
  
786
    ReportError ("ColorMatrix1 is not invertable");
787
           
788
    #endif
789
           
790
0
    return false;
791
  
792
0
    }
793
    
794
  // Make sure ColorMatrix2 is invertable.
795
  
796
0
  if (fColorMatrix2.NotEmpty ())
797
0
    {
798
            
799
0
    try
800
0
      {
801
      
802
0
      if (fReductionMatrix2.NotEmpty ())
803
0
        {
804
        
805
0
        (void) Invert (fColorMatrix2,
806
0
                 fReductionMatrix2);
807
        
808
0
        }
809
        
810
0
      else
811
0
        {
812
      
813
0
        (void) Invert (fColorMatrix2);
814
        
815
0
        }
816
817
0
      }
818
      
819
0
    catch (...)
820
0
      {
821
        
822
      #if qDNGValidate
823
  
824
      ReportError ("ColorMatrix2 is not invertable");
825
             
826
      #endif
827
             
828
0
      return false;
829
    
830
0
      }
831
      
832
0
    }
833
834
0
  return true;
835
  
836
0
  }
837
    
838
/*****************************************************************************/
839
840
bool dng_camera_profile::EqualData (const dng_camera_profile &profile) const
841
0
  {
842
843
0
  return fCalibrationIlluminant1       == profile.fCalibrationIlluminant1        &&
844
0
       fCalibrationIlluminant2       == profile.fCalibrationIlluminant2        &&
845
0
       fColorMatrix1           == profile.fColorMatrix1            &&
846
0
       fColorMatrix2           == profile.fColorMatrix2            &&
847
0
       fForwardMatrix1           == profile.fForwardMatrix1            &&
848
0
       fForwardMatrix2           == profile.fForwardMatrix2            &&
849
0
       fReductionMatrix1         == profile.fReductionMatrix1          &&
850
0
       fReductionMatrix2         == profile.fReductionMatrix2          &&
851
0
       fHueSatDeltas1            == profile.fHueSatDeltas1            &&
852
0
       fHueSatDeltas2            == profile.fHueSatDeltas2            &&
853
0
       fHueSatMapEncoding          == profile.fHueSatMapEncoding          &&
854
0
       fLookTable              == profile.fLookTable              &&
855
0
       fLookTableEncoding          == profile.fLookTableEncoding          &&
856
0
       fDefaultBlackRender         == profile.fDefaultBlackRender          &&
857
0
       fToneCurve              == profile.fToneCurve              &&
858
0
       fBaselineExposureOffset.As_real64 () == profile.fBaselineExposureOffset.As_real64 () &&
859
0
       fProfileCalibrationSignature      == profile.fProfileCalibrationSignature;
860
861
0
  }
862
    
863
/*****************************************************************************/
864
865
void dng_camera_profile::ReadHueSatMap (dng_stream &stream,
866
                    dng_hue_sat_map &hueSatMap,
867
                    uint32 hues,
868
                    uint32 sats,
869
                    uint32 vals,
870
                    bool skipSat0)
871
0
  {
872
873
0
  hueSatMap.SetDivisions (hues, sats, vals);
874
875
0
  for (uint32 val = 0; val < vals; val++)
876
0
    {
877
878
0
    for (uint32 hue = 0; hue < hues; hue++)
879
0
      {
880
881
0
      for (uint32 sat = skipSat0 ? 1 : 0; sat < sats; sat++)
882
0
        {
883
884
0
        dng_hue_sat_map::HSBModify modify;
885
886
0
        modify.fHueShift = stream.Get_real32 ();
887
0
        modify.fSatScale = stream.Get_real32 ();
888
0
        modify.fValScale = stream.Get_real32 ();
889
890
0
        hueSatMap.SetDelta (hue, sat, val, modify);
891
        
892
0
        }
893
        
894
0
      }
895
      
896
0
    }
897
  
898
0
  }
899
900
/*****************************************************************************/
901
902
void dng_camera_profile::Parse (dng_stream &stream,
903
                dng_camera_profile_info &profileInfo)
904
0
  {
905
  
906
0
  SetUniqueCameraModelRestriction (profileInfo.fUniqueCameraModel.Get ());
907
908
0
  if (profileInfo.fProfileName.NotEmpty ())
909
0
    {
910
    
911
0
    SetName (profileInfo.fProfileName.Get ());
912
    
913
0
    }
914
  
915
0
  SetCopyright (profileInfo.fProfileCopyright.Get ());
916
917
0
  SetEmbedPolicy (profileInfo.fEmbedPolicy);
918
919
0
  SetCalibrationIlluminant1 (profileInfo.fCalibrationIlluminant1);
920
      
921
0
  SetColorMatrix1 (profileInfo.fColorMatrix1);
922
      
923
0
  if (profileInfo.fForwardMatrix1.NotEmpty ())
924
0
    {
925
    
926
0
    SetForwardMatrix1 (profileInfo.fForwardMatrix1);
927
    
928
0
    }
929
    
930
0
  if (profileInfo.fReductionMatrix1.NotEmpty ())
931
0
    {
932
    
933
0
    SetReductionMatrix1 (profileInfo.fReductionMatrix1);
934
    
935
0
    }
936
    
937
0
  if (profileInfo.fColorMatrix2.NotEmpty ())
938
0
    {
939
    
940
0
    SetCalibrationIlluminant2 (profileInfo.fCalibrationIlluminant2);
941
    
942
0
    SetColorMatrix2 (profileInfo.fColorMatrix2);
943
          
944
0
    if (profileInfo.fForwardMatrix2.NotEmpty ())
945
0
      {
946
      
947
0
      SetForwardMatrix2 (profileInfo.fForwardMatrix2);
948
      
949
0
      }
950
    
951
0
    if (profileInfo.fReductionMatrix2.NotEmpty ())
952
0
      {
953
      
954
0
      SetReductionMatrix2 (profileInfo.fReductionMatrix2);
955
      
956
0
      }
957
    
958
0
    }
959
960
0
  SetProfileCalibrationSignature (profileInfo.fProfileCalibrationSignature.Get ());
961
962
0
  if (profileInfo.fHueSatDeltas1Offset != 0 &&
963
0
    profileInfo.fHueSatDeltas1Count  != 0)
964
0
    {
965
966
0
    TempBigEndian setEndianness (stream, profileInfo.fBigEndian);
967
968
0
    stream.SetReadPosition (profileInfo.fHueSatDeltas1Offset);
969
    
970
0
    bool skipSat0 = (profileInfo.fHueSatDeltas1Count == SafeUint32Mult(
971
0
                               profileInfo.fProfileHues,
972
0
                               SafeUint32Sub(profileInfo.fProfileSats, 1),
973
0
                               profileInfo.fProfileVals, 3));
974
975
0
    ReadHueSatMap (stream,
976
0
             fHueSatDeltas1,
977
0
             profileInfo.fProfileHues,
978
0
             profileInfo.fProfileSats,
979
0
             profileInfo.fProfileVals,
980
0
             skipSat0);
981
982
0
    }
983
984
0
  if (profileInfo.fHueSatDeltas2Offset != 0 &&
985
0
    profileInfo.fHueSatDeltas2Count  != 0)
986
0
    {
987
988
0
    TempBigEndian setEndianness (stream, profileInfo.fBigEndian);
989
990
0
    stream.SetReadPosition (profileInfo.fHueSatDeltas2Offset);
991
992
0
    bool skipSat0 = (profileInfo.fHueSatDeltas2Count == SafeUint32Mult(
993
0
                               profileInfo.fProfileHues,
994
0
                               SafeUint32Sub(profileInfo.fProfileSats, 1),
995
0
                               profileInfo.fProfileVals, 3));
996
997
0
    ReadHueSatMap (stream,
998
0
             fHueSatDeltas2,
999
0
             profileInfo.fProfileHues,
1000
0
             profileInfo.fProfileSats,
1001
0
             profileInfo.fProfileVals,
1002
0
             skipSat0);
1003
1004
0
    }
1005
1006
0
  if (profileInfo.fLookTableOffset != 0 &&
1007
0
    profileInfo.fLookTableCount  != 0)
1008
0
    {
1009
1010
0
    TempBigEndian setEndianness (stream, profileInfo.fBigEndian);
1011
1012
0
    stream.SetReadPosition (profileInfo.fLookTableOffset);
1013
1014
0
    bool skipSat0 = (profileInfo.fLookTableCount == SafeUint32Mult(
1015
0
                             profileInfo.fLookTableHues,
1016
0
                             SafeUint32Sub(profileInfo.fLookTableSats, 1),
1017
0
                             profileInfo.fLookTableVals, 3));
1018
1019
0
    ReadHueSatMap (stream,
1020
0
             fLookTable,
1021
0
             profileInfo.fLookTableHues,
1022
0
             profileInfo.fLookTableSats,
1023
0
             profileInfo.fLookTableVals,
1024
0
             skipSat0);
1025
1026
0
    }
1027
1028
0
  if ((profileInfo.fToneCurveCount & 1) == 0)
1029
0
    {
1030
1031
0
    TempBigEndian setEndianness (stream, profileInfo.fBigEndian);
1032
1033
0
    stream.SetReadPosition (profileInfo.fToneCurveOffset);
1034
1035
0
    uint32 points = profileInfo.fToneCurveCount / 2;
1036
1037
0
    fToneCurve.fCoord.resize (points);
1038
1039
0
    for (size_t i = 0; i < points; i++)
1040
0
      {
1041
1042
0
      dng_point_real64 point;
1043
1044
0
      point.h = stream.Get_real32 ();
1045
0
      point.v = stream.Get_real32 ();
1046
1047
0
      fToneCurve.fCoord [i] = point;
1048
1049
0
      }
1050
      
1051
0
    }
1052
1053
0
  SetHueSatMapEncoding (profileInfo.fHueSatMapEncoding);
1054
    
1055
0
  SetLookTableEncoding (profileInfo.fLookTableEncoding);
1056
1057
0
  SetBaselineExposureOffset (profileInfo.fBaselineExposureOffset.As_real64 ());
1058
1059
0
  SetDefaultBlackRender (profileInfo.fDefaultBlackRender);
1060
    
1061
0
  }
1062
    
1063
/*****************************************************************************/
1064
1065
bool dng_camera_profile::ParseExtended (dng_stream &stream)
1066
0
  {
1067
1068
0
  try
1069
0
    {
1070
    
1071
0
    dng_camera_profile_info profileInfo;
1072
    
1073
0
    if (!profileInfo.ParseExtended (stream))
1074
0
      {
1075
0
      return false;
1076
0
      }
1077
      
1078
0
    Parse (stream, profileInfo);
1079
1080
0
    return true;
1081
1082
0
    }
1083
    
1084
0
  catch (...)
1085
0
    {
1086
    
1087
    // Eat parsing errors.
1088
    
1089
0
    }
1090
1091
0
  return false;
1092
1093
0
  }
1094
1095
/*****************************************************************************/
1096
1097
void dng_camera_profile::SetFourColorBayer ()
1098
0
  {
1099
  
1100
0
  uint32 j;
1101
  
1102
0
  if (!IsValid (3))
1103
0
    {
1104
0
    ThrowProgramError ();
1105
0
    }
1106
    
1107
0
  if (fColorMatrix1.NotEmpty ())
1108
0
    {
1109
    
1110
0
    dng_matrix m (4, 3);
1111
    
1112
0
    for (j = 0; j < 3; j++)
1113
0
      {
1114
0
      m [0] [j] = fColorMatrix1 [0] [j];
1115
0
      m [1] [j] = fColorMatrix1 [1] [j];
1116
0
      m [2] [j] = fColorMatrix1 [2] [j];
1117
0
      m [3] [j] = fColorMatrix1 [1] [j];
1118
0
      }
1119
      
1120
0
    fColorMatrix1 = m;
1121
    
1122
0
    }
1123
  
1124
0
  if (fColorMatrix2.NotEmpty ())
1125
0
    {
1126
    
1127
0
    dng_matrix m (4, 3);
1128
    
1129
0
    for (j = 0; j < 3; j++)
1130
0
      {
1131
0
      m [0] [j] = fColorMatrix2 [0] [j];
1132
0
      m [1] [j] = fColorMatrix2 [1] [j];
1133
0
      m [2] [j] = fColorMatrix2 [2] [j];
1134
0
      m [3] [j] = fColorMatrix2 [1] [j];
1135
0
      }
1136
      
1137
0
    fColorMatrix2 = m;
1138
    
1139
0
    }
1140
      
1141
0
  fReductionMatrix1.Clear ();
1142
0
  fReductionMatrix2.Clear ();
1143
  
1144
0
  fForwardMatrix1.Clear ();
1145
0
  fForwardMatrix2.Clear ();
1146
  
1147
0
  }
1148
1149
/*****************************************************************************/
1150
1151
dng_hue_sat_map * dng_camera_profile::HueSatMapForWhite (const dng_xy_coord &white) const
1152
0
  {
1153
  
1154
0
  if (fHueSatDeltas1.IsValid ())
1155
0
    {
1156
1157
    // If we only have the first table, just use it for any color temperature.
1158
    
1159
0
    if (!fHueSatDeltas2.IsValid ())
1160
0
      {
1161
      
1162
0
      return new dng_hue_sat_map (fHueSatDeltas1);
1163
      
1164
0
      }
1165
      
1166
    // Else we need to interpolate based on color temperature.
1167
    
1168
0
    real64 temperature1 = CalibrationTemperature1 ();
1169
0
    real64 temperature2 = CalibrationTemperature2 ();
1170
    
1171
0
    if (temperature1 <= 0.0 ||
1172
0
      temperature2 <= 0.0 ||
1173
0
      temperature1 == temperature2)
1174
0
      {
1175
      
1176
0
      return new dng_hue_sat_map (fHueSatDeltas1);
1177
      
1178
0
      }
1179
      
1180
0
    bool reverseOrder = temperature1 > temperature2;
1181
    
1182
0
    if (reverseOrder)
1183
0
      {
1184
0
      real64 temp  = temperature1;
1185
0
      temperature1 = temperature2;
1186
0
      temperature2 = temp;
1187
0
      }
1188
1189
    // Convert to temperature/offset space.
1190
    
1191
0
    dng_temperature td (white);
1192
    
1193
    // Find fraction to weight the first calibration.
1194
    
1195
0
    real64 g;
1196
    
1197
0
    if (td.Temperature () <= temperature1)
1198
0
      g = 1.0;
1199
    
1200
0
    else if (td.Temperature () >= temperature2)
1201
0
      g = 0.0;
1202
    
1203
0
    else
1204
0
      {
1205
      
1206
0
      real64 invT = 1.0 / td.Temperature ();
1207
      
1208
0
      g = (invT                 - (1.0 / temperature2)) /
1209
0
        ((1.0 / temperature1) - (1.0 / temperature2));
1210
        
1211
0
      }
1212
      
1213
    // Fix up if we swapped the order.
1214
    
1215
0
    if (reverseOrder)
1216
0
      {
1217
0
      g = 1.0 - g;
1218
0
      }
1219
    
1220
    // Do the interpolation.
1221
    
1222
0
    return dng_hue_sat_map::Interpolate (HueSatDeltas1 (),
1223
0
                       HueSatDeltas2 (),
1224
0
                       g);
1225
    
1226
0
    }
1227
    
1228
0
  return NULL;
1229
1230
0
  }
1231
1232
/*****************************************************************************/
1233
1234
void dng_camera_profile::Stub ()
1235
0
  {
1236
  
1237
0
  (void) Fingerprint ();
1238
  
1239
0
  dng_hue_sat_map nullTable;
1240
  
1241
0
  fHueSatDeltas1 = nullTable;
1242
0
  fHueSatDeltas2 = nullTable;
1243
  
1244
0
  fLookTable = nullTable;
1245
  
1246
0
  fToneCurve.SetInvalid ();
1247
  
1248
0
  fWasStubbed = true;
1249
  
1250
0
  }
1251
1252
/*****************************************************************************/
1253
1254
void SplitCameraProfileName (const dng_string &name,
1255
               dng_string &baseName,
1256
               int32 &version)
1257
0
  {
1258
  
1259
0
  baseName = name;
1260
  
1261
0
  version = 0;
1262
  
1263
0
  uint32 len = baseName.Length ();
1264
  
1265
0
  if (len > 5 && baseName.EndsWith (" beta"))
1266
0
    {
1267
    
1268
0
    baseName.Truncate (len - 5);
1269
    
1270
0
    version += -10;
1271
    
1272
0
    }
1273
    
1274
0
  else if (len > 7)
1275
0
    {
1276
    
1277
0
    char lastChar = name.Get () [len - 1];
1278
    
1279
0
    if (lastChar >= '0' && lastChar <= '9')
1280
0
      {
1281
      
1282
0
      dng_string temp = name;
1283
      
1284
0
      temp.Truncate (len - 1);
1285
      
1286
0
      if (temp.EndsWith (" beta "))
1287
0
        {
1288
        
1289
0
        baseName.Truncate (len - 7);
1290
        
1291
0
        version += ((int32) (lastChar - '0')) - 10;
1292
        
1293
0
        }
1294
        
1295
0
      }
1296
      
1297
0
    }
1298
    
1299
0
  len = baseName.Length ();
1300
  
1301
0
  if (len > 3)
1302
0
    {
1303
    
1304
0
    char lastChar = name.Get () [len - 1];
1305
    
1306
0
    if (lastChar >= '0' && lastChar <= '9')
1307
0
      {
1308
      
1309
0
      dng_string temp = name;
1310
      
1311
0
      temp.Truncate (len - 1);
1312
      
1313
0
      if (temp.EndsWith (" v"))
1314
0
        {
1315
        
1316
0
        baseName.Truncate (len - 3);
1317
        
1318
0
        version += ((int32) (lastChar - '0')) * 100;
1319
        
1320
0
        }
1321
        
1322
0
      }
1323
      
1324
0
    }
1325
1326
0
  }
1327
1328
/*****************************************************************************/
1329
1330
void BuildHueSatMapEncodingTable (dng_memory_allocator &allocator,
1331
                  uint32 encoding,
1332
                  AutoPtr<dng_1d_table> &encodeTable,
1333
                  AutoPtr<dng_1d_table> &decodeTable,
1334
                  bool subSample)
1335
0
  {
1336
1337
0
  encodeTable.Reset ();
1338
0
  decodeTable.Reset ();
1339
  
1340
0
  switch (encoding)
1341
0
    {
1342
    
1343
0
    case encoding_Linear:
1344
0
      {
1345
1346
0
      break;
1347
1348
0
      }
1349
    
1350
0
    case encoding_sRGB:
1351
0
      {
1352
1353
0
      encodeTable.Reset (new dng_1d_table);
1354
0
      decodeTable.Reset (new dng_1d_table);
1355
1356
0
      const dng_1d_function & curve = dng_function_GammaEncode_sRGB::Get ();
1357
1358
0
      encodeTable->Initialize (allocator,
1359
0
                   curve,
1360
0
                   subSample);
1361
1362
0
      const dng_1d_inverse inverse (curve);
1363
1364
0
      decodeTable->Initialize (allocator,
1365
0
                   inverse,
1366
0
                   subSample);
1367
1368
0
      break;
1369
1370
0
      }
1371
1372
0
    default:
1373
0
      {
1374
1375
0
      DNG_REPORT ("Unsupported hue sat map / look table encoding.");
1376
1377
0
      break;
1378
1379
0
      }
1380
    
1381
0
    }
1382
1383
0
  }
1384
              
1385
/*****************************************************************************/