Coverage Report

Created: 2025-11-24 06:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/dng_sdk/source/dng_ifd.cpp
Line
Count
Source
1
/*****************************************************************************/
2
// Copyright 2006-2012 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_ifd.cpp#3 $ */ 
10
/* $DateTime: 2012/06/05 11:05:39 $ */
11
/* $Change: 833352 $ */
12
/* $Author: tknoll $ */
13
14
/*****************************************************************************/
15
16
#include "dng_ifd.h"
17
18
#include "dng_exceptions.h"
19
#include "dng_flags.h"
20
#include "dng_globals.h"
21
#include "dng_ifd.h"
22
#include "dng_types.h"
23
#include "dng_parse_utils.h"
24
#include "dng_read_image.h"
25
#include "dng_stream.h"
26
#include "dng_tag_codes.h"
27
#include "dng_tag_types.h"
28
#include "dng_tag_values.h"
29
#include "dng_utils.h"
30
31
/*****************************************************************************/
32
33
dng_preview_info::dng_preview_info ()
34
  
35
496k
  : fIsPrimary          (true)
36
496k
  , fApplicationName    ()
37
496k
  , fApplicationVersion ()
38
496k
  , fSettingsName       ()
39
496k
  , fSettingsDigest     ()
40
496k
  , fColorSpace     (previewColorSpace_MaxEnum)
41
496k
  , fDateTime     ()
42
496k
  , fRawToPreviewGain   (1.0)
43
496k
  , fCacheVersion   (0)
44
  
45
496k
  {
46
  
47
496k
  }
48
49
/*****************************************************************************/
50
51
dng_preview_info::~dng_preview_info ()
52
496k
  {
53
  
54
496k
  }
55
56
/*****************************************************************************/
57
58
dng_ifd::dng_ifd ()
59
60
489k
  : fUsesNewSubFileType (false)
61
489k
  , fNewSubFileType     (0)
62
63
489k
  , fImageWidth  (0)
64
489k
  , fImageLength (0)
65
66
489k
  , fCompression (ccUncompressed)
67
489k
  , fPredictor   (cpNullPredictor)
68
69
489k
  , fPhotometricInterpretation (0xFFFFFFFF)
70
71
489k
  , fFillOrder (1)
72
73
489k
  , fOrientation          (0)
74
489k
  , fOrientationType      (0)
75
489k
  , fOrientationOffset    (kDNGStreamInvalidOffset)
76
489k
  , fOrientationBigEndian (false)
77
78
489k
  , fSamplesPerPixel (1)
79
80
489k
  , fPlanarConfiguration (pcInterleaved)
81
82
489k
  , fXResolution    (0.0)
83
489k
  , fYResolution    (0.0)
84
489k
  , fResolutionUnit (0)
85
    
86
489k
  , fUsesStrips (false)
87
489k
  , fUsesTiles  (false)
88
  
89
489k
  , fTileWidth  (0)
90
489k
  , fTileLength (0)
91
  
92
489k
  , fTileOffsetsType   (0)
93
489k
  , fTileOffsetsCount  (0)
94
489k
  , fTileOffsetsOffset (0)
95
  
96
489k
  , fTileByteCountsType   (0)
97
489k
  , fTileByteCountsCount  (0)
98
489k
  , fTileByteCountsOffset (0)
99
  
100
489k
  , fSubIFDsCount  (0)
101
489k
  , fSubIFDsOffset (0)
102
  
103
489k
  , fExtraSamplesCount (0)
104
  
105
489k
  , fJPEGTablesCount  (0)
106
489k
  , fJPEGTablesOffset (0)
107
    
108
489k
  , fJPEGInterchangeFormat     (0)
109
489k
  , fJPEGInterchangeFormatLength (0)
110
111
489k
  , fYCbCrCoefficientR (0.0)
112
489k
  , fYCbCrCoefficientG (0.0)
113
489k
  , fYCbCrCoefficientB (0.0)
114
  
115
489k
  , fYCbCrSubSampleH (0)
116
489k
  , fYCbCrSubSampleV (0)
117
  
118
489k
  , fYCbCrPositioning (0)
119
  
120
489k
  , fCFARepeatPatternRows (0)
121
489k
  , fCFARepeatPatternCols (0)
122
  
123
489k
  , fCFALayout (1)
124
  
125
489k
  , fLinearizationTableType   (0)
126
489k
  , fLinearizationTableCount  (0)
127
489k
  , fLinearizationTableOffset (0)
128
129
489k
  , fBlackLevelRepeatRows (1)
130
489k
  , fBlackLevelRepeatCols (1)
131
  
132
489k
  , fBlackLevelDeltaHType   (0)
133
489k
  , fBlackLevelDeltaHCount  (0)
134
489k
  , fBlackLevelDeltaHOffset (0)
135
136
489k
  , fBlackLevelDeltaVType   (0)
137
489k
  , fBlackLevelDeltaVCount  (0)
138
489k
  , fBlackLevelDeltaVOffset (0)
139
  
140
489k
  , fDefaultScaleH (1, 1)
141
489k
  , fDefaultScaleV (1, 1)
142
  
143
489k
  , fBestQualityScale (1, 1)
144
  
145
489k
  , fDefaultCropOriginH (0, 1)
146
489k
  , fDefaultCropOriginV (0, 1)
147
  
148
489k
  , fDefaultCropSizeH ()
149
489k
  , fDefaultCropSizeV ()
150
  
151
489k
  , fDefaultUserCropT (0, 1)
152
489k
  , fDefaultUserCropL (0, 1)
153
489k
  , fDefaultUserCropB (1, 1)
154
489k
  , fDefaultUserCropR (1, 1)
155
  
156
489k
  , fBayerGreenSplit (0)
157
  
158
489k
  , fChromaBlurRadius ()
159
  
160
489k
  , fAntiAliasStrength (1, 1)
161
  
162
489k
  , fActiveArea ()
163
  
164
489k
  , fMaskedAreaCount (0)
165
  
166
489k
  , fRowInterleaveFactor (1)
167
  
168
489k
  , fSubTileBlockRows (1)
169
489k
  , fSubTileBlockCols (1)
170
  
171
489k
  , fPreviewInfo ()
172
  
173
489k
  , fOpcodeList1Count  (0)
174
489k
  , fOpcodeList1Offset (0)
175
  
176
489k
  , fOpcodeList2Count  (0)
177
489k
  , fOpcodeList2Offset (0)
178
  
179
489k
  , fOpcodeList3Count  (0)
180
489k
  , fOpcodeList3Offset (0)
181
  
182
489k
  , fLosslessJPEGBug16 (false)
183
  
184
489k
  , fSampleBitShift (0)
185
    
186
489k
  , fThisIFD (0)
187
489k
  , fNextIFD (0)
188
  
189
489k
  , fCompressionQuality (-1)
190
  
191
489k
  , fPatchFirstJPEGByte (false)
192
193
489k
  {
194
  
195
489k
  uint32 j;
196
489k
  uint32 k;
197
489k
  uint32 n;
198
  
199
2.44M
  for (j = 0; j < kMaxSamplesPerPixel; j++)
200
1.95M
    {
201
1.95M
    fBitsPerSample [j] = 0;
202
1.95M
    }
203
  
204
16.1M
  for (j = 0; j < kMaxTileInfo; j++)
205
15.6M
    {
206
15.6M
    fTileOffset    [j] = 0;
207
15.6M
    fTileByteCount [j] = 0;
208
15.6M
    }
209
  
210
2.44M
  for (j = 0; j < kMaxSamplesPerPixel; j++)
211
1.95M
    {
212
1.95M
    fExtraSamples [j] = esUnspecified;
213
1.95M
    }
214
  
215
2.44M
  for (j = 0; j < kMaxSamplesPerPixel; j++)
216
1.95M
    {
217
1.95M
    fSampleFormat [j] = sfUnsignedInteger;
218
1.95M
    }
219
    
220
3.42M
  for (j = 0; j < 6; j++)
221
2.93M
    {
222
2.93M
    fReferenceBlackWhite [j] = 0.0;
223
2.93M
    }
224
  
225
4.40M
  for (j = 0; j < kMaxCFAPattern; j++)
226
35.2M
    for (k = 0; k < kMaxCFAPattern; k++)
227
31.3M
      {
228
31.3M
      fCFAPattern [j] [k] = 255;
229
31.3M
      }
230
      
231
2.44M
  for (j = 0; j < kMaxColorPlanes; j++)
232
1.95M
    {
233
1.95M
    fCFAPlaneColor [j] = (uint8) (j < 3 ? j : 255);
234
1.95M
    }
235
    
236
4.40M
  for (j = 0; j < kMaxBlackPattern; j++)
237
35.2M
    for (k = 0; k < kMaxBlackPattern; k++)
238
156M
      for (n = 0; n < kMaxSamplesPerPixel; n++)
239
125M
        {
240
125M
        fBlackLevel [j] [k] [n] = 0.0;
241
125M
        }
242
      
243
2.44M
  for (j = 0; j < kMaxSamplesPerPixel; j++)
244
1.95M
    {
245
1.95M
    fWhiteLevel [j] = -1.0;   // Don't know real default yet.
246
1.95M
    }
247
  
248
489k
  }
249
  
250
/*****************************************************************************/
251
252
dng_ifd::~dng_ifd ()
253
489k
  {
254
  
255
489k
  }
256
  
257
/*****************************************************************************/
258
259
// Parses tags that should only appear in IFDs that contain images.
260
261
bool dng_ifd::ParseTag (dng_stream &stream,
262
            uint32 parentCode,
263
            uint32 tagCode,
264
            uint32 tagType,
265
            uint32 tagCount,
266
            uint64 tagOffset)
