Coverage Report

Created: 2025-01-23 06:31

/src/dng_sdk/source/dng_ifd.cpp
Line
Count
Source (jump to first uncovered line)
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
459k
  : fIsPrimary          (true)
36
459k
  , fApplicationName    ()
37
459k
  , fApplicationVersion ()
38
459k
  , fSettingsName       ()
39
459k
  , fSettingsDigest     ()
40
459k
  , fColorSpace     (previewColorSpace_MaxEnum)
41
459k
  , fDateTime     ()
42
459k
  , fRawToPreviewGain   (1.0)
43
459k
  , fCacheVersion   (0)
44
  
45
459k
  {
46
  
47
459k
  }
48
49
/*****************************************************************************/
50
51
dng_preview_info::~dng_preview_info ()
52
459k
  {
53
  
54
459k
  }
55
56
/*****************************************************************************/
57
58
dng_ifd::dng_ifd ()
59
60
455k
  : fUsesNewSubFileType (false)
61
455k
  , fNewSubFileType     (0)
62
63
455k
  , fImageWidth  (0)
64
455k
  , fImageLength (0)
65
66
455k
  , fCompression (ccUncompressed)
67
455k
  , fPredictor   (cpNullPredictor)
68
69
455k
  , fPhotometricInterpretation (0xFFFFFFFF)
70
71
455k
  , fFillOrder (1)
72
73
455k
  , fOrientation          (0)
74
455k
  , fOrientationType      (0)
75
455k
  , fOrientationOffset    (kDNGStreamInvalidOffset)
76
455k
  , fOrientationBigEndian (false)
77
78
455k
  , fSamplesPerPixel (1)
79
80
455k
  , fPlanarConfiguration (pcInterleaved)
81
82
455k
  , fXResolution    (0.0)
83
455k
  , fYResolution    (0.0)
84
455k
  , fResolutionUnit (0)
85
    
86
455k
  , fUsesStrips (false)
87
455k
  , fUsesTiles  (false)
88
  
89
455k
  , fTileWidth  (0)
90
455k
  , fTileLength (0)
91
  
92
455k
  , fTileOffsetsType   (0)
93
455k
  , fTileOffsetsCount  (0)
94
455k
  , fTileOffsetsOffset (0)
95
  
96
455k
  , fTileByteCountsType   (0)
97
455k
  , fTileByteCountsCount  (0)
98
455k
  , fTileByteCountsOffset (0)
99
  
100
455k
  , fSubIFDsCount  (0)
101
455k
  , fSubIFDsOffset (0)
102
  
103
455k
  , fExtraSamplesCount (0)
104
  
105
455k
  , fJPEGTablesCount  (0)
106
455k
  , fJPEGTablesOffset (0)
107
    
108
455k
  , fJPEGInterchangeFormat     (0)
109
455k
  , fJPEGInterchangeFormatLength (0)
110
111
455k
  , fYCbCrCoefficientR (0.0)
112
455k
  , fYCbCrCoefficientG (0.0)
113
455k
  , fYCbCrCoefficientB (0.0)
114
  
115
455k
  , fYCbCrSubSampleH (0)
116
455k
  , fYCbCrSubSampleV (0)
117
  
118
455k
  , fYCbCrPositioning (0)
119
  
120
455k
  , fCFARepeatPatternRows (0)
121
455k
  , fCFARepeatPatternCols (0)
122
  
123
455k
  , fCFALayout (1)
124
  
125
455k
  , fLinearizationTableType   (0)
126
455k
  , fLinearizationTableCount  (0)
127
455k
  , fLinearizationTableOffset (0)
128
129
455k
  , fBlackLevelRepeatRows (1)
130
455k
  , fBlackLevelRepeatCols (1)
131
  
132
455k
  , fBlackLevelDeltaHType   (0)
133
455k
  , fBlackLevelDeltaHCount  (0)
134
455k
  , fBlackLevelDeltaHOffset (0)
135
136
455k
  , fBlackLevelDeltaVType   (0)
137
455k
  , fBlackLevelDeltaVCount  (0)
138
455k
  , fBlackLevelDeltaVOffset (0)
139
  
140
455k
  , fDefaultScaleH (1, 1)
141
455k
  , fDefaultScaleV (1, 1)
142
  
143
455k
  , fBestQualityScale (1, 1)
144
  
145
455k
  , fDefaultCropOriginH (0, 1)
146
455k
  , fDefaultCropOriginV (0, 1)
147
  
148
455k
  , fDefaultCropSizeH ()
149
455k
  , fDefaultCropSizeV ()
150
  
151
455k
  , fDefaultUserCropT (0, 1)
152
455k
  , fDefaultUserCropL (0, 1)
153
455k
  , fDefaultUserCropB (1, 1)
154
455k
  , fDefaultUserCropR (1, 1)
155
  
156
455k
  , fBayerGreenSplit (0)
157
  
158
455k
  , fChromaBlurRadius ()
159
  
160
455k
  , fAntiAliasStrength (1, 1)
161
  
162
455k
  , fActiveArea ()
163
  
164
455k
  , fMaskedAreaCount (0)
165
  
166
455k
  , fRowInterleaveFactor (1)
167
  
168
455k
  , fSubTileBlockRows (1)
169
455k
  , fSubTileBlockCols (1)
170
  
171
455k
  , fPreviewInfo ()
172
  
173
455k
  , fOpcodeList1Count  (0)
174
455k
  , fOpcodeList1Offset (0)
175
  
176
455k
  , fOpcodeList2Count  (0)
177
455k
  , fOpcodeList2Offset (0)
178
  
179
455k
  , fOpcodeList3Count  (0)
180
455k
  , fOpcodeList3Offset (0)
181
  
182
455k
  , fLosslessJPEGBug16 (false)
183
  
184
455k
  , fSampleBitShift (0)
185
    
186
455k
  , fThisIFD (0)
187
455k
  , fNextIFD (0)
188
  
189
455k
  , fCompressionQuality (-1)
190
  
191
455k
  , fPatchFirstJPEGByte (false)
192
193
455k
  {
194
  
195
455k
  uint32 j;
196
455k
  uint32 k;
197
455k
  uint32 n;
198
  
199
2.27M
  for (j = 0; j < kMaxSamplesPerPixel; j++)
200
1.82M
    {
201
1.82M
    fBitsPerSample [j] = 0;
202
1.82M
    }
203
  
204
15.0M
  for (j = 0; j < kMaxTileInfo; j++)
205
14.5M
    {
206
14.5M
    fTileOffset    [j] = 0;
207
14.5M
    fTileByteCount [j] = 0;
208
14.5M
    }
209
  
210
2.27M
  for (j = 0; j < kMaxSamplesPerPixel; j++)
211
1.82M
    {
212
1.82M
    fExtraSamples [j] = esUnspecified;
213
1.82M
    }
214
  
215
2.27M
  for (j = 0; j < kMaxSamplesPerPixel; j++)
216
1.82M
    {
217
1.82M
    fSampleFormat [j] = sfUnsignedInteger;
218
1.82M
    }
219
    
220
3.18M
  for (j = 0; j < 6; j++)
221
2.73M
    {
222
2.73M
    fReferenceBlackWhite [j] = 0.0;
223
2.73M
    }
224
  
225
4.10M
  for (j = 0; j < kMaxCFAPattern; j++)
226
32.8M
    for (k = 0; k < kMaxCFAPattern; k++)
227
29.1M
      {
228
29.1M
      fCFAPattern [j] [k] = 255;
229
29.1M
      }
230
      
231
2.27M
  for (j = 0; j < kMaxColorPlanes; j++)
232
1.82M
    {
233
1.82M
    fCFAPlaneColor [j] = (uint8) (j < 3 ? j : 255);
234
1.82M
    }
235
    
236
4.10M
  for (j = 0; j < kMaxBlackPattern; j++)
237
32.8M
    for (k = 0; k < kMaxBlackPattern; k++)
238
145M
      for (n = 0; n < kMaxSamplesPerPixel; n++)
239
116M
        {
240
116M
        fBlackLevel [j] [k] [n] = 0.0;
241
116M
        }
242
      
243
2.27M
  for (j = 0; j < kMaxSamplesPerPixel; j++)
244
1.82M
    {
245
1.82M
    fWhiteLevel [j] = -1.0;   // Don't know real default yet.
246
1.82M
    }
247
  
248
455k
  }
249
  
