Coverage Report

Created: 2026-08-13 06:45

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