267
5.77M
  {
268
  
269
5.77M
  uint32 j;
270
5.77M
  uint32 k;
271
5.77M
  uint32 n;
272
  
273
5.77M
  switch (tagCode)
274
5.77M
    {
275
    
276
233k
    case tcNewSubFileType:
277
233k
      {
278
      
279
233k
      CheckTagType (parentCode, tagCode, tagType, ttLong);
280
      
281
233k
      CheckTagCount (parentCode, tagCode, tagCount, 1);
282
      
283
233k
      fUsesNewSubFileType = true;
284
      
285
233k
      fNewSubFileType = stream.TagValue_uint32 (tagType);
286
      
287
233k
      fPreviewInfo.fIsPrimary = (fNewSubFileType == sfPreviewImage);
288
      
289
      #if qDNGValidate
290
      
291
      if (gVerbose)
292
        {
293
        
294
        printf ("NewSubFileType: %s\n",
295
            LookupNewSubFileType (fNewSubFileType));
296
297
        }
298
        
299
      #endif
300
        
301
233k
      break;
302
      
303
0
      }
304
305
253k
    case tcImageWidth:
306
253k
      {
307
      
308
253k
      CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
309
      
310
253k
      CheckTagCount (parentCode, tagCode, tagCount, 1);
311
      
312
253k
      fImageWidth = stream.TagValue_uint32 (tagType);
313
      
314
      #if qDNGValidate
315
      
316
      if (gVerbose)
317
        {
318
        printf ("ImageWidth: %u\n", (unsigned) fImageWidth);
319
        }
320
        
321
      #endif
322
        
323
253k
      break;
324
      
325
0
      }
326
    
327
269k
    case tcImageLength:
328
269k
      {
329
      
330
269k
      CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
331
      
332
269k
      CheckTagCount (parentCode, tagCode, tagCount, 1);
333
      
334
269k
      fImageLength = stream.TagValue_uint32 (tagType);
335
      
336
      #if qDNGValidate
337
      
338
      if (gVerbose)
339
        {
340
        printf ("ImageLength: %u\n", (unsigned) fImageLength);
341
        }
342
        
343
      #endif
344
        
345
269k
      break;
346
      
347
0
      }
348
        
349
224k
    case tcBitsPerSample:
350
224k
      {
351
      
352
224k
      CheckTagType (parentCode, tagCode, tagType, ttShort);
353
      
354
224k
      CheckTagCount (parentCode, tagCode, tagCount, 1, 0x0FFFF);
355
      
356
      #if qDNGValidate
357
      
358
      if (gVerbose)
359
        {
360
        printf ("BitsPerSample:");
361
        }
362
        
363
      #endif
364
      
365
224k
      bool extrasMatch = true;
366
      
367
209M
      for (j = 0; j < tagCount; j++)
368
209M
        {
369
        
370
209M
        uint32 x = stream.TagValue_uint32 (tagType);
371
        
372
209M
        const uint32 maxBitsPerSample = 32;
373
        
374
209M
        if (j < kMaxSamplesPerPixel)
375
525k
          {
376
          
377
525k
          if (x > maxBitsPerSample)
378
496
            {
379
496
            ThrowBadFormat ("BitsPerSample out of bounds.");
380
496
            }
381
            
382
525k
          fBitsPerSample [j] = x;
383
525k
          }
384
          
385
208M
        else if (x != fBitsPerSample [kMaxSamplesPerPixel - 1])
386
715k
          {
387
715k
          extrasMatch = false;
388
715k
          }
389
          
390
        #if qDNGValidate
391
      
392
        if (gVerbose)
393
          {
394
          printf (" %u", (unsigned) x);
395
          }
396
          
397
        #endif
398
        
399
209M
        }
400
          
401
      #if qDNGValidate
402
      
403
      if (gVerbose)
404
        {
405
        printf ("\n");
406
        }
407
        
408
      #endif
409
      
410
224k
      if (!extrasMatch)
411
17
        {
412
        
413
        #if qDNGValidate
414
      
415
        ReportError ("BitsPerSample not constant");
416
        
417
        #endif
418
419
17
        ThrowBadFormat ();
420
        
421
17
        }
422
      
423
224k
      break;
424
      
425
0
      }
426
        
427
81.4k
    case tcCompression:
428
81.4k
      {
429
      
430
81.4k
      CheckTagType (parentCode, tagCode, tagType, ttShort);
431
      
432
81.4k
      CheckTagCount (parentCode, tagCode, tagCount, 1);
433
      
434
81.4k
      fCompression = stream.TagValue_uint32 (tagType);
435
      
436
      #if qDNGValidate
437
        
438
      if (gVerbose)
439
        {
440
        
441
        printf ("Compression: %s\n",
442
              LookupCompression (fCompression));
443
              
444
        }
445
        
446
      #endif
447
  
448
      // Correct a common TIFF writer mistake.
449
      
450
81.4k
      if (fCompression == 0)
451
5.80k
        {
452
        
453
        #if qDNGValidate
454
        
455
          {
456
            
457
          char message [256];
458
          
459
          sprintf (message,
460
               "%s has invalid zero compression code",
461
               LookupParentCode (parentCode));
462
               
463
          ReportWarning (message);
464
                 
465
          }
466
        
467
        #endif
468
        
469
5.80k
        fCompression = ccUncompressed;
470
        
471
5.80k
        }
472
        
473
81.4k
      break;
474
      
475
0
      }
476
        
477
198k
    case tcPhotometricInterpretation:
478
198k
      {
479
      
480
198k
      CheckTagType (parentCode, tagCode, tagType, ttShort);
481
      
482
198k
      CheckTagCount (parentCode, tagCode, tagCount, 1);
483
      
484
198k
      fPhotometricInterpretation = stream.TagValue_uint32 (tagType);
485
              
486
      #if qDNGValidate
487
        
488
      if (gVerbose)
489
        {
490
        
491
        printf ("PhotometricInterpretation: %s\n",
492
            LookupPhotometricInterpretation (fPhotometricInterpretation));
493
        
494
        }
495
        
496
      #endif
497
        
498
198k
      break;
499
      
500
0
      }
501
        
502
3.07k
    case tcFillOrder:
503
3.07k
      {
504
      
505
3.07k
      CheckTagType (parentCode, tagCode, tagType, ttShort);
506
      
507
3.07k
      CheckTagCount (parentCode, tagCode, tagCount, 1);
508
      
509
3.07k
      fFillOrder = stream.TagValue_uint32 (tagType);
510
      
511
      #if qDNGValidate
512
        
513
      if (gVerbose)
514
        {
515
        printf ("FillOrder: %u\n", (unsigned) fFillOrder);
516
        }
517
        
518
      #endif
519
      
520
3.07k
      break;
521
      
522
0
      }
523
524
185k
    case tcStripOffsets:
525
185k
      {
526
      
527
185k
      CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
528
      
529
185k
      fUsesStrips = true;
530
      
531
185k
      fTileOffsetsType   = tagType;
532
185k
      fTileOffsetsCount  = tagCount;
533
185k
      fTileOffsetsOffset = tagOffset;
534
      
535
185k
      if (tagCount <= kMaxTileInfo)
536
180k
        {
537
        
538
405k
        for (j = 0; j < tagCount; j++)
539
225k
          {
540
        
541
225k
          fTileOffset [j] = stream.TagValue_uint32 (tagType);
542
          
543
225k
          }
544
          
545
180k
        }
546
      
547
      #if qDNGValidate
548
        
549
      if (gVerbose)
550
        {
551
        
552
        stream.SetReadPosition (tagOffset);
553
        
554
        DumpTagValues (stream,
555
                 "Offset",
556
                 parentCode,
557
                 tagCode,
558
                 tagType,
559
                 tagCount);
560
561
        }
562
        
563
      #endif
564
      
565
185k
      break;
566
      
567
0
      }
568
        
569
35.0k
    case tcOrientation:
570
35.0k
      {
571
      
572
35.0k
      CheckTagType (parentCode, tagCode, tagType, ttShort);
573
      
574
35.0k
      CheckTagCount (parentCode, tagCode, tagCount, 1);
575
      
576
35.0k
      fOrientationType      = tagType;
577
35.0k
      fOrientationOffset    = stream.PositionInOriginalFile ();
578
35.0k
      fOrientationBigEndian = stream.BigEndian ();
579
      
580
35.0k
      fOrientation = stream.TagValue_uint32 (tagType);
581
        
582
      #if qDNGValidate
583
        
584
      if (gVerbose)
585
        {
586
        
587
        printf ("Orientation: %s\n",
588
              LookupOrientation (fOrientation));
589
        
590
        }
591
        
592
      #endif
593
        
594
35.0k
      break;
595
      
596
0
      }
597
        
598
55.1k
    case tcSamplesPerPixel:
599
55.1k
      {
600
      
601
55.1k
      CheckTagType (parentCode, tagCode, tagType, ttShort);
602
      
603
55.1k
      CheckTagCount (parentCode, tagCode, tagCount, 1);
604
      
605
55.1k
      fSamplesPerPixel = stream.TagValue_uint32 (tagType);
606
      
607
      #if qDNGValidate
608
        
609
      if (gVerbose)
610
        {
611
        printf ("SamplesPerPixel: %u\n", (unsigned) fSamplesPerPixel);
612
        }
613
        
614
      #endif
615
616
55.1k
      break;
617
      
618
0
      }
619
620
48.4k
    case tcRowsPerStrip:
621
48.4k
      {
622
      
623
48.4k
      CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
624
      
625
48.4k
      CheckTagCount (parentCode, tagCode, tagCount, 1);
626
      
627
48.4k
      fUsesStrips = true;
628
      
629
48.4k
      fTileLength = stream.TagValue_uint32 (tagType);
630
      
631
      #if qDNGValidate
632
        
633
      if (gVerbose)
634
        {
635
        printf ("RowsPerStrip: %u\n", (unsigned) fTileLength);
636
        }
637
        
638
      #endif
639
640
48.4k
      break;
641
      
642
0
      }
643
        
644
175k
    case tcStripByteCounts:
645
175k
      {
646
      
647
175k
      CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
648
      
649
175k
      fUsesStrips = true;
650
      
651
175k
      fTileByteCountsType   = tagType;
652
175k
      fTileByteCountsCount  = tagCount;
653
175k
      fTileByteCountsOffset = tagOffset;
654
      
655
175k
      if (tagCount <= kMaxTileInfo)
656
172k
        {
657
        
658
420k
        for (j = 0; j < tagCount; j++)
659
248k
          {
660
        
661
248k
          fTileByteCount [j] = stream.TagValue_uint32 (tagType);
662
          
663
248k
          }
664
          
665
172k
        }
666
      
667
      #if qDNGValidate
668
        
669
      if (gVerbose)
670
        {
671
        
672
        stream.SetReadPosition (tagOffset);
673
        
674
        DumpTagValues (stream,
675
                 "Count",
676
                 parentCode,
677
                 tagCode,
678
                 tagType,
679
                 tagCount);
680
                 
681
        }
682
        
683
      #endif
684
685
175k
      break;
686
      
687
0
      }
688
        
689
8.96k
    case tcXResolution:
690
8.96k
      {
691
      
692
8.96k
      CheckTagType (parentCode, tagCode, tagType, ttRational);
693
      
694
8.96k
      CheckTagCount (parentCode, tagCode, tagCount, 1);
695
      
696
8.96k
      fXResolution = stream.TagValue_real64 (tagType);
697
      
698
      #if qDNGValidate
699
        
700
      if (gVerbose)
701
        {
702
        printf ("XResolution: %0.2f\n", fXResolution);
703
        }
704
        
705
      #endif
706
      
707
8.96k
      break;
708
      
709
0
      }
710
      
711
7.25k
    case tcYResolution:
712
7.25k
      {
713
      
714
7.25k
      CheckTagType (parentCode, tagCode, tagType, ttRational);
715
      
716
7.25k
      CheckTagCount (parentCode, tagCode, tagCount, 1);
717
      
718
7.25k
      fYResolution = stream.TagValue_real64 (tagType);
719
      
720
      #if qDNGValidate
721
        
722
      if (gVerbose)
723
        {
724
        printf ("YResolution: %0.2f\n", fYResolution);
725
        }
726
        
727
      #endif
728
        
729
7.25k
      break;
730
      
731
0
      }
732
        
733
48.0k
    case tcPlanarConfiguration:
734
48.0k
      {
735
      
736
48.0k
      CheckTagType (parentCode, tagCode, tagType, ttShort);
737
      
738
48.0k
      CheckTagCount (parentCode, tagCode, tagCount, 1);
739
      
740
48.0k
      fPlanarConfiguration = stream.TagValue_uint32 (tagType);
741
      
742
      #if qDNGValidate
743
        
744
      if (gVerbose)
745
        {
746
        printf ("PlanarConfiguration: %u\n", (unsigned) fPlanarConfiguration);
747
        }
748
      
749
      #endif
750
        
751
48.0k
      break;
752
      
753
0
      }
754
755
10.6k
    case tcResolutionUnit:
756
10.6k
      {
757
      
758
10.6k
      CheckTagType (parentCode, tagCode, tagType, ttShort);
759
      
760
10.6k
      CheckTagCount (parentCode, tagCode, tagCount, 1);
761
      
762
10.6k
      fResolutionUnit = stream.TagValue_uint32 (tagType);
763
      
764
      #if qDNGValidate
765
        
766
      if (gVerbose)
767
        {
768
        
769
        printf ("ResolutionUnit: %s\n",
770
              LookupResolutionUnit (fResolutionUnit));
771
        
772
        }
773
        
774
      #endif
775
        
776
10.6k
      break;
777
      
778
0
      }
779
        
780
5.87k
    case tcPredictor:
781
5.87k
      {
782
      
783
5.87k
      CheckTagType (parentCode, tagCode, tagType, ttShort);
784
      
785
5.87k
      CheckTagCount (parentCode, tagCode, tagCount, 1);
786
      
787
5.87k
      fPredictor = stream.TagValue_uint32 (tagType);
788
      
789
      #if qDNGValidate
790
        
791
      if (gVerbose)
792
        {
793
        
794
        printf ("Predictor: %s\n",
795
            LookupPredictor (fPredictor));
796
              
797
        }
798
        
799
      #endif
800
        
801
5.87k
      break;
802
      
803
0
      }
804
        
805
26.2k
    case tcTileWidth:
806
26.2k
      {
807
      
808
26.2k
      CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
809
      
810
26.2k
      CheckTagCount (parentCode, tagCode, tagCount, 1);
811
      
812
26.2k
      fUsesTiles = true;
813
      
814
26.2k
      fTileWidth = stream.TagValue_uint32 (tagType);
815
      
816
      #if qDNGValidate
817
        
818
      if (gVerbose)
819
        {
820
        printf ("TileWidth: %u\n", (unsigned) fTileWidth);
821
        }
822
      
823
      #endif
824
        
825
26.2k
      break;
826
      
827
0
      }
828
      
829
28.1k
    case tcTileLength:
830
28.1k
      {
831
      
832
28.1k
      CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
833
      
834
28.1k
      CheckTagCount (parentCode, tagCode, tagCount, 1);
835
      
836
28.1k
      fUsesTiles = true;
837
      
838
28.1k
      fTileLength = stream.TagValue_uint32 (tagType);
839
      
840
      #if qDNGValidate
841
        
842
      if (gVerbose)
843
        {
844
        printf ("TileLength: %u\n", (unsigned) fTileLength);
845
        }
846
        
847
      #endif
848
      
849
28.1k
      break;
850
      
851
0
      }
852
      
853
21.8k
    case tcTileOffsets:
854
21.8k
      {
855
      
856
21.8k
      CheckTagType (parentCode, tagCode, tagType, ttLong);
857
      
858
21.8k
      fUsesTiles = true;
859
      
860
21.8k
      fTileOffsetsType   = tagType;
861
21.8k
      fTileOffsetsCount  = tagCount;
862
21.8k
      fTileOffsetsOffset = tagOffset;
863
      
864
21.8k
      if (tagCount <= kMaxTileInfo)
865
20.3k
        {
866
        
867
74.5k
        for (j = 0; j < tagCount; j++)
868
54.2k
          {
869
        
870
54.2k
          fTileOffset [j] = stream.TagValue_uint32 (tagType);
871
          
872
54.2k
          }
873
          
874
20.3k
        }
875
      
876
      #if qDNGValidate
877
        
878
      if (gVerbose)
879
        {
880
        
881
        stream.SetReadPosition (tagOffset);
882
        
883
        DumpTagValues (stream,
884
                 "Offset",
885
                 parentCode,
886
                 tagCode,
887
                 tagType,
888
                 tagCount);
889
                 
890
        }
891
        
892
      #endif
893
      
894
21.8k
      break;
895
      
896
0
      }
897
      
898
24.2k
    case tcTileByteCounts:
899
24.2k
      {
900
      
901
24.2k
      CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
902
      
903
24.2k
      fUsesTiles = true;
904
      
905
24.2k
      fTileByteCountsType   = tagType;
906
24.2k
      fTileByteCountsCount  = tagCount;
907
24.2k
      fTileByteCountsOffset = tagOffset;
908
      
909
24.2k
      if (tagCount <= kMaxTileInfo)
910
22.6k
        {
911
        
912
83.3k
        for (j = 0; j < tagCount; j++)
913
60.7k
          {
914
        
915
60.7k
          fTileByteCount [j] = stream.TagValue_uint32 (tagType);
916
          
917
60.7k
          }
918
          
919
22.6k
        }
920
      
921
      #if qDNGValidate
922
        
923
      if (gVerbose)
924
        {
925
        
926
        stream.SetReadPosition (tagOffset);
927
        
928
        DumpTagValues (stream,
929
                 "Count",
930
                 parentCode,
931
                 tagCode,
932
                 tagType,
933
                 tagCount);
934
                 
935
        }
936
        
937
      #endif
938
      
939
24.2k
      break;
940
      
941
0
      }
942
        
943
163k
    case tcSubIFDs:
944
163k
      {
945
      
946
163k
      CheckTagType (parentCode, tagCode, tagType, ttLong, ttIFD);
947
      
948
163k
      fSubIFDsCount  = tagCount;
949
163k
      fSubIFDsOffset = tagOffset;
950
      
951
      #if qDNGValidate
952
        
953
      if (gVerbose)
954
        {
955
        
956
        DumpTagValues (stream,
957
                 "IFD",
958
                 parentCode,
959
                 tagCode,
960
                 ttLong,
961
                 tagCount);
962
        
963
        }
964
        
965
      #endif
966
      
967
163k
      break;
968
      
969
0
      }
970
        
971
5.52k
    case tcExtraSamples:
972
5.52k
      {
973
      
974
5.52k
      CheckTagType (parentCode, tagCode, tagType, ttShort);
975
      
976
5.52k
      CheckTagCount (parentCode, tagCode, tagCount, 1, fSamplesPerPixel);
977
      
978
      #if qDNGValidate
979
      
980
      if (gVerbose)
981
        {
982
        printf ("ExtraSamples:");
983
        }
984
        
985
      #endif
986
      
987
5.52k
      fExtraSamplesCount = tagCount;
988
      
989
107M
      for (j = 0; j < tagCount; j++)
990
107M
        {
991
        
992
107M
        uint32 x = stream.TagValue_uint32 (tagType);
993
        
994
107M
        if (j < kMaxSamplesPerPixel)
995
14.6k
          {
996
14.6k
          fExtraSamples [j] = x;
997
14.6k
          }
998
          
999
        #if qDNGValidate
1000
      
1001
        if (gVerbose)
1002
          {
1003
          printf (" %u", (unsigned) x);
1004
          }
1005
          
1006
        #endif
1007
        
1008
107M
        }
1009
          
1010
      #if qDNGValidate
1011
      
1012
      if (gVerbose)
1013
        {
1014
        printf ("\n");
1015
        }
1016
        
1017
      #endif
1018
      
1019
5.52k
      break;
1020
      
1021
0
      }
1022
        
1023
19.8k
    case tcSampleFormat:
1024
19.8k
      {
1025
      
1026
19.8k
      CheckTagType (parentCode, tagCode, tagType, ttShort);
1027
      
1028
19.8k
      CheckTagCount (parentCode, tagCode, tagCount, fSamplesPerPixel);
1029
      
1030
      #if qDNGValidate
1031
      
1032
      if (gVerbose)
1033
        {
1034
        printf ("SampleFormat:");
1035
        }
1036
        
1037
      #endif
1038
      
1039
19.8k
      bool extrasMatch = true;
1040
      
1041
130M
      for (j = 0; j < tagCount; j++)
1042
130M
        {
1043
        
1044
130M
        uint32 x = stream.TagValue_uint32 (tagType);
1045
        
1046
130M
        if (j < kMaxSamplesPerPixel)
1047
39.0k
          {
1048
39.0k
          fSampleFormat [j] = x;
1049
39.0k
          }
1050
          
1051
130M
        else if (x != fSampleFormat [kMaxSamplesPerPixel - 1])
1052
18.7k
          {
1053
18.7k
          extrasMatch = false;
1054
18.7k
          }
1055
          
1056
        #if qDNGValidate
1057
      
1058
        if (gVerbose)
1059
          {
1060
          printf (" %s", LookupSampleFormat (x));
1061
          }
1062
          
1063
        #endif
1064
        
1065
130M
        }
1066
          
1067
      #if qDNGValidate
1068
      
1069
      if (gVerbose)
1070
        {
1071
        printf ("\n");
1072
        }
1073
        
1074
      #endif
1075
      
1076
19.8k
      if (!extrasMatch)
1077
10
        {
1078
        
1079
        #if qDNGValidate
1080
        
1081
        ReportError ("SampleFormat not constant");
1082
      
1083
        #endif
1084
        
1085
10
        ThrowBadFormat ();
1086
        
1087
10
        }
1088
      
1089
19.8k
      break;
1090
      
1091
0
      }
1092
        
1093
10.1k
    case tcJPEGTables:
1094
10.1k
      {
1095
      
1096
10.1k
      CheckTagType (parentCode, tagCode, tagType, ttUndefined);
1097
      
1098
10.1k
      fJPEGTablesCount  = tagCount;
1099
10.1k
      fJPEGTablesOffset = tagOffset;
1100
      
1101
      #if qDNGValidate
1102
        
1103
      if (gVerbose)
1104
        {
1105
        
1106
        printf ("JPEGTables: count = %u, offset = %u\n",
1107
            (unsigned) fJPEGTablesCount,
1108
            (unsigned) fJPEGTablesOffset);
1109
            
1110
        }
1111
        
1112
      #endif
1113
      
1114
10.1k
      break;
1115
      
1116
0
      }
1117
      
1118
1.40k
    case tcJPEGInterchangeFormat:
1119
1.40k
      {
1120
      
1121
1.40k
      CheckTagType (parentCode, tagCode, tagType, ttLong);
1122
      
1123
1.40k
      CheckTagCount (parentCode, tagCode, tagCount, 1);
1124
      
1125
1.40k
      fJPEGInterchangeFormat = stream.TagValue_uint32 (tagType);
1126
      
1127
      #if qDNGValidate
1128
        
1129
      if (gVerbose)
1130
        {
1131
        printf ("JPEGInterchangeFormat: %u\n",
1132
            (unsigned) fJPEGInterchangeFormat);
1133
        }
1134
        
1135
      #endif
1136
      
1137
1.40k
      break;
1138
      
1139
0
      }
1140
      
1141
3.89k
    case tcJPEGInterchangeFormatLength:
1142
3.89k
      {
1143
      
1144
3.89k
      CheckTagType (parentCode, tagCode, tagType, ttLong);
1145
      
1146
3.89k
      CheckTagCount (parentCode, tagCode, tagCount, 1);
1147
      
1148
3.89k
      fJPEGInterchangeFormatLength = stream.TagValue_uint32 (tagType);
1149
      
1150
      #if qDNGValidate
1151
        
1152
      if (gVerbose)
1153
        {
1154
        printf ("JPEGInterchangeFormatLength: %u\n",
1155
            (unsigned) fJPEGInterchangeFormatLength);
1156
        }
1157
        
1158
      #endif
1159
      
1160
3.89k
      break;
1161
      
1162
0
      }
1163
      
1164
11.9k
    case tcYCbCrCoefficients:
1165
11.9k
      {
1166
      
1167
11.9k
      CheckTagType (parentCode, tagCode, tagType, ttRational);
1168
      
1169
11.9k
      if (!CheckTagCount (parentCode, tagCode, tagCount, 3))
1170
2.94k
        {
1171
2.94k
        return false;
1172
2.94k
        }
1173
      
1174
8.95k
      fYCbCrCoefficientR = stream.TagValue_real64 (tagType);
1175
8.95k
      fYCbCrCoefficientG = stream.TagValue_real64 (tagType);
1176
8.95k
      fYCbCrCoefficientB = stream.TagValue_real64 (tagType);
1177
      
1178
      #if qDNGValidate
1179
        
1180
      if (gVerbose)
1181
        {
1182
        
1183
        printf ("YCbCrCoefficients: R = %0.3f, G = %0.3f, B = %0.3f\n",
1184
            fYCbCrCoefficientR,
1185
            fYCbCrCoefficientG,
1186
            fYCbCrCoefficientB);
1187
            
1188
        }
1189
        
1190
      #endif
1191
      
1192
8.95k
      break;
1193
      
1194
11.9k
      }
1195
1196
14.9k
    case tcYCbCrSubSampling:
1197
14.9k
      {
1198
      
1199
14.9k
      CheckTagType (parentCode, tagCode, tagType, ttShort);
1200
      
1201
14.9k
      if (!CheckTagCount (parentCode, tagCode, tagCount, 2))
1202
5.48k
        {
1203
5.48k
        return false;
1204
5.48k
        }
1205
      
1206
9.42k
      fYCbCrSubSampleH = stream.TagValue_uint32 (tagType);
1207
9.42k
      fYCbCrSubSampleV = stream.TagValue_uint32 (tagType);
1208
      
1209
      #if qDNGValidate
1210
        
1211
      if (gVerbose)
1212
        {
1213
        
1214
        printf ("YCbCrSubSampling: H = %u, V = %u\n",
1215
            (unsigned) fYCbCrSubSampleH,
1216
            (unsigned) fYCbCrSubSampleV);
1217
            
1218
        }
1219
        
1220
      #endif
1221
      
1222
9.42k
      break;
1223
      
1224
14.9k
      }
1225
      
1226
10.9k
    case tcYCbCrPositioning:
1227
10.9k
      {
1228
      
1229
10.9k
      CheckTagType (parentCode, tagCode, tagType, ttShort);
1230
      
1231
10.9k
      CheckTagCount (parentCode, tagCode, tagCount, 1);
1232
      
1233
10.9k
      fYCbCrPositioning = stream.TagValue_uint32 (tagType);
1234
      
1235
      #if qDNGValidate
1236
        
1237
      if (gVerbose)
1238
        {
1239
        
1240
        printf ("YCbCrPositioning: %u\n",
1241
            (unsigned) fYCbCrPositioning);
1242
            
1243
        }
1244
        
1245
      #endif
1246
      
1247
10.9k
      break;
1248
      
1249
14.9k
      }
1250
1251
5.65k
    case tcReferenceBlackWhite:
1252
5.65k
      {
1253
      
1254
5.65k
      CheckTagType (parentCode, tagCode, tagType, ttRational);
1255
      
1256
5.65k
      if (!CheckTagCount (parentCode, tagCode, tagCount, 6))
1257
992
        {
1258
992
        return false;
1259
992
        }
1260
      
1261
32.5k
      for (j = 0; j < 6; j++)
1262
27.9k
        {
1263
27.9k
        fReferenceBlackWhite [j] = stream.TagValue_real64 (tagType);
1264
27.9k
        }
1265
      
1266
      #if qDNGValidate
1267
        
1268
      if (gVerbose)
1269
        {
1270
        
1271
        printf ("ReferenceBlackWhite: %0.1f %0.1f %0.1f %0.1f %0.1f %0.1f\n",
1272
            fReferenceBlackWhite [0],
1273
            fReferenceBlackWhite [1],
1274
            fReferenceBlackWhite [2],
1275
            fReferenceBlackWhite [3],
1276
            fReferenceBlackWhite [4],
1277
            fReferenceBlackWhite [5]);
1278
1279
        }
1280
        
1281
      #endif
1282
      
1283
4.66k
      break;
1284
      
1285
5.65k
      }
1286
      
1287
21.2k
    case tcCFARepeatPatternDim:
1288
21.2k
      {
1289
      
1290
21.2k
      CheckCFA (parentCode, tagCode, fPhotometricInterpretation);
1291
1292
21.2k
      CheckTagType (parentCode, tagCode, tagType, ttShort);
1293
      
1294
21.2k
      if (!CheckTagCount (parentCode, tagCode, tagCount, 2))
1295
1.04k
        {
1296
1.04k
        return false;
1297
1.04k
        }
1298
      
1299
20.1k
      fCFARepeatPatternRows = stream.TagValue_uint32 (tagType);
1300
20.1k
      fCFARepeatPatternCols = stream.TagValue_uint32 (tagType);
1301
      
1302
      #if qDNGValidate
1303
        
1304
      if (gVerbose)
1305
        {
1306
        
1307
        printf ("CFARepeatPatternDim: Rows = %u, Cols = %u\n",
1308
            (unsigned) fCFARepeatPatternRows,
1309
            (unsigned) fCFARepeatPatternCols);
1310
        
1311
        }
1312
        
1313
      #endif
1314
        
1315
20.1k
      break;
1316
    
1317
21.2k
      }
1318
      
1319
30.4k
    case tcCFAPattern:
1320
30.4k
      {
1321
      
1322
30.4k
      CheckCFA (parentCode, tagCode, fPhotometricInterpretation);
1323
1324
30.4k
      if (!CheckTagType (parentCode, tagCode, tagType, ttByte))
1325
1.03k
        {
1326
1.03k
        return false;
1327
1.03k
        }
1328
      
1329
29.4k
      if (!CheckTagCount (parentCode, tagCode, tagCount,
1330
29.4k
                SafeUint32Mult(fCFARepeatPatternRows, fCFARepeatPatternCols)))
1331
5.21k
        {
1332
5.21k
        return false;
1333
5.21k
        }
1334
        
1335
24.1k
      if (fCFARepeatPatternRows < 1 || fCFARepeatPatternRows > kMaxCFAPattern ||
1336
22.1k
        fCFARepeatPatternCols < 1 || fCFARepeatPatternCols > kMaxCFAPattern)
1337
4.27k
        {
1338
4.27k
        return false;
1339
4.27k
        }
1340
        
1341
      // Note that the Exif spec stores this array in a different
1342
      // scan order than the TIFF-EP spec.
1343
      
1344
65.0k
      for (j = 0; j < fCFARepeatPatternRows; j++)
1345
132k
        for (k = 0; k < fCFARepeatPatternCols; k++)
1346
87.3k
          {
1347
          
1348
87.3k
          fCFAPattern [j] [k] = stream.Get_uint8 ();
1349
          
1350
87.3k
          }
1351
          
1352
      #if qDNGValidate
1353
        
1354
      if (gVerbose)
1355
        {
1356
        
1357
        printf ("CFAPattern:\n");
1358
        
1359
        for (j = 0; j < fCFARepeatPatternRows; j++)
1360
          {
1361
          
1362
          int32 spaces = 4;
1363
          
1364
          for (k = 0; k < fCFARepeatPatternCols; k++)
1365
            {
1366
            
1367
            while (spaces-- > 0)
1368
              {
1369
              printf (" ");
1370
              }
1371
              
1372
            const char *name = LookupCFAColor (fCFAPattern [j] [k]);
1373
            
1374
            spaces = 9 - (int32) strlen (name);
1375
            
1376
            printf ("%s", name);
1377
            
1378
            }
1379
            
1380
          printf ("\n");
1381
          
1382
          }
1383
          
1384
        }
1385
        
1386
      #endif
1387
      
1388
19.9k
      break;
1389
      
1390
24.1k
      }
1391
      
1392
9.35k
    case tcCFAPlaneColor:
1393
9.35k
      {
1394
      
1395
9.35k
      CheckCFA (parentCode, tagCode, fPhotometricInterpretation);
1396
1397
9.35k
      if (!CheckTagType (parentCode, tagCode, tagType, ttByte))
1398
2.76k
        {
1399
2.76k
        return false;
1400
2.76k
        }
1401
      
1402
6.59k
      if (!CheckTagCount (parentCode, tagCode, tagCount, 3, kMaxColorPlanes))
1403
1.17k
        {
1404
1.17k
        return false;
1405
1.17k
        }
1406
        
1407
26.9k
      for (j = 0; j < kMaxColorPlanes; j++)
1408
21.5k
        {
1409
        
1410
21.5k
        if (j < tagCount)
1411
20.6k
          fCFAPlaneColor [j] = stream.Get_uint8 ();
1412
          
1413
895
        else
1414
895
          fCFAPlaneColor [j] = 255;
1415
          
1416
21.5k
        }
1417
        
1418
      #if qDNGValidate
1419
        
1420
      if (gVerbose)
1421
        {
1422
        
1423
        printf ("CFAPlaneColor:");
1424
        
1425
        for (j = 0; j < tagCount; j++)
1426
          {
1427
          
1428
          printf (" %s", LookupCFAColor (fCFAPlaneColor [j]));
1429
          
1430
          }
1431
          
1432
        printf ("\n");
1433
        
1434
        }
1435
        
1436
      #endif
1437
        
1438
5.41k
      break;
1439
      
1440
6.59k
      }
1441
        
1442
4.35k
    case tcCFALayout:
1443
4.35k
      {
1444
      
1445
4.35k
      CheckCFA (parentCode, tagCode, fPhotometricInterpretation);
1446
1447
4.35k
      CheckTagType (parentCode, tagCode, tagType, ttShort);
1448
      
1449
4.35k
      CheckTagCount (parentCode, tagCode, tagCount, 1);
1450
      
1451
4.35k
      fCFALayout = stream.TagValue_uint32 (tagType);
1452
      
1453
      #if qDNGValidate
1454
        
1455
      if (gVerbose)
1456
        {
1457
        
1458
        printf ("CFALayout: %s\n",
1459
            LookupCFALayout (fCFALayout));
1460
        
1461
        }
1462
        
1463
      #endif
1464
        
1465
4.35k
      break;
1466
      
1467
6.59k
      }
1468
        
1469
16.0k
    case tcLinearizationTable:
1470
16.0k
      {
1471
      
1472
16.0k
      CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation);
1473
1474
16.0k
      CheckTagType (parentCode, tagCode, tagType, ttShort);
1475
      
1476
16.0k
      fLinearizationTableType   = tagType;
1477
16.0k
      fLinearizationTableCount  = tagCount;
1478
16.0k
      fLinearizationTableOffset = tagOffset;
1479
      
1480
      #if qDNGValidate
1481
        
1482
      if (gVerbose)
1483
        {
1484
        
1485
        DumpTagValues (stream,
1486
                 "Table",
1487
                 parentCode,
1488
                 tagCode,
1489
                 tagType,
1490
                 tagCount);
1491
1492
        }
1493
        
1494
      #endif
1495
      
1496
16.0k
      break;
1497
      
1498
6.59k
      }
1499
        
1500
25.4k
    case tcBlackLevelRepeatDim:
1501
25.4k
      {
1502
1503
25.4k
      CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation);
1504
1505
25.4k
      CheckTagType (parentCode, tagCode, tagType, ttShort);
1506
      
1507
25.4k
      if (!CheckTagCount (parentCode, tagCode, tagCount, 2))
1508
3.99k
        {
1509
3.99k
        return false;
1510
3.99k
        }
1511
      
1512
21.4k
      fBlackLevelRepeatRows = stream.TagValue_uint32 (tagType);
1513
21.4k
      fBlackLevelRepeatCols = stream.TagValue_uint32 (tagType);
1514
      
1515
      #if qDNGValidate
1516
        
1517
      if (gVerbose)
1518
        {
1519
        
1520
        printf ("BlackLevelRepeatDim: Rows = %u, Cols = %u\n",
1521
            (unsigned) fBlackLevelRepeatRows,
1522
            (unsigned) fBlackLevelRepeatCols);
1523
        
1524
        }
1525
        
1526
      #endif
1527
        
1528
21.4k
      break;
1529
    
1530
25.4k
      }
