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