File indexing completed on 2025-01-19 03:54:59
0001 /*****************************************************************************/ 0002 // Copyright 2006-2019 Adobe Systems Incorporated 0003 // All Rights Reserved. 0004 // 0005 // NOTICE: Adobe permits you to use, modify, and distribute this file in 0006 // accordance with the terms of the Adobe license agreement accompanying it. 0007 /*****************************************************************************/ 0008 0009 #include "dng_ifd.h" 0010 0011 #include "dng_exceptions.h" 0012 #include "dng_flags.h" 0013 #include "dng_globals.h" 0014 #include "dng_ifd.h" 0015 #include "dng_types.h" 0016 #include "dng_parse_utils.h" 0017 #include "dng_read_image.h" 0018 #include "dng_stream.h" 0019 #include "dng_tag_codes.h" 0020 #include "dng_tag_types.h" 0021 #include "dng_tag_values.h" 0022 #include "dng_utils.h" 0023 0024 /*****************************************************************************/ 0025 0026 dng_preview_info::dng_preview_info () 0027 0028 : fIsPrimary (true) 0029 , fApplicationName () 0030 , fApplicationVersion () 0031 , fSettingsName () 0032 , fSettingsDigest () 0033 , fColorSpace (previewColorSpace_MaxEnum) 0034 , fDateTime () 0035 , fRawToPreviewGain (1.0) 0036 , fCacheVersion (0) 0037 0038 { 0039 0040 } 0041 0042 /*****************************************************************************/ 0043 0044 dng_preview_info::~dng_preview_info () 0045 { 0046 0047 } 0048 0049 /*****************************************************************************/ 0050 0051 dng_ifd::dng_ifd () 0052 0053 : fUsesNewSubFileType (false) 0054 , fNewSubFileType (0) 0055 0056 , fImageWidth (0) 0057 , fImageLength (0) 0058 0059 , fCompression (ccUncompressed) 0060 , fPredictor (cpNullPredictor) 0061 0062 , fPhotometricInterpretation (0xFFFFFFFF) 0063 0064 , fFillOrder (1) 0065 0066 , fOrientation (0) 0067 , fOrientationType (0) 0068 , fOrientationOffset (kDNGStreamInvalidOffset) 0069 , fOrientationBigEndian (false) 0070 0071 , fSamplesPerPixel (1) 0072 0073 , fPlanarConfiguration (pcInterleaved) 0074 0075 , fXResolution (0.0) 0076 , fYResolution (0.0) 0077 , fResolutionUnit (0) 0078 0079 , fUsesStrips (false) 0080 , fUsesTiles (false) 0081 0082 , fTileWidth (0) 0083 , fTileLength (0) 0084 0085 , fTileOffsetsType (0) 0086 , fTileOffsetsCount (0) 0087 , fTileOffsetsOffset (0) 0088 0089 , fTileByteCountsType (0) 0090 , fTileByteCountsCount (0) 0091 , fTileByteCountsOffset (0) 0092 0093 , fSubIFDsCount (0) 0094 , fSubIFDsOffset (0) 0095 0096 , fExtraSamplesCount (0) 0097 0098 , fJPEGTablesCount (0) 0099 , fJPEGTablesOffset (0) 0100 0101 , fJPEGInterchangeFormat (0) 0102 , fJPEGInterchangeFormatLength (0) 0103 0104 , fYCbCrCoefficientR (0.0) 0105 , fYCbCrCoefficientG (0.0) 0106 , fYCbCrCoefficientB (0.0) 0107 0108 , fYCbCrSubSampleH (0) 0109 , fYCbCrSubSampleV (0) 0110 0111 , fYCbCrPositioning (0) 0112 0113 , fCFARepeatPatternRows (0) 0114 , fCFARepeatPatternCols (0) 0115 0116 , fCFALayout (1) 0117 0118 , fLinearizationTableType (0) 0119 , fLinearizationTableCount (0) 0120 , fLinearizationTableOffset (0) 0121 0122 , fBlackLevelRepeatRows (1) 0123 , fBlackLevelRepeatCols (1) 0124 0125 , fBlackLevelDeltaHType (0) 0126 , fBlackLevelDeltaHCount (0) 0127 , fBlackLevelDeltaHOffset (0) 0128 0129 , fBlackLevelDeltaVType (0) 0130 , fBlackLevelDeltaVCount (0) 0131 , fBlackLevelDeltaVOffset (0) 0132 0133 , fDefaultScaleH (1, 1) 0134 , fDefaultScaleV (1, 1) 0135 0136 , fBestQualityScale (1, 1) 0137 0138 , fDefaultCropOriginH (0, 1) 0139 , fDefaultCropOriginV (0, 1) 0140 0141 , fDefaultCropSizeH () 0142 , fDefaultCropSizeV () 0143 0144 , fDefaultUserCropT (0, 1) 0145 , fDefaultUserCropL (0, 1) 0146 , fDefaultUserCropB (1, 1) 0147 , fDefaultUserCropR (1, 1) 0148 0149 , fBayerGreenSplit (0) 0150 0151 , fChromaBlurRadius () 0152 0153 , fAntiAliasStrength (1, 1) 0154 0155 , fActiveArea () 0156 0157 , fMaskedAreaCount (0) 0158 0159 , fRowInterleaveFactor (1) 0160 0161 , fSubTileBlockRows (1) 0162 , fSubTileBlockCols (1) 0163 0164 , fPreviewInfo () 0165 0166 , fOpcodeList1Count (0) 0167 , fOpcodeList1Offset (0) 0168 0169 , fOpcodeList2Count (0) 0170 , fOpcodeList2Offset (0) 0171 0172 , fOpcodeList3Count (0) 0173 , fOpcodeList3Offset (0) 0174 0175 , fNoiseProfile () 0176 0177 , fEnhanceParams () 0178 0179 , fBaselineSharpness (0, 0) 0180 0181 , fNoiseReductionApplied (0, 0) 0182 0183 , fLosslessJPEGBug16 (false) 0184 0185 , fSampleBitShift (0) 0186 0187 , fThisIFD (0) 0188 , fNextIFD (0) 0189 0190 , fCompressionQuality (-1) 0191 0192 , fPatchFirstJPEGByte (false) 0193 0194 { 0195 0196 uint32 j; 0197 uint32 k; 0198 uint32 n; 0199 0200 for (j = 0; j < kMaxSamplesPerPixel; j++) 0201 { 0202 fBitsPerSample [j] = 0; 0203 } 0204 0205 for (j = 0; j < kMaxTileInfo; j++) 0206 { 0207 fTileOffset [j] = 0; 0208 fTileByteCount [j] = 0; 0209 } 0210 0211 for (j = 0; j < kMaxSamplesPerPixel; j++) 0212 { 0213 fExtraSamples [j] = esUnspecified; 0214 } 0215 0216 for (j = 0; j < kMaxSamplesPerPixel; j++) 0217 { 0218 fSampleFormat [j] = sfUnsignedInteger; 0219 } 0220 0221 for (j = 0; j < 6; j++) 0222 { 0223 fReferenceBlackWhite [j] = 0.0; 0224 } 0225 0226 for (j = 0; j < kMaxCFAPattern; j++) 0227 for (k = 0; k < kMaxCFAPattern; k++) 0228 { 0229 fCFAPattern [j] [k] = 255; 0230 } 0231 0232 for (j = 0; j < kMaxColorPlanes; j++) 0233 { 0234 fCFAPlaneColor [j] = (uint8) (j < 3 ? j : 255); 0235 } 0236 0237 for (j = 0; j < kMaxBlackPattern; j++) 0238 for (k = 0; k < kMaxBlackPattern; k++) 0239 for (n = 0; n < kMaxSamplesPerPixel; n++) 0240 { 0241 fBlackLevel [j] [k] [n] = 0.0; 0242 } 0243 0244 for (j = 0; j < kMaxSamplesPerPixel; j++) 0245 { 0246 fWhiteLevel [j] = -1.0; // Don't know real default yet. 0247 } 0248 0249 } 0250 0251 /*****************************************************************************/ 0252 0253 dng_ifd::~dng_ifd () 0254 { 0255 0256 } 0257 0258 /*****************************************************************************/ 0259 0260 dng_ifd * dng_ifd::Clone () const 0261 { 0262 0263 return new dng_ifd (*this); 0264 0265 } 0266 0267 /*****************************************************************************/ 0268 0269 // Parses tags that should only appear in IFDs that contain images. 0270 0271 bool dng_ifd::ParseTag (dng_stream &stream, 0272 uint32 parentCode, 0273 uint32 tagCode, 0274 uint32 tagType, 0275 uint32 tagCount, 0276 uint64 tagOffset) 0277 { 0278 0279 uint32 j; 0280 uint32 k; 0281 uint32 n; 0282 0283 switch (tagCode) 0284 { 0285 0286 case tcNewSubFileType: 0287 { 0288 0289 CheckTagType (parentCode, tagCode, tagType, ttLong); 0290 0291 CheckTagCount (parentCode, tagCode, tagCount, 1); 0292 0293 fUsesNewSubFileType = true; 0294 0295 fNewSubFileType = stream.TagValue_uint32 (tagType); 0296 0297 fPreviewInfo.fIsPrimary = (fNewSubFileType == sfPreviewImage); 0298 0299 #if qDNGValidate 0300 0301 if (gVerbose) 0302 { 0303 0304 printf ("NewSubFileType: %s\n", 0305 LookupNewSubFileType (fNewSubFileType)); 0306 0307 } 0308 0309 #endif 0310 0311 break; 0312 0313 } 0314 0315 case tcImageWidth: 0316 { 0317 0318 CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong); 0319 0320 CheckTagCount (parentCode, tagCode, tagCount, 1); 0321 0322 fImageWidth = stream.TagValue_uint32 (tagType); 0323 0324 #if qDNGValidate 0325 0326 if (gVerbose) 0327 { 0328 printf ("ImageWidth: %u\n", (unsigned) fImageWidth); 0329 } 0330 0331 #endif 0332 0333 break; 0334 0335 } 0336 0337 case tcImageLength: 0338 { 0339 0340 CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong); 0341 0342 CheckTagCount (parentCode, tagCode, tagCount, 1); 0343 0344 fImageLength = stream.TagValue_uint32 (tagType); 0345 0346 #if qDNGValidate 0347 0348 if (gVerbose) 0349 { 0350 printf ("ImageLength: %u\n", (unsigned) fImageLength); 0351 } 0352 0353 #endif 0354 0355 break; 0356 0357 } 0358 0359 case tcBitsPerSample: 0360 { 0361 0362 CheckTagType (parentCode, tagCode, tagType, ttShort); 0363 0364 CheckTagCount (parentCode, tagCode, tagCount, 1, 0x0FFFF); 0365 0366 #if qDNGValidate 0367 0368 if (gVerbose) 0369 { 0370 printf ("BitsPerSample:"); 0371 } 0372 0373 #endif 0374 0375 bool extrasMatch = true; 0376 0377 for (j = 0; j < tagCount; j++) 0378 { 0379 0380 uint32 x = stream.TagValue_uint32 (tagType); 0381 0382 const uint32 maxBitsPerSample = 32; 0383 0384 if (j < kMaxSamplesPerPixel) 0385 { 0386 0387 if (x > maxBitsPerSample) 0388 { 0389 //ThrowBadFormat ("BitsPerSample out of bounds"); 0390 DNG_REPORT ("BitsPerSample > 32"); 0391 x = maxBitsPerSample; 0392 } 0393 0394 fBitsPerSample [j] = x; 0395 0396 } 0397 0398 else if (x != fBitsPerSample [kMaxSamplesPerPixel - 1]) 0399 { 0400 extrasMatch = false; 0401 } 0402 0403 #if qDNGValidate 0404 0405 if (gVerbose) 0406 { 0407 printf (" %u", (unsigned) x); 0408 } 0409 0410 #endif 0411 0412 } 0413 0414 #if qDNGValidate 0415 0416 if (gVerbose) 0417 { 0418 printf ("\n"); 0419 } 0420 0421 #endif 0422 0423 if (!extrasMatch) 0424 { 0425 0426 #if qDNGValidate 0427 0428 ReportError ("BitsPerSample not constant"); 0429 0430 #endif 0431 0432 ThrowBadFormat (); 0433 0434 } 0435 0436 break; 0437 0438 } 0439 0440 case tcCompression: 0441 { 0442 0443 CheckTagType (parentCode, tagCode, tagType, ttShort); 0444 0445 CheckTagCount (parentCode, tagCode, tagCount, 1); 0446 0447 fCompression = stream.TagValue_uint32 (tagType); 0448 0449 #if qDNGValidate 0450 0451 if (gVerbose) 0452 { 0453 0454 printf ("Compression: %s\n", 0455 LookupCompression (fCompression)); 0456 0457 } 0458 0459 #endif 0460 0461 // Correct a common TIFF writer mistake. 0462 0463 if (fCompression == 0) 0464 { 0465 0466 #if qDNGValidate 0467 0468 { 0469 0470 char message [256]; 0471 0472 sprintf (message, 0473 "%s has invalid zero compression code", 0474 LookupParentCode (parentCode)); 0475 0476 ReportWarning (message); 0477 0478 } 0479 0480 #endif 0481 0482 fCompression = ccUncompressed; 0483 0484 } 0485 0486 break; 0487 0488 } 0489 0490 case tcPhotometricInterpretation: 0491 { 0492 0493 CheckTagType (parentCode, tagCode, tagType, ttShort); 0494 0495 CheckTagCount (parentCode, tagCode, tagCount, 1); 0496 0497 fPhotometricInterpretation = stream.TagValue_uint32 (tagType); 0498 0499 #if qDNGValidate 0500 0501 if (gVerbose) 0502 { 0503 0504 printf ("PhotometricInterpretation: %s\n", 0505 LookupPhotometricInterpretation (fPhotometricInterpretation)); 0506 0507 } 0508 0509 #endif 0510 0511 break; 0512 0513 } 0514 0515 case tcFillOrder: 0516 { 0517 0518 CheckTagType (parentCode, tagCode, tagType, ttShort); 0519 0520 CheckTagCount (parentCode, tagCode, tagCount, 1); 0521 0522 fFillOrder = stream.TagValue_uint32 (tagType); 0523 0524 #if qDNGValidate 0525 0526 if (gVerbose) 0527 { 0528 printf ("FillOrder: %u\n", (unsigned) fFillOrder); 0529 } 0530 0531 #endif 0532 0533 break; 0534 0535 } 0536 0537 case tcStripOffsets: 0538 { 0539 0540 CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong); 0541 0542 fUsesStrips = true; 0543 0544 fTileOffsetsType = tagType; 0545 fTileOffsetsCount = tagCount; 0546 fTileOffsetsOffset = tagOffset; 0547 0548 if (tagCount <= kMaxTileInfo) 0549 { 0550 0551 for (j = 0; j < tagCount; j++) 0552 { 0553 0554 fTileOffset [j] = stream.TagValue_uint32 (tagType); 0555 0556 } 0557 0558 } 0559 0560 #if qDNGValidate 0561 0562 if (gVerbose) 0563 { 0564 0565 stream.SetReadPosition (tagOffset); 0566 0567 DumpTagValues (stream, 0568 "Offset", 0569 parentCode, 0570 tagCode, 0571 tagType, 0572 tagCount); 0573 0574 } 0575 0576 #endif 0577 0578 break; 0579 0580 } 0581 0582 case tcOrientation: 0583 { 0584 0585 CheckTagType (parentCode, tagCode, tagType, ttShort); 0586 0587 CheckTagCount (parentCode, tagCode, tagCount, 1); 0588 0589 fOrientationType = tagType; 0590 fOrientationOffset = stream.PositionInOriginalFile (); 0591 fOrientationBigEndian = stream.BigEndian (); 0592 0593 fOrientation = stream.TagValue_uint32 (tagType); 0594 0595 #if qDNGValidate 0596 0597 if (gVerbose) 0598 { 0599 0600 printf ("Orientation: %s\n", 0601 LookupOrientation (fOrientation)); 0602 0603 } 0604 0605 #endif 0606 0607 break; 0608 0609 } 0610 0611 case tcSamplesPerPixel: 0612 { 0613 0614 CheckTagType (parentCode, tagCode, tagType, ttShort); 0615 0616 CheckTagCount (parentCode, tagCode, tagCount, 1); 0617 0618 fSamplesPerPixel = stream.TagValue_uint32 (tagType); 0619 0620 #if qDNGValidate 0621 0622 if (gVerbose) 0623 { 0624 printf ("SamplesPerPixel: %u\n", (unsigned) fSamplesPerPixel); 0625 } 0626 0627 #endif 0628 0629 break; 0630 0631 } 0632 0633 case tcRowsPerStrip: 0634 { 0635 0636 CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong); 0637 0638 CheckTagCount (parentCode, tagCode, tagCount, 1); 0639 0640 fUsesStrips = true; 0641 0642 fTileLength = stream.TagValue_uint32 (tagType); 0643 0644 #if qDNGValidate 0645 0646 if (gVerbose) 0647 { 0648 printf ("RowsPerStrip: %u\n", (unsigned) fTileLength); 0649 } 0650 0651 #endif 0652 0653 break; 0654 0655 } 0656 0657 case tcStripByteCounts: 0658 { 0659 0660 CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong); 0661 0662 fUsesStrips = true; 0663 0664 fTileByteCountsType = tagType; 0665 fTileByteCountsCount = tagCount; 0666 fTileByteCountsOffset = tagOffset; 0667 0668 if (tagCount <= kMaxTileInfo) 0669 { 0670 0671 for (j = 0; j < tagCount; j++) 0672 { 0673 0674 fTileByteCount [j] = stream.TagValue_uint32 (tagType); 0675 0676 } 0677 0678 } 0679 0680 #if qDNGValidate 0681 0682 if (gVerbose) 0683 { 0684 0685 stream.SetReadPosition (tagOffset); 0686 0687 DumpTagValues (stream, 0688 "Count", 0689 parentCode, 0690 tagCode, 0691 tagType, 0692 tagCount); 0693 0694 } 0695 0696 #endif 0697 0698 break; 0699 0700 } 0701 0702 case tcXResolution: 0703 { 0704 0705 CheckTagType (parentCode, tagCode, tagType, ttRational); 0706 0707 CheckTagCount (parentCode, tagCode, tagCount, 1); 0708 0709 fXResolution = stream.TagValue_real64 (tagType); 0710 0711 #if qDNGValidate 0712 0713 if (gVerbose) 0714 { 0715 printf ("XResolution: %0.2f\n", fXResolution); 0716 } 0717 0718 #endif 0719 0720 break; 0721 0722 } 0723 0724 case tcYResolution: 0725 { 0726 0727 CheckTagType (parentCode, tagCode, tagType, ttRational); 0728 0729 CheckTagCount (parentCode, tagCode, tagCount, 1); 0730 0731 fYResolution = stream.TagValue_real64 (tagType); 0732 0733 #if qDNGValidate 0734 0735 if (gVerbose) 0736 { 0737 printf ("YResolution: %0.2f\n", fYResolution); 0738 } 0739 0740 #endif 0741 0742 break; 0743 0744 } 0745 0746 case tcPlanarConfiguration: 0747 { 0748 0749 CheckTagType (parentCode, tagCode, tagType, ttShort); 0750 0751 CheckTagCount (parentCode, tagCode, tagCount, 1); 0752 0753 fPlanarConfiguration = stream.TagValue_uint32 (tagType); 0754 0755 #if qDNGValidate 0756 0757 if (gVerbose) 0758 { 0759 printf ("PlanarConfiguration: %u\n", (unsigned) fPlanarConfiguration); 0760 } 0761 0762 #endif 0763 0764 break; 0765 0766 } 0767 0768 case tcResolutionUnit: 0769 { 0770 0771 CheckTagType (parentCode, tagCode, tagType, ttShort); 0772 0773 CheckTagCount (parentCode, tagCode, tagCount, 1); 0774 0775 fResolutionUnit = stream.TagValue_uint32 (tagType); 0776 0777 #if qDNGValidate 0778 0779 if (gVerbose) 0780 { 0781 0782 printf ("ResolutionUnit: %s\n", 0783 LookupResolutionUnit (fResolutionUnit)); 0784 0785 } 0786 0787 #endif 0788 0789 break; 0790 0791 } 0792 0793 case tcPredictor: 0794 { 0795 0796 CheckTagType (parentCode, tagCode, tagType, ttShort); 0797 0798 CheckTagCount (parentCode, tagCode, tagCount, 1); 0799 0800 fPredictor = stream.TagValue_uint32 (tagType); 0801 0802 #if qDNGValidate 0803 0804 if (gVerbose) 0805 { 0806 0807 printf ("Predictor: %s\n", 0808 LookupPredictor (fPredictor)); 0809 0810 } 0811 0812 #endif 0813 0814 break; 0815 0816 } 0817 0818 case tcTileWidth: 0819 { 0820 0821 CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong); 0822 0823 CheckTagCount (parentCode, tagCode, tagCount, 1); 0824 0825 fUsesTiles = true; 0826 0827 fTileWidth = stream.TagValue_uint32 (tagType); 0828 0829 #if qDNGValidate 0830 0831 if (gVerbose) 0832 { 0833 printf ("TileWidth: %u\n", (unsigned) fTileWidth); 0834 } 0835 0836 #endif 0837 0838 break; 0839 0840 } 0841 0842 case tcTileLength: 0843 { 0844 0845 CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong); 0846 0847 CheckTagCount (parentCode, tagCode, tagCount, 1); 0848 0849 fUsesTiles = true; 0850 0851 fTileLength = stream.TagValue_uint32 (tagType); 0852 0853 #if qDNGValidate 0854 0855 if (gVerbose) 0856 { 0857 printf ("TileLength: %u\n", (unsigned) fTileLength); 0858 } 0859 0860 #endif 0861 0862 break; 0863 0864 } 0865 0866 case tcTileOffsets: 0867 { 0868 0869 CheckTagType (parentCode, tagCode, tagType, ttLong); 0870 0871 fUsesTiles = true; 0872 0873 fTileOffsetsType = tagType; 0874 fTileOffsetsCount = tagCount; 0875 fTileOffsetsOffset = tagOffset; 0876 0877 if (tagCount <= kMaxTileInfo) 0878 { 0879 0880 for (j = 0; j < tagCount; j++) 0881 { 0882 0883 fTileOffset [j] = stream.TagValue_uint32 (tagType); 0884 0885 } 0886 0887 } 0888 0889 #if qDNGValidate 0890 0891 if (gVerbose) 0892 { 0893 0894 stream.SetReadPosition (tagOffset); 0895 0896 DumpTagValues (stream, 0897 "Offset", 0898 parentCode, 0899 tagCode, 0900 tagType, 0901 tagCount); 0902 0903 } 0904 0905 #endif 0906 0907 break; 0908 0909 } 0910 0911 case tcTileByteCounts: 0912 { 0913 0914 CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong); 0915 0916 fUsesTiles = true; 0917 0918 fTileByteCountsType = tagType; 0919 fTileByteCountsCount = tagCount; 0920 fTileByteCountsOffset = tagOffset; 0921 0922 if (tagCount <= kMaxTileInfo) 0923 { 0924 0925 for (j = 0; j < tagCount; j++) 0926 { 0927 0928 fTileByteCount [j] = stream.TagValue_uint32 (tagType); 0929 0930 } 0931 0932 } 0933 0934 #if qDNGValidate 0935 0936 if (gVerbose) 0937 { 0938 0939 stream.SetReadPosition (tagOffset); 0940 0941 DumpTagValues (stream, 0942 "Count", 0943 parentCode, 0944 tagCode, 0945 tagType, 0946 tagCount); 0947 0948 } 0949 0950 #endif 0951 0952 break; 0953 0954 } 0955 0956 case tcSubIFDs: 0957 { 0958 0959 CheckTagType (parentCode, tagCode, tagType, ttLong, ttIFD); 0960 0961 fSubIFDsCount = tagCount; 0962 fSubIFDsOffset = tagOffset; 0963 0964 #if qDNGValidate 0965 0966 if (gVerbose) 0967 { 0968 0969 DumpTagValues (stream, 0970 "IFD", 0971 parentCode, 0972 tagCode, 0973 ttLong, 0974 tagCount); 0975 0976 } 0977 0978 #endif 0979 0980 break; 0981 0982 } 0983 0984 case tcExtraSamples: 0985 { 0986 0987 CheckTagType (parentCode, tagCode, tagType, ttShort); 0988 0989 CheckTagCount (parentCode, tagCode, tagCount, 1, fSamplesPerPixel); 0990 0991 #if qDNGValidate 0992 0993 if (gVerbose) 0994 { 0995 printf ("ExtraSamples:"); 0996 } 0997 0998 #endif 0999 1000 fExtraSamplesCount = tagCount; 1001 1002 for (j = 0; j < tagCount; j++) 1003 { 1004 1005 uint32 x = stream.TagValue_uint32 (tagType); 1006 1007 if (j < kMaxSamplesPerPixel) 1008 { 1009 fExtraSamples [j] = x; 1010 } 1011 1012 #if qDNGValidate 1013 1014 if (gVerbose) 1015 { 1016 printf (" %u", (unsigned) x); 1017 } 1018 1019 #endif 1020 1021 } 1022 1023 #if qDNGValidate 1024 1025 if (gVerbose) 1026 { 1027 printf ("\n"); 1028 } 1029 1030 #endif 1031 1032 break; 1033 1034 } 1035 1036 case tcSampleFormat: 1037 { 1038 1039 CheckTagType (parentCode, tagCode, tagType, ttShort); 1040 1041 CheckTagCount (parentCode, tagCode, tagCount, fSamplesPerPixel); 1042 1043 #if qDNGValidate 1044 1045 if (gVerbose) 1046 { 1047 printf ("SampleFormat:"); 1048 } 1049 1050 #endif 1051 1052 bool extrasMatch = true; 1053 1054 for (j = 0; j < tagCount; j++) 1055 { 1056 1057 uint32 x = stream.TagValue_uint32 (tagType); 1058 1059 if (j < kMaxSamplesPerPixel) 1060 { 1061 fSampleFormat [j] = x; 1062 } 1063 1064 else if (x != fSampleFormat [kMaxSamplesPerPixel - 1]) 1065 { 1066 extrasMatch = false; 1067 } 1068 1069 #if qDNGValidate 1070 1071 if (gVerbose) 1072 { 1073 printf (" %s", LookupSampleFormat (x)); 1074 } 1075 1076 #endif 1077 1078 } 1079 1080 #if qDNGValidate 1081 1082 if (gVerbose) 1083 { 1084 printf ("\n"); 1085 } 1086 1087 #endif 1088 1089 if (!extrasMatch) 1090 { 1091 1092 #if qDNGValidate 1093 1094 ReportError ("SampleFormat not constant"); 1095 1096 #endif 1097 1098 ThrowBadFormat (); 1099 1100 } 1101 1102 break; 1103 1104 } 1105 1106 case tcJPEGTables: 1107 { 1108 1109 CheckTagType (parentCode, tagCode, tagType, ttUndefined); 1110 1111 fJPEGTablesCount = tagCount; 1112 fJPEGTablesOffset = tagOffset; 1113 1114 #if qDNGValidate 1115 1116 if (gVerbose) 1117 { 1118 1119 printf ("JPEGTables: count = %u, offset = %u\n", 1120 (unsigned) fJPEGTablesCount, 1121 (unsigned) fJPEGTablesOffset); 1122 1123 } 1124 1125 #endif 1126 1127 break; 1128 1129 } 1130 1131 case tcJPEGInterchangeFormat: 1132 { 1133 1134 CheckTagType (parentCode, tagCode, tagType, ttLong); 1135 1136 CheckTagCount (parentCode, tagCode, tagCount, 1); 1137 1138 fJPEGInterchangeFormat = stream.TagValue_uint32 (tagType); 1139 1140 #if qDNGValidate 1141 1142 if (gVerbose) 1143 { 1144 printf ("JPEGInterchangeFormat: %u\n", 1145 (unsigned) fJPEGInterchangeFormat); 1146 } 1147 1148 #endif 1149 1150 break; 1151 1152 } 1153 1154 case tcJPEGInterchangeFormatLength: 1155 { 1156 1157 CheckTagType (parentCode, tagCode, tagType, ttLong); 1158 1159 CheckTagCount (parentCode, tagCode, tagCount, 1); 1160 1161 fJPEGInterchangeFormatLength = stream.TagValue_uint32 (tagType); 1162 1163 #if qDNGValidate 1164 1165 if (gVerbose) 1166 { 1167 printf ("JPEGInterchangeFormatLength: %u\n", 1168 (unsigned) fJPEGInterchangeFormatLength); 1169 } 1170 1171 #endif 1172 1173 break; 1174 1175 } 1176 1177 case tcYCbCrCoefficients: 1178 { 1179 1180 CheckTagType (parentCode, tagCode, tagType, ttRational); 1181 1182 if (!CheckTagCount (parentCode, tagCode, tagCount, 3)) 1183 { 1184 return false; 1185 } 1186 1187 fYCbCrCoefficientR = stream.TagValue_real64 (tagType); 1188 fYCbCrCoefficientG = stream.TagValue_real64 (tagType); 1189 fYCbCrCoefficientB = stream.TagValue_real64 (tagType); 1190 1191 #if qDNGValidate 1192 1193 if (gVerbose) 1194 { 1195 1196 printf ("YCbCrCoefficients: R = %0.3f, G = %0.3f, B = %0.3f\n", 1197 fYCbCrCoefficientR, 1198 fYCbCrCoefficientG, 1199 fYCbCrCoefficientB); 1200 1201 } 1202 1203 #endif 1204 1205 break; 1206 1207 } 1208 1209 case tcYCbCrSubSampling: 1210 { 1211 1212 CheckTagType (parentCode, tagCode, tagType, ttShort); 1213 1214 if (!CheckTagCount (parentCode, tagCode, tagCount, 2)) 1215 { 1216 return false; 1217 } 1218 1219 fYCbCrSubSampleH = stream.TagValue_uint32 (tagType); 1220 fYCbCrSubSampleV = stream.TagValue_uint32 (tagType); 1221 1222 #if qDNGValidate 1223 1224 if (gVerbose) 1225 { 1226 1227 printf ("YCbCrSubSampling: H = %u, V = %u\n", 1228 (unsigned) fYCbCrSubSampleH, 1229 (unsigned) fYCbCrSubSampleV); 1230 1231 } 1232 1233 #endif 1234 1235 break; 1236 1237 } 1238 1239 case tcYCbCrPositioning: 1240 { 1241 1242 CheckTagType (parentCode, tagCode, tagType, ttShort); 1243 1244 CheckTagCount (parentCode, tagCode, tagCount, 1); 1245 1246 fYCbCrPositioning = stream.TagValue_uint32 (tagType); 1247 1248 #if qDNGValidate 1249 1250 if (gVerbose) 1251 { 1252 1253 printf ("YCbCrPositioning: %u\n", 1254 (unsigned) fYCbCrPositioning); 1255 1256 } 1257 1258 #endif 1259 1260 break; 1261 1262 } 1263 1264 case tcReferenceBlackWhite: 1265 { 1266 1267 CheckTagType (parentCode, tagCode, tagType, ttRational); 1268 1269 if (!CheckTagCount (parentCode, tagCode, tagCount, 6)) 1270 { 1271 return false; 1272 } 1273 1274 for (j = 0; j < 6; j++) 1275 { 1276 fReferenceBlackWhite [j] = stream.TagValue_real64 (tagType); 1277 } 1278 1279 #if qDNGValidate 1280 1281 if (gVerbose) 1282 { 1283 1284 printf ("ReferenceBlackWhite: %0.1f %0.1f %0.1f %0.1f %0.1f %0.1f\n", 1285 fReferenceBlackWhite [0], 1286 fReferenceBlackWhite [1], 1287 fReferenceBlackWhite [2], 1288 fReferenceBlackWhite [3], 1289 fReferenceBlackWhite [4], 1290 fReferenceBlackWhite [5]); 1291 1292 } 1293 1294 #endif 1295 1296 break; 1297 1298 } 1299 1300 case tcCFARepeatPatternDim: 1301 { 1302 1303 CheckCFA (parentCode, tagCode, fPhotometricInterpretation); 1304 1305 CheckTagType (parentCode, tagCode, tagType, ttShort); 1306 1307 if (!CheckTagCount (parentCode, tagCode, tagCount, 2)) 1308 { 1309 return false; 1310 } 1311 1312 fCFARepeatPatternRows = stream.TagValue_uint32 (tagType); 1313 fCFARepeatPatternCols = stream.TagValue_uint32 (tagType); 1314 1315 #if qDNGValidate 1316 1317 if (gVerbose) 1318 { 1319 1320 printf ("CFARepeatPatternDim: Rows = %u, Cols = %u\n", 1321 (unsigned) fCFARepeatPatternRows, 1322 (unsigned) fCFARepeatPatternCols); 1323 1324 } 1325 1326 #endif 1327 1328 break; 1329 1330 } 1331 1332 case tcCFAPattern: 1333 { 1334 1335 CheckCFA (parentCode, tagCode, fPhotometricInterpretation); 1336 1337 if (!CheckTagType (parentCode, tagCode, tagType, ttByte)) 1338 { 1339 return false; 1340 } 1341 1342 if (!CheckTagCount (parentCode, tagCode, tagCount, fCFARepeatPatternRows * 1343 fCFARepeatPatternCols)) 1344 { 1345 return false; 1346 } 1347 1348 if (fCFARepeatPatternRows < 1 || fCFARepeatPatternRows > kMaxCFAPattern || 1349 fCFARepeatPatternCols < 1 || fCFARepeatPatternCols > kMaxCFAPattern) 1350 { 1351 return false; 1352 } 1353 1354 // Note that the Exif spec stores this array in a different 1355 // scan order than the TIFF-EP spec. 1356 1357 for (j = 0; j < fCFARepeatPatternRows; j++) 1358 for (k = 0; k < fCFARepeatPatternCols; k++) 1359 { 1360 1361 fCFAPattern [j] [k] = stream.Get_uint8 (); 1362 1363 } 1364 1365 #if qDNGValidate 1366 1367 if (gVerbose) 1368 { 1369 1370 printf ("CFAPattern:\n"); 1371 1372 for (j = 0; j < fCFARepeatPatternRows; j++) 1373 { 1374 1375 int32 spaces = 4; 1376 1377 for (k = 0; k < fCFARepeatPatternCols; k++) 1378 { 1379 1380 while (spaces-- > 0) 1381 { 1382 printf (" "); 1383 } 1384 1385 const char *name = LookupCFAColor (fCFAPattern [j] [k]); 1386 1387 spaces = 9 - (int32) strlen (name); 1388 1389 printf ("%s", name); 1390 1391 } 1392 1393 printf ("\n"); 1394 1395 } 1396 1397 } 1398 1399 #endif 1400 1401 break; 1402 1403 } 1404 1405 case tcCFAPlaneColor: 1406 { 1407 1408 CheckCFA (parentCode, tagCode, fPhotometricInterpretation); 1409 1410 if (!CheckTagType (parentCode, tagCode, tagType, ttByte)) 1411 { 1412 return false; 1413 } 1414 1415 if (!CheckTagCount (parentCode, tagCode, tagCount, 3, kMaxColorPlanes)) 1416 { 1417 return false; 1418 } 1419 1420 for (j = 0; j < kMaxColorPlanes; j++) 1421 { 1422 1423 if (j < tagCount) 1424 fCFAPlaneColor [j] = stream.Get_uint8 (); 1425 1426 else 1427 fCFAPlaneColor [j] = 255; 1428 1429 } 1430 1431 #if qDNGValidate 1432 1433 if (gVerbose) 1434 { 1435 1436 printf ("CFAPlaneColor:"); 1437 1438 for (j = 0; j < tagCount; j++) 1439 { 1440 1441 printf (" %s", LookupCFAColor (fCFAPlaneColor [j])); 1442 1443 } 1444 1445 printf ("\n"); 1446 1447 } 1448 1449 #endif 1450 1451 break; 1452 1453 } 1454 1455 case tcCFALayout: 1456 { 1457 1458 CheckCFA (parentCode, tagCode, fPhotometricInterpretation); 1459 1460 CheckTagType (parentCode, tagCode, tagType, ttShort); 1461 1462 CheckTagCount (parentCode, tagCode, tagCount, 1); 1463 1464 fCFALayout = stream.TagValue_uint32 (tagType); 1465 1466 #if qDNGValidate 1467 1468 if (gVerbose) 1469 { 1470 1471 printf ("CFALayout: %s\n", 1472 LookupCFALayout (fCFALayout)); 1473 1474 } 1475 1476 #endif 1477 1478 break; 1479 1480 } 1481 1482 case tcLinearizationTable: 1483 { 1484 1485 CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation); 1486 1487 CheckTagType (parentCode, tagCode, tagType, ttShort); 1488 1489 fLinearizationTableType = tagType; 1490 fLinearizationTableCount = tagCount; 1491 fLinearizationTableOffset = tagOffset; 1492 1493 #if qDNGValidate 1494 1495 if (gVerbose) 1496 { 1497 1498 DumpTagValues (stream, 1499 "Table", 1500 parentCode, 1501 tagCode, 1502 tagType, 1503 tagCount); 1504 1505 } 1506 1507 #endif 1508 1509 break; 1510 1511 } 1512 1513 case tcBlackLevelRepeatDim: 1514 { 1515 1516 CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation); 1517 1518 CheckTagType (parentCode, tagCode, tagType, ttShort); 1519 1520 if (!CheckTagCount (parentCode, tagCode, tagCount, 2)) 1521 { 1522 return false; 1523 } 1524 1525 fBlackLevelRepeatRows = stream.TagValue_uint32 (tagType); 1526 fBlackLevelRepeatCols = stream.TagValue_uint32 (tagType); 1527 1528 #if qDNGValidate 1529 1530 if (gVerbose) 1531 { 1532 1533 printf ("BlackLevelRepeatDim: Rows = %u, Cols = %u\n", 1534 (unsigned) fBlackLevelRepeatRows, 1535 (unsigned) fBlackLevelRepeatCols); 1536 1537 } 1538 1539 #endif 1540 1541 break; 1542 1543 } 1544 1545 case tcBlackLevel: 1546 { 1547 1548 CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation); 1549 1550 CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong, ttRational); 1551 1552 if (!CheckTagCount (parentCode, tagCode, tagCount, fBlackLevelRepeatRows * 1553 fBlackLevelRepeatCols * 1554 fSamplesPerPixel)) 1555 { 1556 return false; 1557 } 1558 1559 if (fBlackLevelRepeatRows < 1 || fBlackLevelRepeatRows > kMaxBlackPattern || 1560 fBlackLevelRepeatCols < 1 || fBlackLevelRepeatCols > kMaxBlackPattern || 1561 fSamplesPerPixel < 1 || fSamplesPerPixel > kMaxSamplesPerPixel) 1562 { 1563 return false; 1564 } 1565 1566 for (j = 0; j < fBlackLevelRepeatRows; j++) 1567 for (k = 0; k < fBlackLevelRepeatCols; k++) 1568 for (n = 0; n < fSamplesPerPixel; n++) 1569 { 1570 1571 fBlackLevel [j] [k] [n] = stream.TagValue_real64 (tagType); 1572 1573 } 1574 1575 #if qDNGValidate 1576 1577 if (gVerbose) 1578 { 1579 1580 printf ("BlackLevel:"); 1581 1582 if (fBlackLevelRepeatRows == 1 && 1583 fBlackLevelRepeatCols == 1) 1584 { 1585 1586 for (n = 0; n < fSamplesPerPixel; n++) 1587 { 1588 printf (" %0.2f", fBlackLevel [0] [0] [n]); 1589 } 1590 1591 printf ("\n"); 1592 1593 } 1594 1595 else 1596 { 1597 1598 printf ("\n"); 1599 1600 for (n = 0; n < fSamplesPerPixel; n++) 1601 { 1602 1603 if (fSamplesPerPixel > 1) 1604 { 1605 printf (" Sample: %u\n", (unsigned) n); 1606 } 1607 1608 for (j = 0; j < fBlackLevelRepeatRows; j++) 1609 { 1610 1611 printf (" "); 1612 1613 for (k = 0; k < fBlackLevelRepeatCols; k++) 1614 { 1615 1616 printf (" %8.2f", fBlackLevel [j] [k] [n]); 1617 1618 } 1619 1620 printf ("\n"); 1621 1622 } 1623 1624 } 1625 1626 } 1627 1628 } 1629 1630 #endif 1631 1632 break; 1633 1634 } 1635 1636 case tcBlackLevelDeltaH: 1637 { 1638 1639 CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation); 1640 1641 CheckTagType (parentCode, tagCode, tagType, ttSRational); 1642 1643 fBlackLevelDeltaHType = tagType; 1644 fBlackLevelDeltaHCount = tagCount; 1645 fBlackLevelDeltaHOffset = tagOffset; 1646 1647 #if qDNGValidate 1648 1649 if (gVerbose) 1650 { 1651 1652 DumpTagValues (stream, 1653 "Delta", 1654 parentCode, 1655 tagCode, 1656 tagType, 1657 tagCount); 1658 1659 } 1660 1661 #endif 1662 1663 break; 1664 1665 } 1666 1667 case tcBlackLevelDeltaV: 1668 { 1669 1670 CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation); 1671 1672 CheckTagType (parentCode, tagCode, tagType, ttSRational); 1673 1674 fBlackLevelDeltaVType = tagType; 1675 fBlackLevelDeltaVCount = tagCount; 1676 fBlackLevelDeltaVOffset = tagOffset; 1677 1678 #if qDNGValidate 1679 1680 if (gVerbose) 1681 { 1682 1683 DumpTagValues (stream, 1684 "Delta", 1685 parentCode, 1686 tagCode, 1687 tagType, 1688 tagCount); 1689 1690 } 1691 1692 #endif 1693 1694 break; 1695 1696 } 1697 1698 case tcWhiteLevel: 1699 { 1700 1701 CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation); 1702 1703 CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong); 1704 1705 if (!CheckTagCount (parentCode, tagCode, tagCount, fSamplesPerPixel)) 1706 return false; 1707 1708 for (j = 0; j < tagCount && j < kMaxSamplesPerPixel; j++) 1709 { 1710 1711 fWhiteLevel [j] = stream.TagValue_real64 (tagType); 1712 1713 } 1714 1715 #if qDNGValidate 1716 1717 if (gVerbose) 1718 { 1719 1720 printf ("WhiteLevel:"); 1721 1722 for (j = 0; j < tagCount && j < kMaxSamplesPerPixel; j++) 1723 { 1724 1725 printf (" %0.0f", fWhiteLevel [j]); 1726 1727 } 1728 1729 printf ("\n"); 1730 1731 } 1732 1733 #endif 1734 1735 break; 1736 1737 } 1738 1739 case tcDefaultScale: 1740 { 1741 1742 CheckMainIFD (parentCode, tagCode, fNewSubFileType); 1743 1744 CheckTagType (parentCode, tagCode, tagType, ttRational); 1745 1746 if (!CheckTagCount (parentCode, tagCode, tagCount, 2)) 1747 return false; 1748 1749 fDefaultScaleH = stream.TagValue_urational (tagType); 1750 fDefaultScaleV = stream.TagValue_urational (tagType); 1751 1752 #if qDNGValidate 1753 1754 if (gVerbose) 1755 { 1756 1757 printf ("DefaultScale: H = %0.4f V = %0.4f\n", 1758 fDefaultScaleH.As_real64 (), 1759 fDefaultScaleV.As_real64 ()); 1760 1761 } 1762 1763 #endif 1764 1765 break; 1766 1767 } 1768 1769 case tcDefaultCropOrigin: 1770 { 1771 1772 CheckMainIFD (parentCode, tagCode, fNewSubFileType); 1773 1774 CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong, ttRational); 1775 1776 if (!CheckTagCount (parentCode, tagCode, tagCount, 2)) 1777 return false; 1778 1779 fDefaultCropOriginH = stream.TagValue_urational (tagType); 1780 fDefaultCropOriginV = stream.TagValue_urational (tagType); 1781 1782 #if qDNGValidate 1783 1784 if (gVerbose) 1785 { 1786 1787 printf ("DefaultCropOrigin: H = %0.2f V = %0.2f\n", 1788 fDefaultCropOriginH.As_real64 (), 1789 fDefaultCropOriginV.As_real64 ()); 1790 1791 } 1792 1793 #endif 1794 1795 break; 1796 1797 } 1798 1799 case tcDefaultCropSize: 1800 { 1801 1802 CheckMainIFD (parentCode, tagCode, fNewSubFileType); 1803 1804 CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong, ttRational); 1805 1806 if (!CheckTagCount (parentCode, tagCode, tagCount, 2)) 1807 return false; 1808 1809 fDefaultCropSizeH = stream.TagValue_urational (tagType); 1810 fDefaultCropSizeV = stream.TagValue_urational (tagType); 1811 1812 #if qDNGValidate 1813 1814 if (gVerbose) 1815 { 1816 1817 printf ("DefaultCropSize: H = %0.2f V = %0.2f\n", 1818 fDefaultCropSizeH.As_real64 (), 1819 fDefaultCropSizeV.As_real64 ()); 1820 1821 } 1822 1823 #endif 1824 1825 break; 1826 1827 } 1828 1829 case tcDefaultUserCrop: 1830 { 1831 1832 CheckMainIFD (parentCode, tagCode, fNewSubFileType); 1833 1834 CheckTagType (parentCode, tagCode, tagType, ttRational); 1835 1836 if (!CheckTagCount (parentCode, tagCode, tagCount, 4)) 1837 return false; 1838 1839 fDefaultUserCropT = stream.TagValue_urational (tagType); 1840 fDefaultUserCropL = stream.TagValue_urational (tagType); 1841 fDefaultUserCropB = stream.TagValue_urational (tagType); 1842 fDefaultUserCropR = stream.TagValue_urational (tagType); 1843 1844 #if qDNGValidate 1845 1846 if (gVerbose) 1847 { 1848 1849 printf ("DefaultUserCrop: T = %0.2lf L = %0.2lf B = %0.2lf R = %0.2lf\n", 1850 (double) fDefaultUserCropT.As_real64 (), 1851 (double) fDefaultUserCropL.As_real64 (), 1852 (double) fDefaultUserCropB.As_real64 (), 1853 (double) fDefaultUserCropR.As_real64 ()); 1854 1855 1856 } 1857 1858 #endif // qDNGValidate 1859 1860 break; 1861 1862 } 1863 1864 case tcBayerGreenSplit: 1865 { 1866 1867 CheckCFA (parentCode, tagCode, fPhotometricInterpretation); 1868 1869 CheckTagType (parentCode, tagCode, tagType, ttLong); 1870 1871 CheckTagCount (parentCode, tagCode, tagCount, 1); 1872 1873 fBayerGreenSplit = stream.TagValue_uint32 (tagType); 1874 1875 #if qDNGValidate 1876 1877 if (gVerbose) 1878 { 1879 printf ("BayerGreenSplit: %u\n", (unsigned) fBayerGreenSplit); 1880 } 1881 1882 #endif 1883 1884 break; 1885 1886 } 1887 1888 case tcChromaBlurRadius: 1889 { 1890 1891 CheckMainIFD (parentCode, tagCode, fNewSubFileType); 1892 1893 CheckTagType (parentCode, tagCode, tagType, ttRational); 1894 1895 CheckTagCount (parentCode, tagCode, tagCount, 1); 1896 1897 fChromaBlurRadius = stream.TagValue_urational (tagType); 1898 1899 #if qDNGValidate 1900 1901 if (gVerbose) 1902 { 1903 1904 printf ("ChromaBlurRadius: %0.2f\n", 1905 fChromaBlurRadius.As_real64 ()); 1906 1907 } 1908 1909 #endif 1910 1911 break; 1912 1913 } 1914 1915 case tcAntiAliasStrength: 1916 { 1917 1918 CheckMainIFD (parentCode, tagCode, fNewSubFileType); 1919 1920 CheckTagType (parentCode, tagCode, tagType, ttRational); 1921 1922 CheckTagCount (parentCode, tagCode, tagCount, 1); 1923 1924 fAntiAliasStrength = stream.TagValue_urational (tagType); 1925 1926 #if qDNGValidate 1927 1928 if (gVerbose) 1929 { 1930 1931 printf ("AntiAliasStrength: %0.2f\n", 1932 fAntiAliasStrength.As_real64 ()); 1933 1934 } 1935 1936 #endif 1937 1938 break; 1939 1940 } 1941 1942 case tcBestQualityScale: 1943 { 1944 1945 CheckMainIFD (parentCode, tagCode, fNewSubFileType); 1946 1947 CheckTagType (parentCode, tagCode, tagType, ttRational); 1948 1949 CheckTagCount (parentCode, tagCode, tagCount, 1); 1950 1951 fBestQualityScale = stream.TagValue_urational (tagType); 1952 1953 #if qDNGValidate 1954 1955 if (gVerbose) 1956 { 1957 1958 printf ("BestQualityScale: %0.4f\n", 1959 fBestQualityScale.As_real64 ()); 1960 1961 } 1962 1963 #endif 1964 1965 break; 1966 1967 } 1968 1969 case tcActiveArea: 1970 { 1971 1972 CheckMainIFD (parentCode, tagCode, fNewSubFileType); 1973 1974 CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong); 1975 1976 if (!CheckTagCount (parentCode, tagCode, tagCount, 4)) 1977 return false; 1978 1979 fActiveArea.t = stream.TagValue_int32 (tagType); 1980 fActiveArea.l = stream.TagValue_int32 (tagType); 1981 fActiveArea.b = stream.TagValue_int32 (tagType); 1982 fActiveArea.r = stream.TagValue_int32 (tagType); 1983 1984 #if qDNGValidate 1985 1986 if (gVerbose) 1987 { 1988 1989 printf ("ActiveArea: T = %d L = %d B = %d R = %d\n", 1990 (int) fActiveArea.t, 1991 (int) fActiveArea.l, 1992 (int) fActiveArea.b, 1993 (int) fActiveArea.r); 1994 1995 } 1996 1997 #endif 1998 1999 break; 2000 2001 } 2002 2003 case tcMaskedAreas: 2004 { 2005 2006 CheckMainIFD (parentCode, tagCode, fNewSubFileType); 2007 2008 CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong); 2009 2010 uint32 rect_count = tagCount / 4; 2011 2012 if (!CheckTagCount (parentCode, tagCode, tagCount, rect_count * 4)) 2013 return false; 2014 2015 fMaskedAreaCount = rect_count; 2016 2017 if (fMaskedAreaCount > kMaxMaskedAreas) 2018 fMaskedAreaCount = kMaxMaskedAreas; 2019 2020 for (j = 0; j < fMaskedAreaCount; j++) 2021 { 2022 2023 fMaskedArea [j].t = stream.TagValue_int32 (tagType); 2024 fMaskedArea [j].l = stream.TagValue_int32 (tagType); 2025 fMaskedArea [j].b = stream.TagValue_int32 (tagType); 2026 fMaskedArea [j].r = stream.TagValue_int32 (tagType); 2027 2028 } 2029 2030 #if qDNGValidate 2031 2032 if (gVerbose) 2033 { 2034 2035 printf ("MaskedAreas: %u\n", (unsigned) fMaskedAreaCount); 2036 2037 for (j = 0; j < fMaskedAreaCount; j++) 2038 { 2039 2040 printf (" Area [%u]: T = %d L = %d B = %d R = %d\n", 2041 (unsigned) j, 2042 (int) fMaskedArea [j].t, 2043 (int) fMaskedArea [j].l, 2044 (int) fMaskedArea [j].b, 2045 (int) fMaskedArea [j].r); 2046 2047 } 2048 2049 } 2050 2051 #endif 2052 2053 break; 2054 2055 } 2056 2057 case tcPreviewApplicationName: 2058 { 2059 2060 CheckTagType (parentCode, tagCode, tagType, ttAscii, ttByte); 2061 2062 ParseStringTag (stream, 2063 parentCode, 2064 tagCode, 2065 tagCount, 2066 fPreviewInfo.fApplicationName, 2067 false); 2068 2069 #if qDNGValidate 2070 2071 if (gVerbose) 2072 { 2073 2074 printf ("PreviewApplicationName: "); 2075 2076 DumpString (fPreviewInfo.fApplicationName); 2077 2078 printf ("\n"); 2079 2080 } 2081 2082 #endif 2083 2084 break; 2085 2086 } 2087 2088 case tcPreviewApplicationVersion: 2089 { 2090 2091 CheckTagType (parentCode, tagCode, tagType, ttAscii, ttByte); 2092 2093 ParseStringTag (stream, 2094 parentCode, 2095 tagCode, 2096 tagCount, 2097 fPreviewInfo.fApplicationVersion, 2098 false); 2099 2100 #if qDNGValidate 2101 2102 if (gVerbose) 2103 { 2104 2105 printf ("PreviewApplicationVersion: "); 2106 2107 DumpString (fPreviewInfo.fApplicationVersion); 2108 2109 printf ("\n"); 2110 2111 } 2112 2113 #endif 2114 2115 break; 2116 2117 } 2118 2119 case tcPreviewSettingsName: 2120 { 2121 2122 CheckTagType (parentCode, tagCode, tagType, ttAscii, ttByte); 2123 2124 ParseStringTag (stream, 2125 parentCode, 2126 tagCode, 2127 tagCount, 2128 fPreviewInfo.fSettingsName, 2129 false); 2130 2131 #if qDNGValidate 2132 2133 if (gVerbose) 2134 { 2135 2136 printf ("PreviewSettingsName: "); 2137 2138 DumpString (fPreviewInfo.fSettingsName); 2139 2140 printf ("\n"); 2141 2142 } 2143 2144 #endif 2145 2146 break; 2147 2148 } 2149 2150 case tcPreviewSettingsDigest: 2151 { 2152 2153 if (!CheckTagType (parentCode, tagCode, tagType, ttByte)) 2154 return false; 2155 2156 if (!CheckTagCount (parentCode, tagCode, tagCount, 16)) 2157 return false; 2158 2159 stream.Get (fPreviewInfo.fSettingsDigest.data, 16); 2160 2161 #if qDNGValidate 2162 2163 if (gVerbose) 2164 { 2165 2166 printf ("PreviewSettingsDigest: "); 2167 2168 DumpFingerprint (fPreviewInfo.fSettingsDigest); 2169 2170 printf ("\n"); 2171 2172 } 2173 2174 #endif 2175 2176 break; 2177 2178 } 2179 2180 case tcPreviewColorSpace: 2181 { 2182 2183 CheckTagType (parentCode, tagCode, tagType, ttLong); 2184 2185 CheckTagCount (parentCode, tagCode, tagCount, 1); 2186 2187 fPreviewInfo.fColorSpace = (PreviewColorSpaceEnum) 2188 stream.TagValue_uint32 (tagType); 2189 2190 #if qDNGValidate 2191 2192 if (gVerbose) 2193 { 2194 2195 printf ("PreviewColorSpace: %s\n", 2196 LookupPreviewColorSpace ((uint32) fPreviewInfo.fColorSpace)); 2197 2198 } 2199 2200 #endif 2201 2202 break; 2203 2204 } 2205 2206 case tcPreviewDateTime: 2207 { 2208 2209 CheckTagType (parentCode, tagCode, tagType, ttAscii); 2210 2211 ParseStringTag (stream, 2212 parentCode, 2213 tagCode, 2214 tagCount, 2215 fPreviewInfo.fDateTime, 2216 false); 2217 2218 #if qDNGValidate 2219 2220 if (gVerbose) 2221 { 2222 2223 printf ("PreviewDateTime: "); 2224 2225 DumpString (fPreviewInfo.fDateTime); 2226 2227 printf ("\n"); 2228 2229 } 2230 2231 #endif 2232 2233 break; 2234 2235 } 2236 2237 case tcRowInterleaveFactor: 2238 { 2239 2240 CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong); 2241 2242 if (!CheckTagCount (parentCode, tagCode, tagCount, 1)) 2243 return false; 2244 2245 fRowInterleaveFactor = stream.TagValue_uint32 (tagType); 2246 2247 #if qDNGValidate 2248 2249 if (gVerbose) 2250 { 2251 2252 printf ("RowInterleaveFactor: %u\n", 2253 (unsigned) fRowInterleaveFactor); 2254 2255 } 2256 2257 #endif 2258 2259 break; 2260 2261 } 2262 2263 case tcSubTileBlockSize: 2264 { 2265 2266 CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong); 2267 2268 if (!CheckTagCount (parentCode, tagCode, tagCount, 2)) 2269 return false; 2270 2271 fSubTileBlockRows = stream.TagValue_uint32 (tagType); 2272 fSubTileBlockCols = stream.TagValue_uint32 (tagType); 2273 2274 #if qDNGValidate 2275 2276 if (gVerbose) 2277 { 2278 2279 printf ("SubTileBlockSize: rows = %u, cols = %u\n", 2280 (unsigned) fSubTileBlockRows, 2281 (unsigned) fSubTileBlockCols); 2282 2283 } 2284 2285 #endif 2286 2287 break; 2288 2289 } 2290 2291 case tcOpcodeList1: 2292 { 2293 2294 CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation); 2295 2296 CheckTagType (parentCode, tagCode, tagType, ttUndefined); 2297 2298 fOpcodeList1Count = tagCount; 2299 fOpcodeList1Offset = tagOffset; 2300 2301 #if qDNGValidate 2302 2303 if (gVerbose) 2304 { 2305 2306 printf ("OpcodeList1: count = %u, offset = %u\n", 2307 (unsigned) fOpcodeList1Count, 2308 (unsigned) fOpcodeList1Offset); 2309 2310 } 2311 2312 #endif 2313 2314 break; 2315 2316 } 2317 2318 case tcOpcodeList2: 2319 { 2320 2321 CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation); 2322 2323 CheckTagType (parentCode, tagCode, tagType, ttUndefined); 2324 2325 fOpcodeList2Count = tagCount; 2326 fOpcodeList2Offset = tagOffset; 2327 2328 #if qDNGValidate 2329 2330 if (gVerbose) 2331 { 2332 2333 printf ("OpcodeList2: count = %u, offset = %u\n", 2334 (unsigned) fOpcodeList2Count, 2335 (unsigned) fOpcodeList2Offset); 2336 2337 } 2338 2339 #endif 2340 2341 break; 2342 2343 } 2344 2345 case tcOpcodeList3: 2346 { 2347 2348 CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation); 2349 2350 CheckTagType (parentCode, tagCode, tagType, ttUndefined); 2351 2352 fOpcodeList3Count = tagCount; 2353 fOpcodeList3Offset = tagOffset; 2354 2355 #if qDNGValidate 2356 2357 if (gVerbose) 2358 { 2359 2360 printf ("OpcodeList3: count = %u, offset = %u\n", 2361 (unsigned) fOpcodeList3Count, 2362 (unsigned) fOpcodeList3Offset); 2363 2364 } 2365 2366 #endif 2367 2368 break; 2369 2370 } 2371 2372 case tcRawToPreviewGain: 2373 { 2374 2375 #if qDNGValidate 2376 2377 if (fNewSubFileType != sfPreviewImage) 2378 { 2379 2380 char message [256]; 2381 2382 sprintf (message, 2383 "%s %s is not allowed IFDs with NewSubFileType != PreviewImage", 2384 LookupParentCode (parentCode), 2385 LookupTagCode (parentCode, tagCode)); 2386 2387 ReportWarning (message); 2388 2389 } 2390 2391 #endif 2392 2393 CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation); 2394 2395 CheckTagType (parentCode, tagCode, tagType, ttDouble); 2396 2397 if (!CheckTagCount (parentCode, tagCode, tagCount, 1)) 2398 return false; 2399 2400 fPreviewInfo.fRawToPreviewGain = stream.TagValue_real64 (tagType); 2401 2402 #if qDNGValidate 2403 2404 if (gVerbose) 2405 { 2406 2407 printf ("RawToPreviewGain = %f\n", 2408 fPreviewInfo.fRawToPreviewGain); 2409 2410 } 2411 2412 #endif 2413 2414 break; 2415 2416 } 2417 2418 case tcNoiseProfile: 2419 { 2420 2421 if (!CheckTagType (parentCode, tagCode, tagType, ttDouble)) 2422 return false; 2423 2424 // This tag will be parsed even in non-raw IFDs (such as 2425 // thumbnails, previews, etc.) to support legacy DNGs that have 2426 // the tag in the wrong IFD, but we'll now issue a warning. 2427 // (Turn off the warning for IFD0 since we are writing it 2428 // there for backward compatiblity). 2429 2430 if (parentCode != 0) 2431 { 2432 2433 CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation); 2434 2435 } 2436 2437 // Must be an even, positive number of doubles in a noise profile. 2438 2439 if (!tagCount || (tagCount & 1)) 2440 return false; 2441 2442 // Determine number of planes (i.e., half the number of doubles). 2443 2444 const uint32 numPlanes = Pin_uint32 (0, 2445 tagCount >> 1, 2446 kMaxColorPlanes); 2447 2448 // Parse the noise function parameters. 2449 2450 dng_std_vector<dng_noise_function> noiseFunctions; 2451 2452 for (uint32 i = 0; i < numPlanes; i++) 2453 { 2454 2455 const real64 scale = stream.TagValue_real64 (tagType); 2456 const real64 offset = stream.TagValue_real64 (tagType); 2457 2458 noiseFunctions.push_back (dng_noise_function (scale, offset)); 2459 2460 } 2461 2462 // Store the noise profile. 2463 2464 fNoiseProfile = dng_noise_profile (noiseFunctions); 2465 2466 // Debug. 2467 2468 #if qDNGValidate 2469 2470 if (gVerbose) 2471 { 2472 2473 printf ("NoiseProfile:\n"); 2474 2475 printf (" Planes: %u\n", (unsigned) numPlanes); 2476 2477 for (uint32 plane = 0; plane < numPlanes; plane++) 2478 { 2479 2480 printf (" Noise function for plane %u: scale = %.20lf, offset = %.20lf\n", 2481 (unsigned) plane, 2482 noiseFunctions [plane].Scale (), 2483 noiseFunctions [plane].Offset ()); 2484 2485 } 2486 2487 } 2488 2489 #endif 2490 2491 break; 2492 2493 } 2494 2495 case tcCacheVersion: 2496 { 2497 2498 #if qDNGValidate 2499 2500 if (fNewSubFileType != sfPreviewImage) 2501 { 2502 2503 char message [256]; 2504 2505 sprintf (message, 2506 "%s %s is not allowed IFDs with NewSubFileType != PreviewImage", 2507 LookupParentCode (parentCode), 2508 LookupTagCode (parentCode, tagCode)); 2509 2510 ReportWarning (message); 2511 2512 } 2513 2514 #endif 2515 2516 CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation); 2517 2518 CheckTagType (parentCode, tagCode, tagType, ttLong); 2519 2520 if (!CheckTagCount (parentCode, tagCode, tagCount, 1)) 2521 return false; 2522 2523 fPreviewInfo.fCacheVersion = stream.TagValue_uint32 (tagType); 2524 2525 #if qDNGValidate 2526 2527 if (gVerbose) 2528 { 2529 2530 printf ("CacheVersion = 0x%x\n", 2531 (unsigned) fPreviewInfo.fCacheVersion); 2532 2533 } 2534 2535 #endif 2536 2537 break; 2538 2539 } 2540 2541 case tcEnhanceParams: 2542 { 2543 2544 #if qDNGValidate 2545 2546 if (fNewSubFileType != sfEnhancedImage) 2547 { 2548 2549 char message [256]; 2550 2551 sprintf (message, 2552 "%s %s is not allowed IFDs with NewSubFileType != EnhancedImage", 2553 LookupParentCode (parentCode), 2554 LookupTagCode (parentCode, tagCode)); 2555 2556 ReportWarning (message); 2557 2558 } 2559 2560 #endif 2561 2562 CheckTagType (parentCode, tagCode, tagType, ttAscii, ttByte); 2563 2564 ParseStringTag (stream, 2565 parentCode, 2566 tagCode, 2567 tagCount, 2568 fEnhanceParams, 2569 false); 2570 2571 #if qDNGValidate 2572 2573 if (gVerbose) 2574 { 2575 2576 printf ("EnhanceParams: "); 2577 2578 DumpString (fEnhanceParams); 2579 2580 printf ("\n"); 2581 2582 } 2583 2584 #endif 2585 2586 break; 2587 2588 } 2589 2590 case tcBaselineSharpness: 2591 { 2592 2593 if (fNewSubFileType != sfEnhancedImage) 2594 { 2595 return false; 2596 } 2597 2598 CheckTagType (parentCode, tagCode, tagType, ttRational); 2599 2600 CheckTagCount (parentCode, tagCode, tagCount, 1); 2601 2602 fBaselineSharpness = stream.TagValue_urational (tagType); 2603 2604 #if qDNGValidate 2605 2606 if (gVerbose) 2607 { 2608 2609 printf ("BaselineSharpness (EnhancedImage): %0.2f\n", 2610 fBaselineSharpness.As_real64 ()); 2611 2612 } 2613 2614 #endif 2615 2616 break; 2617 2618 } 2619 2620 case tcNoiseReductionApplied: 2621 { 2622 2623 if (!CheckTagType (parentCode, tagCode, tagType, ttRational)) 2624 return false; 2625 2626 if (!CheckTagCount (parentCode, tagCode, tagCount, 1)) 2627 return false; 2628 2629 // This tag will be parsed even in non-raw IFDs (such as 2630 // thumbnails, previews, etc.) to support legacy DNGs that have 2631 // the tag in the wrong IFD, but we'll now issue a warning. 2632 // (Turn off the warning for IFD0 since we are writing it 2633 // there for backward compatiblity). 2634 2635 if (parentCode != 0) 2636 { 2637 2638 CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation); 2639 2640 } 2641 2642 fNoiseReductionApplied = stream.TagValue_urational (tagType); 2643 2644 #if qDNGValidate 2645 2646 if (gVerbose) 2647 { 2648 2649 printf ("NoiseReductionApplied: %u/%u\n", 2650 (unsigned) fNoiseReductionApplied.n, 2651 (unsigned) fNoiseReductionApplied.d); 2652 2653 } 2654 2655 #endif 2656 2657 break; 2658 2659 } 2660 2661 default: 2662 { 2663 2664 return false; 2665 2666 } 2667 2668 } 2669 2670 return true; 2671 2672 } 2673 2674 /*****************************************************************************/ 2675 2676 void dng_ifd::PostParse () 2677 { 2678 2679 uint32 j; 2680 uint32 k; 2681 2682 // There is only one PlanarConfiguration for single sample imaages. 2683 2684 if (fSamplesPerPixel == 1) 2685 { 2686 fPlanarConfiguration = pcInterleaved; 2687 } 2688 2689 // Default tile size. 2690 2691 if (fTileWidth == 0) 2692 { 2693 fTileWidth = fImageWidth; 2694 } 2695 2696 if (fTileLength == 0) 2697 { 2698 fTileLength = fImageLength; 2699 } 2700 2701 // Default ActiveArea. 2702 2703 dng_rect imageArea (0, 0, fImageLength, fImageWidth); 2704 2705 if (fActiveArea.IsZero ()) 2706 { 2707 fActiveArea = imageArea; 2708 } 2709 2710 // Default crop size. 2711 2712 if (fDefaultCropSizeH.d == 0) 2713 { 2714 fDefaultCropSizeH = dng_urational (fActiveArea.W (), 1); 2715 } 2716 2717 if (fDefaultCropSizeV.d == 0) 2718 { 2719 fDefaultCropSizeV = dng_urational (fActiveArea.H (), 1); 2720 } 2721 2722 // Default white level. 2723 2724 uint32 defaultWhite = (fSampleFormat [0] == sfFloatingPoint) ? 2725 1 : 2726 (uint32) ((((uint64) 1) << fBitsPerSample [0]) - 1); 2727 2728 for (j = 0; j < kMaxSamplesPerPixel; j++) 2729 { 2730 2731 if (fWhiteLevel [j] < 0.0) 2732 { 2733 fWhiteLevel [j] = (real64) defaultWhite; 2734 } 2735 2736 } 2737 2738 // Check AntiAliasStrength. 2739 2740 if (fAntiAliasStrength.As_real64 () < 0.0 || 2741 fAntiAliasStrength.As_real64 () > 1.0) 2742 { 2743 2744 #if qDNGValidate 2745 2746 ReportWarning ("Invalid AntiAliasStrength"); 2747 2748 #endif 2749 2750 fAntiAliasStrength = dng_urational (1, 1); 2751 2752 } 2753 2754 // Check MaskedAreas. 2755 2756 for (j = 0; j < fMaskedAreaCount; j++) 2757 { 2758 2759 const dng_rect &r = fMaskedArea [j]; 2760 2761 if (r.IsEmpty () || ((r & imageArea) != r)) 2762 { 2763 2764 #if qDNGValidate 2765 2766 ReportWarning ("Invalid MaskedArea"); 2767 2768 #endif 2769 2770 fMaskedAreaCount = 0; 2771 2772 break; 2773 2774 } 2775 2776 if ((r & fActiveArea).NotEmpty ()) 2777 { 2778 2779 #if qDNGValidate 2780 2781 ReportWarning ("MaskedArea overlaps ActiveArea"); 2782 2783 #endif 2784 2785 fMaskedAreaCount = 0; 2786 2787 break; 2788 2789 } 2790 2791 for (k = 0; k < j; k++) 2792 { 2793 2794 if ((r & fMaskedArea [k]).NotEmpty ()) 2795 { 2796 2797 #if qDNGValidate 2798 2799 ReportWarning ("MaskedAreas overlap each other"); 2800 2801 #endif 2802 2803 fMaskedAreaCount = 0; 2804 2805 break; 2806 2807 } 2808 2809 } 2810 2811 } 2812 2813 // Check NoiseProfile. 2814 2815 if (!fNoiseProfile.IsValid () && fNoiseProfile.NumFunctions () != 0) 2816 { 2817 2818 #if qDNGValidate 2819 2820 ReportWarning ("Invalid NoiseProfile"); 2821 2822 #endif 2823 2824 fNoiseProfile = dng_noise_profile (); 2825 2826 } 2827 2828 } 2829 2830 /*****************************************************************************/ 2831 2832 bool dng_ifd::IsValidCFA (dng_shared &shared, 2833 uint32 parentCode) 2834 { 2835 2836 uint32 j; 2837 uint32 k; 2838 uint32 n; 2839 2840 #if !qDNGValidate 2841 2842 (void) parentCode; // Unused 2843 2844 #endif 2845 2846 if (fCFARepeatPatternRows < 1 || fCFARepeatPatternRows > kMaxCFAPattern || 2847 fCFARepeatPatternCols < 1 || fCFARepeatPatternCols > kMaxCFAPattern) 2848 { 2849 2850 #if qDNGValidate 2851 2852 ReportError ("Missing or invalid CFAPatternRepeatDim", 2853 LookupParentCode (parentCode)); 2854 2855 #endif 2856 2857 return false; 2858 2859 } 2860 2861 uint32 count [kMaxColorPlanes]; 2862 2863 for (n = 0; n < shared.fCameraProfile.fColorPlanes; n++) 2864 { 2865 count [n] = 0; 2866 } 2867 2868 for (j = 0; j < fCFARepeatPatternRows; j++) 2869 { 2870 2871 for (k = 0; k < fCFARepeatPatternCols; k++) 2872 { 2873 2874 bool found = false; 2875 2876 for (n = 0; n < shared.fCameraProfile.fColorPlanes; n++) 2877 { 2878 2879 if (fCFAPattern [j] [k] == fCFAPlaneColor [n]) 2880 { 2881 found = true; 2882 count [n] ++; 2883 break; 2884 } 2885 2886 } 2887 2888 if (!found) 2889 { 2890 2891 #if qDNGValidate 2892 2893 ReportError ("CFAPattern contains colors not included in the CFAPlaneColor tag", 2894 LookupParentCode (parentCode)); 2895 2896 #endif 2897 2898 return false; 2899 2900 } 2901 2902 } 2903 2904 } 2905 2906 for (n = 0; n < shared.fCameraProfile.fColorPlanes; n++) 2907 { 2908 2909 if (count [n] == 0) 2910 { 2911 2912 #if qDNGValidate 2913 2914 ReportError ("CFAPattern does not contain all the colors in the CFAPlaneColor tag", 2915 LookupParentCode (parentCode)); 2916 2917 #endif 2918 2919 return false; 2920 2921 } 2922 2923 } 2924 2925 if (fCFALayout < 1 || fCFALayout > 9) 2926 { 2927 2928 #if qDNGValidate 2929 2930 ReportError ("Invalid CFALayout", 2931 LookupParentCode (parentCode)); 2932 2933 #endif 2934 2935 return false; 2936 2937 } 2938 2939 return true; 2940 2941 } 2942 2943 /*****************************************************************************/ 2944 2945 bool dng_ifd::IsValidDNG (dng_shared &shared, 2946 uint32 parentCode) 2947 { 2948 2949 uint32 j; 2950 2951 bool isFloatingPoint = (fSampleFormat [0] == sfFloatingPoint); 2952 2953 dng_rect imageArea (0, 0, fImageLength, fImageWidth); 2954 2955 uint32 defaultWhite = isFloatingPoint ? 2956 1 : 2957 (uint32) ((((uint64) 1) << fBitsPerSample [0]) - 1); 2958 2959 bool isMonochrome = (shared.fCameraProfile.fColorPlanes == 1); 2960 bool isColor = !isMonochrome; 2961 2962 bool isMainIFD = (fNewSubFileType == sfMainImage); 2963 2964 // Check NewSubFileType. 2965 2966 if (!fUsesNewSubFileType) 2967 { 2968 2969 #if qDNGValidate 2970 2971 ReportError ("Missing NewSubFileType", 2972 LookupParentCode (parentCode)); 2973 2974 #endif 2975 2976 return false; 2977 2978 } 2979 2980 if (fNewSubFileType != sfMainImage && 2981 fNewSubFileType != sfPreviewImage && 2982 fNewSubFileType != sfTransparencyMask && 2983 fNewSubFileType != sfPreviewMask && 2984 fNewSubFileType != sfDepthMap && 2985 fNewSubFileType != sfPreviewDepthMap && 2986 fNewSubFileType != sfEnhancedImage && 2987 fNewSubFileType != sfAltPreviewImage) 2988 { 2989 2990 #if qDNGValidate 2991 2992 ReportError ("Unexpected NewSubFileType", 2993 LookupParentCode (parentCode)); 2994 2995 #endif 2996 2997 return false; 2998 2999 } 3000 3001 // Check ImageWidth and ImageLength. 3002 3003 if (fImageWidth < 1) 3004 { 3005 3006 #if qDNGValidate 3007 3008 ReportError ("Missing or invalid ImageWidth", 3009 LookupParentCode (parentCode)); 3010 3011 #endif 3012 3013 return false; 3014 3015 } 3016 3017 if (fImageLength < 1) 3018 { 3019 3020 #if qDNGValidate 3021 3022 ReportError ("Missing or invalid ImageLength", 3023 LookupParentCode (parentCode)); 3024 3025 #endif 3026 3027 return false; 3028 3029 } 3030 3031 if (fImageWidth > kMaxImageSide || 3032 fImageLength > kMaxImageSide) 3033 { 3034 3035 #if qDNGValidate 3036 3037 ReportWarning ("Image size is larger than supported"); 3038 3039 #endif 3040 3041 return false; 3042 3043 } 3044 3045 // Check PhotometricInterpretation. 3046 3047 if (fNewSubFileType == sfTransparencyMask || 3048 fNewSubFileType == sfPreviewMask) 3049 { 3050 3051 if (fPhotometricInterpretation != piTransparencyMask) 3052 { 3053 3054 #if qDNGValidate 3055 3056 ReportError ("NewSubFileType requires PhotometricInterpretation = TransparencyMask", 3057 LookupParentCode (parentCode)); 3058 3059 #endif 3060 3061 return false; 3062 3063 } 3064 3065 } 3066 3067 else if (fNewSubFileType == sfDepthMap || 3068 fNewSubFileType == sfPreviewDepthMap) 3069 { 3070 3071 if (fPhotometricInterpretation != piDepth) 3072 { 3073 3074 #if qDNGValidate 3075 3076 ReportError ("NewSubFileType requires PhotometricInterpretation = Depth", 3077 LookupParentCode (parentCode)); 3078 3079 #endif 3080 3081 return false; 3082 3083 } 3084 3085 } 3086 3087 else 3088 { 3089 3090 switch (fPhotometricInterpretation) 3091 { 3092 3093 case piBlackIsZero: 3094 case piRGB: 3095 case piYCbCr: 3096 { 3097 3098 if (isMainIFD) 3099 { 3100 3101 #if qDNGValidate 3102 3103 ReportError ("PhotometricInterpretation requires NewSubFileType = 1", 3104 LookupParentCode (parentCode)); 3105 3106 #endif 3107 3108 return false; 3109 3110 } 3111 3112 break; 3113 3114 } 3115 3116 case piCFA: 3117 { 3118 3119 if (!isMainIFD) 3120 { 3121 3122 #if qDNGValidate 3123 3124 ReportError ("PhotometricInterpretation requires NewSubFileType = 0", 3125 LookupParentCode (parentCode)); 3126 3127 #endif 3128 3129 return false; 3130 3131 } 3132 3133 break; 3134 3135 } 3136 3137 case piLinearRaw: 3138 break; 3139 3140 default: 3141 { 3142 3143 #if qDNGValidate 3144 3145 ReportError ("Missing or invalid PhotometricInterpretation", 3146 LookupParentCode (parentCode)); 3147 3148 #endif 3149 3150 return false; 3151 3152 } 3153 3154 } 3155 3156 } 3157 3158 switch (fPhotometricInterpretation) 3159 { 3160 3161 case piBlackIsZero: 3162 { 3163 3164 // Allow black in white previews even in color images since the 3165 // raw processing software may be converting to grayscale. 3166 3167 if (isColor && isMainIFD) 3168 { 3169 3170 #if qDNGValidate 3171 3172 ReportError ("PhotometricInterpretation forbids use of ColorMatrix1 tag", 3173 LookupParentCode (parentCode)); 3174 3175 #endif 3176 3177 return false; 3178 3179 } 3180 3181 break; 3182 3183 } 3184 3185 case piRGB: 3186 case piYCbCr: 3187 { 3188 3189 // Allow color previews even in monochrome DNG files, since the 3190 // raw procesing software may be adding color effects. 3191 3192 break; 3193 3194 } 3195 3196 case piCFA: 3197 { 3198 3199 if (isMonochrome) 3200 { 3201 3202 #if qDNGValidate 3203 3204 ReportError ("PhotometricInterpretation requires use of ColorMatrix1 tag", 3205 LookupParentCode (parentCode)); 3206 3207 #endif 3208 3209 return false; 3210 3211 } 3212 3213 break; 3214 3215 } 3216 3217 } 3218 3219 if (isFloatingPoint) 3220 { 3221 3222 if (fPhotometricInterpretation != piCFA && 3223 fPhotometricInterpretation != piLinearRaw && 3224 fPhotometricInterpretation != piTransparencyMask) 3225 { 3226 3227 #if qDNGValidate 3228 3229 ReportError ("Floating point data requires PhotometricInterpretation CFA or LinearRaw or TransparencyMask", 3230 LookupParentCode (parentCode)); 3231 3232 #endif 3233 3234 return false; 3235 3236 } 3237 3238 } 3239 3240 // Check SamplesPerPixel and BitsPerSample. 3241 3242 uint32 minSamplesPerPixel = 1; 3243 uint32 maxSamplesPerPixel = 1; 3244 3245 uint32 minBitsPerSample = 8; 3246 uint32 maxBitsPerSample = 16; 3247 3248 switch (fPhotometricInterpretation) 3249 { 3250 3251 case piBlackIsZero: 3252 break; 3253 3254 case piRGB: 3255 case piYCbCr: 3256 { 3257 minSamplesPerPixel = 3; 3258 maxSamplesPerPixel = 3; 3259 break; 3260 } 3261 3262 case piCFA: 3263 { 3264 maxSamplesPerPixel = kMaxSamplesPerPixel; 3265 maxBitsPerSample = 32; 3266 break; 3267 } 3268 3269 case piLinearRaw: 3270 { 3271 minSamplesPerPixel = shared.fCameraProfile.fColorPlanes; 3272 maxSamplesPerPixel = shared.fCameraProfile.fColorPlanes; 3273 maxBitsPerSample = 32; 3274 break; 3275 } 3276 3277 case piTransparencyMask: 3278 { 3279 minBitsPerSample = 8; 3280 maxBitsPerSample = 16; 3281 break; 3282 } 3283 3284 case piDepth: 3285 { 3286 minBitsPerSample = 8; 3287 maxBitsPerSample = 16; 3288 break; 3289 } 3290 3291 } 3292 3293 if (isFloatingPoint) 3294 { 3295 minBitsPerSample = 16; 3296 maxBitsPerSample = 32; 3297 } 3298 3299 if (fSamplesPerPixel < minSamplesPerPixel || 3300 fSamplesPerPixel > maxSamplesPerPixel) 3301 { 3302 3303 #if qDNGValidate 3304 3305 ReportError ("Missing or invalid SamplesPerPixel", 3306 LookupParentCode (parentCode)); 3307 3308 #endif 3309 3310 return false; 3311 3312 } 3313 3314 for (j = 0; j < kMaxSamplesPerPixel; j++) 3315 { 3316 3317 if (j < fSamplesPerPixel) 3318 { 3319 3320 if (fBitsPerSample [j] < minBitsPerSample || 3321 fBitsPerSample [j] > maxBitsPerSample) 3322 { 3323 3324 #if qDNGValidate 3325 3326 ReportError ("Missing or invalid BitsPerSample", 3327 LookupParentCode (parentCode)); 3328 3329 #endif 3330 3331 return false; 3332 3333 } 3334 3335 if (isFloatingPoint && 3336 fBitsPerSample [j] != 16 && 3337 fBitsPerSample [j] != 24 && 3338 fBitsPerSample [j] != 32) 3339 { 3340 3341 #if qDNGValidate 3342 3343 ReportError ("Invalid BitsPerSample for floating point", 3344 LookupParentCode (parentCode)); 3345 3346 #endif 3347 3348 return false; 3349 3350 } 3351 3352 if (minBitsPerSample == 8 && 3353 maxBitsPerSample == 16 && 3354 fBitsPerSample [j] != 8 && 3355 fBitsPerSample [j] != 16) 3356 { 3357 3358 #if qDNGValidate 3359 3360 ReportError ("Rendered previews and integer masks require 8 or 16 bits per sample", 3361 LookupParentCode (parentCode)); 3362 3363 #endif 3364 3365 return false; 3366 3367 } 3368 3369 if (j > 0 && fBitsPerSample [j] != fBitsPerSample [0]) 3370 { 3371 3372 #if qDNGValidate 3373 3374 ReportError ("BitsPerSample not equal for all samples", 3375 LookupParentCode (parentCode)); 3376 3377 #endif 3378 3379 return false; 3380 3381 } 3382 3383 } 3384 3385 else 3386 { 3387 3388 if (fBitsPerSample [j] != 0) 3389 { 3390 3391 #if qDNGValidate 3392 3393 ReportError ("Too many values specified in BitsPerSample", 3394 LookupParentCode (parentCode)); 3395 3396 #endif 3397 3398 return false; 3399 3400 } 3401 3402 } 3403 3404 } 3405 3406 // Check Compression. 3407 3408 switch (fCompression) 3409 { 3410 3411 case ccUncompressed: 3412 break; 3413 3414 #if qDNGSupportVC5 3415 3416 case ccVc5: 3417 break; 3418 3419 #endif // qDNGSupportVC5 3420 3421 case ccJPEG: 3422 { 3423 3424 if (fPhotometricInterpretation == piRGB) 3425 { 3426 3427 #if qDNGValidate 3428 3429 ReportError ("JPEG previews should use PhotometricInterpretation = YCbYb", 3430 LookupParentCode (parentCode)); 3431 3432 #endif 3433 3434 return false; 3435 3436 } 3437 3438 if (fBitsPerSample [0] > 16) 3439 { 3440 3441 #if qDNGValidate 3442 3443 ReportError ("JPEG compression is limited to 16 bits/sample", 3444 LookupParentCode (parentCode)); 3445 3446 #endif 3447 3448 return false; 3449 3450 } 3451 3452 break; 3453 3454 } 3455 3456 case ccLossyJPEG: 3457 { 3458 3459 if (fPhotometricInterpretation != piLinearRaw) 3460 { 3461 3462 #if qDNGValidate 3463 3464 ReportError ("Lossy JPEG compression code requires PhotometricInterpretation = LinearRaw", 3465 LookupParentCode (parentCode)); 3466 3467 #endif 3468 3469 return false; 3470 3471 } 3472 3473 if (fBitsPerSample [0] != 8) 3474 { 3475 3476 #if qDNGValidate 3477 3478 ReportError ("Lossy JPEG compression is limited to 8 bits/sample", 3479 LookupParentCode (parentCode)); 3480 3481 #endif 3482 3483 return false; 3484 3485 } 3486 3487 break; 3488 3489 } 3490 3491 case ccDeflate: 3492 { 3493 3494 if (!isFloatingPoint && 3495 fBitsPerSample [0] != 32 && 3496 fPhotometricInterpretation != piTransparencyMask && 3497 fPhotometricInterpretation != piDepth) 3498 { 3499 3500 #if qDNGValidate 3501 3502 ReportError ("ZIP compression is limited to floating point, 32-bit integer," 3503 " transparency masks, and depth maps", 3504 LookupParentCode (parentCode)); 3505 3506 #endif 3507 3508 } 3509 3510 break; 3511 3512 } 3513 3514 default: 3515 { 3516 3517 #if qDNGValidate 3518 3519 ReportError ("Unsupported Compression", 3520 LookupParentCode (parentCode)); 3521 3522 #endif 3523 3524 return false; 3525 3526 } 3527 3528 } 3529 3530 // Check Predictor. 3531 3532 if (isFloatingPoint && fCompression == ccDeflate && 3533 (fPredictor == cpFloatingPoint || 3534 fPredictor == cpFloatingPointX2 || 3535 fPredictor == cpFloatingPointX4)) 3536 { 3537 3538 // These combinations are supported. 3539 3540 } 3541 3542 else if (!isFloatingPoint && fCompression == ccDeflate && 3543 (fPredictor == cpHorizontalDifference || 3544 fPredictor == cpHorizontalDifferenceX2 || 3545 fPredictor == cpHorizontalDifferenceX4)) 3546 { 3547 3548 // These combinations are supported. 3549 3550 } 3551 3552 else if (fPredictor != cpNullPredictor) 3553 { 3554 3555 #if qDNGValidate 3556 3557 ReportError ("Unsupported Predictor", 3558 LookupParentCode (parentCode)); 3559 3560 #endif 3561 3562 return false; 3563 3564 } 3565 3566 // Check FillOrder. 3567 3568 if (fFillOrder != 1) 3569 { 3570 3571 #if qDNGValidate 3572 3573 ReportError ("Unsupported FillOrder", 3574 LookupParentCode (parentCode)); 3575 3576 #endif 3577 3578 return false; 3579 3580 } 3581 3582 // Check PlanarConfiguration. 3583 3584 if (fPlanarConfiguration != pcInterleaved) 3585 { 3586 3587 #if qDNGValidate 3588 3589 ReportError ("Unsupported PlanarConfiguration", 3590 LookupParentCode (parentCode)); 3591 3592 #endif 3593 3594 return false; 3595 3596 } 3597 3598 // Check ExtraSamples. 3599 3600 if (fExtraSamplesCount != 0) 3601 { 3602 3603 #if qDNGValidate 3604 3605 ReportError ("Unsupported ExtraSamples", 3606 LookupParentCode (parentCode)); 3607 3608 #endif 3609 3610 return false; 3611 3612 } 3613 3614 // Check SampleFormat. 3615 3616 for (j = 0; j < fSamplesPerPixel; j++) 3617 { 3618 3619 if (fSampleFormat [j] != (isFloatingPoint ? sfFloatingPoint : sfUnsignedInteger)) 3620 { 3621 3622 #if qDNGValidate 3623 3624 ReportError ("Unsupported SampleFormat", 3625 LookupParentCode (parentCode)); 3626 3627 #endif 3628 3629 return false; 3630 3631 } 3632 3633 } 3634 3635 // Check Orientation. 3636 3637 if (fOrientation > 9) 3638 { 3639 3640 #if qDNGValidate 3641 3642 ReportError ("Unknown Orientation", 3643 LookupParentCode (parentCode)); 3644 3645 #endif 3646 3647 return false; 3648 3649 } 3650 3651 #if qDNGValidate 3652 3653 if (fOrientation != 0 && parentCode != 0) 3654 { 3655 3656 ReportWarning ("Unexpected Orientation tag", 3657 LookupParentCode (parentCode)); 3658 3659 } 3660 3661 if (fOrientation == 0 && parentCode == 0) 3662 { 3663 3664 ReportWarning ("Missing Orientation tag", 3665 LookupParentCode (parentCode)); 3666 3667 } 3668 3669 #endif 3670 3671 // Check Strips vs. Tiles. 3672 3673 if (!fUsesStrips && !fUsesTiles) 3674 { 3675 3676 #if qDNGValidate 3677 3678 ReportError ("IFD uses neither strips nor tiles", 3679 LookupParentCode (parentCode)); 3680 3681 #endif 3682 3683 return false; 3684 3685 } 3686 3687 if (fUsesStrips && fUsesTiles) 3688 { 3689 3690 #if qDNGValidate 3691 3692 ReportError ("IFD uses both strips and tiles", 3693 LookupParentCode (parentCode)); 3694 3695 #endif 3696 3697 return false; 3698 3699 } 3700 3701 // Check tile info. 3702 3703 uint32 tilesWide = (fImageWidth + fTileWidth - 1) / fTileWidth; 3704 uint32 tilesHigh = (fImageLength + fTileLength - 1) / fTileLength; 3705 3706 uint32 tileCount = tilesWide * tilesHigh; 3707 3708 if (fTileOffsetsCount != tileCount) 3709 { 3710 3711 #if qDNGValidate 3712 3713 ReportError ("Missing or invalid Strip/TileOffsets", 3714 LookupParentCode (parentCode)); 3715 3716 #endif 3717 3718 return false; 3719 3720 } 3721 3722 if (fTileByteCountsCount != tileCount) 3723 { 3724 3725 #if qDNGValidate 3726 3727 ReportError ("Missing or invalid Strip/TileByteCounts", 3728 LookupParentCode (parentCode)); 3729 3730 #endif 3731 3732 return false; 3733 3734 } 3735 3736 // Check CFA pattern. 3737 3738 if (fPhotometricInterpretation == piCFA) 3739 { 3740 3741 if (!IsValidCFA (shared, parentCode)) 3742 { 3743 3744 return false; 3745 3746 } 3747 3748 } 3749 3750 // Check ActiveArea. 3751 3752 if (((fActiveArea & imageArea) != fActiveArea) || fActiveArea.IsEmpty ()) 3753 { 3754 3755 #if qDNGValidate 3756 3757 ReportError ("Invalid ActiveArea", 3758 LookupParentCode (parentCode)); 3759 3760 #endif 3761 3762 return false; 3763 3764 } 3765 3766 if (fActiveArea != imageArea) 3767 { 3768 3769 if (shared.fDNGBackwardVersion < dngVersion_1_1_0_0) 3770 { 3771 3772 #if qDNGValidate 3773 3774 ReportError ("Non-default ActiveArea tag not allowed in this DNG version", 3775 LookupParentCode (parentCode)); 3776 3777 #endif 3778 3779 return false; 3780 3781 } 3782 3783 } 3784 3785 // Check LinearizationTable. 3786 3787 if (fLinearizationTableCount) 3788 { 3789 3790 if (fLinearizationTableType != ttShort) 3791 { 3792 3793 #if qDNGValidate 3794 3795 ReportError ("Invalidate LinearizationTable type", 3796 LookupParentCode (parentCode)); 3797 3798 #endif 3799 3800 return false; 3801 3802 } 3803 3804 if (fLinearizationTableCount < 2 || 3805 fLinearizationTableCount > 65536) 3806 { 3807 3808 #if qDNGValidate 3809 3810 ReportError ("Invalidate LinearizationTable count", 3811 LookupParentCode (parentCode)); 3812 3813 #endif 3814 3815 return false; 3816 3817 } 3818 3819 if (isFloatingPoint || fBitsPerSample [0] > 16) 3820 { 3821 3822 #if qDNGValidate 3823 3824 ReportError ("Linearization table not allowed for this data type", 3825 LookupParentCode (parentCode)); 3826 3827 #endif 3828 3829 return false; 3830 3831 } 3832 3833 } 3834 3835 // Check BlackLevelRepeatDim. 3836 3837 if (fBlackLevelRepeatRows < 1 || fBlackLevelRepeatRows > kMaxBlackPattern || 3838 fBlackLevelRepeatCols < 1 || fBlackLevelRepeatCols > kMaxBlackPattern) 3839 { 3840 3841 #if qDNGValidate 3842 3843 ReportError ("Invalid BlackLevelRepeatDim", 3844 LookupParentCode (parentCode)); 3845 3846 #endif 3847 3848 return false; 3849 3850 } 3851 3852 // Check BlackLevelDeltaH. 3853 3854 if (fBlackLevelDeltaHCount != 0 && 3855 fBlackLevelDeltaHCount != fActiveArea.W ()) 3856 { 3857 3858 #if qDNGValidate 3859 3860 ReportError ("Invalid BlackLevelDeltaH count", 3861 LookupParentCode (parentCode)); 3862 3863 #endif 3864 3865 return false; 3866 3867 } 3868 3869 // Check BlackLevelDeltaV. 3870 3871 if (fBlackLevelDeltaVCount != 0 && 3872 fBlackLevelDeltaVCount != fActiveArea.H ()) 3873 { 3874 3875 #if qDNGValidate 3876 3877 ReportError ("Invalid BlackLevelDeltaV count", 3878 LookupParentCode (parentCode)); 3879 3880 #endif 3881 3882 return false; 3883 3884 } 3885 3886 // Check WhiteLevel. 3887 3888 real64 maxWhite = fLinearizationTableCount ? 65535.0 3889 : (real64) defaultWhite; 3890 3891 for (j = 0; j < fSamplesPerPixel; j++) 3892 { 3893 3894 if (fWhiteLevel [j] < 1.0 || (fWhiteLevel [j] > maxWhite && !isFloatingPoint)) 3895 { 3896 3897 #if qDNGValidate 3898 3899 ReportError ("Invalid WhiteLevel", 3900 LookupParentCode (parentCode)); 3901 3902 #endif 3903 3904 return false; 3905 3906 } 3907 3908 } 3909 3910 // Check BlackLevel. 3911 3912 for (j = 0; j < kMaxBlackPattern; j++) 3913 { 3914 3915 for (uint32 k = 0; k < kMaxBlackPattern; k++) 3916 { 3917 3918 for (uint32 s = 0; s < kMaxSamplesPerPixel; s++) 3919 { 3920 3921 const real64 black = fBlackLevel [j][k][s]; 3922 3923 if (black >= fWhiteLevel [s]) 3924 { 3925 3926 #if qDNGValidate 3927 3928 ReportError ("Invalid BlackLevel", 3929 LookupParentCode (parentCode)); 3930 3931 #endif 3932 3933 return false; 3934 3935 } 3936 3937 } 3938 3939 } 3940 3941 } 3942 3943 // Check DefaultScale. 3944 3945 if (fDefaultScaleH.As_real64 () <= 0.0 || 3946 fDefaultScaleV.As_real64 () <= 0.0) 3947 { 3948 3949 #if qDNGValidate 3950 3951 ReportError ("Invalid DefaultScale"); 3952 3953 #endif 3954 3955 return false; 3956 3957 } 3958 3959 // Check BestQualityScale. 3960 3961 if (fBestQualityScale.As_real64 () < 1.0) 3962 { 3963 3964 #if qDNGValidate 3965 3966 ReportError ("Invalid BestQualityScale"); 3967 3968 #endif 3969 3970 return false; 3971 3972 } 3973 3974 // Check DefaultCropOrigin. 3975 3976 if (fDefaultCropOriginH.As_real64 () < 0.0 || 3977 fDefaultCropOriginV.As_real64 () < 0.0 || 3978 fDefaultCropOriginH.As_real64 () >= (real64) fActiveArea.W () || 3979 fDefaultCropOriginV.As_real64 () >= (real64) fActiveArea.H ()) 3980 { 3981 3982 #if qDNGValidate 3983 3984 ReportError ("Invalid DefaultCropOrigin"); 3985 3986 #endif 3987 3988 return false; 3989 3990 } 3991 3992 // Check DefaultCropSize. 3993 3994 if (fDefaultCropSizeH.As_real64 () <= 0.0 || 3995 fDefaultCropSizeV.As_real64 () <= 0.0 || 3996 fDefaultCropSizeH.As_real64 () > (real64) fActiveArea.W () || 3997 fDefaultCropSizeV.As_real64 () > (real64) fActiveArea.H ()) 3998 { 3999 4000 #if qDNGValidate 4001 4002 ReportError ("Invalid DefaultCropSize"); 4003 4004 #endif 4005 4006 return false; 4007 4008 } 4009 4010 // Check DefaultCrop area. 4011 4012 if (fDefaultCropOriginH.As_real64 () + 4013 fDefaultCropSizeH .As_real64 () > (real64) fActiveArea.W () || 4014 fDefaultCropOriginV.As_real64 () + 4015 fDefaultCropSizeV .As_real64 () > (real64) fActiveArea.H ()) 4016 { 4017 4018 #if qDNGValidate 4019 4020 ReportError ("Default crop extends outside ActiveArea"); 4021 4022 #endif 4023 4024 return false; 4025 4026 } 4027 4028 // Check DefaultUserCrop. 4029 4030 if (fDefaultUserCropT.As_real64 () < 0.0 || 4031 fDefaultUserCropL.As_real64 () < 0.0 || 4032 fDefaultUserCropB.As_real64 () > 1.0 || 4033 fDefaultUserCropR.As_real64 () > 1.0 || 4034 fDefaultUserCropT.As_real64 () >= fDefaultUserCropB.As_real64 () || 4035 fDefaultUserCropL.As_real64 () >= fDefaultUserCropR.As_real64 ()) 4036 { 4037 4038 #if qDNGValidate 4039 4040 ReportError ("Invalid DefaultUserCrop"); 4041 4042 #endif // qDNGValidate 4043 4044 return false; 4045 4046 } 4047 4048 // The default crop and default user crop tags are not allowed for the 4049 // non-main image. If they are there, at least require that they be NOPs. 4050 4051 if (!isMainIFD) 4052 { 4053 4054 if (Round_int32 (fDefaultCropOriginH.As_real64 ()) != 0 || 4055 Round_int32 (fDefaultCropOriginV.As_real64 ()) != 0) 4056 { 4057 4058 #if qDNGValidate 4059 4060 ReportError ("non-default DefaultCropOrigin on non-main image"); 4061 4062 #endif 4063 4064 return false; 4065 4066 } 4067 4068 if (Round_int32 (fDefaultCropSizeH.As_real64 ()) != (int32) fImageWidth || 4069 Round_int32 (fDefaultCropSizeV.As_real64 ()) != (int32) fImageLength) 4070 { 4071 4072 #if qDNGValidate 4073 4074 ReportError ("non-default DefaultCropSize on non-main image"); 4075 4076 #endif 4077 4078 return false; 4079 4080 } 4081 4082 if (fDefaultUserCropT.As_real64 () != 0.0 || 4083 fDefaultUserCropL.As_real64 () != 0.0 || 4084 fDefaultUserCropB.As_real64 () != 1.0 || 4085 fDefaultUserCropR.As_real64 () != 1.0) 4086 { 4087 4088 #if qDNGValidate 4089 4090 ReportError ("non-default DefaultCUserCrop on non-main image"); 4091 4092 #endif // qDNGValidate 4093 4094 return false; 4095 4096 } 4097 4098 } 4099 4100 // Warning if too little padding on CFA image. 4101 4102 #if qDNGValidate 4103 4104 if (fPhotometricInterpretation == piCFA) 4105 { 4106 4107 const real64 kMinPad = 1.9; 4108 4109 if (fDefaultCropOriginH.As_real64 () < kMinPad) 4110 { 4111 4112 ReportWarning ("Too little padding on left edge of CFA image", 4113 "possible interpolation artifacts"); 4114 4115 } 4116 4117 if (fDefaultCropOriginV.As_real64 () < kMinPad) 4118 { 4119 4120 ReportWarning ("Too little padding on top edge of CFA image", 4121 "possible interpolation artifacts"); 4122 4123 } 4124 4125 if (fDefaultCropOriginH.As_real64 () + 4126 fDefaultCropSizeH .As_real64 () > (real64) fActiveArea.W () - kMinPad) 4127 { 4128 4129 ReportWarning ("Too little padding on right edge of CFA image", 4130 "possible interpolation artifacts"); 4131 4132 } 4133 4134 if (fDefaultCropOriginV.As_real64 () + 4135 fDefaultCropSizeV .As_real64 () > (real64) fActiveArea.H () - kMinPad) 4136 { 4137 4138 ReportWarning ("Too little padding on bottom edge of CFA image", 4139 "possible interpolation artifacts"); 4140 4141 } 4142 4143 } 4144 4145 #endif 4146 4147 // Check RowInterleaveFactor 4148 4149 if (fRowInterleaveFactor != 1) 4150 { 4151 4152 if (fRowInterleaveFactor < 1 || 4153 fRowInterleaveFactor > fImageLength) 4154 { 4155 4156 #if qDNGValidate 4157 4158 ReportError ("RowInterleaveFactor out of valid range", 4159 LookupParentCode (parentCode)); 4160 4161 #endif 4162 4163 return false; 4164 4165 } 4166 4167 if (shared.fDNGBackwardVersion < dngVersion_1_2_0_0) 4168 { 4169 4170 #if qDNGValidate 4171 4172 ReportError ("Non-default RowInterleaveFactor tag not allowed in this DNG version", 4173 LookupParentCode (parentCode)); 4174 4175 #endif 4176 4177 return false; 4178 4179 } 4180 4181 } 4182 4183 // Check SubTileBlockSize 4184 4185 if (fSubTileBlockRows != 1 || fSubTileBlockCols != 1) 4186 { 4187 4188 if (fSubTileBlockRows < 2 || fSubTileBlockRows > fTileLength || 4189 fSubTileBlockCols < 1 || fSubTileBlockCols > fTileWidth) 4190 { 4191 4192 #if qDNGValidate 4193 4194 ReportError ("SubTileBlockSize out of valid range", 4195 LookupParentCode (parentCode)); 4196 4197 #endif 4198 4199 return false; 4200 4201 } 4202 4203 if ((fTileLength % fSubTileBlockRows) != 0 || 4204 (fTileWidth % fSubTileBlockCols) != 0) 4205 { 4206 4207 #if qDNGValidate 4208 4209 ReportError ("TileSize not exact multiple of SubTileBlockSize", 4210 LookupParentCode (parentCode)); 4211 4212 #endif 4213 4214 return false; 4215 4216 } 4217 4218 if (shared.fDNGBackwardVersion < dngVersion_1_2_0_0) 4219 { 4220 4221 #if qDNGValidate 4222 4223 ReportError ("Non-default SubTileBlockSize tag not allowed in this DNG version", 4224 LookupParentCode (parentCode)); 4225 4226 #endif 4227 4228 return false; 4229 4230 } 4231 4232 } 4233 4234 return true; 4235 4236 } 4237 4238 /*****************************************************************************/ 4239 4240 uint32 dng_ifd::TilesAcross () const 4241 { 4242 4243 if (fTileWidth) 4244 { 4245 4246 uint64 width64 = (uint64) fTileWidth; 4247 4248 return (uint32) (((fImageWidth + width64) - 1) / width64); 4249 4250 } 4251 4252 return 0; 4253 4254 } 4255 4256 /*****************************************************************************/ 4257 4258 uint32 dng_ifd::TilesDown () const 4259 { 4260 4261 if (fTileLength) 4262 { 4263 4264 // Use 64-bit math to prevent overflow. RowsPerStrip (assigned to 4265 // fImageLength during parsing) may be 2^32 - 1, indicating a single 4266 // strip. 4267 4268 uint64 length64 = (uint64) fTileLength; 4269 4270 return (uint32) (((fImageLength + length64) - 1) / length64); 4271 4272 } 4273 4274 return 0; 4275 4276 } 4277 4278 /*****************************************************************************/ 4279 4280 uint32 dng_ifd::TilesPerImage () const 4281 { 4282 4283 uint32 total = TilesAcross () * TilesDown (); 4284 4285 if (fPlanarConfiguration == pcPlanar) 4286 { 4287 4288 total *= fSamplesPerPixel; 4289 4290 } 4291 4292 return total; 4293 4294 } 4295 4296 /*****************************************************************************/ 4297 4298 dng_rect dng_ifd::TileArea (uint32 rowIndex, 4299 uint32 colIndex) const 4300 { 4301 4302 dng_rect r; 4303 4304 r.t = rowIndex * fTileLength; 4305 r.b = r.t + fTileLength; 4306 4307 r.l = colIndex * fTileWidth; 4308 r.r = r.l + fTileWidth; 4309 4310 // If this IFD is using strips rather than tiles, the last strip 4311 // is trimmed so it does not extend beyond the end of the image. 4312 4313 if (fUsesStrips) 4314 { 4315 4316 r.b = Min_uint32 (r.b, fImageLength); 4317 4318 } 4319 4320 return r; 4321 4322 } 4323 4324 /*****************************************************************************/ 4325 4326 uint32 dng_ifd::TileByteCount (const dng_rect &tile) const 4327 { 4328 4329 if (fCompression == ccUncompressed) 4330 { 4331 4332 uint32 bitsPerRow = tile.W () * 4333 fBitsPerSample [0]; 4334 4335 if (fPlanarConfiguration == pcInterleaved) 4336 { 4337 4338 bitsPerRow *= fSamplesPerPixel; 4339 4340 } 4341 4342 uint32 bytesPerRow = (bitsPerRow + 7) >> 3; 4343 4344 if (fPlanarConfiguration == pcRowInterleaved) 4345 { 4346 4347 bytesPerRow *= fSamplesPerPixel; 4348 4349 } 4350 4351 return bytesPerRow * tile.H (); 4352 4353 } 4354 4355 return 0; 4356 4357 } 4358 4359 /*****************************************************************************/ 4360 4361 void dng_ifd::SetSingleStrip () 4362 { 4363 4364 fTileWidth = fImageWidth; 4365 fTileLength = fImageLength; 4366 4367 fUsesTiles = false; 4368 fUsesStrips = true; 4369 4370 } 4371 4372 /*****************************************************************************/ 4373 4374 void dng_ifd::FindTileSize (uint32 bytesPerTile, 4375 uint32 cellH, 4376 uint32 cellV) 4377 { 4378 4379 uint32 bytesPerSample = fSamplesPerPixel * 4380 ((fBitsPerSample [0] + 7) >> 3); 4381 4382 uint32 samplesPerTile = bytesPerTile / bytesPerSample; 4383 4384 uint32 tileSide = Round_uint32 (sqrt ((real64) samplesPerTile)); 4385 4386 fTileWidth = Min_uint32 (fImageWidth, tileSide); 4387 4388 uint32 across = TilesAcross (); 4389 4390 DNG_REQUIRE (across > 0, "Bad number of tiles across in dng_ifd::FindTileSize"); 4391 4392 fTileWidth = (fImageWidth + across - 1) / across; 4393 4394 fTileWidth = ((fTileWidth + cellH - 1) / cellH) * cellH; 4395 4396 fTileLength = Pin_uint32 (1, 4397 samplesPerTile / fTileWidth, 4398 fImageLength); 4399 4400 uint32 down = TilesDown (); 4401 4402 fTileLength = (fImageLength + down - 1) / down; 4403 4404 fTileLength = ((fTileLength + cellV - 1) / cellV) * cellV; 4405 4406 fUsesTiles = true; 4407 fUsesStrips = false; 4408 4409 } 4410 4411 /*****************************************************************************/ 4412 4413 void dng_ifd::FindStripSize (uint32 bytesPerStrip, 4414 uint32 cellV) 4415 { 4416 4417 uint32 bytesPerSample = fSamplesPerPixel * 4418 ((fBitsPerSample [0] + 7) >> 3); 4419 4420 uint32 samplesPerStrip = bytesPerStrip / bytesPerSample; 4421 4422 fTileWidth = fImageWidth; 4423 4424 fTileLength = Pin_uint32 (1, 4425 samplesPerStrip / fTileWidth, 4426 fImageLength); 4427 4428 uint32 down = TilesDown (); 4429 4430 fTileLength = (fImageLength + down - 1) / down; 4431 4432 fTileLength = ((fTileLength + cellV - 1) / cellV) * cellV; 4433 4434 fUsesTiles = false; 4435 fUsesStrips = true; 4436 4437 } 4438 4439 /*****************************************************************************/ 4440 4441 uint32 dng_ifd::PixelType () const 4442 { 4443 4444 if (fSampleFormat [0] == sfFloatingPoint) 4445 { 4446 return ttFloat; 4447 } 4448 4449 if (fBitsPerSample [0] <= 8) 4450 { 4451 return ttByte; 4452 } 4453 4454 else if (fBitsPerSample [0] <= 16) 4455 { 4456 return ttShort; 4457 } 4458 4459 return ttLong; 4460 4461 } 4462 4463 /*****************************************************************************/ 4464 4465 bool dng_ifd::IsBaselineJPEG () const 4466 { 4467 4468 if (fBitsPerSample [0] != 8) 4469 { 4470 return false; 4471 } 4472 4473 if (fSampleFormat [0] != sfUnsignedInteger) 4474 { 4475 return false; 4476 } 4477 4478 if (fCompression == ccLossyJPEG) 4479 { 4480 return true; 4481 } 4482 4483 if (fCompression != ccJPEG) 4484 { 4485 return false; 4486 } 4487 4488 switch (fPhotometricInterpretation) 4489 { 4490 4491 case piBlackIsZero: 4492 { 4493 return (fSamplesPerPixel == 1); 4494 } 4495 4496 case piYCbCr: 4497 { 4498 return (fSamplesPerPixel == 3 ) && 4499 (fPlanarConfiguration == pcInterleaved); 4500 } 4501 4502 default: 4503 break; 4504 4505 } 4506 4507 return false; 4508 4509 } 4510 4511 /*****************************************************************************/ 4512 4513 bool dng_ifd::CanRead () const 4514 { 4515 4516 dng_read_image reader; 4517 4518 return reader.CanRead (*this); 4519 4520 } 4521 4522 /*****************************************************************************/ 4523 4524 void dng_ifd::ReadImage (dng_host &host, 4525 dng_stream &stream, 4526 dng_image &image, 4527 dng_jpeg_image *jpegImage, 4528 dng_fingerprint *jpegDigest) const 4529 { 4530 4531 dng_read_image reader; 4532 4533 reader.Read (host, 4534 *this, 4535 stream, 4536 image, 4537 jpegImage, 4538 jpegDigest); 4539 4540 } 4541 4542 /*****************************************************************************/