250
/*****************************************************************************/
251
252
dng_ifd::~dng_ifd ()
253
455k
  {
254
  
255
455k
  }
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
4.37M
  {
268
  
269
4.37M
  uint32 j;
270
4.37M
  uint32 k;
271
4.37M
  uint32 n;
272
  
273
4.37M
  switch (tagCode)
274
4.37M
    {
275
    
276
215k
    case tcNewSubFileType:
277
215k
      {
278
      
279
215k
      CheckTagType (parentCode, tagCode, tagType, ttLong);
280
      
281
215k
      CheckTagCount (parentCode, tagCode, tagCount, 1);
282
      
283
215k
      fUsesNewSubFileType = true;
284
      
285
215k
      fNewSubFileType = stream.TagValue_uint32 (tagType);
286
      
287
215k
      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
215k
      break;
302
      
303
0
      }
304
305
216k
    case tcImageWidth:
306
216k
      {
307
      
308
216k
      CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
309
      
310
216k
      CheckTagCount (parentCode, tagCode, tagCount, 1);
311
      
312
216k
      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
216k
      break;
324
      
325
0
      }
326
    
327
226k
    case tcImageLength:
328
226k
      {
329
      
330
226k
      CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
331
      
332
226k
      CheckTagCount (parentCode, tagCode, tagCount, 1);
333
      
334
226k
      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
226k
      break;
346
      
347
0
      }
348
        
349
186k
    case tcBitsPerSample:
350
186k
      {
351
      
352
186k
      CheckTagType (parentCode, tagCode, tagType, ttShort);
353
      
354
186k
      CheckTagCount (parentCode, tagCode, tagCount, 1, 0x0FFFF);
355
      
356
      #if qDNGValidate
357
      
358
      if (gVerbose)
359
        {
360
        printf ("BitsPerSample:");
361
        }
362
        
363
      #endif
364
      
365
186k
      bool extrasMatch = true;
366
      
367
11.8M
      for (j = 0; j < tagCount; j++)
368
11.6M
        {
369
        
370
11.6M
        uint32 x = stream.TagValue_uint32 (tagType);
371
        
372
11.6M
        const uint32 maxBitsPerSample = 32;
373
        
374
11.6M
        if (j < kMaxSamplesPerPixel)
375
493k
          {
376
          
377
493k
          if (x > maxBitsPerSample)
378
451
            {
379
451
            ThrowBadFormat ("BitsPerSample out of bounds.");
380
451
            }
381
            
382
493k
          fBitsPerSample [j] = x;
383
493k
          }
384
          
385
11.1M
        else if (x != fBitsPerSample [kMaxSamplesPerPixel - 1])
386
108k
          {
387
108k
          extrasMatch = false;
388
108k
          }
389
          
390
        #if qDNGValidate
391
      
392
        if (gVerbose)
393
          {
394
          printf (" %u", (unsigned) x);
395
          }
396
          
397
        #endif
398
        
399
11.6M
        }
400
          
401
      #if qDNGValidate
402
      
403
      if (gVerbose)
404
        {
405
        printf ("\n");
406
        }
407
        
408
      #endif
409
      
410
186k
      if (!extrasMatch)
411
11
        {
412
        
413
        #if qDNGValidate
414
      
415
        ReportError ("BitsPerSample not constant");
416
        
417
        #endif
418
419
11
        ThrowBadFormat ();
420
        
421
11
        }
422
      
423
186k
      break;
424
      
425
0
      }
426
        
427
79.0k
    case tcCompression:
428
79.0k
      {
429
      
430
79.0k
      CheckTagType (parentCode, tagCode, tagType, ttShort);
431
      
432
79.0k
      CheckTagCount (parentCode, tagCode, tagCount, 1);
433
      
434
79.0k
      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
79.0k
      if (fCompression == 0)
451
12.4k
        {
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
12.4k
        fCompression = ccUncompressed;
470
        
471
12.4k
        }
472
        
473
79.0k
      break;
474
      
475
0
      }
476
        
477
160k
    case tcPhotometricInterpretation:
478
160k
      {
479
      
480
160k
      CheckTagType (parentCode, tagCode, tagType, ttShort);
481
      
482
160k
      CheckTagCount (parentCode, tagCode, tagCount, 1);
483
      
484
160k
      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
160k
      break;
499
      
500
0
      }
501
        
502
2.35k
    case tcFillOrder:
503
2.35k
      {
504
      
505
2.35k
      CheckTagType (parentCode, tagCode, tagType, ttShort);
506
      
507
2.35k
      CheckTagCount (parentCode, tagCode, tagCount, 1);
508
      
509
2.35k
      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
2.35k
      break;
521
      
522
0
      }
523
524
148k
    case tcStripOffsets:
525
148k
      {
526
      
527
148k
      CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
528
      
529
148k
      fUsesStrips = true;
530
      
531
148k
      fTileOffsetsType   = tagType;
532
148k
      fTileOffsetsCount  = tagCount;
533
148k
      fTileOffsetsOffset = tagOffset;
534
      
535
148k
      if (tagCount <= kMaxTileInfo)
536
138k
        {
537
        
538
316k
        for (j = 0; j < tagCount; j++)
539
178k
          {
540
        
541
178k
          fTileOffset [j] = stream.TagValue_uint32 (tagType);
542
          
543
178k
          }
544
          
545
138k
        }
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
148k
      break;
566
      
567
0
      }
568
        
569
26.9k
    case tcOrientation:
570
26.9k
      {
571
      
572
26.9k
      CheckTagType (parentCode, tagCode, tagType, ttShort);
573
      
574
26.9k
      CheckTagCount (parentCode, tagCode, tagCount, 1);
575
      
576
26.9k
      fOrientationType      = tagType;
577
26.9k
      fOrientationOffset    = stream.PositionInOriginalFile ();
578
26.9k
      fOrientationBigEndian = stream.BigEndian ();
579
      
580
26.9k
      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
26.9k
      break;
595
      
596
0
      }
597
        
598
56.2k
    case tcSamplesPerPixel:
599
56.2k
      {
600
      
601
56.2k
      CheckTagType (parentCode, tagCode, tagType, ttShort);
602
      
603
56.2k
      CheckTagCount (parentCode, tagCode, tagCount, 1);
604
      
605
56.2k
      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
56.2k
      break;
617
      
618
0
      }
619
620
45.0k
    case tcRowsPerStrip:
621
45.0k
      {
622
      
623
45.0k
      CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
624
      
625
45.0k
      CheckTagCount (parentCode, tagCode, tagCount, 1);
626
      
627
45.0k
      fUsesStrips = true;
628
      
629
45.0k
      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
45.0k
      break;
641
      
642
0
      }
643
        
644
131k
    case tcStripByteCounts:
645
131k
      {
646
      
647
131k
      CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
648
      
649
131k
      fUsesStrips = true;
650
      
651
131k
      fTileByteCountsType   = tagType;
652
131k
      fTileByteCountsCount  = tagCount;
653
131k
      fTileByteCountsOffset = tagOffset;
654
      
655
131k
      if (tagCount <= kMaxTileInfo)
656
127k
        {
657
        
658
268k
        for (j = 0; j < tagCount; j++)
659
140k
          {
660
        
661
140k
          fTileByteCount [j] = stream.TagValue_uint32 (tagType);
662
          
663
140k
          }
664
          
665
127k
        }
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
131k
      break;
686
      
687
0
      }
688
        
689
8.04k
    case tcXResolution:
690
8.04k
      {
691
      
692
8.04k
      CheckTagType (parentCode, tagCode, tagType, ttRational);
693
      
694
8.04k
      CheckTagCount (parentCode, tagCode, tagCount, 1);
695
      
696
8.04k
      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.04k
      break;
708
      
709
0
      }
710
      
711
2.40k
    case tcYResolution:
712
2.40k
      {
713
      
714
2.40k
      CheckTagType (parentCode, tagCode, tagType, ttRational);
715
      
716
2.40k
      CheckTagCount (parentCode, tagCode, tagCount, 1);
717
      
718
2.40k
      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
2.40k
      break;
730
      
731
0
      }
732
        
733
51.2k
    case tcPlanarConfiguration:
734
51.2k
      {
735
      
736
51.2k
      CheckTagType (parentCode, tagCode, tagType, ttShort);
737
      
738
51.2k
      CheckTagCount (parentCode, tagCode, tagCount, 1);
739
      
740
51.2k
      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
51.2k
      break;
752
      
753
0
      }
754
755
7.72k
    case tcResolutionUnit:
756
7.72k
      {
757
      
758
7.72k
      CheckTagType (parentCode, tagCode, tagType, ttShort);
759
      
760
7.72k
      CheckTagCount (parentCode, tagCode, tagCount, 1);
761
      
762
7.72k
      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
7.72k
      break;
777
      
778
0
      }
779
        
780
6.09k
    case tcPredictor:
781
6.09k
      {
782
      
783
6.09k
      CheckTagType (parentCode, tagCode, tagType, ttShort);
784
      
785
6.09k
      CheckTagCount (parentCode, tagCode, tagCount, 1);
786
      
787
6.09k
      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
6.09k
      break;
802
      
803
0
      }
804
        
805
26.1k
    case tcTileWidth:
806
26.1k
      {
807
      
808
26.1k
      CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
809
      
810
26.1k
      CheckTagCount (parentCode, tagCode, tagCount, 1);
811
      
812
26.1k
      fUsesTiles = true;
813
      
814
26.1k
      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.1k
      break;
826
      
827
0
      }
828
      
829
30.4k
    case tcTileLength:
830
30.4k
      {
831
      
832
30.4k
      CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
833
      
834
30.4k
      CheckTagCount (parentCode, tagCode, tagCount, 1);
835
      
836
30.4k
      fUsesTiles = true;
837
      
838
30.4k
      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
30.4k
      break;
850
      
851
0
      }
852
      
853
26.9k
    case tcTileOffsets:
854
26.9k
      {
855
      
856
26.9k
      CheckTagType (parentCode, tagCode, tagType, ttLong);
857
      
858
26.9k
      fUsesTiles = true;
859
      
860
26.9k
      fTileOffsetsType   = tagType;
861
26.9k
      fTileOffsetsCount  = tagCount;
862
26.9k
      fTileOffsetsOffset = tagOffset;
863
      
864
26.9k
      if (tagCount <= kMaxTileInfo)
865
23.2k
        {
866
        
867
81.3k
        for (j = 0; j < tagCount; j++)
868
58.1k
          {
869
        
870
58.1k
          fTileOffset [j] = stream.TagValue_uint32 (tagType);
871
          
872
58.1k
          }
873
          
874
23.2k
        }
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
26.9k
      break;
895
      
896
0
      }
897
      
898
26.4k
    case tcTileByteCounts:
899
26.4k
      {
900
      
901
26.4k
      CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
902
      
903
26.4k
      fUsesTiles = true;
904
      
905
26.4k
      fTileByteCountsType   = tagType;
906
26.4k
      fTileByteCountsCount  = tagCount;
907
26.4k
      fTileByteCountsOffset = tagOffset;
908
      
909
26.4k
      if (tagCount <= kMaxTileInfo)
910
22.9k
        {
911
        
912
80.6k
        for (j = 0; j < tagCount; j++)
913
57.6k
          {
914
        
915
57.6k
          fTileByteCount [j] = stream.TagValue_uint32 (tagType);
916
          
917
57.6k
          }
918
          
919
22.9k
        }
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
26.4k
      break;
940
      
941
0
      }
942
        
943
173k
    case tcSubIFDs:
944
173k
      {
945
      
946
173k
      CheckTagType (parentCode, tagCode, tagType, ttLong, ttIFD);
947
      
948
173k
      fSubIFDsCount  = tagCount;
949
173k
      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
173k
      break;
968
      
969
0
      }
970
        
971
13.9k
    case tcExtraSamples:
972
13.9k
      {
973
      
974
13.9k
      CheckTagType (parentCode, tagCode, tagType, ttShort);
975
      
976
13.9k
      CheckTagCount (parentCode, tagCode, tagCount, 1, fSamplesPerPixel);
977
      
978
      #if qDNGValidate
979
      
980
      if (gVerbose)
981
        {
982
        printf ("ExtraSamples:");
983
        }
984
        
985
      #endif
986
      
987
13.9k
      fExtraSamplesCount = tagCount;
988
      
989
157M
      for (j = 0; j < tagCount; j++)
990
157M
        {
991
        
992
157M
        uint32 x = stream.TagValue_uint32 (tagType);
993
        
994
157M
        if (j < kMaxSamplesPerPixel)
995
47.7k
          {
996
47.7k
          fExtraSamples [j] = x;
997
47.7k
          }
998
          
999
        #if qDNGValidate
1000
      
1001
        if (gVerbose)
1002
          {
1003
          printf (" %u", (unsigned) x);
1004
          }
1005
          
1006
        #endif
1007
        
1008
157M
        }
1009
          
1010
      #if qDNGValidate
1011
      
1012
      if (gVerbose)
1013
        {
1014
        printf ("\n");
1015
        }
1016
        
1017
      #endif
1018
      
1019
13.9k
      break;
1020
      
1021
0
      }
1022
        
1023
18.5k
    case tcSampleFormat:
1024
18.5k
      {
1025
      
1026
18.5k
      CheckTagType (parentCode, tagCode, tagType, ttShort);
1027
      
1028
18.5k
      CheckTagCount (parentCode, tagCode, tagCount, fSamplesPerPixel);
1029
      
1030
      #if qDNGValidate
1031
      
1032
      if (gVerbose)
1033
        {
1034
        printf ("SampleFormat:");
1035
        }
1036
        
1037
      #endif
1038
      
1039
18.5k
      bool extrasMatch = true;
1040
      
1041
120M
      for (j = 0; j < tagCount; j++)
1042
120M
        {
1043
        
1044
120M
        uint32 x = stream.TagValue_uint32 (tagType);
1045
        
1046
120M
        if (j < kMaxSamplesPerPixel)
1047
36.7k
          {
1048
36.7k
          fSampleFormat [j] = x;
1049
36.7k
          }
1050
          
1051
120M
        else if (x != fSampleFormat [kMaxSamplesPerPixel - 1])
1052
8.39k
          {
1053
8.39k
          extrasMatch = false;
1054
8.39k
          }
1055
          
1056
        #if qDNGValidate
1057
      
1058
        if (gVerbose)
1059
          {
1060
          printf (" %s", LookupSampleFormat (x));
1061
          }
1062
          
1063
        #endif
1064
        
1065
120M
        }
1066
          
1067
      #if qDNGValidate
1068
      
1069
      if (gVerbose)
1070
        {
1071
        printf ("\n");
1072
        }
1073
        
1074
      #endif
1075
      
1076
18.5k
      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
18.5k
      break;
1090
      
1091
0
      }
1092
        
1093
3.40k
    case tcJPEGTables:
1094
3.40k
      {
1095
      
1096
3.40k
      CheckTagType (parentCode, tagCode, tagType, ttUndefined);
1097
      
1098
3.40k
      fJPEGTablesCount  = tagCount;
1099
3.40k
      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
3.40k
      break;
1115
      
1116
0
      }
1117
      
1118
1.99k
    case tcJPEGInterchangeFormat:
1119
1.99k
      {
1120
      
1121
1.99k
      CheckTagType (parentCode, tagCode, tagType, ttLong);
1122
      
1123
1.99k
      CheckTagCount (parentCode, tagCode, tagCount, 1);
1124
      
1125
1.99k
      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.99k
      break;
1138
      
1139
0
      }
1140
      
1141
797
    case tcJPEGInterchangeFormatLength:
1142
797
      {
1143
      
1144
797
      CheckTagType (parentCode, tagCode, tagType, ttLong);
1145
      
1146
797
      CheckTagCount (parentCode, tagCode, tagCount, 1);
1147
      
1148
797
      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
797
      break;
1161
      
1162
0
      }
1163
      
1164
9.74k
    case tcYCbCrCoefficients:
1165
9.74k
      {
1166
      
1167
9.74k
      CheckTagType (parentCode, tagCode, tagType, ttRational);
1168
      
1169
9.74k
      if (!CheckTagCount (parentCode, tagCode, tagCount, 3))
1170
4.23k
        {
1171
4.23k
        return false;
1172
4.23k
        }
1173
      
1174
5.51k
      fYCbCrCoefficientR = stream.TagValue_real64 (tagType);
1175
5.51k
      fYCbCrCoefficientG = stream.TagValue_real64 (tagType);
1176
5.51k
      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
5.51k
      break;
1193
      
1194
9.74k
      }
1195
1196
6.93k
    case tcYCbCrSubSampling:
1197
6.93k
      {
1198
      
1199
6.93k
      CheckTagType (parentCode, tagCode, tagType, ttShort);
1200
      
1201
6.93k
      if (!CheckTagCount (parentCode, tagCode, tagCount, 2))
1202
1.86k
        {
1203
1.86k
        return false;
1204
1.86k
        }
1205
      
1206
5.07k
      fYCbCrSubSampleH = stream.TagValue_uint32 (tagType);
1207
5.07k
      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
5.07k
      break;
1223
      
1224
6.93k
      }
1225
      
1226
5.12k
    case tcYCbCrPositioning:
1227
5.12k
      {
1228
      
1229
5.12k
      CheckTagType (parentCode, tagCode, tagType, ttShort);
1230
      
1231
5.12k
      CheckTagCount (parentCode, tagCode, tagCount, 1);
1232
      
1233
5.12k
      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
5.12k
      break;
1248
      
1249
6.93k
      }
1250
1251
6.09k
    case tcReferenceBlackWhite:
1252
6.09k
      {
1253
      
1254
6.09k
      CheckTagType (parentCode, tagCode, tagType, ttRational);
1255
      
1256
6.09k
      if (!CheckTagCount (parentCode, tagCode, tagCount, 6))
1257
817
        {
1258
817
        return false;
1259
817
        }
1260
      
1261
36.8k
      for (j = 0; j < 6; j++)
1262
31.5k
        {
1263
31.5k
        fReferenceBlackWhite [j] = stream.TagValue_real64 (tagType);
1264
31.5k
        }
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
5.27k
      break;
1284
      
1285
6.09k
      }
1286
      
1287
13.5k
    case tcCFARepeatPatternDim:
1288
13.5k
      {
1289
      
1290
13.5k
      CheckCFA (parentCode, tagCode, fPhotometricInterpretation);
1291
1292
13.5k
      CheckTagType (parentCode, tagCode, tagType, ttShort);
1293
      
1294
13.5k
      if (!CheckTagCount (parentCode, tagCode, tagCount, 2))
1295
1.98k
        {
1296
1.98k
        return false;
1297
1.98k
        }
1298
      
1299
11.5k
      fCFARepeatPatternRows = stream.TagValue_uint32 (tagType);
1300
11.5k
      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
11.5k
      break;
1316
    
1317
13.5k
      }
1318
      
1319
20.0k
    case tcCFAPattern:
1320
20.0k
      {
1321
      
1322
20.0k
      CheckCFA (parentCode, tagCode, fPhotometricInterpretation);
1323
1324
20.0k
      if (!CheckTagType (parentCode, tagCode, tagType, ttByte))
1325
916
        {
1326
916
        return false;
1327
916
        }
1328
      
1329
19.0k
      if (!CheckTagCount (parentCode, tagCode, tagCount,
1330
19.0k
                SafeUint32Mult(fCFARepeatPatternRows, fCFARepeatPatternCols)))
1331
5.75k
        {
1332
5.75k
        return false;
1333
5.75k
        }
1334
        
1335
13.3k
      if (fCFARepeatPatternRows < 1 || fCFARepeatPatternRows > kMaxCFAPattern ||
1336
13.3k
        fCFARepeatPatternCols < 1 || fCFARepeatPatternCols > kMaxCFAPattern)
1337
4.90k
        {
1338
4.90k
        return false;
1339
4.90k
        }
1340
        
1341
      // Note that the Exif spec stores this array in a different
1342
      // scan order than the TIFF-EP spec.
1343
      
1344
24.1k
      for (j = 0; j < fCFARepeatPatternRows; j++)
1345
65.0k
        for (k = 0; k < fCFARepeatPatternCols; k++)
1346
49.3k
          {
1347
          
1348
49.3k
          fCFAPattern [j] [k] = stream.Get_uint8 ();
1349
          
1350
49.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
8.42k
      break;
1389
      
1390
13.3k
      }
1391
      
1392
6.33k
    case tcCFAPlaneColor:
1393
6.33k
      {
1394
      
1395
6.33k
      CheckCFA (parentCode, tagCode, fPhotometricInterpretation);
1396
1397
6.33k
      if (!CheckTagType (parentCode, tagCode, tagType, ttByte))
1398
3.12k
        {
1399
3.12k
        return false;
1400
3.12k
        }
1401
      
1402
3.20k
      if (!CheckTagCount (parentCode, tagCode, tagCount, 3, kMaxColorPlanes))
1403
819
        {
1404
819
        return false;
1405
819
        }
1406
        
1407
11.8k
      for (j = 0; j < kMaxColorPlanes; j++)
1408
9.47k
        {
1409
        
1410
9.47k
        if (j < tagCount)
1411
8.33k
          fCFAPlaneColor [j] = stream.Get_uint8 ();
1412
          
1413
1.14k
        else
1414
1.14k
          fCFAPlaneColor [j] = 255;
1415
          
1416
9.47k
        }
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
2.39k
      break;
1439
      
1440
3.20k
      }
1441
        
1442
2.60k
    case tcCFALayout:
1443
2.60k
      {
1444
      
1445
2.60k
      CheckCFA (parentCode, tagCode, fPhotometricInterpretation);
1446
1447
2.60k
      CheckTagType (parentCode, tagCode, tagType, ttShort);
1448
      
1449
2.60k
      CheckTagCount (parentCode, tagCode, tagCount, 1);
1450
      
1451
2.60k
      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
2.60k
      break;
1466
      
1467
3.20k
      }
1468
        
1469
12.9k
    case tcLinearizationTable:
1470
12.9k
      {
1471
      
1472
12.9k
      CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation);
1473
1474
12.9k
      CheckTagType (parentCode, tagCode, tagType, ttShort);
1475
      
1476
12.9k
      fLinearizationTableType   = tagType;
1477
12.9k
      fLinearizationTableCount  = tagCount;
1478
12.9k
      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
12.9k
      break;
1497
      
1498
3.20k
      }
1499
        
1500
30.5k
    case tcBlackLevelRepeatDim:
1501
30.5k
      {
1502
1503
30.5k
      CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation);
1504
1505
30.5k
      CheckTagType (parentCode, tagCode, tagType, ttShort);
1506
      
1507
30.5k
      if (!CheckTagCount (parentCode, tagCode, tagCount, 2))
1508
3.44k
        {
1509
3.44k
        return false;
1510
3.44k
        }
1511
      
1512
27.1k
      fBlackLevelRepeatRows = stream.TagValue_uint32 (tagType);
1513
27.1k
      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
27.1k
      break;
1529
    
1530
30.5k
      }
1531
      
1532
26.2k
    case tcBlackLevel:
1533
26.2k
      {
1534
      
1535
26.2k
      CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation);
1536
1537
26.2k
      CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong, ttRational);