1531
      
1532
26.6k
    case tcBlackLevel:
1533
26.6k
      {
1534
      
1535
26.6k
      CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation);
1536
1537
26.6k
      CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong, ttRational);
1538
1539
26.6k
      if (!CheckTagCount (parentCode, tagCode, tagCount, SafeUint32Mult(fBlackLevelRepeatRows,
1540
26.6k
                                 fBlackLevelRepeatCols,
1541
26.6k
                                 fSamplesPerPixel)))
1542
6.22k
        {
1543
6.22k
        return false;
1544
6.22k
        }
1545
      
1546
20.4k
      if (fBlackLevelRepeatRows < 1 || fBlackLevelRepeatRows > kMaxBlackPattern   ||
1547
17.1k
        fBlackLevelRepeatCols < 1 || fBlackLevelRepeatCols > kMaxBlackPattern   ||
1548
14.5k
        fSamplesPerPixel      < 1 || fSamplesPerPixel      > kMaxSamplesPerPixel)
1549
6.46k
        {
1550
6.46k
        return false;
1551
6.46k
        }
1552
        
1553
28.8k
      for (j = 0; j < fBlackLevelRepeatRows; j++)
1554
31.1k
        for (k = 0; k < fBlackLevelRepeatCols; k++)
1555
50.6k
          for (n = 0; n < fSamplesPerPixel; n++)
1556
34.4k
            {
1557
            
1558
34.4k
            fBlackLevel [j] [k] [n] = stream.TagValue_real64 (tagType);
1559
            
1560
34.4k
            }
1561
            
1562
      #if qDNGValidate
1563
        
1564
      if (gVerbose)
1565
        {
1566
        
1567
        printf ("BlackLevel:");
1568
        
1569
        if (fBlackLevelRepeatRows == 1 &&
1570
          fBlackLevelRepeatCols == 1)
1571
          {
1572
          
1573
          for (n = 0; n < fSamplesPerPixel; n++)
1574
            {
1575
            printf (" %0.2f", fBlackLevel [0] [0] [n]);
1576
            }
1577
            
1578
          printf ("\n");
1579
          
1580
          }
1581
          
1582
        else
1583
          {
1584
          
1585
          printf ("\n");
1586
          
1587
          for (n = 0; n < fSamplesPerPixel; n++)
1588
            {
1589
            
1590
            if (fSamplesPerPixel > 1)
1591
              {
1592
              printf ("    Sample: %u\n", (unsigned) n);
1593
              }
1594
              
1595
            for (j = 0; j < fBlackLevelRepeatRows; j++)
1596
              {
1597
              
1598
              printf ("   ");
1599
              
1600
              for (k = 0; k < fBlackLevelRepeatCols; k++)
1601
                {
1602
                
1603
                printf (" %8.2f", fBlackLevel [j] [k] [n]);
1604
                
1605
                }
1606
                
1607
              printf ("\n");
1608
              
1609
              }
1610
            
1611
            }
1612
            
1613
          }
1614
        
1615
        }
1616
        
1617
      #endif
1618
        
1619
13.9k
      break;
1620
      
1621
20.4k
      }
1622
1623
6.31k
    case tcBlackLevelDeltaH:
1624
6.31k
      {
1625
      
1626
6.31k
      CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation);
1627
1628
6.31k
      CheckTagType (parentCode, tagCode, tagType, ttSRational);
1629
      
1630
6.31k
      fBlackLevelDeltaHType   = tagType;
