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