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 /*****************************************************************************/