1631
6.31k
      fBlackLevelDeltaHCount  = tagCount;
1632
6.31k
      fBlackLevelDeltaHOffset = tagOffset;
1633
      
1634
      #if qDNGValidate
1635
        
1636
      if (gVerbose)
1637
        {
1638
        
1639
        DumpTagValues (stream,
1640
                 "Delta",
1641
                 parentCode,
1642
                 tagCode,
1643
                 tagType,
1644
                 tagCount);
1645
1646
        }
1647
        
1648
      #endif
1649
      
1650
6.31k
      break;
1651
      
1652
20.4k
      }
1653
        
1654
5.63k
    case tcBlackLevelDeltaV:
1655
5.63k
      {
1656
      
1657
5.63k
      CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation);
1658
1659
5.63k
      CheckTagType (parentCode, tagCode, tagType, ttSRational);
1660
      
1661
5.63k
      fBlackLevelDeltaVType   = tagType;
1662
5.63k
      fBlackLevelDeltaVCount  = tagCount;
1663
5.63k
      fBlackLevelDeltaVOffset = tagOffset;
1664
      
1665
      #if qDNGValidate
1666
        
1667
      if (gVerbose)
1668
        {
1669
        
1670
        DumpTagValues (stream,
1671
                 "Delta",
1672
                 parentCode,
1673
                 tagCode,
1674
                 tagType,
1675
                 tagCount);
1676
1677
        }
1678
        
1679
      #endif
1680
      
1681
5.63k
      break;
1682
      
1683
20.4k
      }
1684
        
1685
34.4k
    case tcWhiteLevel:
1686
34.4k
      {
1687
      
1688
34.4k
      CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation);
1689
1690
34.4k
      CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
1691
      
1692
34.4k
      if (!CheckTagCount (parentCode, tagCode, tagCount, fSamplesPerPixel))
1693
20.8k
        return false;
1694
        
1695
45.6k
      for (j = 0; j < tagCount && j < kMaxSamplesPerPixel; j++)
1696
32.0k
        {
1697
1698
32.0k
        fWhiteLevel [j] = stream.TagValue_real64 (tagType);
1699
1700
32.0k
        }
1701
      
1702
      #if qDNGValidate
1703
        
1704
      if (gVerbose)
1705
        {
1706
        
1707
        printf ("WhiteLevel:");
1708
        
1709
        for (j = 0; j < tagCount && j < kMaxSamplesPerPixel; j++)
1710
          {
1711
1712
          printf (" %0.0f", fWhiteLevel [j]);
1713
1714
          }
1715
          
1716
        printf ("\n");
1717
        
1718
        }
1719
        
1720
      #endif
1721
        
1722
13.6k
      break;
1723
      
1724
34.4k
      }
1725
      
1726
24.3k
    case tcDefaultScale:
1727
24.3k
      {
1728
      
1729
24.3k
      CheckMainIFD (parentCode, tagCode, fNewSubFileType);
1730
      
1731
24.3k
      CheckTagType (parentCode, tagCode, tagType, ttRational);
1732
      
1733
24.3k
      if (!CheckTagCount (parentCode, tagCode, tagCount, 2))
1734
5.39k
        return false;
1735
        
1736
18.9k
      fDefaultScaleH = stream.TagValue_urational (tagType);
1737
18.9k
      fDefaultScaleV = stream.TagValue_urational (tagType);
1738
      
1739
      #if qDNGValidate
1740
        
1741
      if (gVerbose)
1742
        {
1743
        
1744
        printf ("DefaultScale: H = %0.4f V = %0.4f\n",
1745
            fDefaultScaleH.As_real64 (),
1746
            fDefaultScaleV.As_real64 ());
1747
            
1748
        }
1749
        
1750
      #endif
1751
      
1752
18.9k
      break;
1753
      
1754
24.3k
      }
1755
        
1756
22.9k
    case tcDefaultCropOrigin:
1757
22.9k
      {
1758
      
1759
22.9k
      CheckMainIFD (parentCode, tagCode, fNewSubFileType);
1760
      
1761
22.9k
      CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong, ttRational);
1762
      
1763
22.9k
      if (!CheckTagCount (parentCode, tagCode, tagCount, 2))
1764
6.48k
        return false;
1765
        
1766
16.4k
      fDefaultCropOriginH = stream.TagValue_urational (tagType);
1767
16.4k
      fDefaultCropOriginV = stream.TagValue_urational (tagType);
1768
      
1769
      #if qDNGValidate
1770
        
1771
      if (gVerbose)
1772
        {
1773
        
1774
        printf ("DefaultCropOrigin: H = %0.2f V = %0.2f\n",
1775
            fDefaultCropOriginH.As_real64 (),
1776
            fDefaultCropOriginV.As_real64 ());
1777
            
1778
        }
1779
        
1780
      #endif
1781
      
1782
16.4k
      break;
1783
      
1784
22.9k
      }
1785
        
1786
24.7k
    case tcDefaultCropSize:
1787
24.7k
      {
1788
      
1789
24.7k
      CheckMainIFD (parentCode, tagCode, fNewSubFileType);
1790
      
1791
24.7k
      CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong, ttRational);
1792
      
1793
24.7k
      if (!CheckTagCount (parentCode, tagCode, tagCount, 2))
1794
5.43k
        return false;
1795
        
1796
19.3k
      fDefaultCropSizeH = stream.TagValue_urational (tagType);
1797
19.3k
      fDefaultCropSizeV = stream.TagValue_urational (tagType);
1798
      
1799
      #if qDNGValidate
1800
        
1801
      if (gVerbose)
1802
        {
1803
        
1804
        printf ("DefaultCropSize: H = %0.2f V = %0.2f\n",
1805
            fDefaultCropSizeH.As_real64 (),
1806
            fDefaultCropSizeV.As_real64 ());
1807
            
1808
        }
1809
        
1810
      #endif
1811
      
1812
19.3k
      break;
1813
      
1814
24.7k
      }
1815
      
1816
5.23k
    case tcDefaultUserCrop:
1817
5.23k
      {
1818
      
1819
5.23k
      CheckMainIFD (parentCode, tagCode, fNewSubFileType);
1820
      
1821
5.23k
      CheckTagType (parentCode, tagCode, tagType, ttRational);
1822
      
1823
5.23k
      if (!CheckTagCount (parentCode, tagCode, tagCount, 4))
1824
1.11k
        return false;
1825
        
1826
4.12k
      fDefaultUserCropT = stream.TagValue_urational (tagType);
1827
4.12k
      fDefaultUserCropL = stream.TagValue_urational (tagType);
1828
4.12k
      fDefaultUserCropB = stream.TagValue_urational (tagType);
1829
4.12k
      fDefaultUserCropR = stream.TagValue_urational (tagType);
1830
      
1831
      #if qDNGValidate
1832
        
1833
      if (gVerbose)
1834
        {
1835
        
1836
        printf ("DefaultUserCrop: T = %0.2lf L = %0.2lf B = %0.2lf R = %0.2lf\n",
1837
            (double) fDefaultUserCropT.As_real64 (),
1838
            (double) fDefaultUserCropL.As_real64 (),
1839
            (double) fDefaultUserCropB.As_real64 (),
1840
            (double) fDefaultUserCropR.As_real64 ());
1841
            
1842
            
1843
        }
1844
        
1845
      #endif  // qDNGValidate
1846
      
1847
4.12k
      break;
1848
      
1849
5.23k
      }
1850
        
1851
4.34k
    case tcBayerGreenSplit:
1852
4.34k
      {
1853
      
1854
4.34k
      CheckCFA (parentCode, tagCode, fPhotometricInterpretation);
1855
1856
4.34k
      CheckTagType (parentCode, tagCode, tagType, ttLong);
1857
      
1858
4.34k
      CheckTagCount (parentCode, tagCode, tagCount, 1);
1859
      
1860
4.34k
      fBayerGreenSplit = stream.TagValue_uint32 (tagType);
1861
      
1862
      #if qDNGValidate
1863
        
1864
      if (gVerbose)
1865
        {
1866
        printf ("BayerGreenSplit: %u\n", (unsigned) fBayerGreenSplit);
1867
        }
1868
        
1869
      #endif
1870
        
1871
4.34k
      break;
1872
      
1873
5.23k
      }
1874
        
1875
28.0k
    case tcChromaBlurRadius:
1876
28.0k
      {
1877
      
1878
28.0k
      CheckMainIFD (parentCode, tagCode, fNewSubFileType);
1879
      
1880
28.0k
      CheckTagType (parentCode, tagCode, tagType, ttRational);
1881
      
1882
28.0k
      CheckTagCount (parentCode, tagCode, tagCount, 1);
1883
        
1884
28.0k
      fChromaBlurRadius = stream.TagValue_urational (tagType);
1885
      
1886
      #if qDNGValidate
1887
        
1888
      if (gVerbose)
1889
        {
1890
        
1891
        printf ("ChromaBlurRadius: %0.2f\n",
1892
            fChromaBlurRadius.As_real64 ());
1893
            
1894
        }
1895
        
1896
      #endif
1897
      
1898
28.0k
      break;
1899
      
1900
5.23k
      }
1901
        
1902
31.2k
    case tcAntiAliasStrength:
1903
31.2k
      {
1904
      
1905
31.2k
      CheckMainIFD (parentCode, tagCode, fNewSubFileType);
1906
      
1907
31.2k
      CheckTagType (parentCode, tagCode, tagType, ttRational);
1908
      
1909
31.2k
      CheckTagCount (parentCode, tagCode, tagCount, 1);
1910
        
1911
31.2k
      fAntiAliasStrength = stream.TagValue_urational (tagType);
1912
      
1913
      #if qDNGValidate
1914
        
1915
      if (gVerbose)
1916
        {
1917
        
1918
        printf ("AntiAliasStrength: %0.2f\n",
1919
            fAntiAliasStrength.As_real64 ());
1920
            
1921
        }
1922
        
1923
      #endif
1924
      
1925
31.2k
      break;
1926
      
1927
5.23k
      }
1928
        
1929
12.7k
    case tcBestQualityScale:
1930
12.7k
      {
1931
      
1932
12.7k
      CheckMainIFD (parentCode, tagCode, fNewSubFileType);
1933
      
1934
12.7k
      CheckTagType (parentCode, tagCode, tagType, ttRational);
1935
      
1936
12.7k
      CheckTagCount (parentCode, tagCode, tagCount, 1);
1937
        
1938
12.7k
      fBestQualityScale = stream.TagValue_urational (tagType);
1939
      
1940
      #if qDNGValidate
1941
        
1942
      if (gVerbose)
1943
        {
1944
        
1945
        printf ("BestQualityScale: %0.4f\n",
1946
            fBestQualityScale.As_real64 ());
1947
            
1948
        }
1949
        
1950
      #endif
1951
      
1952
12.7k
      break;
1953
      
1954
5.23k
      }
1955
        
1956
22.5k
    case tcActiveArea:
1957
22.5k
      {
1958
      
1959
22.5k
      CheckMainIFD (parentCode, tagCode, fNewSubFileType);
1960
      
1961
22.5k
      CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
1962
      
1963
22.5k
      if (!CheckTagCount (parentCode, tagCode, tagCount, 4))
1964
2.31k
        return false;
1965
        
1966
20.2k
      fActiveArea.t = stream.TagValue_int32 (tagType);
1967
20.2k
      fActiveArea.l = stream.TagValue_int32 (tagType);
1968
20.2k
      fActiveArea.b = stream.TagValue_int32 (tagType);
1969
20.2k
      fActiveArea.r = stream.TagValue_int32 (tagType);
1970
      
1971
      #if qDNGValidate
1972
        
1973
      if (gVerbose)
1974
        {
1975
        
1976
        printf ("ActiveArea: T = %d L = %d B = %d R = %d\n",
1977
            (int) fActiveArea.t,
1978
            (int) fActiveArea.l,
1979
            (int) fActiveArea.b,
1980
            (int) fActiveArea.r);
1981
            
1982
        }
1983
        
1984
      #endif
1985
      
1986
20.2k
      break;
1987
      
1988
22.5k
      }
1989
        
1990
12.4k
    case tcMaskedAreas:
1991
12.4k
      {
1992
      
1993
12.4k
      CheckMainIFD (parentCode, tagCode, fNewSubFileType);
1994
      
1995
12.4k
      CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
1996
      
1997
12.4k
      uint32 rect_count = tagCount / 4;
1998
      
1999
12.4k
      if (!CheckTagCount (parentCode, tagCode, tagCount, rect_count * 4))
2000
1.65k
        return false;
2001
        
2002
10.8k
      fMaskedAreaCount = rect_count;
2003
        
2004
10.8k
      if (fMaskedAreaCount > kMaxMaskedAreas)
2005
6.80k
        fMaskedAreaCount = kMaxMaskedAreas;
2006
        
2007
40.8k
      for (j = 0; j < fMaskedAreaCount; j++)
2008
29.9k
        {
2009
        
2010
29.9k
        fMaskedArea [j].t = stream.TagValue_int32 (tagType);
2011
29.9k
        fMaskedArea [j].l = stream.TagValue_int32 (tagType);
2012
29.9k
        fMaskedArea [j].b = stream.TagValue_int32 (tagType);
2013
29.9k
        fMaskedArea [j].r = stream.TagValue_int32 (tagType);
2014
        
2015
29.9k
        }
2016
      
2017
      #if qDNGValidate
2018
        
2019
      if (gVerbose)
2020
        {
2021
        
2022
        printf ("MaskedAreas: %u\n", (unsigned) fMaskedAreaCount);
2023
        
2024
        for (j = 0; j < fMaskedAreaCount; j++)
2025
          {
2026
        
2027
          printf ("    Area [%u]: T = %d L = %d B = %d R = %d\n",
2028
              (unsigned) j,
2029
              (int) fMaskedArea [j].t,
2030
              (int) fMaskedArea [j].l,
2031
              (int) fMaskedArea [j].b,
2032
              (int) fMaskedArea [j].r);
2033
              
2034
          }
2035
            
2036
        }
2037
        
2038
      #endif
2039
      
2040
10.8k
      break;
2041
      
2042
12.4k
      }
2043
      
2044
67.2k
    case tcPreviewApplicationName:
2045
67.2k
      {
2046
2047
67.2k
      CheckTagType (parentCode, tagCode, tagType, ttAscii, ttByte);
2048
      
2049
67.2k
      ParseStringTag (stream,
2050
67.2k
              parentCode,
2051
67.2k
              tagCode,
2052
67.2k
              tagCount,
2053
67.2k
              fPreviewInfo.fApplicationName,
2054
67.2k
              false);
2055
      
2056
      #if qDNGValidate
2057
            
2058
      if (gVerbose)
2059
        {
2060
        
2061
        printf ("PreviewApplicationName: ");
2062
        
2063
        DumpString (fPreviewInfo.fApplicationName);
2064
        
2065
        printf ("\n");
2066
        
2067
        }
2068
2069
      #endif
2070
      
2071
67.2k
      break;
2072
      
2073
12.4k
      }
2074
        
2075
38.2k
    case tcPreviewApplicationVersion:
2076
38.2k
      {
2077
2078
38.2k
      CheckTagType (parentCode, tagCode, tagType, ttAscii, ttByte);
2079
      
2080
38.2k
      ParseStringTag (stream,
2081
38.2k
              parentCode,
2082
38.2k
              tagCode,
2083
38.2k
              tagCount,
2084
38.2k
              fPreviewInfo.fApplicationVersion,
2085
38.2k
              false);
2086
      
2087
      #if qDNGValidate
2088
            
2089
      if (gVerbose)
2090
        {
2091
        
2092
        printf ("PreviewApplicationVersion: ");
2093
        
2094
        DumpString (fPreviewInfo.fApplicationVersion);
2095
        
2096
        printf ("\n");
2097
        
2098
        }
2099
2100
      #endif
2101
      
2102
38.2k
      break;
2103
      
2104
12.4k
      }
2105
        
2106
570
    case tcPreviewSettingsName:
2107
570
      {
2108
2109
570
      CheckTagType (parentCode, tagCode, tagType, ttAscii, ttByte);
2110
      
2111
570
      ParseStringTag (stream,
2112
570
              parentCode,
2113
570
              tagCode,
2114
570
              tagCount,
2115
570
              fPreviewInfo.fSettingsName,
2116
570
              false);
2117
      
2118
      #if qDNGValidate
2119
            
2120
      if (gVerbose)
2121
        {
2122
        
2123
        printf ("PreviewSettingsName: ");
2124
        
2125
        DumpString (fPreviewInfo.fSettingsName);
2126
        
2127
        printf ("\n");
2128
        
2129
        }
2130
2131
      #endif
2132
      
2133
570
      break;
2134
      
2135
12.4k
      }