1538
1539
26.2k
      if (!CheckTagCount (parentCode, tagCode, tagCount, SafeUint32Mult(fBlackLevelRepeatRows,
1540
26.2k
                                 fBlackLevelRepeatCols,
1541
26.2k
                                 fSamplesPerPixel)))
1542
5.29k
        {
1543
5.29k
        return false;
1544
5.29k
        }
1545
      
1546
20.9k
      if (fBlackLevelRepeatRows < 1 || fBlackLevelRepeatRows > kMaxBlackPattern   ||
1547
20.9k
        fBlackLevelRepeatCols < 1 || fBlackLevelRepeatCols > kMaxBlackPattern   ||
1548
20.9k
        fSamplesPerPixel      < 1 || fSamplesPerPixel      > kMaxSamplesPerPixel)
1549
6.26k
        {
1550
6.26k
        return false;
1551
6.26k
        }
1552
        
1553
30.1k
      for (j = 0; j < fBlackLevelRepeatRows; j++)
1554
32.1k
        for (k = 0; k < fBlackLevelRepeatCols; k++)
1555
48.4k
          for (n = 0; n < fSamplesPerPixel; n++)
1556
31.6k
            {
1557
            
1558
31.6k
            fBlackLevel [j] [k] [n] = stream.TagValue_real64 (tagType);
1559
            
1560
31.6k
            }
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
14.6k
      break;
1620
      
1621
20.9k
      }
1622
1623
7.54k
    case tcBlackLevelDeltaH:
1624
7.54k
      {
1625
      
1626
7.54k
      CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation);
1627
1628
7.54k
      CheckTagType (parentCode, tagCode, tagType, ttSRational);
1629
      
1630
7.54k
      fBlackLevelDeltaHType   = tagType;
1631
7.54k
      fBlackLevelDeltaHCount  = tagCount;
1632
7.54k
      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
7.54k
      break;
1651
      
1652
20.9k
      }
1653
        
1654
5.78k
    case tcBlackLevelDeltaV:
1655
5.78k
      {
1656
      
1657
5.78k
      CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation);
1658
1659
5.78k
      CheckTagType (parentCode, tagCode, tagType, ttSRational);
1660
      
1661
5.78k
      fBlackLevelDeltaVType   = tagType;
1662
5.78k
      fBlackLevelDeltaVCount  = tagCount;
1663
5.78k
      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.78k
      break;
1682
      
1683
20.9k
      }
1684
        
1685
29.8k
    case tcWhiteLevel:
1686
29.8k
      {
1687
      
1688
29.8k
      CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation);
1689
1690
29.8k
      CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
1691
      
1692
29.8k
      if (!CheckTagCount (parentCode, tagCode, tagCount, fSamplesPerPixel))
1693
20.4k
        return false;
1694
        
1695
32.6k
      for (j = 0; j < tagCount && j < kMaxSamplesPerPixel; j++)
1696
23.2k
        {
1697
1698
23.2k
        fWhiteLevel [j] = stream.TagValue_real64 (tagType);
1699
1700
23.2k
        }
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
9.36k
      break;
1723
      
1724
29.8k
      }
1725
      
1726
18.5k
    case tcDefaultScale:
1727
18.5k
      {
1728
      
1729
18.5k
      CheckMainIFD (parentCode, tagCode, fNewSubFileType);
1730
      
1731
18.5k
      CheckTagType (parentCode, tagCode, tagType, ttRational);
1732
      
1733
18.5k
      if (!CheckTagCount (parentCode, tagCode, tagCount, 2))
1734
2.54k
        return false;
1735
        
1736
15.9k
      fDefaultScaleH = stream.TagValue_urational (tagType);
1737
15.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
15.9k
      break;
1753
      
1754
18.5k
      }
1755
        
1756
20.8k
    case tcDefaultCropOrigin:
1757
20.8k
      {
1758
      
1759
20.8k
      CheckMainIFD (parentCode, tagCode, fNewSubFileType);
1760
      
1761
20.8k
      CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong, ttRational);
1762
      
1763
20.8k
      if (!CheckTagCount (parentCode, tagCode, tagCount, 2))
1764
7.67k
        return false;
1765
        
1766
13.2k
      fDefaultCropOriginH = stream.TagValue_urational (tagType);
1767
13.2k
      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
13.2k
      break;
1783
      
1784
20.8k
      }
1785
        
1786
20.4k
    case tcDefaultCropSize:
1787
20.4k
      {
1788
      
1789
20.4k
      CheckMainIFD (parentCode, tagCode, fNewSubFileType);
1790
      
1791
20.4k
      CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong, ttRational);
1792
      
1793
20.4k
      if (!CheckTagCount (parentCode, tagCode, tagCount, 2))
1794
2.89k
        return false;
1795
        
1796
17.5k
      fDefaultCropSizeH = stream.TagValue_urational (tagType);
1797
17.5k
      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
17.5k
      break;
1813
      
1814
20.4k
      }
1815
      
1816
4.76k
    case tcDefaultUserCrop:
1817
4.76k
      {
1818
      
1819
4.76k
      CheckMainIFD (parentCode, tagCode, fNewSubFileType);
1820
      
1821
4.76k
      CheckTagType (parentCode, tagCode, tagType, ttRational);
1822
      
1823
4.76k
      if (!CheckTagCount (parentCode, tagCode, tagCount, 4))
1824
1.54k
        return false;
1825
        
1826
3.22k
      fDefaultUserCropT = stream.TagValue_urational (tagType);
1827
3.22k
      fDefaultUserCropL = stream.TagValue_urational (tagType);
1828
3.22k
      fDefaultUserCropB = stream.TagValue_urational (tagType);
1829
3.22k
      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
3.22k
      break;
1848
      
1849
4.76k
      }
