void dng_info::ParseIFD (dng_host &host, dng_stream &stream, dng_exif *exif, dng_shared *shared, dng_ifd *ifd, uint64 ifdOffset, int64 offsetDelta, uint32 parentCode) { #if qDNGValidate bool isMakerNote = (parentCode >= tcFirstMakerNoteIFD && parentCode <= tcLastMakerNoteIFD); #endif stream.SetReadPosition (ifdOffset); if (ifd) { ifd->fThisIFD = ifdOffset; } uint32 ifdEntries = stream.Get_uint16 (); #if qDNGValidate if (gVerbose) { printf ("%s: Offset = %u, Entries = %u\n\n", LookupParentCode (parentCode), (unsigned) ifdOffset, (unsigned) ifdEntries); } if ((ifdOffset & 1) && !isMakerNote) { char message [256]; sprintf (message, "%s has odd offset (%u)", LookupParentCode (parentCode), (unsigned) ifdOffset); ReportWarning (message); } #endif uint32 prev_tag_code = 0; for (uint32 tag_index = 0; tag_index < ifdEntries; tag_index++) { stream.SetReadPosition (ifdOffset + 2 + tag_index * 12); uint32 tagCode = stream.Get_uint16 (); uint32 tagType = stream.Get_uint16 (); // Minolta 7D files have a bug in the EXIF block where the count // is wrong, and we run off into next IFD link. So if abort parsing // if we get a zero code/type combinations. if (tagCode == 0 && tagType == 0) { #if qDNGValidate char message [256]; sprintf (message, "%s had zero/zero tag code/type entry", LookupParentCode (parentCode)); ReportWarning (message); #endif return; } uint32 tagCount = stream.Get_uint32 (); #if qDNGValidate { if (tag_index > 0 && tagCode <= prev_tag_code && !isMakerNote) { char message [256]; sprintf (message, "%s tags are not sorted in ascending numerical order", LookupParentCode (parentCode)); ReportWarning (message); } } #endif prev_tag_code = tagCode; uint32 tag_type_size = TagTypeSize (tagType); if (tag_type_size == 0) { #if qDNGValidate { char message [256]; sprintf (message, "%s %s has unknown type (%u)", LookupParentCode (parentCode), LookupTagCode (parentCode, tagCode), (unsigned) tagType); ReportWarning (message); } #endif continue; } uint64 tagOffset = ifdOffset + 2 + tag_index * 12 + 8; if (tagCount * tag_type_size > 4) { tagOffset = stream.Get_uint32 (); #if qDNGValidate { if (!(ifdOffset & 1) && (tagOffset & 1) && !isMakerNote && parentCode != tcKodakDCRPrivateIFD && parentCode != tcKodakKDCPrivateIFD) { char message [256]; sprintf (message, "%s %s has odd data offset (%u)", LookupParentCode (parentCode), LookupTagCode (parentCode, tagCode), (unsigned) tagOffset); ReportWarning (message); } } #endif tagOffset += offsetDelta; stream.SetReadPosition (tagOffset); } ParseTag (host, stream, exif, shared, ifd, parentCode, tagCode, tagType, tagCount, tagOffset, offsetDelta); } stream.SetReadPosition (ifdOffset + 2 + ifdEntries * 12); uint32 nextIFD = stream.Get_uint32 (); #if qDNGValidate if (gVerbose) { printf ("NextIFD = %u\n", (unsigned) nextIFD); } #endif if (ifd) { ifd->fNextIFD = nextIFD; } #if qDNGValidate if (nextIFD) { if (parentCode != 0 && (parentCode < tcFirstChainedIFD || parentCode > tcLastChainedIFD )) { char message [256]; sprintf (message, "%s has an unexpected non-zero NextIFD (%u)", LookupParentCode (parentCode), (unsigned) nextIFD); ReportWarning (message); } } if (gVerbose) { printf ("\n"); } #endif }
bool dng_camera_profile_info::ParseTag (dng_stream &stream, uint32 parentCode, uint32 tagCode, uint32 tagType, uint32 tagCount, uint64 tagOffset) { switch (tagCode) { case tcCalibrationIlluminant1: { CheckTagType (parentCode, tagCode, tagType, ttShort); CheckTagCount (parentCode, tagCode, tagCount, 1); fCalibrationIlluminant1 = stream.TagValue_uint32 (tagType); #if qDNGValidate if (gVerbose) { printf ("CalibrationIlluminant1: %s\n", LookupLightSource (fCalibrationIlluminant1)); } #endif break; } case tcCalibrationIlluminant2: { CheckTagType (parentCode, tagCode, tagType, ttShort); CheckTagCount (parentCode, tagCode, tagCount, 1); fCalibrationIlluminant2 = stream.TagValue_uint32 (tagType); #if qDNGValidate if (gVerbose) { printf ("CalibrationIlluminant2: %s\n", LookupLightSource (fCalibrationIlluminant2)); } #endif break; } case tcColorMatrix1: { CheckTagType (parentCode, tagCode, tagType, ttSRational); if (fColorPlanes == 0) { fColorPlanes = Pin_uint32 (0, tagCount / 3, kMaxColorPlanes); } if (!CheckColorImage (parentCode, tagCode, fColorPlanes)) return false; if (!ParseMatrixTag (stream, parentCode, tagCode, tagType, tagCount, fColorPlanes, 3, fColorMatrix1)) return false; #if qDNGValidate if (gVerbose) { printf ("ColorMatrix1:\n"); DumpMatrix (fColorMatrix1); } #endif break; } case tcColorMatrix2: { CheckTagType (parentCode, tagCode, tagType, ttSRational); if (!CheckColorImage (parentCode, tagCode, fColorPlanes)) return false; if (!ParseMatrixTag (stream, parentCode, tagCode, tagType, tagCount, fColorPlanes, 3, fColorMatrix2)) return false; #if qDNGValidate if (gVerbose) { printf ("ColorMatrix2:\n"); DumpMatrix (fColorMatrix2); } #endif break; } case tcForwardMatrix1: { CheckTagType (parentCode, tagCode, tagType, ttSRational); if (!CheckColorImage (parentCode, tagCode, fColorPlanes)) return false; if (!ParseMatrixTag (stream, parentCode, tagCode, tagType, tagCount, 3, fColorPlanes, fForwardMatrix1)) return false; #if qDNGValidate if (gVerbose) { printf ("ForwardMatrix1:\n"); DumpMatrix (fForwardMatrix1); } #endif break; } case tcForwardMatrix2: { CheckTagType (parentCode, tagCode, tagType, ttSRational); if (!CheckColorImage (parentCode, tagCode, fColorPlanes)) return false; if (!ParseMatrixTag (stream, parentCode, tagCode, tagType, tagCount, 3, fColorPlanes, fForwardMatrix2)) return false; #if qDNGValidate if (gVerbose) { printf ("ForwardMatrix2:\n"); DumpMatrix (fForwardMatrix2); } #endif break; } case tcReductionMatrix1: { CheckTagType (parentCode, tagCode, tagType, ttSRational); if (!CheckColorImage (parentCode, tagCode, fColorPlanes)) return false; if (!ParseMatrixTag (stream, parentCode, tagCode, tagType, tagCount, 3, fColorPlanes, fReductionMatrix1)) return false; #if qDNGValidate if (gVerbose) { printf ("ReductionMatrix1:\n"); DumpMatrix (fReductionMatrix1); } #endif break; } case tcReductionMatrix2: { CheckTagType (parentCode, tagCode, tagType, ttSRational); if (!CheckColorImage (parentCode, tagCode, fColorPlanes)) return false; if (!ParseMatrixTag (stream, parentCode, tagCode, tagType, tagCount, 3, fColorPlanes, fReductionMatrix2)) return false; #if qDNGValidate if (gVerbose) { printf ("ReductionMatrix2:\n"); DumpMatrix (fReductionMatrix2); } #endif break; } case tcProfileCalibrationSignature: { CheckTagType (parentCode, tagCode, tagType, ttAscii, ttByte); ParseStringTag (stream, parentCode, tagCode, tagCount, fProfileCalibrationSignature, false, false); #if qDNGValidate if (gVerbose) { printf ("ProfileCalibrationSignature: "); DumpString (fProfileCalibrationSignature); printf ("\n"); } #endif break; } case tcProfileName: { CheckTagType (parentCode, tagCode, tagType, ttAscii, ttByte); ParseStringTag (stream, parentCode, tagCode, tagCount, fProfileName, false, false); #if qDNGValidate if (gVerbose) { printf ("ProfileName: "); DumpString (fProfileName); printf ("\n"); } #endif break; } case tcProfileCopyright: { CheckTagType (parentCode, tagCode, tagType, ttAscii, ttByte); ParseStringTag (stream, parentCode, tagCode, tagCount, fProfileCopyright, false, false); #if qDNGValidate if (gVerbose) { printf ("ProfileCopyright: "); DumpString (fProfileCopyright); printf ("\n"); } #endif break; } case tcProfileEmbedPolicy: { CheckTagType (parentCode, tagCode, tagType, ttLong); CheckTagCount (parentCode, tagCode, tagCount, 1); fEmbedPolicy = stream.TagValue_uint32 (tagType); #if qDNGValidate if (gVerbose) { const char *policy; switch (fEmbedPolicy) { case pepAllowCopying: policy = "Allow copying"; break; case pepEmbedIfUsed: policy = "Embed if used"; break; case pepEmbedNever: policy = "Embed never"; break; case pepNoRestrictions: policy = "No restrictions"; break; default: policy = "INVALID VALUE"; } printf ("ProfileEmbedPolicy: %s\n", policy); } #endif break; } case tcProfileHueSatMapDims: { CheckTagType (parentCode, tagCode, tagType, ttLong); CheckTagCount (parentCode, tagCode, tagCount, 2, 3); fProfileHues = stream.TagValue_uint32 (tagType); fProfileSats = stream.TagValue_uint32 (tagType); if (tagCount > 2) fProfileVals = stream.TagValue_uint32 (tagType); else fProfileVals = 1; #if qDNGValidate if (gVerbose) { printf ("ProfileHueSatMapDims: Hues = %u, Sats = %u, Vals = %u\n", (unsigned) fProfileHues, (unsigned) fProfileSats, (unsigned) fProfileVals); } #endif break; } case tcProfileHueSatMapData1: { if (!CheckTagType (parentCode, tagCode, tagType, ttFloat)) return false; bool skipSat0 = (tagCount == fProfileHues * (fProfileSats - 1) * fProfileVals * 3); if (!skipSat0) { if (!CheckTagCount (parentCode, tagCode, tagCount, fProfileHues * fProfileSats * fProfileVals * 3)) return false; } fBigEndian = stream.BigEndian (); fHueSatDeltas1Offset = tagOffset; fHueSatDeltas1Count = tagCount; #if qDNGValidate if (gVerbose) { printf ("ProfileHueSatMapData1:\n"); DumpHueSatMap (stream, fProfileHues, fProfileSats, fProfileVals, skipSat0); } #endif break; } case tcProfileHueSatMapData2: { if (!CheckTagType (parentCode, tagCode, tagType, ttFloat)) return false; bool skipSat0 = (tagCount == fProfileHues * (fProfileSats - 1) * fProfileVals * 3); if (!skipSat0) { if (!CheckTagCount (parentCode, tagCode, tagCount, fProfileHues * fProfileSats * fProfileVals * 3)) return false; } fBigEndian = stream.BigEndian (); fHueSatDeltas2Offset = tagOffset; fHueSatDeltas2Count = tagCount; #if qDNGValidate if (gVerbose) { printf ("ProfileHueSatMapData2:\n"); DumpHueSatMap (stream, fProfileHues, fProfileSats, fProfileVals, skipSat0); } #endif break; } case tcProfileLookTableDims: { CheckTagType (parentCode, tagCode, tagType, ttLong); CheckTagCount (parentCode, tagCode, tagCount, 2, 3); fLookTableHues = stream.TagValue_uint32 (tagType); fLookTableSats = stream.TagValue_uint32 (tagType); if (tagCount > 2) fLookTableVals = stream.TagValue_uint32 (tagType); else fLookTableVals = 1; #if qDNGValidate if (gVerbose) { printf ("ProfileLookTableDims: Hues = %u, Sats = %u, Vals = %u\n", (unsigned) fLookTableHues, (unsigned) fLookTableSats, (unsigned) fLookTableVals); } #endif break; } case tcProfileLookTableData: { if (!CheckTagType (parentCode, tagCode, tagType, ttFloat)) return false; bool skipSat0 = (tagCount == fLookTableHues * (fLookTableSats - 1) * fLookTableVals * 3); if (!skipSat0) { if (!CheckTagCount (parentCode, tagCode, tagCount, fLookTableHues * fLookTableSats * fLookTableVals * 3)) return false; } fBigEndian = stream.BigEndian (); fLookTableOffset = tagOffset; fLookTableCount = tagCount; #if qDNGValidate if (gVerbose) { printf ("ProfileLookTableData:\n"); DumpHueSatMap (stream, fLookTableHues, fLookTableSats, fLookTableVals, skipSat0); } #endif break; } case tcProfileToneCurve: { if (!CheckTagType (parentCode, tagCode, tagType, ttFloat)) return false; if (!CheckTagCount (parentCode, tagCode, tagCount, 4, tagCount)) return false; if ((tagCount & 1) != 0) { #if qDNGValidate { char message [256]; sprintf (message, "%s %s has odd count (%u)", LookupParentCode (parentCode), LookupTagCode (parentCode, tagCode), (unsigned) tagCount); ReportWarning (message); } #endif return false; } fBigEndian = stream.BigEndian (); fToneCurveOffset = tagOffset; fToneCurveCount = tagCount; #if qDNGValidate if (gVerbose) { DumpTagValues (stream, "Coord", parentCode, tagCode, tagType, tagCount); } #endif break; } case tcUniqueCameraModel: { // Note: This code is only used when parsing stand-alone // profiles. The embedded profiles are assumed to be restricted // to the model they are embedded in. CheckTagType (parentCode, tagCode, tagType, ttAscii); ParseStringTag (stream, parentCode, tagCode, tagCount, fUniqueCameraModel, false); bool didTrim = fUniqueCameraModel.TrimTrailingBlanks (); #if qDNGValidate if (didTrim) { ReportWarning ("UniqueCameraModel string has trailing blanks"); } if (gVerbose) { printf ("UniqueCameraModel: "); DumpString (fUniqueCameraModel); printf ("\n"); } #else (void) didTrim; // Unused #endif break; } default: { return false; } } return true; }