2136
        
2137
30.7k
    case tcPreviewSettingsDigest:
2138
30.7k
      {
2139
      
2140
30.7k
      if (!CheckTagType (parentCode, tagCode, tagType, ttByte))
2141
1.37k
        return false;
2142
        
2143
29.3k
      if (!CheckTagCount (parentCode, tagCode, tagCount, 16))
2144
12.4k
        return false;
2145
        
2146
16.8k
      stream.Get (fPreviewInfo.fSettingsDigest.data, 16);
2147
        
2148
      #if qDNGValidate
2149
2150
      if (gVerbose)
2151
        {
2152
        
2153
        printf ("PreviewSettingsDigest: ");
2154
        
2155
        DumpFingerprint (fPreviewInfo.fSettingsDigest);
2156
                  
2157
        printf ("\n");
2158
        
2159
        }
2160
        
2161
      #endif
2162
        
2163
16.8k
      break;
2164
      
2165
29.3k
      }
2166
        
2167
23.3k
    case tcPreviewColorSpace:
2168
23.3k
      {
2169
      
2170
23.3k
      CheckTagType (parentCode, tagCode, tagType, ttLong);
2171
        
2172
23.3k
      CheckTagCount (parentCode, tagCode, tagCount, 1);
2173
      
2174
23.3k
      fPreviewInfo.fColorSpace = (PreviewColorSpaceEnum)
2175
23.3k
                     stream.TagValue_uint32 (tagType);
2176
        
2177
      #if qDNGValidate
2178
2179
      if (gVerbose)
2180
        {
2181
        
2182
        printf ("PreviewColorSpace: %s\n",
2183
            LookupPreviewColorSpace ((uint32) fPreviewInfo.fColorSpace));
2184
        
2185
        }
2186
        
2187
      #endif
2188
        
2189
23.3k
      break;
2190
      
2191
29.3k
      }
2192
        
2193
27.3k
    case tcPreviewDateTime:
2194
27.3k
      {
2195
2196
27.3k
      CheckTagType (parentCode, tagCode, tagType, ttAscii);
2197
      
2198
27.3k
      ParseStringTag (stream,
2199
27.3k
              parentCode,
2200
27.3k
              tagCode,
2201
27.3k
              tagCount,
2202
27.3k
              fPreviewInfo.fDateTime,
2203
27.3k
              false);
2204
      
2205
      #if qDNGValidate
2206
            
2207
      if (gVerbose)
2208
        {
2209
        
2210
        printf ("PreviewDateTime: ");
2211
        
2212
        DumpString (fPreviewInfo.fDateTime);
2213
        
2214
        printf ("\n");
2215
        
2216
        }
2217
2218
      #endif
2219
      
2220
27.3k
      break;
2221
      
2222
29.3k
      }
2223
        
2224
9.86k
    case tcRowInterleaveFactor:
2225
9.86k
      {
2226
      
2227
9.86k
      CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
2228
      
2229
9.86k
      if (!CheckTagCount (parentCode, tagCode, tagCount, 1))
2230
1.51k
        return false;
2231
      
2232
8.34k
      fRowInterleaveFactor = stream.TagValue_uint32 (tagType);
2233
2234
      #if qDNGValidate
2235
            
2236
      if (gVerbose)
2237
        {
2238
        
2239
        printf ("RowInterleaveFactor: %u\n",
2240
            (unsigned) fRowInterleaveFactor);
2241
        
2242
        }
2243
2244
      #endif
2245
      
2246
8.34k
      break;
2247
      
2248
9.86k
      }
2249
      
2250
21.2k
    case tcSubTileBlockSize:
2251
21.2k
      {
2252
      
2253
21.2k
      CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
2254
      
2255
21.2k
      if (!CheckTagCount (parentCode, tagCode, tagCount, 2))
2256
13.8k
        return false;
2257
      
2258
7.38k
      fSubTileBlockRows = stream.TagValue_uint32 (tagType);
2259
7.38k
      fSubTileBlockCols = stream.TagValue_uint32 (tagType);
2260
2261
      #if qDNGValidate
2262
            
2263
      if (gVerbose)
2264
        {
2265
        
2266
        printf ("SubTileBlockSize: rows = %u, cols = %u\n",
2267
            (unsigned) fSubTileBlockRows,
2268
            (unsigned) fSubTileBlockCols);
2269
        
2270
        }
2271
2272
      #endif
2273
      
2274
7.38k
      break;
2275
      
2276
21.2k
      }
2277
      
2278
4.03k
    case tcOpcodeList1:
2279
4.03k
      {
2280
      
2281
4.03k
      CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation);
2282
      
2283
4.03k
      CheckTagType (parentCode, tagCode, tagType, ttUndefined);
2284
      
2285
4.03k
      fOpcodeList1Count  = tagCount;
2286
4.03k
      fOpcodeList1Offset = tagOffset;
2287
      
2288
      #if qDNGValidate
2289
            
2290
      if (gVerbose)
2291
        {
2292
        
2293
        printf ("OpcodeList1: count = %u, offset = %u\n",
2294
            (unsigned) fOpcodeList1Count,
2295
            (unsigned) fOpcodeList1Offset);
2296
        
2297
        }
2298
2299
      #endif
2300
      
2301
4.03k
      break;
2302
      
2303
21.2k
      }
2304
        
2305
7.52k
    case tcOpcodeList2:
2306
7.52k
      {
2307
      
2308
7.52k
      CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation);
2309
      
2310
7.52k
      CheckTagType (parentCode, tagCode, tagType, ttUndefined);
2311
      
2312
7.52k
      fOpcodeList2Count  = tagCount;
2313
7.52k
      fOpcodeList2Offset = tagOffset;
2314
      
2315
      #if qDNGValidate
2316
            
2317
      if (gVerbose)
2318
        {
2319
        
2320
        printf ("OpcodeList2: count = %u, offset = %u\n",
2321
            (unsigned) fOpcodeList2Count,
2322
            (unsigned) fOpcodeList2Offset);
2323
        
2324
        }
2325
2326
      #endif
2327
      
2328
7.52k
      break;
2329
      
2330
21.2k
      }
2331
        
2332
10.1k
    case tcOpcodeList3:
2333
10.1k
      {
2334
      
2335
10.1k
      CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation);
2336
      
2337
10.1k
      CheckTagType (parentCode, tagCode, tagType, ttUndefined);
2338
      
2339
10.1k
      fOpcodeList3Count  = tagCount;
2340
10.1k
      fOpcodeList3Offset = tagOffset;
2341
      
2342
      #if qDNGValidate
2343
            
2344
      if (gVerbose)
2345
        {
2346
        
2347
        printf ("OpcodeList3: count = %u, offset = %u\n",
2348
            (unsigned) fOpcodeList3Count,
2349
            (unsigned) fOpcodeList3Offset);
2350
        
2351
        }
2352
2353
      #endif
2354
      
2355
10.1k
      break;
2356
      
2357
21.2k
      }
2358
      
2359
2.06k
    case tcRawToPreviewGain:
2360
2.06k
      {
2361
      
2362
      #if qDNGValidate
2363
            
2364
      if (fNewSubFileType != sfPreviewImage)
2365
        {
2366
            
2367
        char message [256];
2368
        
2369
        sprintf (message,
2370
             "%s %s is not allowed IFDs with NewSubFileType != PreviewImage",
2371
             LookupParentCode (parentCode),
2372
             LookupTagCode (parentCode, tagCode));
2373
             
2374
        ReportWarning (message);
2375
               
2376
        }
2377
        
2378
      #endif
2379
      
2380
2.06k
      CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation);
2381
      
2382
2.06k
      CheckTagType (parentCode, tagCode, tagType, ttDouble);
2383
      
2384
2.06k
      if (!CheckTagCount (parentCode, tagCode, tagCount, 1))
2385
1.13k
        return false;
2386
        
2387
930
      fPreviewInfo.fRawToPreviewGain = stream.TagValue_real64 (tagType);
2388
      
2389
      #if qDNGValidate
2390
            
2391
      if (gVerbose)
2392
        {
2393
        
2394
        printf ("RawToPreviewGain = %f\n",
2395
            fPreviewInfo.fRawToPreviewGain);
2396
        
2397
        }
2398
2399
      #endif
2400
      
2401
930
      break;
2402
      
2403
2.06k
      }
2404
        
2405
6.15k
    case tcCacheVersion:
2406
6.15k
      {
2407
      
2408
      #if qDNGValidate
2409
            
2410
      if (fNewSubFileType != sfPreviewImage)
2411
        {
2412
            
2413
        char message [256];
2414
        
2415
        sprintf (message,
2416
             "%s %s is not allowed IFDs with NewSubFileType != PreviewImage",
2417
             LookupParentCode (parentCode),
2418
             LookupTagCode (parentCode, tagCode));
2419
             
2420
        ReportWarning (message);
2421
               
2422
        }
2423
        
2424
      #endif
2425
      
2426
6.15k
      CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation);
2427
      
2428
6.15k
      CheckTagType (parentCode, tagCode, tagType, ttLong);
2429
      
2430
6.15k
      if (!CheckTagCount (parentCode, tagCode, tagCount, 1))
2431
1.29k
        return false;
2432
        
2433
4.86k
      fPreviewInfo.fCacheVersion = stream.TagValue_uint32 (tagType);
2434
      
2435
      #if qDNGValidate
2436
            
2437
      if (gVerbose)
2438
        {
2439
        
2440
        printf ("CacheVersion = 0x%x\n",
2441
            (unsigned) fPreviewInfo.fCacheVersion);
2442
        
2443
        }
2444
2445
      #endif
2446
      
2447
4.86k
      break;
2448
      
2449
6.15k
      }
2450
        
2451
2.96M
    default:
2452
2.96M
      {
2453
      
2454
2.96M
      return false;
2455
      
2456
6.15k
      }
2457
2458
5.77M
    }
2459
  
2460
2.69M
  return true;
2461
  
2462
5.77M
  }
2463
                 
2464
/*****************************************************************************/
2465
2466
void dng_ifd::PostParse ()
2467
340k
  {
2468
  
2469
340k
  uint32 j;
2470
340k
  uint32 k;
2471
  
2472
  // There is only one PlanarConfiguration for single sample imaages.
2473
  
2474
340k
  if (fSamplesPerPixel == 1)
2475
297k
    {
2476
297k
    fPlanarConfiguration = pcInterleaved;
2477
297k
    }
2478
    
2479
  // Default tile size.
2480
    
2481
340k
  if (fTileWidth == 0)
2482
315k
    {
2483
315k
    fTileWidth = fImageWidth;
2484
315k
    }
2485
    
2486
340k
  if (fTileLength == 0)
2487
284k
    {
2488
284k
    fTileLength = fImageLength;
2489
284k
    }
2490
    
2491
  // Default ActiveArea.
2492
    
2493
340k
  dng_rect imageArea (0, 0, fImageLength, fImageWidth);
2494
2495
340k
  if (fActiveArea.IsZero ())
2496
320k
    {
2497
320k
    fActiveArea = imageArea;
2498
320k
    }
2499
    
2500
  // Default crop size.
2501
    
2502
340k
  if (fDefaultCropSizeH.d == 0)
2503
323k
    {
2504
323k
    fDefaultCropSizeH = dng_urational (fActiveArea.W (), 1);
2505
323k
    }
2506
    
2507
340k
  if (fDefaultCropSizeV.d == 0)
2508
325k
    {
2509
325k
    fDefaultCropSizeV = dng_urational (fActiveArea.H (), 1);
2510
325k
    }
2511
    
2512
  // Default white level.
2513
    
2514
340k
  uint32 defaultWhite = (fSampleFormat [0] == sfFloatingPoint) ?
2515
11.7k
              1 :
2516
340k
              (uint32) ((((uint64) 1) << fBitsPerSample [0]) - 1);
2517
            
2518
1.69M
  for (j = 0; j < kMaxSamplesPerPixel; j++)
2519
1.35M
    {
2520
    
2521
1.35M
    if (fWhiteLevel [j] < 0.0)
2522
1.32M
      {
2523
1.32M
      fWhiteLevel [j] = (real64) defaultWhite;
2524
1.32M
      }
2525
    
2526
1.35M
    }
2527
    
2528
  // Check AntiAliasStrength.
2529
2530
340k
  if (fAntiAliasStrength.As_real64 () < 0.0 ||
2531
339k
    fAntiAliasStrength.As_real64 () > 1.0)
2532
9.39k
    {
2533
    
2534
    #if qDNGValidate
2535
    
2536
    ReportWarning ("Invalid AntiAliasStrength");
2537
           
2538
    #endif
2539
           
2540
9.39k
    fAntiAliasStrength = dng_urational (1, 1);
2541
           
2542
9.39k
    }
2543
    
2544
  // Check MaskedAreas.
2545
    
2546
341k
  for (j = 0; j < fMaskedAreaCount; j++)
2547
9.11k
    {
2548
    
2549
9.11k
    const dng_rect &r = fMaskedArea [j];
2550
    
2551
9.11k
    if (r.IsEmpty () || ((r & imageArea) != r))
2552
6.63k
      {
2553
      
2554
      #if qDNGValidate
2555
    
2556
      ReportWarning ("Invalid MaskedArea");
2557
             
2558
      #endif
2559
             
2560
6.63k
      fMaskedAreaCount = 0;
2561
      
2562
6.63k
      break;
2563
           
2564
6.63k
      }
2565
    
2566
2.47k
    if ((r & fActiveArea).NotEmpty ())
2567
590
      {
2568
        
2569
      #if qDNGValidate
2570
2571
      ReportWarning ("MaskedArea overlaps ActiveArea");
2572
             
2573
      #endif
2574
           
2575
590
      fMaskedAreaCount = 0;
2576
      
2577
590
      break;
2578
           
2579
590
      }
2580
    
2581
2.90k
    for (k = 0; k < j; k++)
2582
1.21k
      {
2583
      
2584
1.21k
      if ((r & fMaskedArea [k]).NotEmpty ())
2585
201
        {
2586
        
2587
        #if qDNGValidate
2588
2589
        ReportWarning ("MaskedAreas overlap each other");
2590
               
2591
        #endif
2592
             
2593
201
        fMaskedAreaCount = 0;
2594
        
2595
201
        break;
2596
             
2597
201
        }
2598
2599
1.21k
      }
2600
    
2601
1.88k
    }
2602
    
2603
340k
  }
2604
                 
2605
/*****************************************************************************/
2606
2607
bool dng_ifd::IsValidCFA (dng_shared &shared,
2608
              uint32 parentCode)
2609
11.0k
  {
2610
  
2611
11.0k
  uint32 j;
2612
11.0k
  uint32 k;
2613
11.0k
  uint32 n;
2614
  
2615
11.0k
  #if !qDNGValidate
2616
  
2617
11.0k
  (void) parentCode;      // Unused
2618
  
2619
11.0k
  #endif
2620
  
2621
11.0k
  if (fCFARepeatPatternRows < 1 || fCFARepeatPatternRows > kMaxCFAPattern ||
2622
10.6k
    fCFARepeatPatternCols < 1 || fCFARepeatPatternCols > kMaxCFAPattern)
2623
632
    {
2624
    
2625
    #if qDNGValidate
2626
    
2627
    ReportError ("Missing or invalid CFAPatternRepeatDim",
2628
           LookupParentCode (parentCode));
2629
           
2630
    #endif
2631
           
2632
632
    return false;
2633
           
2634
632
    }
2635
    
2636
10.4k
  uint32 count [kMaxColorPlanes];
2637
  
2638
33.7k
  for (n = 0; n < shared.fCameraProfile.fColorPlanes; n++)
2639
23.3k
    {
2640
23.3k
    count [n] = 0;
2641
23.3k
    }
2642
    
2643
32.6k
  for (j = 0; j < fCFARepeatPatternRows; j++)
2644
22.5k
    {
2645
    
2646
63.1k
    for (k = 0; k < fCFARepeatPatternCols; k++)
2647
40.9k
      {
2648
      
2649
40.9k
      bool found = false;
2650
      
2651
62.3k
      for (n = 0; n < shared.fCameraProfile.fColorPlanes; n++)
2652
62.1k
        {
2653
        
2654
62.1k
        if (fCFAPattern [j] [k] == fCFAPlaneColor [n])
2655
40.6k
          {
2656
40.6k
          found = true;
2657
40.6k
          count [n] ++;
2658
40.6k
          break;
2659
40.6k
          }
2660
        
2661
62.1k
        }
2662
        
2663
40.9k
      if (!found)
2664
273
        {
2665
        
2666
        #if qDNGValidate
2667
    
2668
        ReportError ("CFAPattern contains colors not included in the CFAPlaneColor tag",
2669
               LookupParentCode (parentCode));
2670
               
2671
        #endif
2672
               
2673
273
        return false;
2674
           
2675
273
        }
2676
      
2677
40.9k
      }
2678
      
2679
22.5k
    }
2680
  
2681
32.7k
  for (n = 0; n < shared.fCameraProfile.fColorPlanes; n++)
2682
22.6k
    {
2683
    
2684
22.6k
    if (count [n] == 0)
2685
44
      {
2686
      
2687
      #if qDNGValidate
2688
    
2689
      ReportError ("CFAPattern does not contain all the colors in the CFAPlaneColor tag",
2690
             LookupParentCode (parentCode));
2691
             
2692
      #endif
2693
             
2694
44
      return false;
2695
2696
44
      }
2697
  
2698
22.6k
    }
2699
    
2700
10.1k
  if (fCFALayout < 1 || fCFALayout > 9)
2701
49
    {
2702
    
2703
    #if qDNGValidate
2704
    
2705
    ReportError ("Invalid CFALayout",
2706
           LookupParentCode (parentCode));
2707
           
2708
    #endif
2709
           
2710
49
    return false;
2711
2712
49
    }
2713
    
2714
10.0k
  return true;
2715
  
2716
10.1k
  }