1850
        
1851
3.43k
    case tcBayerGreenSplit:
1852
3.43k
      {
1853
      
1854
3.43k
      CheckCFA (parentCode, tagCode, fPhotometricInterpretation);
1855
1856
3.43k
      CheckTagType (parentCode, tagCode, tagType, ttLong);
1857
      
1858
3.43k
      CheckTagCount (parentCode, tagCode, tagCount, 1);
1859
      
1860
3.43k
      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
3.43k
      break;
1872
      
1873
4.76k
      }
1874
        
1875
22.2k
    case tcChromaBlurRadius:
1876
22.2k
      {
1877
      
1878
22.2k
      CheckMainIFD (parentCode, tagCode, fNewSubFileType);
1879
      
1880
22.2k
      CheckTagType (parentCode, tagCode, tagType, ttRational);
1881
      
1882
22.2k
      CheckTagCount (parentCode, tagCode, tagCount, 1);
1883
        
1884
22.2k
      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
22.2k
      break;
1899
      
1900
4.76k
      }
1901
        
1902
22.2k
    case tcAntiAliasStrength:
1903
22.2k
      {
1904
      
1905
22.2k
      CheckMainIFD (parentCode, tagCode, fNewSubFileType);
1906
      
1907
22.2k
      CheckTagType (parentCode, tagCode, tagType, ttRational);
1908
      
1909
22.2k
      CheckTagCount (parentCode, tagCode, tagCount, 1);
1910
        
1911
22.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
22.2k
      break;
1926
      
1927
4.76k
      }
1928
        
1929
9.69k
    case tcBestQualityScale:
1930
9.69k
      {
1931
      
1932
9.69k
      CheckMainIFD (parentCode, tagCode, fNewSubFileType);
1933
      
1934
9.69k
      CheckTagType (parentCode, tagCode, tagType, ttRational);
1935
      
1936
9.69k
      CheckTagCount (parentCode, tagCode, tagCount, 1);
1937
        
1938
9.69k
      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
9.69k
      break;
1953
      
1954
4.76k
      }
1955
        
1956
17.9k
    case tcActiveArea:
1957
17.9k
      {
1958
      
1959
17.9k
      CheckMainIFD (parentCode, tagCode, fNewSubFileType);
1960
      
1961
17.9k
      CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
1962
      
1963
17.9k
      if (!CheckTagCount (parentCode, tagCode, tagCount, 4))
1964
2.62k
        return false;
1965
        
1966
15.3k
      fActiveArea.t = stream.TagValue_int32 (tagType);
1967
15.3k
      fActiveArea.l = stream.TagValue_int32 (tagType);
1968
15.3k
      fActiveArea.b = stream.TagValue_int32 (tagType);
1969
15.3k
      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
15.3k
      break;
1987
      
1988
17.9k
      }
1989
        
1990
17.4k
    case tcMaskedAreas:
1991
17.4k
      {
1992
      
1993
17.4k
      CheckMainIFD (parentCode, tagCode, fNewSubFileType);
1994
      
1995
17.4k
      CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
1996
      
1997
17.4k
      uint32 rect_count = tagCount / 4;
1998
      
1999
17.4k
      if (!CheckTagCount (parentCode, tagCode, tagCount, rect_count * 4))
2000
6.14k
        return false;
2001
        
2002
11.2k
      fMaskedAreaCount = rect_count;
2003
        
2004
11.2k
      if (fMaskedAreaCount > kMaxMaskedAreas)
2005
6.85k
        fMaskedAreaCount = kMaxMaskedAreas;
2006
        
2007
43.1k
      for (j = 0; j < fMaskedAreaCount; j++)
2008
31.8k
        {
2009
        
2010
31.8k
        fMaskedArea [j].t = stream.TagValue_int32 (tagType);
2011
31.8k
        fMaskedArea [j].l = stream.TagValue_int32 (tagType);
2012
31.8k
        fMaskedArea [j].b = stream.TagValue_int32 (tagType);
2013
31.8k
        fMaskedArea [j].r = stream.TagValue_int32 (tagType);
2014
        
2015
31.8k
        }
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
11.2k
      break;
2041
      
2042
17.4k
      }
2043
      
2044
33.1k
    case tcPreviewApplicationName:
2045
33.1k
      {
2046
2047
33.1k
      CheckTagType (parentCode, tagCode, tagType, ttAscii, ttByte);
2048
      
2049
33.1k
      ParseStringTag (stream,
2050
33.1k
              parentCode,
2051
33.1k
              tagCode,
2052
33.1k
              tagCount,
2053
33.1k
              fPreviewInfo.fApplicationName,
2054
33.1k
              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
33.1k
      break;
2072
      
2073
17.4k
      }
2074
        
2075
32.8k
    case tcPreviewApplicationVersion:
2076
32.8k
      {
2077
2078
32.8k
      CheckTagType (parentCode, tagCode, tagType, ttAscii, ttByte);
2079
      
2080
32.8k
      ParseStringTag (stream,
2081
32.8k
              parentCode,
2082
32.8k
              tagCode,
2083
32.8k
              tagCount,
2084
32.8k
              fPreviewInfo.fApplicationVersion,
2085
32.8k
              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
32.8k
      break;
2103
      
2104
17.4k
      }
2105
        
2106
1.00k
    case tcPreviewSettingsName:
2107
1.00k
      {
2108
2109
1.00k
      CheckTagType (parentCode, tagCode, tagType, ttAscii, ttByte);
2110
      
2111
1.00k
      ParseStringTag (stream,
2112
1.00k
              parentCode,
2113
1.00k
              tagCode,
2114
1.00k
              tagCount,
2115
1.00k
              fPreviewInfo.fSettingsName,
2116
1.00k
              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
1.00k
      break;
2134
      
2135
17.4k
      }
2136
        
2137
20.7k
    case tcPreviewSettingsDigest:
2138
20.7k
      {
2139
      
2140
20.7k
      if (!CheckTagType (parentCode, tagCode, tagType, ttByte))
2141
1.66k
        return false;
2142
        
2143
19.0k
      if (!CheckTagCount (parentCode, tagCode, tagCount, 16))
2144
4.59k
        return false;
2145
        
2146
14.4k
      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
14.4k
      break;
2164
      
2165
19.0k
      }
2166
        
2167
18.0k
    case tcPreviewColorSpace:
2168
18.0k
      {
2169
      
2170
18.0k
      CheckTagType (parentCode, tagCode, tagType, ttLong);
2171
        
2172
18.0k
      CheckTagCount (parentCode, tagCode, tagCount, 1);
2173
      
2174
18.0k
      fPreviewInfo.fColorSpace = (PreviewColorSpaceEnum)
2175
18.0k
                     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
18.0k
      break;
2190
      
2191
19.0k
      }
2192
        
2193
15.8k
    case tcPreviewDateTime:
2194
15.8k
      {
2195
2196
15.8k
      CheckTagType (parentCode, tagCode, tagType, ttAscii);
2197
      
2198
15.8k
      ParseStringTag (stream,
2199
15.8k
              parentCode,
2200
15.8k
              tagCode,
2201
15.8k
              tagCount,
2202
15.8k
              fPreviewInfo.fDateTime,
2203
15.8k
              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
15.8k
      break;
2221
      
2222
19.0k
      }
2223
        
2224
6.46k
    case tcRowInterleaveFactor:
2225
6.46k
      {
2226
      
2227
6.46k
      CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
2228
      
2229
6.46k
      if (!CheckTagCount (parentCode, tagCode, tagCount, 1))
2230
2.10k
        return false;
2231
      
2232
4.35k
      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
4.35k
      break;
2247
      
2248
6.46k
      }
2249
      
2250
18.8k
    case tcSubTileBlockSize:
2251
18.8k
      {
2252
      
2253
18.8k
      CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
2254
      
2255
18.8k
      if (!CheckTagCount (parentCode, tagCode, tagCount, 2))
2256
7.59k
        return false;
2257
      
2258
11.2k
      fSubTileBlockRows = stream.TagValue_uint32 (tagType);
2259
11.2k
      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
11.2k
      break;
2275
      
2276
18.8k
      }
2277
      
2278
2.51k
    case tcOpcodeList1:
2279
2.51k
      {
2280
      
2281
2.51k
      CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation);
2282
      
2283
2.51k
      CheckTagType (parentCode, tagCode, tagType, ttUndefined);
2284
      
2285
2.51k
      fOpcodeList1Count  = tagCount;
2286
2.51k
      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
2.51k
      break;
2302
      
2303
18.8k
      }
2304
        
2305
10.2k
    case tcOpcodeList2:
2306
10.2k
      {
2307
      
2308
10.2k
      CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation);
2309
      
2310
10.2k
      CheckTagType (parentCode, tagCode, tagType, ttUndefined);
2311
      
2312
10.2k
      fOpcodeList2Count  = tagCount;
2313
10.2k
      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
10.2k
      break;
2329
      
2330
18.8k
      }
2331
        
2332
4.14k
    case tcOpcodeList3:
2333
4.14k
      {
2334
      
2335
4.14k
      CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation);
2336
      
2337
4.14k
      CheckTagType (parentCode, tagCode, tagType, ttUndefined);
2338
      
2339
4.14k
      fOpcodeList3Count  = tagCount;
2340
4.14k
      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
4.14k
      break;
2356
      
2357
18.8k
      }
2358
      
2359
1.90k
    case tcRawToPreviewGain:
2360
1.90k
      {
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
1.90k
      CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation);
2381
      
2382
1.90k
      CheckTagType (parentCode, tagCode, tagType, ttDouble);
2383
      
2384
1.90k
      if (!CheckTagCount (parentCode, tagCode, tagCount, 1))
2385
415
        return false;
2386
        
2387
1.48k
      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
1.48k
      break;
2402
      
2403
1.90k
      }
2404
        
2405
11.3k
    case tcCacheVersion:
2406
11.3k
      {
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
11.3k
      CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation);
2427
      
2428
11.3k
      CheckTagType (parentCode, tagCode, tagType, ttLong);
2429
      
2430
11.3k
      if (!CheckTagCount (parentCode, tagCode, tagCount, 1))
2431
3.84k
        return false;
2432
        
2433
7.53k
      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
7.53k
      break;
2448
      
2449
11.3k
      }
2450
        
2451
1.96M
    default:
2452
1.96M
      {
2453
      
2454
1.96M
      return false;
2455
      
2456
11.3k
      }
2457
2458
4.37M
    }
2459
  
2460
2.30M
  return true;
2461
  
2462
4.37M
  }
2463
                 
