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