2717
  
2718
/*****************************************************************************/
2719
2720
bool dng_ifd::IsValidDNG (dng_shared &shared,
2721
                uint32 parentCode)
2722
230k
  {
2723
  
2724
230k
  uint32 j;
2725
    
2726
230k
  bool isFloatingPoint = (fSampleFormat [0] == sfFloatingPoint);
2727
  
2728
230k
  dng_rect imageArea (0, 0, fImageLength, fImageWidth);
2729
  
2730
230k
  uint32 defaultWhite = isFloatingPoint ?
2731
8.87k
              1 :
2732
230k
              (uint32) ((((uint64) 1) << fBitsPerSample [0]) - 1);
2733
            
2734
230k
  bool isMonochrome = (shared.fCameraProfile.fColorPlanes == 1);
2735
230k
  bool isColor      = !isMonochrome;
2736
    
2737
230k
  bool isMainIFD = (fNewSubFileType == sfMainImage);
2738
  
2739
  // Check NewSubFileType.
2740
  
2741
230k
  if (!fUsesNewSubFileType)
2742
79.0k
    {
2743
    
2744
    #if qDNGValidate
2745
    
2746
    ReportError ("Missing NewSubFileType",
2747
           LookupParentCode (parentCode));
2748
           
2749
    #endif
2750
           
2751
79.0k
    return false;
2752
    
2753
79.0k
    }
2754
    
2755
151k
  if (fNewSubFileType != sfMainImage      &&
2756
36.4k
    fNewSubFileType != sfPreviewImage    &&
2757
18.1k
    fNewSubFileType != sfTransparencyMask &&
2758
18.0k
    fNewSubFileType != sfPreviewMask      &&
2759
17.4k
    fNewSubFileType != sfAltPreviewImage)
2760
16.8k
    {
2761
    
2762
    #if qDNGValidate
2763
    
2764
    ReportError ("Unexpected NewSubFileType",
2765
           LookupParentCode (parentCode));
2766
           
2767
    #endif
2768
           
2769
16.8k
    return false;
2770
    
2771
16.8k
    }
2772
    
2773
  // Check ImageWidth and ImageLength.
2774
      
2775
134k
  if (fImageWidth < 1)
2776
3.67k
    {
2777
    
2778
    #if qDNGValidate
2779
    
2780
    ReportError ("Missing or invalid ImageWidth",
2781
           LookupParentCode (parentCode));
2782
           
2783
    #endif
2784
           
2785
3.67k
    return false;
2786
    
2787
3.67k
    }
2788
  
2789
130k
  if (fImageLength < 1)
2790
2.25k
    {
2791
    
2792
    #if qDNGValidate
2793
    
2794
    ReportError ("Missing or invalid ImageLength",
2795
           LookupParentCode (parentCode));
2796
           
2797
    #endif
2798
           
2799
2.25k
    return false;
2800
    
2801
2.25k
    }
2802
    
2803
128k
  if (fImageWidth  > kMaxImageSide ||
2804
126k
    fImageLength > kMaxImageSide)
2805
4.00k
    {
2806
    
2807
    #if qDNGValidate
2808
    
2809
    ReportWarning ("Image size is larger than supported");
2810
           
2811
    #endif
2812
           
2813
4.00k
    return false;
2814
    
2815
4.00k
    }
2816
  
2817
  // Check PhotometricInterpretation.
2818
  
2819
124k
  if (fNewSubFileType == sfTransparencyMask ||
2820
124k
    fNewSubFileType == sfPreviewMask)
2821
515
    {
2822
    
2823
515
    if (fPhotometricInterpretation != piTransparencyMask)
2824
383
      {
2825
      
2826
      #if qDNGValidate
2827
  
2828
      ReportError ("NewSubFileType requires PhotometricInterpretation = TransparencyMask",
2829
             LookupParentCode (parentCode));
2830
             
2831
      #endif
2832
             
2833
383
      return false;
2834
      
2835
383
      }
2836
    
2837
515
    }
2838
    
2839
124k
  else
2840
124k
    {
2841
    
2842
124k
    switch (fPhotometricInterpretation)
2843
124k
      {
2844
      
2845
1.90k
      case piBlackIsZero:
2846
3.97k
      case piRGB:
2847
5.76k
      case piYCbCr:
2848
5.76k
        {
2849
        
2850
5.76k
        if (isMainIFD)
2851
350
          {
2852
          
2853
          #if qDNGValidate
2854
      
2855
          ReportError ("PhotometricInterpretation requires NewSubFileType = 1",
2856
                 LookupParentCode (parentCode));
2857
                 
2858
          #endif
2859
                 
2860
350
          return false;
2861
                 
2862
350
          }
2863
          
2864
5.41k
        break;
2865
        
2866
5.76k
        }
2867
        
2868
13.0k
      case piCFA:
2869
13.0k
        {
2870
        
2871
13.0k
        if (!isMainIFD)
2872
374
          {
2873
          
2874
          #if qDNGValidate
2875
      
2876
          ReportError ("PhotometricInterpretation requires NewSubFileType = 0",
2877
                 LookupParentCode (parentCode));
2878
                 
2879
          #endif
2880
                 
2881
374
          return false;
2882
                 
2883
374
          }
2884
          
2885
12.6k
        break;
2886
        
2887
13.0k
        }
2888
        
2889
103k
      case piLinearRaw:
2890
103k
        break;
2891
        
2892
2.08k
      default:
2893
2.08k
        {
2894
          
2895
        #if qDNGValidate
2896
      
2897
        ReportError ("Missing or invalid PhotometricInterpretation",
2898
               LookupParentCode (parentCode));
2899
               
2900
        #endif
2901
               
2902
2.08k
        return false;
2903
2904
13.0k
        }
2905
        
2906
124k
      }
2907
      
2908
124k
    }
2909
    
2910
121k
  switch (fPhotometricInterpretation)
2911
121k
    {
2912
    
2913
1.62k
    case piBlackIsZero:
2914
1.62k
      {
2915
      
2916
      // Allow black in white previews even in color images since the
2917
      // raw processing software may be converting to grayscale.
2918
      
2919
1.62k
      if (isColor && isMainIFD)
2920
0
        {
2921
        
2922
        #if qDNGValidate
2923
    
2924
        ReportError ("PhotometricInterpretation forbids use of ColorMatrix1 tag",
2925
               LookupParentCode (parentCode));
2926
               
2927
        #endif
2928
               
2929
0
        return false;
2930
2931
0
        }
2932
        
2933
1.62k
      break;
2934
      
2935
1.62k
      }
2936
      
2937
2.02k
    case piRGB:
2938
3.78k
    case piYCbCr:
2939
3.78k
      {
2940
      
2941
      // Allow color previews even in monochrome DNG files, since the
2942
      // raw procesing software may be adding color effects.
2943
      
2944
3.78k
      break;
2945
      
2946
2.02k
      }
2947
2948
12.6k
    case piCFA:
2949
12.6k
      {
2950
      
2951
12.6k
      if (isMonochrome)
2952
375
        {
2953
        
2954
        #if qDNGValidate
2955
    
2956
        ReportError ("PhotometricInterpretation requires use of ColorMatrix1 tag",
2957
               LookupParentCode (parentCode));
2958
               
2959
        #endif
2960
               
2961
375
        return false;
2962
2963
375
        }
2964
        
2965
12.2k
      break;
2966
      
2967
12.6k
      }
2968
      
2969
121k
    }
2970
    
2971
121k
  if (isFloatingPoint)
2972
8.44k
    {
2973
    
2974
8.44k
    if (fPhotometricInterpretation != piCFA &&
2975
7.11k
      fPhotometricInterpretation != piLinearRaw &&
2976
203
      fPhotometricInterpretation != piTransparencyMask)
2977
141
      {
2978
      
2979
      #if qDNGValidate
2980
  
2981
      ReportError ("Floating point data requires PhotometricInterpretation CFA or LinearRaw or TransparencyMask",
2982
             LookupParentCode (parentCode));
2983
             
2984
      #endif
2985
             
2986
141
      return false;
2987
2988
141
      }
2989
    
2990
8.44k
    }
2991
    
2992
  // Check SamplesPerPixel and BitsPerSample.
2993
    
2994
120k
  uint32 minSamplesPerPixel = 1;
2995
120k
  uint32 maxSamplesPerPixel = 1;
2996
  
2997
120k
  uint32 minBitsPerSample = 8;
2998
120k
  uint32 maxBitsPerSample = 16;
2999
  
3000
120k
  switch (fPhotometricInterpretation)
3001
120k
    {
3002
    
3003
1.58k
    case piBlackIsZero:
3004
1.58k
      break;
3005
      
3006
1.93k
    case piRGB:
3007
3.68k
    case piYCbCr:
3008
3.68k
      {
3009
3.68k
      minSamplesPerPixel = 3;
3010
3.68k
      maxSamplesPerPixel = 3;
3011
3.68k
      break;
3012
1.93k
      }
3013
      
3014
12.2k
    case piCFA:
3015
12.2k
      {
3016
12.2k
      maxSamplesPerPixel = kMaxSamplesPerPixel;
3017
12.2k
      maxBitsPerSample   = 32;
3018
12.2k
      break;
3019
1.93k
      }
3020
      
3021
103k
    case piLinearRaw:
3022
103k
      {
3023
103k
      minSamplesPerPixel = shared.fCameraProfile.fColorPlanes;
3024
103k
      maxSamplesPerPixel = shared.fCameraProfile.fColorPlanes;
3025
103k
      maxBitsPerSample   = 32;
3026
103k
      break;
3027
1.93k
      }
3028
      
3029
132
    case piTransparencyMask:
3030
132
      {
3031
132
      minBitsPerSample = 8;
3032
132
      maxBitsPerSample = 16;
3033
132
      break;
3034
1.93k
      }
3035
      
3036
120k
    }
3037
    
3038
120k
  if (isFloatingPoint)
3039
8.30k
    {
3040
8.30k
    minBitsPerSample = 16;
3041
8.30k
    maxBitsPerSample = 32;
3042
8.30k
    }
3043
    
3044
120k
  if (fSamplesPerPixel < minSamplesPerPixel ||
3045
120k
    fSamplesPerPixel > maxSamplesPerPixel)
3046
1.86k
    {
3047
3048
    #if qDNGValidate
3049
    
3050
    ReportError ("Missing or invalid SamplesPerPixel",
3051
           LookupParentCode (parentCode));
3052
           
3053
    #endif
3054
           
3055
1.86k
    return false;
3056
3057
1.86k
    }
3058
    
3059
581k
  for (j = 0; j < kMaxSamplesPerPixel; j++)
3060
466k
    {
3061
    
3062
466k
    if (j < fSamplesPerPixel)
3063
158k
      {
3064
      
3065
158k
      if (fBitsPerSample [j] < minBitsPerSample ||
3066
157k
        fBitsPerSample [j] > maxBitsPerSample)
3067
1.84k
        {
3068
        
3069
        #if qDNGValidate
3070
    
3071
        ReportError ("Missing or invalid BitsPerSample",
3072
               LookupParentCode (parentCode));
3073
               
3074
        #endif
3075
               
3076
1.84k
        return false;
3077
               
3078
1.84k
        }
3079
        
3080
156k
      if (isFloatingPoint &&
3081
8.29k
        fBitsPerSample [j] != 16 &&
3082
3.66k
        fBitsPerSample [j] != 24 &&
3083
1.37k
        fBitsPerSample [j] != 32)
3084
231
        {
3085
        
3086
        #if qDNGValidate
3087
    
3088
        ReportError ("Invalid BitsPerSample for floating point",
3089
               LookupParentCode (parentCode));
3090
               
3091
        #endif
3092
               
3093
231
        return false;
3094
               
3095
231
        }
3096
        
3097
156k
      if (minBitsPerSample   ==  8 &&
3098
148k
        maxBitsPerSample   == 16 &&
3099
7.60k
        fBitsPerSample [j] !=  8 &&
3100
2.46k
        fBitsPerSample [j] != 16)
3101
477
        {
3102
        
3103
        #if qDNGValidate
3104
    
3105
        ReportError ("Rendered previews and integer masks require 8 or 16 bits per sample",
3106
               LookupParentCode (parentCode));
3107
               
3108
        #endif
3109
               
3110
477
        return false;
3111
               
3112
477
        }
3113
        
3114
155k
      if (j > 0 && fBitsPerSample [j] != fBitsPerSample [0])
3115
874
        {
3116
        
3117
        #if qDNGValidate
3118
3119
        ReportError ("BitsPerSample not equal for all samples",
3120
               LookupParentCode (parentCode));
3121
               
3122
        #endif
3123
               
3124
874
        return false;
3125
    
3126
874
        }
3127
      
3128
155k
      }
3129
      
3130
308k
    else
3131
308k
      {
3132
      
3133
308k
      if (fBitsPerSample [j] != 0)
3134
707
        {
3135
        
3136
        #if qDNGValidate
3137
3138
        ReportError ("Too many values specified in BitsPerSample",
3139
               LookupParentCode (parentCode));
3140
               
3141
        #endif
3142
               
3143
707
        return false;
3144
    
3145
707
        }
3146
      
3147
308k
      }
3148
      
3149
466k
    }
3150
    
3151
  // Check Compression.
3152
    
3153
114k
  switch (fCompression)
3154
114k
    {
3155
    
3156
84.6k
    case ccUncompressed:
3157
84.6k
      break;
3158
      
3159
16.5k
    case ccJPEG:
3160
16.5k
      {
3161
      
3162
16.5k
      if (fPhotometricInterpretation == piRGB)
3163
60
        {
3164
        
3165
        #if qDNGValidate
3166
3167
        ReportError ("JPEG previews should use PhotometricInterpretation = YCbYb",
3168
               LookupParentCode (parentCode));
3169
               
3170
        #endif
3171
               
3172
60
        return false;
3173
             
3174
60
        }
3175
        
3176
16.4k
      if (fBitsPerSample [0] > 16)
3177
147
        {
3178
        
3179
        #if qDNGValidate
3180
3181
        ReportError ("JPEG compression is limited to 16 bits/sample",
3182
               LookupParentCode (parentCode));
3183
               
3184
        #endif
3185
               
3186
147
        return false;
3187
             
3188
147
        }
3189
      
3190
16.3k
      break;
3191
      
3192
16.4k
      }
3193
      
3194
16.3k
    case ccLossyJPEG:
3195
5.17k
      {
3196
      
3197
5.17k
      if (fPhotometricInterpretation != piLinearRaw)
3198
99
        {
3199
        
3200
        #if qDNGValidate
3201
3202
        ReportError ("Lossy JPEG compression code requires PhotometricInterpretation = LinearRaw",
3203
               LookupParentCode (parentCode));
3204
               
3205
        #endif
3206
3207
99
        return false;
3208
        
3209
99
        }
3210
      
3211
5.07k
      if (fBitsPerSample [0] != 8)
3212
407
        {
3213
        
3214
        #if qDNGValidate
3215
3216
        ReportError ("Lossy JPEG compression is limited to 8 bits/sample",
3217
               LookupParentCode (parentCode));
3218
               
3219
        #endif
3220
               
3221
407
        return false;
3222
             
3223
407
        }
3224
        
3225
4.67k
      break;
3226
      
3227
5.07k
      }
3228
      
3229
7.74k
    case ccDeflate:
3230
7.74k
      {
3231
      
3232
7.74k
      if (!isFloatingPoint &&
3233
6.14k
        fBitsPerSample [0] != 32 &&
3234
5.15k
        fPhotometricInterpretation != piTransparencyMask)
3235
5.15k
        {
3236
        
3237
        #if qDNGValidate
3238
3239
        ReportError ("ZIP compression is limited to floating point and 32-bit integer and transparency masks",
3240
               LookupParentCode (parentCode));
3241
               
3242
        #endif
3243
               
3244
5.15k
        }
3245
            
3246
7.74k
      break;
3247
      
3248
5.07k
      }
3249
      
3250
787
    default:
3251
787
      {
3252
      
3253
      #if qDNGValidate
3254
3255
      ReportError ("Unsupported Compression",
3256
             LookupParentCode (parentCode));
3257
             
3258
      #endif
3259
             
3260
787
      return false;
3261
    
3262
5.07k
      }
3263
      
3264
114k
    }
3265
    
3266
  // Check Predictor.
3267
  
3268
113k
  if (isFloatingPoint && fCompression == ccDeflate &&
3269
1.60k
        (fPredictor == cpFloatingPoint   ||
3270
1.06k
         fPredictor == cpFloatingPointX2 ||
3271
1.06k
         fPredictor == cpFloatingPointX4))
3272
551
    {
3273
    
3274
    // These combinations are supported.
3275
    
3276
551
    }
3277
  
3278
112k
  else if (!isFloatingPoint && fCompression == ccDeflate &&
3279
6.14k
        (fPredictor == cpHorizontalDifference   ||
3280
5.55k
         fPredictor == cpHorizontalDifferenceX2 ||
3281
4.91k
         fPredictor == cpHorizontalDifferenceX4))
3282
1.75k
    {
3283
    
3284
    // These combinations are supported.
3285
    
3286
1.75k
    }
3287
  
3288
111k
  else if (fPredictor != cpNullPredictor)
3289
1.06k
    {
3290
    
3291
    #if qDNGValidate
3292
3293
    ReportError ("Unsupported Predictor",
3294
           LookupParentCode (parentCode));
3295
           
3296
    #endif
3297
           
3298
1.06k
    return false;
3299
    
3300
1.06k
    }
3301
    
3302
  // Check FillOrder.
3303
    
3304
112k
  if (fFillOrder != 1)
3305
429
    {
3306
    
3307
    #if qDNGValidate
3308
3309
    ReportError ("Unsupported FillOrder",
3310
           LookupParentCode (parentCode));
3311
           
3312
    #endif
3313
           
3314
429
    return false;
3315
    
3316
429
    }
3317
    
3318
  // Check PlanarConfiguration.
3319
    
3320
111k
  if (fPlanarConfiguration != pcInterleaved)
3321
195
    {
3322
    
3323
    #if qDNGValidate
3324
3325
    ReportError ("Unsupported PlanarConfiguration",
3326
           LookupParentCode (parentCode));
3327
           
3328
    #endif
3329
           
3330
195
    return false;
3331
    
3332
195
    }
3333
    
3334
  // Check ExtraSamples.
3335
  
3336
111k
  if (fExtraSamplesCount != 0)
3337
407
    {
3338
    
3339
    #if qDNGValidate
3340
3341
    ReportError ("Unsupported ExtraSamples",
3342
           LookupParentCode (parentCode));
3343
           
3344
    #endif
3345
           
3346
407
    return false;
3347
    
3348
407
    }
3349
    
3350
  // Check SampleFormat.
3351
  
3352
258k
  for (j = 0; j < fSamplesPerPixel; j++)
3353
147k
    {
3354
  
3355
147k
    if (fSampleFormat [j] != (isFloatingPoint ? sfFloatingPoint : sfUnsignedInteger))
3356
752
      {
3357
      
3358
      #if qDNGValidate
3359
3360
      ReportError ("Unsupported SampleFormat",
3361
             LookupParentCode (parentCode));
3362
             
3363
      #endif
3364
             
3365
752
      return false;
3366
      
3367
752
      }
3368
      
3369
147k
    }
3370
    
3371
  // Check Orientation.
3372
    
3373
110k
  if (fOrientation > 9)
3374
446
    {
3375
    
3376
    #if qDNGValidate
3377
3378
    ReportError ("Unknown Orientation",
3379
           LookupParentCode (parentCode));
3380
           
3381
    #endif
3382
           
3383
446
    return false;
3384
3385
446
    }
3386
    
3387
  #if qDNGValidate
3388
3389
  if (fOrientation != 0 && parentCode != 0)
3390
    {
3391
    
3392
    ReportWarning ("Unexpected Orientation tag",
3393
             LookupParentCode (parentCode));
3394
    
3395
    }
3396
    
3397
  if (fOrientation == 0 && parentCode == 0)
3398
    {
3399
    
3400
    ReportWarning ("Missing Orientation tag",
3401
             LookupParentCode (parentCode));
3402
    
3403
    }
3404
    
3405
  #endif
3406
  
3407
  // Check Strips vs. Tiles.
3408
    
3409
110k
  if (!fUsesStrips && !fUsesTiles)
3410
412
    {
3411
    
3412
    #if qDNGValidate
3413
3414
    ReportError ("IFD uses neither strips nor tiles",
3415
           LookupParentCode (parentCode));
3416
           
3417
    #endif
3418
           
3419
412
    return false;
3420
    
3421
412
    }
3422
  
3423
109k
  if (fUsesStrips && fUsesTiles)
3424
374
    {
3425
    
3426
    #if qDNGValidate
3427
3428
    ReportError ("IFD uses both strips and tiles",
3429
           LookupParentCode (parentCode));
3430
           
3431
    #endif
3432
           
3433
374
    return false;
3434
    
3435
374
    }
3436
    
3437
  // Check tile info.
3438
    
3439
109k
  uint32 tilesWide = SafeUint32DivideUp(fImageWidth, fTileWidth);
3440
109k
  uint32 tilesHigh = SafeUint32DivideUp(fImageLength, fTileLength);
3441
  
3442
109k
  uint32 tileCount = tilesWide * tilesHigh;
3443
  
3444
109k
  if (fTileOffsetsCount != tileCount)
3445
1.21k
    {
3446
    
3447
    #if qDNGValidate
3448
3449
    ReportError ("Missing or invalid Strip/TileOffsets",
3450
           LookupParentCode (parentCode));
3451
           
3452
    #endif
3453
           
3454
1.21k
    return false;
3455
    
3456
1.21k
    }
3457
    
3458
108k
  if (fTileByteCountsCount != tileCount)
3459
923
    {
3460
    
3461
    #if qDNGValidate
3462
3463
    ReportError ("Missing or invalid Strip/TileByteCounts",
3464
           LookupParentCode (parentCode));
3465
           
3466
    #endif
3467
           
3468
923
    return false;
3469
    
3470
923
    }
3471
    
3472
  // Check CFA pattern.
3473
    
3474
107k
  if (fPhotometricInterpretation == piCFA)
3475
11.0k
    {
3476
    
3477
11.0k
    if (!IsValidCFA (shared, parentCode))
3478
998
      {
3479
      
3480
998
      return false;
3481
      
3482
998
      }
3483
    
3484
11.0k
    }
3485
    
3486
  // Check ActiveArea.
3487
    
3488
106k
  if (((fActiveArea & imageArea) != fActiveArea) || fActiveArea.IsEmpty ())
3489
524
    {
3490
    
3491
    #if qDNGValidate
3492
3493
    ReportError ("Invalid ActiveArea",
3494
           LookupParentCode (parentCode));
3495
           
3496
    #endif
3497
           
3498
524
    return false;
3499
      
3500
524
    }
3501
    
3502
105k
  if (fActiveArea != imageArea)
3503
3.43k
    {
3504
    
3505
3.43k
    if (shared.fDNGBackwardVersion < dngVersion_1_1_0_0)
3506
394
      {
3507
      
3508
      #if qDNGValidate
3509
3510
      ReportError ("Non-default ActiveArea tag not allowed in this DNG version",
3511
             LookupParentCode (parentCode));
3512
             
3513
      #endif
3514
             
3515
394
      return false;
3516
      
3517
394
      }
3518
    
3519
3.43k
    }
3520
    
3521
  // Check LinearizationTable.
3522
    
3523
105k
  if (fLinearizationTableCount)
3524
10.6k
    {
3525
    
3526
10.6k
    if (fLinearizationTableType != ttShort)
3527
434
      {
3528
      
3529
      #if qDNGValidate
3530
3531
      ReportError ("Invalidate LinearizationTable type",
3532
             LookupParentCode (parentCode));
3533
             
3534
      #endif
3535
             
3536
434
      return false;
3537
      
3538
434
      }
3539
    
3540
10.1k
    if (fLinearizationTableCount < 2 ||
3541
9.98k
      fLinearizationTableCount > 65536)
3542
404
      {
3543
      
3544
      #if qDNGValidate
3545
3546
      ReportError ("Invalidate LinearizationTable count",
3547
             LookupParentCode (parentCode));
3548
             
3549
      #endif
3550
             
3551
404
      return false;
3552
      
3553
404
      }
3554
      
3555
9.76k
    if (isFloatingPoint || fBitsPerSample [0] > 16)
3556
253
      {
3557
      
3558
      #if qDNGValidate
3559
3560
      ReportError ("Linearization table not allowed for this data type",
3561
             LookupParentCode (parentCode));
3562
             
3563
      #endif
3564
             
3565
253
      return false;
3566
      
3567
253
      }
3568
    
3569
9.76k
    }
3570
    
3571
  // Check BlackLevelRepeatDim.
3572
    
3573
104k
  if (fBlackLevelRepeatRows < 1 || fBlackLevelRepeatRows > kMaxBlackPattern ||
3574
103k
    fBlackLevelRepeatCols < 1 || fBlackLevelRepeatCols > kMaxBlackPattern)
3575
1.87k
    {
3576
    
3577
    #if qDNGValidate
3578
3579
    ReportError ("Invalid BlackLevelRepeatDim",
3580
           LookupParentCode (parentCode));
3581
           
3582
    #endif
3583
           
3584
1.87k
    return false;
3585
           
3586
1.87k
    }
3587
    
3588
  // Check BlackLevelDeltaH.
3589
    
3590
102k
  if (fBlackLevelDeltaHCount != 0 &&
3591
2.17k
    fBlackLevelDeltaHCount != fActiveArea.W ())
3592
582
    {
3593
    
3594
    #if qDNGValidate
3595
3596
    ReportError ("Invalid BlackLevelDeltaH count",
3597
           LookupParentCode (parentCode));
3598
           
3599
    #endif
3600
           
3601
582
    return false;
3602
           
3603
582
    }
3604
    
3605
  // Check BlackLevelDeltaV.
3606
    
3607
101k
  if (fBlackLevelDeltaVCount != 0 &&
3608
2.52k
    fBlackLevelDeltaVCount != fActiveArea.H ())
3609
450
    {
3610
    
3611
    #if qDNGValidate
3612
3613
    ReportError ("Invalid BlackLevelDeltaV count",
3614
           LookupParentCode (parentCode));
3615
           
3616
    #endif
3617
           
3618
450
    return false;
3619
           
3620
450
    }
3621
    
3622
  // Check WhiteLevel.
3623
  
3624
101k
  real64 maxWhite = fLinearizationTableCount ? 65535.0
3625
101k
                         : (real64) defaultWhite;
3626
    
3627
236k
  for (j = 0; j < fSamplesPerPixel; j++)
3628
136k
    {
3629
    
3630
136k
    if (fWhiteLevel [j] < 1.0 || (fWhiteLevel [j] > maxWhite && !isFloatingPoint))
3631
813
      {
3632
      
3633
      #if qDNGValidate
3634
3635
      ReportError ("Invalid WhiteLevel",
3636
             LookupParentCode (parentCode));
3637
             
3638
      #endif
3639
             
3640
813
      return false;
3641
           
3642
813
      }
3643
      
3644
136k
    }
3645
3646
  // Check BlackLevel.
3647
3648
901k
  for (j = 0; j < kMaxBlackPattern; j++)
3649
801k
    {
3650
    
3651
7.20M
    for (uint32 k = 0; k < kMaxBlackPattern; k++)
3652
6.40M
      {
3653
      
3654
32.0M
      for (uint32 s = 0; s < kMaxSamplesPerPixel; s++)
3655
25.6M
        {
3656
3657
25.6M
        const real64 black = fBlackLevel [j][k][s];
3658
3659
25.6M
        if (black >= fWhiteLevel [s])
3660
345
          {
3661
          
3662
          #if qDNGValidate
3663
3664
          ReportError ("Invalid BlackLevel",
3665
                 LookupParentCode (parentCode));
3666
3667
          #endif
3668
3669
345
          return false;
3670
          
3671
345
          }
3672
        
3673
25.6M
        }
3674
      
3675
6.40M
      }
3676
    
3677
801k
    }
3678
    
3679
  // Check DefaultScale.
3680
    
3681
100k
  if (fDefaultScaleH.As_real64 () <= 0.0 ||
3682
99.7k
    fDefaultScaleV.As_real64 () <= 0.0)
3683
661
    {
3684
      
3685
    #if qDNGValidate
3686
3687
    ReportError ("Invalid DefaultScale");
3688
           
3689
    #endif
3690
           
3691
661
    return false;
3692
3693
661
    }
3694
    
3695
  // Check BestQualityScale.
3696
    
3697
99.4k
  if (fBestQualityScale.As_real64 () < 1.0)
3698
363
    {
3699
    
3700
    #if qDNGValidate
3701
3702
    ReportError ("Invalid BestQualityScale");
3703
           
3704
    #endif
3705
           
3706
363
    return false;
3707
3708
363
    }
3709
    
3710
  // Check DefaultCropOrigin.
3711
    
3712
99.0k
  if (fDefaultCropOriginH.As_real64 () < 0.0 ||
3713
99.0k
    fDefaultCropOriginV.As_real64 () < 0.0 ||
3714
99.0k
    fDefaultCropOriginH.As_real64 () >= (real64) fActiveArea.W () ||
3715
98.7k
    fDefaultCropOriginV.As_real64 () >= (real64) fActiveArea.H ())
3716
738
    {
3717
    
3718
    #if qDNGValidate
3719
3720
    ReportError ("Invalid DefaultCropOrigin");
3721
           
3722
    #endif
3723
           
3724
738
    return false;
3725
3726
738
    }
3727
    
3728
  // Check DefaultCropSize.
3729
    
3730
98.3k
  if (fDefaultCropSizeH.As_real64 () <= 0.0             ||
3731
98.0k
    fDefaultCropSizeV.As_real64 () <= 0.0             ||
3732
97.6k
    fDefaultCropSizeH.As_real64 () > (real64) fActiveArea.W () ||
3733
97.2k
    fDefaultCropSizeV.As_real64 () > (real64) fActiveArea.H ())
3734
1.51k
    {
3735
    
3736
    #if qDNGValidate
3737
3738
    ReportError ("Invalid DefaultCropSize");
3739
           
3740
    #endif
3741
           
3742
1.51k
    return false;
3743
3744
1.51k
    }
3745
    
3746
  // Check DefaultCrop area.
3747
    
3748
96.8k
  if (fDefaultCropOriginH.As_real64 () +
3749
96.8k
    fDefaultCropSizeH  .As_real64 () > (real64) fActiveArea.W () ||
3750
96.4k
    fDefaultCropOriginV.As_real64 () +
3751
96.4k
    fDefaultCropSizeV  .As_real64 () > (real64) fActiveArea.H ())
3752
684
    {
3753
    
3754
    #if qDNGValidate
3755
3756
    ReportError ("Default crop extends outside ActiveArea");
3757
           
3758
    #endif
3759
           
3760
684
    return false;
3761
3762
684
    }
3763
    
3764
  // Check DefaultUserCrop.
3765
    
3766
96.1k
  if (fDefaultUserCropT.As_real64 () < 0.0 ||
3767
96.1k
    fDefaultUserCropL.As_real64 () < 0.0 ||
3768
96.1k
    fDefaultUserCropB.As_real64 () > 1.0 ||
3769
95.7k
    fDefaultUserCropR.As_real64 () > 1.0 ||
3770
95.4k
    fDefaultUserCropT.As_real64 () >= fDefaultUserCropB.As_real64 () ||
3771
95.0k
    fDefaultUserCropL.As_real64 () >= fDefaultUserCropR.As_real64 ())
3772
1.52k
    {
3773
    
3774
    #if qDNGValidate
3775
3776
    ReportError ("Invalid DefaultUserCrop");
3777
           
3778
    #endif  // qDNGValidate
3779
           
3780
1.52k
    return false;
3781
3782
1.52k
    }
3783
    
3784
  // The default crop and default user crop tags are not allowed for the
3785
  // non-main image. If they are there, at least require that they be NOPs.
3786
  
3787
94.6k
  if (!isMainIFD)
3788
3.41k
    {
3789
    
3790
3.41k
    if (Round_int32 (fDefaultCropOriginH.As_real64 ()) != 0 ||
3791
3.10k
      Round_int32 (fDefaultCropOriginV.As_real64 ()) != 0)
3792
628
      {
3793
      
3794
      #if qDNGValidate
3795
3796
      ReportError ("non-default DefaultCropOrigin on non-main image");
3797
             
3798
      #endif
3799
             
3800
628
      return false;
3801
3802
628
      }
3803
    
3804
2.78k
    if (Round_int32 (fDefaultCropSizeH.As_real64 ()) != (int32) fImageWidth ||
3805
2.36k
      Round_int32 (fDefaultCropSizeV.As_real64 ()) != (int32) fImageLength)
3806
736
      {
3807
      
3808
      #if qDNGValidate
3809
3810
      ReportError ("non-default DefaultCropSize on non-main image");
3811
             
3812
      #endif
3813
             
3814
736
      return false;
3815
3816
736
      }
3817
3818
2.04k
    if (fDefaultUserCropT.As_real64 () != 0.0 ||
3819
2.03k
      fDefaultUserCropL.As_real64 () != 0.0 ||
3820
2.01k
      fDefaultUserCropB.As_real64 () != 1.0 ||
3821
1.99k
      fDefaultUserCropR.As_real64 () != 1.0)
3822
59
      {
3823
      
3824
      #if qDNGValidate
3825
3826
      ReportError ("non-default DefaultCUserCrop on non-main image");
3827
             
3828
      #endif  // qDNGValidate
3829
             
3830
59
      return false;
3831
      
3832
59
      }
3833
3834
2.04k
    }
3835
    
3836
  // Warning if too little padding on CFA image.
3837
  
3838
  #if qDNGValidate
3839
  
3840
  if (fPhotometricInterpretation == piCFA)
3841
    {
3842
    
3843
    const real64 kMinPad = 1.9;
3844
    
3845
    if (fDefaultCropOriginH.As_real64 () < kMinPad)
3846
      {
3847
      
3848
      ReportWarning ("Too little padding on left edge of CFA image",
3849
               "possible interpolation artifacts");
3850
           
3851
      }
3852
    
3853
    if (fDefaultCropOriginV.As_real64 () < kMinPad)
3854
      {
3855
      
3856
      ReportWarning ("Too little padding on top edge of CFA image",
3857
               "possible interpolation artifacts");
3858
           
3859
      }
3860
    
3861
    if (fDefaultCropOriginH.As_real64 () +
3862
      fDefaultCropSizeH  .As_real64 () > (real64) fActiveArea.W () - kMinPad)
3863
      {
3864
      
3865
      ReportWarning ("Too little padding on right edge of CFA image",
3866
               "possible interpolation artifacts");
3867
           
3868
      }
3869
    
3870
    if (fDefaultCropOriginV.As_real64 () +
3871
      fDefaultCropSizeV  .As_real64 () > (real64) fActiveArea.H () - kMinPad)
3872
      {
3873
      
3874
      ReportWarning ("Too little padding on bottom edge of CFA image",
3875
               "possible interpolation artifacts");
3876
           
3877
      }
3878
    
3879
    }
3880
  
3881
  #endif
3882
  
3883
  // Check RowInterleaveFactor
3884
    
3885
93.2k
  if (fRowInterleaveFactor != 1)
3886
2.16k
    {
3887
    
3888
2.16k
    if (fRowInterleaveFactor < 1 ||
3889
1.74k
      fRowInterleaveFactor > fImageLength)
3890
882
      {
3891
3892
      #if qDNGValidate
3893
3894
      ReportError ("RowInterleaveFactor out of valid range",
3895
             LookupParentCode (parentCode));
3896
             
3897
      #endif
3898
             
3899
882
      return false;
3900
      
3901
882
      }
3902
    
3903
1.28k
    if (shared.fDNGBackwardVersion < dngVersion_1_2_0_0)
3904
393
      {
3905
      
3906
      #if qDNGValidate
3907
3908
      ReportError ("Non-default RowInterleaveFactor tag not allowed in this DNG version",
3909
             LookupParentCode (parentCode));
3910
             
3911
      #endif
3912
             
3913
393
      return false;
3914
      
3915
393
      }
3916
    
3917
1.28k
    }
3918
    
3919
  // Check SubTileBlockSize
3920
  
3921
91.9k
  if (fSubTileBlockRows != 1 || fSubTileBlockCols != 1)
3922
4.59k
    {
3923
    
3924
4.59k
    if (fSubTileBlockRows < 2 || fSubTileBlockRows > fTileLength ||
3925
2.86k
      fSubTileBlockCols < 1 || fSubTileBlockCols > fTileWidth)
3926
2.96k
      {
3927
      
3928
      #if qDNGValidate
3929
3930
      ReportError ("SubTileBlockSize out of valid range",
3931
             LookupParentCode (parentCode));
3932
             
3933
      #endif
3934
             
3935
2.96k
      return false;
3936
      
3937
2.96k
      }
3938
      
3939
1.63k
    if ((fTileLength % fSubTileBlockRows) != 0 ||
3940
1.21k
      (fTileWidth  % fSubTileBlockCols) != 0)
3941
749
      {
3942
      
3943
      #if qDNGValidate
3944
3945
      ReportError ("TileSize not exact multiple of SubTileBlockSize",
3946
             LookupParentCode (parentCode));
3947
             
3948
      #endif
3949
             
3950
749
      return false;
3951
      
3952
749
      }
3953
    
3954
883
    if (shared.fDNGBackwardVersion < dngVersion_1_2_0_0)
3955
415
      {
3956
      
3957
      #if qDNGValidate
3958
3959
      ReportError ("Non-default SubTileBlockSize tag not allowed in this DNG version",
3960
             LookupParentCode (parentCode));
3961
             
3962
      #endif
3963
             
3964
415
      return false;
3965
      
3966
415
      }
3967
    
3968
883
    }
3969
    
3970
87.8k
  return true;
3971
  
3972
91.9k
  }