2464
/*****************************************************************************/
2465
2466
void dng_ifd::PostParse ()
2467
332k
  {
2468
  
2469
332k
  uint32 j;
2470
332k
  uint32 k;
2471
  
2472
  // There is only one PlanarConfiguration for single sample imaages.
2473
  
2474
332k
  if (fSamplesPerPixel == 1)
2475
285k
    {
2476
285k
    fPlanarConfiguration = pcInterleaved;
2477
285k
    }
2478
    
2479
  // Default tile size.
2480
    
2481
332k
  if (fTileWidth == 0)
2482
308k
    {
2483
308k
    fTileWidth = fImageWidth;
2484
308k
    }
2485
    
2486
332k
  if (fTileLength == 0)
2487
279k
    {
2488
279k
    fTileLength = fImageLength;
2489
279k
    }
2490
    
2491
  // Default ActiveArea.
2492
    
2493
332k
  dng_rect imageArea (0, 0, fImageLength, fImageWidth);
2494
2495
332k
  if (fActiveArea.IsZero ())
2496
318k
    {
2497
318k
    fActiveArea = imageArea;
2498
318k
    }
2499
    
2500
  // Default crop size.
2501
    
2502
332k
  if (fDefaultCropSizeH.d == 0)
2503
317k
    {
2504
317k
    fDefaultCropSizeH = dng_urational (fActiveArea.W (), 1);
2505
317k
    }
2506
    
2507
332k
  if (fDefaultCropSizeV.d == 0)
2508
318k
    {
2509
318k
    fDefaultCropSizeV = dng_urational (fActiveArea.H (), 1);
2510
318k
    }
2511
    
2512
  // Default white level.
2513
    
2514
332k
  uint32 defaultWhite = (fSampleFormat [0] == sfFloatingPoint) ?
2515
10.6k
              1 :
2516
332k
              (uint32) ((((uint64) 1) << fBitsPerSample [0]) - 1);
2517
            
2518
1.66M
  for (j = 0; j < kMaxSamplesPerPixel; j++)
2519
1.32M
    {
2520
    
2521
1.32M
    if (fWhiteLevel [j] < 0.0)
2522
1.30M
      {
2523
1.30M
      fWhiteLevel [j] = (real64) defaultWhite;
2524
1.30M
      }
2525
    
2526
1.32M
    }
2527
    
2528
  // Check AntiAliasStrength.
2529
2530
332k
  if (fAntiAliasStrength.As_real64 () < 0.0 ||
2531
332k
    fAntiAliasStrength.As_real64 () > 1.0)
2532
6.72k
    {
2533
    
2534
    #if qDNGValidate
2535
    
2536
    ReportWarning ("Invalid AntiAliasStrength");
2537
           
2538
    #endif
2539
           
2540
6.72k
    fAntiAliasStrength = dng_urational (1, 1);
2541
           
2542
6.72k
    }
2543
    
2544
  // Check MaskedAreas.
2545
    
2546
334k
  for (j = 0; j < fMaskedAreaCount; j++)
2547
9.95k
    {
2548
    
2549
9.95k
    const dng_rect &r = fMaskedArea [j];
2550
    
2551
9.95k
    if (r.IsEmpty () || ((r & imageArea) != r))
2552
7.37k
      {
2553
      
2554
      #if qDNGValidate
2555
    
2556
      ReportWarning ("Invalid MaskedArea");
2557
             
2558
      #endif
2559
             
2560
7.37k
      fMaskedAreaCount = 0;
2561
      
2562
7.37k
      break;
2563
           
2564
7.37k
      }
2565
    
2566
2.58k
    if ((r & fActiveArea).NotEmpty ())
2567
479
      {
2568
        
2569
      #if qDNGValidate
2570
2571
      ReportWarning ("MaskedArea overlaps ActiveArea");
2572
             
2573
      #endif
2574
           
2575
479
      fMaskedAreaCount = 0;
2576
      
2577
479
      break;
2578
           
2579
479
      }
2580
    
2581
3.30k
    for (k = 0; k < j; k++)
2582
1.51k
      {
2583
      
2584
1.51k
      if ((r & fMaskedArea [k]).NotEmpty ())
2585
311
        {
2586
        
2587
        #if qDNGValidate
2588
2589
        ReportWarning ("MaskedAreas overlap each other");
2590
               
2591
        #endif
2592
             
2593
311
        fMaskedAreaCount = 0;
2594
        
2595
311
        break;
2596
             
2597
311
        }
2598
2599
1.51k
      }
2600
    
2601
2.10k
    }
2602
    
2603
332k
  }
2604
                 
2605
/*****************************************************************************/
2606
2607
bool dng_ifd::IsValidCFA (dng_shared &shared,
2608
              uint32 parentCode)
2609
3.70k
  {
2610
  
2611
3.70k
  uint32 j;
2612
3.70k
  uint32 k;
2613
3.70k
  uint32 n;
2614
  
2615
3.70k
  #if !qDNGValidate
2616
  
2617
3.70k
  (void) parentCode;      // Unused
2618
  
2619
3.70k
  #endif
2620
  
2621
3.70k
  if (fCFARepeatPatternRows < 1 || fCFARepeatPatternRows > kMaxCFAPattern ||
2622
3.70k
    fCFARepeatPatternCols < 1 || fCFARepeatPatternCols > kMaxCFAPattern)
2623
236
    {
2624
    
2625
    #if qDNGValidate
2626
    
2627
    ReportError ("Missing or invalid CFAPatternRepeatDim",
2628
           LookupParentCode (parentCode));
2629
           
2630
    #endif
2631
           
2632
236
    return false;
2633
           
2634
236
    }
2635
    
2636
3.46k
  uint32 count [kMaxColorPlanes];
2637
  
2638
10.5k
  for (n = 0; n < shared.fCameraProfile.fColorPlanes; n++)
2639
7.05k
    {
2640
7.05k
    count [n] = 0;
2641
7.05k
    }
2642
    
2643
10.2k
  for (j = 0; j < fCFARepeatPatternRows; j++)
2644
6.91k
    {
2645
    
2646
20.5k
    for (k = 0; k < fCFARepeatPatternCols; k++)
2647
13.7k
      {
2648
      
2649
13.7k
      bool found = false;
2650
      
2651
21.3k
      for (n = 0; n < shared.fCameraProfile.fColorPlanes; n++)
2652
21.2k
        {
2653
        
2654
21.2k
        if (fCFAPattern [j] [k] == fCFAPlaneColor [n])
2655
13.6k
          {
2656
13.6k
          found = true;
2657
13.6k
          count [n] ++;
2658
13.6k
          break;
2659
13.6k
          }
2660
        
2661
21.2k
        }
2662
        
2663
13.7k
      if (!found)
2664
118
        {
2665
        
2666
        #if qDNGValidate
2667
    
2668
        ReportError ("CFAPattern contains colors not included in the CFAPlaneColor tag",
2669
               LookupParentCode (parentCode));
2670
               
2671
        #endif
2672
               
2673
118
        return false;
2674
           
2675
118
        }
2676
      
2677
13.7k
      }
2678
      
2679
6.91k
    }
2680
  
2681
10.0k
  for (n = 0; n < shared.fCameraProfile.fColorPlanes; n++)
2682
6.72k
    {
2683
    
2684
6.72k
    if (count [n] == 0)
2685
25
      {
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
25
      return false;
2695
2696
25
      }
2697
  
2698
6.72k
    }
2699
    
2700
3.32k
  if (fCFALayout < 1 || fCFALayout > 9)
2701
24
    {
2702
    
2703
    #if qDNGValidate
2704
    
2705
    ReportError ("Invalid CFALayout",
2706
           LookupParentCode (parentCode));
2707
           
2708
    #endif
2709
           
2710
24
    return false;
2711
2712
24
    }
2713
    
2714
3.29k
  return true;
2715
  
2716
3.32k
  }
2717
  
2718
/*****************************************************************************/
2719
2720
bool dng_ifd::IsValidDNG (dng_shared &shared,
2721
                uint32 parentCode)
