void dng_info::ParseTag (dng_host &host, dng_stream &stream, dng_exif *exif, dng_shared *shared, dng_ifd *ifd, uint32 parentCode, uint32 tagCode, uint32 tagType, uint32 tagCount, uint64 tagOffset, int64 offsetDelta) { bool isSubIFD = parentCode >= tcFirstSubIFD && parentCode <= tcLastSubIFD; bool isMainIFD = (parentCode == 0 || isSubIFD) && ifd && ifd->fUsesNewSubFileType && ifd->fNewSubFileType == sfMainImage; // Panasonic RAW format stores private tags using tag codes < 254 in // IFD 0. Redirect the parsing of these tags into a logical // "PanasonicRAW" IFD. // Panasonic is starting to use some higher numbers also (280..283). if (fMagic == 85 && parentCode == 0 && (tagCode < tcNewSubFileType || (tagCode >= 280 && tagCode <= 283))) { parentCode = tcPanasonicRAW; ifd = NULL; } stream.SetReadPosition (tagOffset); if (ifd && ifd->ParseTag (stream, parentCode, tagCode, tagType, tagCount, tagOffset)) { return; } stream.SetReadPosition (tagOffset); if (exif && shared && exif->ParseTag (stream, *shared, parentCode, isMainIFD, tagCode, tagType, tagCount, tagOffset)) { return; } stream.SetReadPosition (tagOffset); if (shared && exif && shared->ParseTag (stream, *exif, parentCode, isMainIFD, tagCode, tagType, tagCount, tagOffset, offsetDelta)) { return; } if (parentCode == tcOlympusMakerNote && tagType == ttUndefined && tagCount >= 14) { uint32 olympusMakerParent = 0; switch (tagCode) { case 8208: olympusMakerParent = tcOlympusMakerNote8208; break; case 8224: olympusMakerParent = tcOlympusMakerNote8224; break; case 8240: olympusMakerParent = tcOlympusMakerNote8240; break; case 8256: olympusMakerParent = tcOlympusMakerNote8256; break; case 8272: olympusMakerParent = tcOlympusMakerNote8272; break; case 12288: olympusMakerParent = tcOlympusMakerNote12288; break; default: break; } if (olympusMakerParent) { // Olympus made a mistake in some camera models in computing // the size of these sub-tags, so we fudge the count. if (ParseMakerNoteIFD (host, stream, stream.Length () - tagOffset, tagOffset, offsetDelta, tagOffset, stream.Length (), olympusMakerParent)) { return; } } } if (parentCode == tcRicohMakerNote && tagCode == 0x2001 && tagType == ttUndefined && tagCount > 22) { char header [20]; stream.SetReadPosition (tagOffset); stream.Get (header, sizeof (header)); if (memcmp (header, "[Ricoh Camera Info]", 19) == 0) { ParseMakerNoteIFD (host, stream, tagCount - 20, tagOffset + 20, offsetDelta, tagOffset + 20, tagOffset + tagCount, tcRicohMakerNoteCameraInfo); return; } } #if qDNGValidate { stream.SetReadPosition (tagOffset); if (gVerbose) { printf ("*"); DumpTagValues (stream, LookupTagType (tagType), parentCode, tagCode, tagType, tagCount); } // If type is ASCII, then parse anyway so we report any ASCII // NULL termination or character set errors. else if (tagType == ttAscii) { dng_string s; ParseStringTag (stream, parentCode, tagCode, tagCount, s, false); } } #endif }
bool dng_camera_profile_info::ParseExtended (dng_stream &stream) { try { // Offsets are relative to the start of this structure, not the entire file. uint64 startPosition = stream.Position (); // Read header. Like a TIFF header, but with different magic number // Plus all offsets are relative to the start of the IFD, not to the // stream or file. uint16 byteOrder = stream.Get_uint16 (); if (byteOrder == byteOrderMM) fBigEndian = true; else if (byteOrder == byteOrderII) fBigEndian = false; else return false; TempBigEndian setEndianness (stream, fBigEndian); uint16 magicNumber = stream.Get_uint16 (); if (magicNumber != magicExtendedProfile) { return false; } uint32 offset = stream.Get_uint32 (); stream.Skip (offset - 8); // Start on IFD entries. uint32 ifdEntries = stream.Get_uint16 (); if (ifdEntries < 1) { return false; } for (uint32 tag_index = 0; tag_index < ifdEntries; tag_index++) { stream.SetReadPosition (startPosition + 8 + 2 + tag_index * 12); uint16 tagCode = stream.Get_uint16 (); uint32 tagType = stream.Get_uint16 (); uint32 tagCount = stream.Get_uint32 (); uint64 tagOffset = stream.Position (); if (TagTypeSize (tagType) * tagCount > 4) { tagOffset = startPosition + stream.Get_uint32 (); stream.SetReadPosition (tagOffset); } if (!ParseTag (stream, 0, tagCode, tagType, tagCount, tagOffset)) { #if qDNGValidate if (gVerbose) { stream.SetReadPosition (tagOffset); printf ("*"); DumpTagValues (stream, LookupTagType (tagType), 0, tagCode, tagType, tagCount); } #endif } } return true; } catch (...) { // Eat parsing errors. } return false; }