3973
                 
3974
/*****************************************************************************/
3975
3976
uint32 dng_ifd::TilesAcross () const
3977
596k
  {
3978
  
3979
596k
  if (fTileWidth)
3980
596k
    {
3981
3982
596k
    return (SafeUint32Sub(SafeUint32Add(fImageWidth, fTileWidth), 1)) / fTileWidth;
3983
    
3984
596k
    }
3985
    
3986
0
  return 0;
3987
3988
596k
  }
3989
    
3990
/*****************************************************************************/
3991
3992
uint32 dng_ifd::TilesDown () const
3993
622k
  {
3994
  
3995
622k
  if (fTileLength)
3996
622k
    {
3997
3998
622k
    return (SafeUint32Sub(SafeUint32Add(fImageLength, fTileLength), 1)) / fTileLength;
3999
    
4000
622k
    }
4001
    
4002
0
  return 0;
4003
4004
622k
  }
4005
    
4006
/*****************************************************************************/
4007
4008
uint32 dng_ifd::TilesPerImage () const
4009
416k
  {
4010
  
4011
416k
  uint32 total = TilesAcross () * TilesDown ();
4012
  
4013
416k
  if (fPlanarConfiguration == pcPlanar)
4014
8
    {
4015
    
4016
8
    total *= fSamplesPerPixel;
4017
    
4018
8
    }
4019
    
4020
416k
  return total;
4021
  
4022
416k
  }