2722
215k
  {
2723
  
2724
215k
  uint32 j;
2725
    
2726
215k
  bool isFloatingPoint = (fSampleFormat [0] == sfFloatingPoint);
2727
  
2728
215k
  dng_rect imageArea (0, 0, fImageLength, fImageWidth);
2729
  
2730
215k
  uint32 defaultWhite = isFloatingPoint ?
2731
8.36k
              1 :
2732
215k
              (uint32) ((((uint64) 1) << fBitsPerSample [0]) - 1);
2733
            
2734
215k
  bool isMonochrome = (shared.fCameraProfile.fColorPlanes == 1);
2735
215k
  bool isColor      = !isMonochrome;
2736
    
2737
215k
  bool isMainIFD = (fNewSubFileType == sfMainImage);
2738
  
2739
  // Check NewSubFileType.
2740
  
2741
215k
  if (!fUsesNewSubFileType)
2742
82.6k
    {
2743
    
2744
    #if qDNGValidate
2745
    
2746
    ReportError ("Missing NewSubFileType",
2747
           LookupParentCode (parentCode));
2748
           
2749
    #endif
2750
           
2751
82.6k
    return false;
2752
    
2753
82.6k
    }
2754
    
2755
133k
  if (fNewSubFileType != sfMainImage      &&
2756
133k
    fNewSubFileType != sfPreviewImage    &&
2757
133k
    fNewSubFileType != sfTransparencyMask &&
2758
133k
    fNewSubFileType != sfPreviewMask      &&
2759
133k
    fNewSubFileType != sfAltPreviewImage)
2760
13.5k
    {
2761
    
2762
    #if qDNGValidate
2763
    
2764
    ReportError ("Unexpected NewSubFileType",
2765
           LookupParentCode (parentCode));
2766
           
2767
    #endif
2768
           
2769
13.5k
    return false;
2770
    
2771
13.5k
    }
2772
    
2773
  // Check ImageWidth and ImageLength.
2774
      
2775
119k
  if (fImageWidth < 1)
2776
4.97k
    {
2777
    
2778
    #if qDNGValidate
2779
    
2780
    ReportError ("Missing or invalid ImageWidth",
2781
           LookupParentCode (parentCode));
2782
           
2783
    #endif
2784
           
2785
4.97k
    return false;
2786
    
2787
4.97k
    }
2788
  
2789
114k
  if (fImageLength < 1)
2790
1.64k
    {
2791
    
2792
    #if qDNGValidate
2793
    
2794
    ReportError ("Missing or invalid ImageLength",
2795
           LookupParentCode (parentCode));
2796
           
2797
    #endif
2798
           
2799
1.64k
    return false;
2800
    
2801
1.64k
    }
2802
    
2803
112k
  if (fImageWidth  > kMaxImageSide ||
2804
112k
    fImageLength > kMaxImageSide)
2805
4.96k
    {
2806
    
2807
    #if qDNGValidate
2808
    
2809
    ReportWarning ("Image size is larger than supported");
2810
           
2811
    #endif
2812
           
2813
4.96k
    return false;
2814
    
2815
4.96k
    }
2816
  
2817
  // Check PhotometricInterpretation.
2818
  
2819
107k
  if (fNewSubFileType == sfTransparencyMask ||
2820
107k
    fNewSubFileType == sfPreviewMask)
2821
438
    {
2822
    
2823
438
    if (fPhotometricInterpretation != piTransparencyMask)
2824
391
      {
2825
      
2826
      #if qDNGValidate
2827
  
2828
      ReportError ("NewSubFileType requires PhotometricInterpretation = TransparencyMask",
2829
             LookupParentCode (parentCode));
2830
             
2831
      #endif
2832
             
2833
391
      return false;
2834
      
2835
391
      }
2836
    
2837
438
    }
2838
    
2839
107k
  else
2840
107k
    {
2841
    
2842
107k
    switch (fPhotometricInterpretation)
2843
107k
      {
2844
      
2845
1.93k
      case piBlackIsZero:
2846
5.08k
      case piRGB:
2847
8.56k
      case piYCbCr:
2848
8.56k
        {
2849
        
2850
8.56k
        if (isMainIFD)
2851
548
          {
2852
          
2853
          #if qDNGValidate
2854
      
2855
          ReportError ("PhotometricInterpretation requires NewSubFileType = 1",
2856
                 LookupParentCode (parentCode));
2857
                 
2858
          #endif
2859
                 
2860
548
          return false;
2861
                 
2862
548
          }
2863
          
2864
8.01k
        break;
2865
        
2866
8.56k
        }
2867
        
2868
8.01k
      case piCFA:
2869
5.98k
        {
2870
        
2871
5.98k
        if (!isMainIFD)
2872
249
          {
2873
          
2874
          #if qDNGValidate
2875
      
2876
          ReportError ("PhotometricInterpretation requires NewSubFileType = 0",
2877
                 LookupParentCode (parentCode));
2878
                 
2879
          #endif
2880
                 
2881
249
          return false;
2882
                 
2883
249
          }
2884
          
2885
5.73k
        break;
2886
        
2887
5.98k
        }
2888
        
2889
91.0k
      case piLinearRaw:
2890
91.0k
        break;
2891
        
2892
1.89k
      default:
2893
1.89k
        {
2894
          
2895
        #if qDNGValidate
2896
      
2897
        ReportError ("Missing or invalid PhotometricInterpretation",
2898
               LookupParentCode (parentCode));
2899
               
2900
        #endif
2901
               
2902
1.89k
        return false;
2903
2904
5.98k
        }
2905
        
2906
107k
      }
2907
      
2908
107k
    }
2909
    
2910
104k
  switch (fPhotometricInterpretation)
2911
104k
    {
2912
    
2913
1.57k
    case piBlackIsZero:
2914
1.57k
      {
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.57k
      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.57k
      break;
2934
      
2935
1.57k
      }
2936
      
2937
2.96k
    case piRGB:
2938
6.44k
    case piYCbCr:
2939
6.44k
      {
2940
      
2941
      // Allow color previews even in monochrome DNG files, since the
2942
      // raw procesing software may be adding color effects.
2943
      
2944
6.44k
      break;
2945
      
2946
2.96k
      }
2947
2948
5.73k
    case piCFA:
2949
5.73k
      {
2950
      
2951
5.73k
      if (isMonochrome)
2952
383
        {
2953
        
2954
        #if qDNGValidate
2955
    
2956
        ReportError ("PhotometricInterpretation requires use of ColorMatrix1 tag",
2957
               LookupParentCode (parentCode));
2958
               
2959
        #endif
2960
               
2961
383
        return false;
2962
2963
383
        }
2964
        
2965
5.35k
      break;
2966
      
2967
5.73k
      }
2968
      
2969
104k
    }
2970
    
2971
104k
  if (isFloatingPoint)
2972
7.48k
    {
2973
    
2974
7.48k
    if (fPhotometricInterpretation != piCFA &&
2975
7.48k
      fPhotometricInterpretation != piLinearRaw &&
2976
7.48k
      fPhotometricInterpretation != piTransparencyMask)
2977
70
      {
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
70
      return false;
2987
2988
70
      }
2989
    
2990
7.48k
    }
2991
    
2992
  // Check SamplesPerPixel and BitsPerSample.
2993
    
2994
104k
  uint32 minSamplesPerPixel = 1;
2995
104k
  uint32 maxSamplesPerPixel = 1;
2996
  
2997
104k
  uint32 minBitsPerSample = 8;
2998
104k
  uint32 maxBitsPerSample = 16;
2999
  
3000
104k
  switch (fPhotometricInterpretation)
3001
104k
    {
3002
    
3003
1.54k
    case piBlackIsZero:
3004
1.54k
      break;
3005
      
3006
2.91k
    case piRGB:
3007
6.39k
    case piYCbCr:
3008
6.39k
      {
3009
6.39k
      minSamplesPerPixel = 3;
3010
6.39k
      maxSamplesPerPixel = 3;
3011
6.39k
      break;
3012
2.91k
      }
3013
      
3014
5.35k
    case piCFA:
3015
5.35k
      {
3016
5.35k
      maxSamplesPerPixel = kMaxSamplesPerPixel;
3017
5.35k
      maxBitsPerSample   = 32;
3018
5.35k
      break;
3019
2.91k
      }
3020
      
3021
91.0k
    case piLinearRaw:
3022
91.0k
      {
3023
91.0k
      minSamplesPerPixel = shared.fCameraProfile.fColorPlanes;
3024
91.0k
      maxSamplesPerPixel = shared.fCameraProfile.fColorPlanes;
3025
91.0k
      maxBitsPerSample   = 32;
3026
91.0k
      break;
3027
2.91k
      }
3028
      
3029
47
    case piTransparencyMask:
3030
47
      {
3031
47
      minBitsPerSample = 8;
3032
47
      maxBitsPerSample = 16;
3033
47
      break;
3034
2.91k
      }
3035
      
3036
104k
    }
3037
    
3038
104k
  if (isFloatingPoint)
3039
7.41k
    {
3040
7.41k
    minBitsPerSample = 16;
3041
7.41k
    maxBitsPerSample = 32;
3042
7.41k
    }
3043
    
3044
104k
  if (fSamplesPerPixel < minSamplesPerPixel ||
3045
104k
    fSamplesPerPixel > maxSamplesPerPixel)
3046
2.85k
    {
3047
3048
    #if qDNGValidate
3049
    
3050
    ReportError ("Missing or invalid SamplesPerPixel",
3051
           LookupParentCode (parentCode));
3052
           
3053
    #endif
3054
           
3055
2.85k
    return false;
3056
3057
2.85k
    }
3058
    
3059
495k
  for (j = 0; j < kMaxSamplesPerPixel; j++)
3060
397k
    {
3061
    
3062
397k
    if (j < fSamplesPerPixel)
3063
151k
      {
3064
      
3065
151k
      if (fBitsPerSample [j] < minBitsPerSample ||
3066
151k
        fBitsPerSample [j] > maxBitsPerSample)
3067
919
        {
3068
        
3069
        #if qDNGValidate
3070
    
3071
        ReportError ("Missing or invalid BitsPerSample",
3072
               LookupParentCode (parentCode));
3073
               
3074
        #endif
3075
               
3076
919
        return false;
3077
               
3078
919
        }
3079
        
3080
150k
      if (isFloatingPoint &&
3081
150k
        fBitsPerSample [j] != 16 &&
3082
150k
        fBitsPerSample [j] != 24 &&
3083
150k
        fBitsPerSample [j] != 32)
3084
238
        {
3085
        
3086
        #if qDNGValidate
3087
    
3088
        ReportError ("Invalid BitsPerSample for floating point",
3089
               LookupParentCode (parentCode));
3090
               
3091
        #endif
3092
               
3093
238
        return false;
3094
               
3095
238
        }
3096
        
3097
150k
      if (minBitsPerSample   ==  8 &&
3098
150k
        maxBitsPerSample   == 16 &&
3099
150k
        fBitsPerSample [j] !=  8 &&
3100
150k
        fBitsPerSample [j] != 16)
3101
623
        {
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
623
        return false;
3111
               
3112
623
        }
3113
        
3114
150k
      if (j > 0 && fBitsPerSample [j] != fBitsPerSample [0])
3115
1.58k
        {
3116
        
3117
        #if qDNGValidate
3118
3119
        ReportError ("BitsPerSample not equal for all samples",
3120
               LookupParentCode (parentCode));
3121
               
3122
        #endif
3123
               
3124
1.58k
        return false;
3125
    
3126
1.58k
        }
3127
      
3128
150k
      }
3129
      
3130
245k
    else
3131
245k
      {
3132
      
3133
245k
      if (fBitsPerSample [j] != 0)
3134
412
        {
3135
        
3136
        #if qDNGValidate
3137
3138
        ReportError ("Too many values specified in BitsPerSample",
3139
               LookupParentCode (parentCode));
3140
               
3141
        #endif
3142
               
3143
412
        return false;
3144
    
3145
412
        }
3146
      
3147
245k
      }
3148
      
3149
397k
    }
3150
    
3151
  // Check Compression.
3152
    
3153
97.7k
  switch (fCompression)
3154
97.7k
    {
3155
    
3156
72.1k
    case ccUncompressed:
3157
72.1k
      break;
3158
      
3159
11.3k
    case ccJPEG:
3160
11.3k
      {
3161
      
3162
11.3k
      if (fPhotometricInterpretation == piRGB)
3163
37
        {
3164
        
3165
        #if qDNGValidate
3166
3167
        ReportError ("JPEG previews should use PhotometricInterpretation = YCbYb",
3168
               LookupParentCode (parentCode));
3169
               
3170
        #endif
3171
               
3172
37
        return false;
3173
             
3174
37
        }
3175
        
3176
11.2k
      if (fBitsPerSample [0] > 16)
3177
206
        {
3178
        
3179
        #if qDNGValidate
3180
3181
        ReportError ("JPEG compression is limited to 16 bits/sample",
3182
               LookupParentCode (parentCode));
3183
               
3184
        #endif
3185
               
3186
206
        return false;
3187
             
3188
206
        }
3189
      
3190
11.0k
      break;
3191
      
3192
11.2k
      }
3193
      
3194
11.0k
    case ccLossyJPEG:
3195
4.86k
      {
3196
      
3197
4.86k
      if (fPhotometricInterpretation != piLinearRaw)
3198
24
        {
3199
        
3200
        #if qDNGValidate
3201
3202
        ReportError ("Lossy JPEG compression code requires PhotometricInterpretation = LinearRaw",
3203
               LookupParentCode (parentCode));
3204
               
3205
        #endif
3206
3207
24
        return false;
3208
        
3209
24
        }
3210
      
3211
4.84k
      if (fBitsPerSample [0] != 8)
3212
317
        {
3213
        
3214
        #if qDNGValidate
3215
3216
        ReportError ("Lossy JPEG compression is limited to 8 bits/sample",
3217
               LookupParentCode (parentCode));
3218
               
3219
        #endif
3220
               
3221
317
        return false;
3222
             
3223
317
        }
3224
        
3225
4.52k
      break;
3226
      
3227
4.84k
      }
3228
      
3229
6.02k
    case ccDeflate:
3230
6.02k
      {
3231
      
3232
6.02k
      if (!isFloatingPoint &&
3233
6.02k
        fBitsPerSample [0] != 32 &&
3234
6.02k
        fPhotometricInterpretation != piTransparencyMask)
3235
3.44k
        {
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
3.44k
        }
3245
            
3246
6.02k
      break;
3247
      
3248
4.84k
      }
3249
      
3250
3.38k
    default:
3251
3.38k
      {
3252
      
3253
      #if qDNGValidate
3254
3255
      ReportError ("Unsupported Compression",
3256
             LookupParentCode (parentCode));
3257
             
3258
      #endif
3259
             
3260
3.38k
      return false;
3261
    
3262
4.84k
      }
3263
      
3264
97.7k
    }
3265
    
3266
  // Check Predictor.
3267
  
3268
93.7k
  if (isFloatingPoint && fCompression == ccDeflate &&
3269
93.7k
        (fPredictor == cpFloatingPoint   ||
3270
1.73k
         fPredictor == cpFloatingPointX2 ||
3271
1.73k
         fPredictor == cpFloatingPointX4))
3272
391
    {
3273
    
3274
    // These combinations are supported.
3275
    
3276
391
    }
3277
  
3278
93.3k
  else if (!isFloatingPoint && fCompression == ccDeflate &&
3279
93.3k
        (fPredictor == cpHorizontalDifference   ||
3280
4.29k
         fPredictor == cpHorizontalDifferenceX2 ||
3281
4.29k
         fPredictor == cpHorizontalDifferenceX4))
3282
740
    {
3283
    
3284
    // These combinations are supported.
3285
    
3286
740
    }
3287
  
3288
92.6k
  else if (fPredictor != cpNullPredictor)
3289
1.16k
    {
3290
    
3291
    #if qDNGValidate
3292
3293
    ReportError ("Unsupported Predictor",
3294
           LookupParentCode (parentCode));
3295
           
3296
    #endif
3297
           
3298
1.16k
    return false;
3299
    
3300
1.16k
    }
3301
    
3302
  // Check FillOrder.
3303
    
3304
92.6k
  if (fFillOrder != 1)
3305
328
    {
3306
    
3307
    #if qDNGValidate
3308
3309
    ReportError ("Unsupported FillOrder",
3310
           LookupParentCode (parentCode));
3311
           
3312
    #endif
3313
           
3314
328
    return false;
3315
    
3316
328
    }
3317
    
3318
  // Check PlanarConfiguration.
3319
    
3320
92.2k
  if (fPlanarConfiguration != pcInterleaved)
3321
369
    {
3322
    
3323
    #if qDNGValidate
3324
3325
    ReportError ("Unsupported PlanarConfiguration",
3326
           LookupParentCode (parentCode));
3327
           
3328
    #endif
3329
           
3330
369
    return false;
3331
    
3332
369
    }
3333
    
3334
  // Check ExtraSamples.
3335
  
3336
91.9k
  if (fExtraSamplesCount != 0)
3337
425
    {
3338
    
3339
    #if qDNGValidate
3340
3341
    ReportError ("Unsupported ExtraSamples",
3342
           LookupParentCode (parentCode));
3343
           
3344
    #endif
3345
           
3346
425
    return false;
3347
    
3348
425
    }
3349
    
3350
  // Check SampleFormat.
3351
  
3352
228k
  for (j = 0; j < fSamplesPerPixel; j++)
3353
137k
    {
3354
  
3355
137k
    if (fSampleFormat [j] != (isFloatingPoint ? sfFloatingPoint : sfUnsignedInteger))
3356
646
      {
3357
      
3358
      #if qDNGValidate
3359
3360
      ReportError ("Unsupported SampleFormat",
3361
             LookupParentCode (parentCode));
3362
             
3363
      #endif
3364
             
3365
646
      return false;
3366
      
3367
646
      }
3368
      
3369
137k
    }
3370
    
3371
  // Check Orientation.
3372
    
3373
90.8k
  if (fOrientation > 9)
3374
613
    {
3375
    
3376
    #if qDNGValidate
3377
3378
    ReportError ("Unknown Orientation",
3379
           LookupParentCode (parentCode));
3380
           
3381
    #endif
3382
           
3383
613
    return false;
3384
3385
613
    }
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
90.2k
  if (!fUsesStrips && !fUsesTiles)
3410
429
    {
3411
    
3412
    #if qDNGValidate
3413
3414
    ReportError ("IFD uses neither strips nor tiles",
3415
           LookupParentCode (parentCode));
3416
           
3417
    #endif
3418
           
3419
429
    return false;
3420
    
3421
429
    }
3422
  
3423
89.8k
  if (fUsesStrips && fUsesTiles)
3424
347
    {
3425
    
3426
    #if qDNGValidate
3427
3428
    ReportError ("IFD uses both strips and tiles",
3429
           LookupParentCode (parentCode));
3430
           
3431
    #endif
3432
           
3433
347
    return false;
3434
    
3435
347
    }
3436
    
3437
  // Check tile info.
3438
    
3439
89.4k
  uint32 tilesWide = SafeUint32DivideUp(fImageWidth, fTileWidth);
3440
89.4k
  uint32 tilesHigh = SafeUint32DivideUp(fImageLength, fTileLength);
3441
  
3442
89.4k
  uint32 tileCount = tilesWide * tilesHigh;
3443
  
3444
89.4k
  if (fTileOffsetsCount != tileCount)
3445
971
    {
3446
    
3447
    #if qDNGValidate
3448
3449
    ReportError ("Missing or invalid Strip/TileOffsets",
3450
           LookupParentCode (parentCode));
3451
           
3452
    #endif
3453
           
3454
971
    return false;
3455
    
3456
971
    }
3457
    
3458
88.4k
  if (fTileByteCountsCount != tileCount)
3459
1.44k
    {
3460
    
3461
    #if qDNGValidate
3462
3463
    ReportError ("Missing or invalid Strip/TileByteCounts",
3464
           LookupParentCode (parentCode));
3465
           
3466
    #endif
3467
           
3468
1.44k
    return false;
3469
    
3470
1.44k
    }
3471
    
3472
  // Check CFA pattern.
3473
    
3474
87.0k
  if (fPhotometricInterpretation == piCFA)
3475
3.70k
    {
3476
    
3477
3.70k
    if (!IsValidCFA (shared, parentCode))
3478
403
      {
3479
      
3480
403
      return false;
3481
      
3482
403
      }
3483
    
3484
3.70k
    }
3485
    
3486
  // Check ActiveArea.
3487
    
3488
86.6k
  if (((fActiveArea & imageArea) != fActiveArea) || fActiveArea.IsEmpty ())
3489
102
    {
3490
    
3491
    #if qDNGValidate
3492
3493
    ReportError ("Invalid ActiveArea",
3494
           LookupParentCode (parentCode));
3495
           
3496
    #endif
3497
           
3498
102
    return false;
3499
      
3500
102
    }
3501
    
3502
86.5k
  if (fActiveArea != imageArea)
3503
1.89k
    {
3504
    
3505
1.89k
    if (shared.fDNGBackwardVersion < dngVersion_1_1_0_0)
3506
14
      {
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
14
      return false;
3516
      
3517
14
      }
3518
    
3519
1.89k
    }
3520
    
3521
  // Check LinearizationTable.
3522
    
3523
86.5k
  if (fLinearizationTableCount)
3524
7.22k
    {
3525
    
3526
7.22k
    if (fLinearizationTableType != ttShort)
3527
138
      {
3528
      
3529
      #if qDNGValidate
3530
3531
      ReportError ("Invalidate LinearizationTable type",
3532
             LookupParentCode (parentCode));
3533
             
3534
      #endif
3535
             
3536
138
      return false;
3537
      
3538
138
      }
3539
    
3540
7.08k
    if (fLinearizationTableCount < 2 ||
3541
7.08k
      fLinearizationTableCount > 65536)
3542
191
      {
3543
      
3544
      #if qDNGValidate
3545
3546
      ReportError ("Invalidate LinearizationTable count",
3547
             LookupParentCode (parentCode));
3548
             
3549
      #endif
3550
             
3551
191
      return false;
3552
      
3553
191
      }
3554
      
3555
6.89k
    if (isFloatingPoint || fBitsPerSample [0] > 16)
3556
29
      {
3557
      
3558
      #if qDNGValidate
3559
3560
      ReportError ("Linearization table not allowed for this data type",
3561
             LookupParentCode (parentCode));
3562
             
3563
      #endif
3564
             
3565
29
      return false;
3566
      
3567
29
      }
3568
    
3569
6.89k
    }
3570
    
3571
  // Check BlackLevelRepeatDim.
3572
    
3573
86.1k
  if (fBlackLevelRepeatRows < 1 || fBlackLevelRepeatRows > kMaxBlackPattern ||
3574
86.1k
    fBlackLevelRepeatCols < 1 || fBlackLevelRepeatCols > kMaxBlackPattern)
3575
1.59k
    {
3576
    
3577
    #if qDNGValidate
3578
3579
    ReportError ("Invalid BlackLevelRepeatDim",
3580
           LookupParentCode (parentCode));
3581
           
3582
    #endif
3583
           
3584
1.59k
    return false;
3585
           
3586
1.59k
    }
3587
    
3588
  // Check BlackLevelDeltaH.
3589
    
3590
84.5k
  if (fBlackLevelDeltaHCount != 0 &&
3591
84.5k
    fBlackLevelDeltaHCount != fActiveArea.W ())
3592
527
    {
3593
    
3594
    #if qDNGValidate
3595
3596
    ReportError ("Invalid BlackLevelDeltaH count",
3597
           LookupParentCode (parentCode));
3598
           
3599
    #endif
3600
           
3601
527
    return false;
3602
           
3603
527
    }
3604
    
3605
  // Check BlackLevelDeltaV.
3606
    
3607
84.0k
  if (fBlackLevelDeltaVCount != 0 &&
3608
84.0k
    fBlackLevelDeltaVCount != fActiveArea.H ())
3609
365
    {
3610
    
3611
    #if qDNGValidate
3612
3613
    ReportError ("Invalid BlackLevelDeltaV count",
3614
           LookupParentCode (parentCode));
3615
           
3616
    #endif
3617
           
3618
365
    return false;
3619
           
3620
365
    }
3621
    
3622
  // Check WhiteLevel.
3623
  
3624
83.6k
  real64 maxWhite = fLinearizationTableCount ? 65535.0
3625
83.6k
                         : (real64) defaultWhite;
3626
    
3627
209k
  for (j = 0; j < fSamplesPerPixel; j++)
3628
125k
    {
3629
    
3630
125k
    if (fWhiteLevel [j] < 1.0 || (fWhiteLevel [j] > maxWhite && !isFloatingPoint))
3631
229
      {
3632
      
3633
      #if qDNGValidate
3634
3635
      ReportError ("Invalid WhiteLevel",
3636
             LookupParentCode (parentCode));
3637
             
3638
      #endif
3639
             
3640
229
      return false;
3641
           
3642
229
      }
3643
      
3644
125k
    }
3645
3646
  // Check BlackLevel.
3647
3648
738k
  for (j = 0; j < kMaxBlackPattern; j++)
3649
656k
    {
3650
    
3651
5.89M
    for (uint32 k = 0; k < kMaxBlackPattern; k++)
3652
5.24M
      {
3653
      
3654
26.2M
      for (uint32 s = 0; s < kMaxSamplesPerPixel; s++)
3655
20.9M
        {
3656
3657
20.9M
        const real64 black = fBlackLevel [j][k][s];
3658
3659
20.9M
        if (black >= fWhiteLevel [s])
3660
1.57k
          {
3661
          
3662
          #if qDNGValidate
3663
3664
          ReportError ("Invalid BlackLevel",
3665
                 LookupParentCode (parentCode));
3666
3667
          #endif
3668
3669
1.57k
          return false;
3670
          
3671
1.57k
          }
3672
        
3673
20.9M
        }
3674
      
3675
5.24M
      }
3676
    
3677
656k
    }
3678
    
3679
  // Check DefaultScale.
3680
    
3681
81.8k
  if (fDefaultScaleH.As_real64 () <= 0.0 ||
3682
81.8k
    fDefaultScaleV.As_real64 () <= 0.0)
3683
727
    {
3684
      
3685
    #if qDNGValidate
3686
3687
    ReportError ("Invalid DefaultScale");
3688
           
3689
    #endif
3690
           
3691
727
    return false;
3692
3693
727
    }
3694
    
3695
  // Check BestQualityScale.
3696
    
3697
81.1k
  if (fBestQualityScale.As_real64 () < 1.0)
3698
121
    {
3699
    
3700
    #if qDNGValidate
3701
3702
    ReportError ("Invalid BestQualityScale");
3703
           
3704
    #endif
3705
           
3706
121
    return false;
3707
3708
121
    }
3709
    
3710
  // Check DefaultCropOrigin.
3711
    
3712
81.0k
  if (fDefaultCropOriginH.As_real64 () < 0.0 ||
3713
81.0k
    fDefaultCropOriginV.As_real64 () < 0.0 ||
3714
81.0k
    fDefaultCropOriginH.As_real64 () >= (real64) fActiveArea.W () ||
3715
81.0k
    fDefaultCropOriginV.As_real64 () >= (real64) fActiveArea.H ())
3716
640
    {
3717
    
3718
    #if qDNGValidate
3719
3720
    ReportError ("Invalid DefaultCropOrigin");
3721
           
3722
    #endif
3723
           
3724
640
    return false;
3725
3726
640
    }
3727
    
3728
  // Check DefaultCropSize.
3729
    
3730
80.3k
  if (fDefaultCropSizeH.As_real64 () <= 0.0             ||
3731
80.3k
    fDefaultCropSizeV.As_real64 () <= 0.0             ||
3732
80.3k
    fDefaultCropSizeH.As_real64 () > (real64) fActiveArea.W () ||
3733
80.3k
    fDefaultCropSizeV.As_real64 () > (real64) fActiveArea.H ())
3734
1.44k
    {
3735
    
3736
    #if qDNGValidate
3737
3738
    ReportError ("Invalid DefaultCropSize");
3739
           
3740
    #endif
3741
           
3742
1.44k
    return false;
3743
3744
1.44k
    }
3745
    
3746
  // Check DefaultCrop area.
3747
    
3748
78.9k
  if (fDefaultCropOriginH.As_real64 () +
3749
78.9k
    fDefaultCropSizeH  .As_real64 () > (real64) fActiveArea.W () ||
3750
78.9k
    fDefaultCropOriginV.As_real64 () +
3751
78.6k
    fDefaultCropSizeV  .As_real64 () > (real64) fActiveArea.H ())
3752
664
    {
3753
    
3754
    #if qDNGValidate
3755
3756
    ReportError ("Default crop extends outside ActiveArea");
3757
           
3758
    #endif
3759
           
3760
664
    return false;
3761
3762
664
    }
3763
    
3764
  // Check DefaultUserCrop.
3765
    
3766
78.2k
  if (fDefaultUserCropT.As_real64 () < 0.0 ||
3767
78.2k
    fDefaultUserCropL.As_real64 () < 0.0 ||
3768
78.2k
    fDefaultUserCropB.As_real64 () > 1.0 ||
3769
78.2k
    fDefaultUserCropR.As_real64 () > 1.0 ||
3770
78.2k
    fDefaultUserCropT.As_real64 () >= fDefaultUserCropB.As_real64 () ||
3771
78.2k
    fDefaultUserCropL.As_real64 () >= fDefaultUserCropR.As_real64 ())
3772
199
    {
3773
    
3774
    #if qDNGValidate
3775
3776
    ReportError ("Invalid DefaultUserCrop");
3777
           
3778
    #endif  // qDNGValidate
3779
           
3780
199
    return false;
3781
3782
199
    }
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
78.0k
  if (!isMainIFD)
3788
5.34k
    {
3789
    
3790
5.34k
    if (Round_int32 (fDefaultCropOriginH.As_real64 ()) != 0 ||
3791
5.34k
      Round_int32 (fDefaultCropOriginV.As_real64 ()) != 0)
3792
968
      {
3793
      
3794
      #if qDNGValidate
3795
3796
      ReportError ("non-default DefaultCropOrigin on non-main image");
3797
             
3798
      #endif
3799
             
3800
968
      return false;
3801
3802
968
      }
3803
    
3804
4.37k
    if (Round_int32 (fDefaultCropSizeH.As_real64 ()) != (int32) fImageWidth ||
3805
4.37k
      Round_int32 (fDefaultCropSizeV.As_real64 ()) != (int32) fImageLength)
3806
720
      {
3807
      
3808
      #if qDNGValidate
3809
3810
      ReportError ("non-default DefaultCropSize on non-main image");
3811
             
3812
      #endif
3813
             
3814
720
      return false;
3815
3816
720
      }
3817
3818
3.65k
    if (fDefaultUserCropT.As_real64 () != 0.0 ||
3819
3.65k
      fDefaultUserCropL.As_real64 () != 0.0 ||
3820
3.65k
      fDefaultUserCropB.As_real64 () != 1.0 ||
3821
3.65k
      fDefaultUserCropR.As_real64 () != 1.0)
3822
52
      {
3823
      
3824
      #if qDNGValidate
3825
3826
      ReportError ("non-default DefaultCUserCrop on non-main image");
3827
             
3828
      #endif  // qDNGValidate
3829
             
3830
52
      return false;
3831
      
3832
52
      }
3833
3834
3.65k
    }
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
76.3k
  if (fRowInterleaveFactor != 1)
3886
2.10k
    {
3887
    
3888
2.10k
    if (fRowInterleaveFactor < 1 ||
3889
2.10k
      fRowInterleaveFactor > fImageLength)
3890
394
      {
3891
3892
      #if qDNGValidate
3893
3894
      ReportError ("RowInterleaveFactor out of valid range",
3895
             LookupParentCode (parentCode));
3896
             
3897
      #endif
3898
             
3899
394
      return false;
3900
      
3901
394
      }
3902
    
3903
1.70k
    if (shared.fDNGBackwardVersion < dngVersion_1_2_0_0)
3904
310
      {
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
310
      return false;
3914
      
3915
310
      }
3916
    
3917
1.70k
    }
3918
    
3919
  // Check SubTileBlockSize
3920
  
3921
75.6k
  if (fSubTileBlockRows != 1 || fSubTileBlockCols != 1)
3922
6.78k
    {
3923
    
3924
6.78k
    if (fSubTileBlockRows < 2 || fSubTileBlockRows > fTileLength ||
3925
6.78k
      fSubTileBlockCols < 1 || fSubTileBlockCols > fTileWidth)
3926
4.87k
      {
3927
      
3928
      #if qDNGValidate
3929
3930
      ReportError ("SubTileBlockSize out of valid range",
3931
             LookupParentCode (parentCode));
3932
             
3933
      #endif
3934
             
3935
4.87k
      return false;
3936
      
3937
4.87k
      }
3938
      
3939
1.91k
    if ((fTileLength % fSubTileBlockRows) != 0 ||
3940
1.91k
      (fTileWidth  % fSubTileBlockCols) != 0)
3941
573
      {
3942
      
3943
      #if qDNGValidate
3944
3945
      ReportError ("TileSize not exact multiple of SubTileBlockSize",
3946
             LookupParentCode (parentCode));
3947
             
3948
      #endif
3949
             
3950
573
      return false;
3951
      
3952
573
      }
3953
    
3954
1.33k
    if (shared.fDNGBackwardVersion < dngVersion_1_2_0_0)
3955
332
      {
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
332
      return false;
3965
      
3966
332
      }
3967
    
3968
1.33k
    }
3969
    
3970
69.8k
  return true;
3971
  
3972
75.6k
  }