4023
    
4024
/*****************************************************************************/
4025
4026
dng_rect dng_ifd::TileArea (uint32 rowIndex,
4027
                uint32 colIndex) const
4028
503k
  {
4029
  
4030
503k
  dng_rect r;
4031
  
4032
503k
  r.t = rowIndex * fTileLength;
4033
503k
  r.b = r.t      + fTileLength;
4034
  
4035
503k
  r.l = colIndex * fTileWidth;
4036
503k
  r.r = r.l      + fTileWidth;
4037
  
4038
  // If this IFD is using strips rather than tiles, the last strip
4039
  // is trimmed so it does not extend beyond the end of the image.
4040
  
4041
503k
  if (fUsesStrips)
4042
257k
    {
4043
    
4044
257k
    r.b = Min_uint32 (r.b, fImageLength);
4045
    
4046
257k
    }
4047
    
4048
503k
  return r;
4049
  
4050
503k
  }
4051
      
4052
/*****************************************************************************/
4053
4054
uint32 dng_ifd::TileByteCount (const dng_rect &tile) const
4055
196k
  {
4056
  
4057
196k
  if (fCompression == ccUncompressed)
4058
131k
    {
4059
    
4060
131k
    uint32 bitsPerRow = SafeUint32Mult(tile.W (), fBitsPerSample [0]);
4061
              
4062
131k
    if (fPlanarConfiguration == pcInterleaved)
4063
130k
      {
4064
      
4065
130k
      bitsPerRow = SafeUint32Mult(bitsPerRow, fSamplesPerPixel);
4066
      
4067
130k
      }
4068
              
4069
131k
    uint32 bytesPerRow = SafeUint32DivideUp(bitsPerRow, 8);
4070
    
4071
131k
    if (fPlanarConfiguration == pcRowInterleaved)
4072
0
      {
4073
      
4074
0
      bytesPerRow = SafeUint32Mult(bytesPerRow, fSamplesPerPixel);
4075
      
4076
0
      }
4077
    
4078
131k
    return SafeUint32Mult(bytesPerRow, tile.H ());
4079
    
4080
131k
    }
4081
4082
65.4k
  return 0;
4083
  
4084
196k
  }
4085
    
4086
/*****************************************************************************/
4087
4088
void dng_ifd::SetSingleStrip ()
4089
42.9k
  {
4090
  
4091
42.9k
  fTileWidth  = fImageWidth;
4092
42.9k
  fTileLength = fImageLength;
4093
  
4094
42.9k
  fUsesTiles  = false;
4095
42.9k
  fUsesStrips = true;
4096
  
4097
42.9k
  }
4098
    
4099
/*****************************************************************************/
4100
4101
void dng_ifd::FindTileSize (uint32 bytesPerTile,
4102
                uint32 cellH,
4103
                uint32 cellV)
4104
22.9k
  {
4105
  
4106
22.9k
  uint32 bytesPerSample = fSamplesPerPixel *
4107
22.9k
              ((fBitsPerSample [0] + 7) >> 3);
4108
                
4109
22.9k
  uint32 samplesPerTile = bytesPerTile / bytesPerSample;
4110
  
4111
22.9k
  uint32 tileSide = Round_uint32 (sqrt ((real64) samplesPerTile));
4112
  
4113
22.9k
  fTileWidth = Min_uint32 (fImageWidth, tileSide);
4114
    
4115
22.9k
  uint32 across = TilesAcross ();
4116
                 
4117
22.9k
  fTileWidth = (fImageWidth + across - 1) / across;
4118
  
4119
22.9k
  fTileWidth = ((fTileWidth + cellH - 1) / cellH) * cellH;
4120
    
4121
22.9k
  fTileLength = Pin_uint32 (1,
4122
22.9k
                  samplesPerTile / fTileWidth,
4123
22.9k
                  fImageLength);
4124
                  
4125
22.9k
  uint32 down = TilesDown ();
4126
                 
4127
22.9k
  fTileLength = (fImageLength + down - 1) / down;
4128
    
4129
22.9k
  fTileLength = ((fTileLength + cellV - 1) / cellV) * cellV;
4130
  
4131
22.9k
  fUsesTiles  = true;
4132
22.9k
  fUsesStrips = false;
4133
    
4134
22.9k
  }
4135
    
4136
/*****************************************************************************/
4137
4138
void dng_ifd::FindStripSize (uint32 bytesPerStrip,
4139
                 uint32 cellV)
4140
32.8k
  {
4141
  
4142
32.8k
  uint32 bytesPerSample = fSamplesPerPixel *
4143
32.8k
              ((fBitsPerSample [0] + 7) >> 3);
4144
                
4145
32.8k
  uint32 samplesPerStrip = bytesPerStrip / bytesPerSample;
4146
  
4147
32.8k
  fTileWidth = fImageWidth;
4148
    
4149
32.8k
  fTileLength = Pin_uint32 (1,
4150
32.8k
                  samplesPerStrip / fTileWidth,
4151
32.8k
                  fImageLength);
4152
                  
4153
32.8k
  uint32 down = TilesDown ();
4154
                 
4155
32.8k
  fTileLength = (fImageLength + down - 1) / down;
4156
    
4157
32.8k
  fTileLength = ((fTileLength + cellV - 1) / cellV) * cellV;
4158
    
4159
32.8k
  fUsesTiles  = false;
4160
32.8k
  fUsesStrips = true;
4161
    
4162
32.8k
  }
4163
    
4164
/*****************************************************************************/
4165
4166
uint32 dng_ifd::PixelType () const
4167
85.2k
  {
4168
  
4169
85.2k
  if (fSampleFormat [0] == sfFloatingPoint)
4170
4.64k
    {
4171
4.64k
    return ttFloat;
4172
4.64k
    }
4173
  
4174
80.5k
  if (fBitsPerSample [0] <= 8)
4175
31.3k
    {
4176
31.3k
    return ttByte;
4177
31.3k
    }
4178
    
4179
49.2k
  else if (fBitsPerSample [0] <= 16)
4180
30.7k
    {
4181
30.7k
    return ttShort;
4182
30.7k
    }
4183
    
4184
18.4k
  return ttLong;
4185
  
4186
80.5k
  }
4187
    
4188
/*****************************************************************************/
4189
4190
bool dng_ifd::IsBaselineJPEG () const
4191
15.3k
  {
4192
  
4193
15.3k
  if (fBitsPerSample [0] != 8)
4194
2.16k
    {
4195
2.16k
    return false;
4196
2.16k
    }
4197
    
4198
13.1k
  if (fSampleFormat [0] != sfUnsignedInteger)
4199
0
    {
4200
0
    return false;
4201
0
    }
4202
4203
13.1k
  if (fCompression == ccLossyJPEG)
4204
624
    {
4205
624
    return true;
4206
624
    }
4207
  
4208
12.5k
  if (fCompression != ccJPEG)
4209
20
    {
4210
20
    return false;
4211
20
    }
4212
    
4213
12.5k
  switch (fPhotometricInterpretation)
4214
12.5k
    {
4215
    
4216
4
    case piBlackIsZero:
4217
4
      {
4218
4
      return (fSamplesPerPixel == 1);
4219
0
      }
4220
      
4221
8
    case piYCbCr:
4222
8
      {
4223
8
      return (fSamplesPerPixel     == 3            ) &&
4224
4
           (fPlanarConfiguration == pcInterleaved);
4225
0
      }
4226
      
4227
12.5k
    default:
4228
12.5k
      break;
4229
      
4230
12.5k
    }
4231
    
4232
12.5k
  return false;
4233
  
4234
12.5k
  }
4235
    
4236
/*****************************************************************************/
4237
4238
bool dng_ifd::CanRead () const
4239
42.8k
  {
4240
  
4241
42.8k
  dng_read_image reader;
4242
  
4243
42.8k
  return reader.CanRead (*this);
4244
  
4245
42.8k
  }
4246
    
4247
/*****************************************************************************/
4248
4249
void dng_ifd::ReadImage (dng_host &host,
4250
             dng_stream &stream,
4251
             dng_image &image,
4252
             dng_jpeg_image *jpegImage,
4253
             dng_fingerprint *jpegDigest) const
4254
50.0k
  {
4255
  
4256
50.0k
  dng_read_image reader;
4257
  
4258
50.0k
  reader.Read (host,
4259
50.0k
         *this,
4260
50.0k
         stream,
4261
50.0k
         image,
4262
50.0k
         jpegImage,
4263
50.0k
         jpegDigest);
4264
           
4265
50.0k
  }
4266
      
4267
/*****************************************************************************/