3973
                 
3974
/*****************************************************************************/
3975
3976
uint32 dng_ifd::TilesAcross () const
3977
407k
  {
3978
  
3979
407k
  if (fTileWidth)
3980
407k
    {
3981
3982
407k
    return (SafeUint32Sub(SafeUint32Add(fImageWidth, fTileWidth), 1)) / fTileWidth;
3983
    
3984
407k
    }
3985
    
3986
0
  return 0;
3987
3988
407k
  }
3989
    
3990
/*****************************************************************************/
3991
3992
uint32 dng_ifd::TilesDown () const
3993
425k
  {
3994
  
3995
425k
  if (fTileLength)
3996
425k
    {
3997
3998
425k
    return (SafeUint32Sub(SafeUint32Add(fImageLength, fTileLength), 1)) / fTileLength;
3999
    
4000
425k
    }
4001
    
4002
0
  return 0;
4003
4004
425k
  }
4005
    
4006
/*****************************************************************************/
4007
4008
uint32 dng_ifd::TilesPerImage () const
4009
284k
  {
4010
  
4011
284k
  uint32 total = TilesAcross () * TilesDown ();
4012
  
4013
284k
  if (fPlanarConfiguration == pcPlanar)
4014
12
    {
4015
    
4016
12
    total *= fSamplesPerPixel;
4017
    
4018
12
    }
4019
    
4020
284k
  return total;
4021
  
4022
284k
  }
4023
    
4024
/*****************************************************************************/
4025
4026
dng_rect dng_ifd::TileArea (uint32 rowIndex,
4027
                uint32 colIndex) const
4028
345k
  {
4029
  
4030
345k
  dng_rect r;
4031
  
4032
345k
  r.t = rowIndex * fTileLength;
4033
345k
  r.b = r.t      + fTileLength;
4034
  
4035
345k
  r.l = colIndex * fTileWidth;
4036
345k
  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
345k
  if (fUsesStrips)
4042
170k
    {
4043
    
4044
170k
    r.b = Min_uint32 (r.b, fImageLength);
4045
    
4046
170k
    }
4047
    
4048
345k
  return r;
4049
  
4050
345k
  }
4051
      
4052
/*****************************************************************************/
4053
4054
uint32 dng_ifd::TileByteCount (const dng_rect &tile) const
4055
134k
  {
4056
  
4057
134k
  if (fCompression == ccUncompressed)
4058
89.0k
    {
4059
    
4060
89.0k
    uint32 bitsPerRow = SafeUint32Mult(tile.W (), fBitsPerSample [0]);
4061
              
4062
89.0k
    if (fPlanarConfiguration == pcInterleaved)
4063
87.4k
      {
4064
      
4065
87.4k
      bitsPerRow = SafeUint32Mult(bitsPerRow, fSamplesPerPixel);
4066
      
4067
87.4k
      }
4068
              
4069
89.0k
    uint32 bytesPerRow = SafeUint32DivideUp(bitsPerRow, 8);
4070
    
4071
89.0k
    if (fPlanarConfiguration == pcRowInterleaved)
4072
0
      {
4073
      
4074
0
      bytesPerRow = SafeUint32Mult(bytesPerRow, fSamplesPerPixel);
4075
      
4076
0
      }
4077
    
4078
89.0k
    return SafeUint32Mult(bytesPerRow, tile.H ());
4079
    
4080
89.0k
    }
4081
4082
45.9k
  return 0;
4083
  
4084
134k
  }
4085
    
4086
/*****************************************************************************/
4087
4088
void dng_ifd::SetSingleStrip ()
4089
27.6k
  {
4090
  
4091
27.6k
  fTileWidth  = fImageWidth;
4092
27.6k
  fTileLength = fImageLength;
4093
  
4094
27.6k
  fUsesTiles  = false;
4095
27.6k
  fUsesStrips = true;
4096
  
4097
27.6k
  }
4098
    
4099
/*****************************************************************************/
4100
4101
void dng_ifd::FindTileSize (uint32 bytesPerTile,
4102
                uint32 cellH,
4103
                uint32 cellV)
4104
16.0k
  {
4105
  
4106
16.0k
  uint32 bytesPerSample = fSamplesPerPixel *
4107
16.0k
              ((fBitsPerSample [0] + 7) >> 3);
4108
                
4109
16.0k
  uint32 samplesPerTile = bytesPerTile / bytesPerSample;
4110
  
4111
16.0k
  uint32 tileSide = Round_uint32 (sqrt ((real64) samplesPerTile));
4112
  
4113
16.0k
  fTileWidth = Min_uint32 (fImageWidth, tileSide);
4114
    
4115
16.0k
  uint32 across = TilesAcross ();
4116
                 
4117
16.0k
  fTileWidth = (fImageWidth + across - 1) / across;
4118
  
4119
16.0k
  fTileWidth = ((fTileWidth + cellH - 1) / cellH) * cellH;
4120
    
4121
16.0k
  fTileLength = Pin_uint32 (1,
4122
16.0k
                  samplesPerTile / fTileWidth,
4123
16.0k
                  fImageLength);
4124
                  
4125
16.0k
  uint32 down = TilesDown ();
4126
                 
4127
16.0k
  fTileLength = (fImageLength + down - 1) / down;
4128
    
4129
16.0k
  fTileLength = ((fTileLength + cellV - 1) / cellV) * cellV;
4130
  
4131
16.0k
  fUsesTiles  = true;
4132
16.0k
  fUsesStrips = false;
4133
    
4134
16.0k
  }
4135
    
4136
/*****************************************************************************/
4137
4138
void dng_ifd::FindStripSize (uint32 bytesPerStrip,
4139
                 uint32 cellV)
4140
23.5k
  {
4141
  
4142
23.5k
  uint32 bytesPerSample = fSamplesPerPixel *
4143
23.5k
              ((fBitsPerSample [0] + 7) >> 3);
4144
                
4145
23.5k
  uint32 samplesPerStrip = bytesPerStrip / bytesPerSample;
4146
  
4147
23.5k
  fTileWidth = fImageWidth;
4148
    
4149
23.5k
  fTileLength = Pin_uint32 (1,
4150
23.5k
                  samplesPerStrip / fTileWidth,
4151
23.5k
                  fImageLength);
4152
                  
4153
23.5k
  uint32 down = TilesDown ();
4154
                 
4155
23.5k
  fTileLength = (fImageLength + down - 1) / down;
4156
    
4157
23.5k
  fTileLength = ((fTileLength + cellV - 1) / cellV) * cellV;
4158
    
4159
23.5k
  fUsesTiles  = false;
4160
23.5k
  fUsesStrips = true;
4161
    
4162
23.5k
  }
4163
    
4164
/*****************************************************************************/
4165
4166
uint32 dng_ifd::PixelType () const
4167
55.9k
  {
4168
  
4169
55.9k
  if (fSampleFormat [0] == sfFloatingPoint)
4170
3.43k
    {
4171
3.43k
    return ttFloat;
4172
3.43k
    }
4173
  
4174
52.5k
  if (fBitsPerSample [0] <= 8)
4175
16.4k
    {
4176
16.4k
    return ttByte;
4177
16.4k
    }
4178
    
4179
36.0k
  else if (fBitsPerSample [0] <= 16)
4180
22.5k
    {
4181
22.5k
    return ttShort;
4182
22.5k
    }
4183
    
4184
13.5k
  return ttLong;
4185
  
4186
52.5k
  }
4187
    
4188
/*****************************************************************************/
4189
4190
bool dng_ifd::IsBaselineJPEG () const
4191
5.97k
  {
4192
  
4193
5.97k
  if (fBitsPerSample [0] != 8)
4194
660
    {
4195
660
    return false;
4196
660
    }
4197
    
4198
5.31k
  if (fSampleFormat [0] != sfUnsignedInteger)
4199
0
    {
4200
0
    return false;
4201
0
    }
4202
4203
5.31k
  if (fCompression == ccLossyJPEG)
4204
492
    {
4205
492
    return true;
4206
492
    }
4207
  
4208
4.81k
  if (fCompression != ccJPEG)
4209
41
    {
4210
41
    return false;
4211
41
    }
4212
    
4213
4.77k
  switch (fPhotometricInterpretation)
4214
4.77k
    {
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
8
           (fPlanarConfiguration == pcInterleaved);
4225
0
      }
4226
      
4227
4.76k
    default:
4228
4.76k
      break;
4229
      
4230
4.77k
    }
4231
    
4232
4.76k
  return false;
4233
  
4234
4.77k
  }
4235
    
4236
/*****************************************************************************/
4237
4238
bool dng_ifd::CanRead () const
4239
35.9k
  {
4240
  
4241
35.9k
  dng_read_image reader;
4242
  
4243
35.9k
  return reader.CanRead (*this);
4244
  
4245
35.9k
  }
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
33.3k
  {
4255
  
4256
33.3k
  dng_read_image reader;
4257
  
4258
33.3k
  reader.Read (host,
4259
33.3k
         *this,
4260
33.3k
         stream,
4261
33.3k
         image,
4262
33.3k
         jpegImage,
4263
33.3k
         jpegDigest);
4264
           
4265
33.3k
  }
4266
      
4267
/*****************************************************************************/