public override bool CustomProcessTag(int tagOffset, ICollection <int> processedIfdOffsets, IndexedReader reader, int tagId, int byteCount) { // Some 0x0000 tags have a 0 byteCount. Determine whether it's bad. if (tagId == 0) { if (CurrentDirectory.ContainsTag(tagId)) { // Let it go through for now. Some directories handle it, some don't. return(false); } // Skip over 0x0000 tags that don't have any associated bytes. No idea what it contains in this case, if anything. if (byteCount == 0) { return(true); } } // Custom processing for the Makernote tag if (tagId == ExifDirectoryBase.TagMakernote && CurrentDirectory is ExifSubIfdDirectory) { return(ProcessMakernote(tagOffset, processedIfdOffsets, reader)); } // Custom processing for embedded IPTC data if (tagId == ExifDirectoryBase.TagIptcNaa && CurrentDirectory is ExifIfd0Directory) { // NOTE Adobe sets type 4 for IPTC instead of 7 if (reader.GetSByte(tagOffset) == 0x1c) { var iptcBytes = reader.GetBytes(tagOffset, byteCount); var iptcDirectory = new IptcReader().Extract(new SequentialByteArrayReader(iptcBytes), iptcBytes.Length); iptcDirectory.Parent = CurrentDirectory; Directories.Add(iptcDirectory); return(true); } return(false); } // Custom processing for embedded XMP data if (tagId == ExifDirectoryBase.TagApplicationNotes && CurrentDirectory is ExifIfd0Directory) { var xmpDirectory = new XmpReader().Extract(reader.GetNullTerminatedBytes(tagOffset, byteCount)); xmpDirectory.Parent = CurrentDirectory; Directories.Add(xmpDirectory); return(true); } if (HandlePrintIM(CurrentDirectory, tagId)) { var dirPrintIm = new PrintIMDirectory(); dirPrintIm.Parent = CurrentDirectory; Directories.Add(dirPrintIm); ProcessPrintIM(dirPrintIm, tagOffset, reader, byteCount); return(true); } // Note: these also appear in TryEnterSubIfd because some are IFD pointers while others begin immediately // for the same directories if (CurrentDirectory is OlympusMakernoteDirectory) { switch (tagId) { case OlympusMakernoteDirectory.TagEquipment: PushDirectory(new OlympusEquipmentMakernoteDirectory()); TiffReader.ProcessIfd(this, reader, processedIfdOffsets, tagOffset); return(true); case OlympusMakernoteDirectory.TagCameraSettings: PushDirectory(new OlympusCameraSettingsMakernoteDirectory()); TiffReader.ProcessIfd(this, reader, processedIfdOffsets, tagOffset); return(true); case OlympusMakernoteDirectory.TagRawDevelopment: PushDirectory(new OlympusRawDevelopmentMakernoteDirectory()); TiffReader.ProcessIfd(this, reader, processedIfdOffsets, tagOffset); return(true); case OlympusMakernoteDirectory.TagRawDevelopment2: PushDirectory(new OlympusRawDevelopment2MakernoteDirectory()); TiffReader.ProcessIfd(this, reader, processedIfdOffsets, tagOffset); return(true); case OlympusMakernoteDirectory.TagImageProcessing: PushDirectory(new OlympusImageProcessingMakernoteDirectory()); TiffReader.ProcessIfd(this, reader, processedIfdOffsets, tagOffset); return(true); case OlympusMakernoteDirectory.TagFocusInfo: PushDirectory(new OlympusFocusInfoMakernoteDirectory()); TiffReader.ProcessIfd(this, reader, processedIfdOffsets, tagOffset); return(true); case OlympusMakernoteDirectory.TagRawInfo: PushDirectory(new OlympusRawInfoMakernoteDirectory()); TiffReader.ProcessIfd(this, reader, processedIfdOffsets, tagOffset); return(true); case OlympusMakernoteDirectory.TagMainInfo: PushDirectory(new OlympusMakernoteDirectory()); TiffReader.ProcessIfd(this, reader, processedIfdOffsets, tagOffset); return(true); } } if (CurrentDirectory is PanasonicRawIfd0Directory) { // these contain binary data with specific offsets, and can't be processed as regular ifd's. // The binary data is broken into 'fake' tags and there is a pattern. switch (tagId) { case PanasonicRawIfd0Directory.TagWbInfo: var dirWbInfo = new PanasonicRawWbInfoDirectory(); dirWbInfo.Parent = CurrentDirectory; Directories.Add(dirWbInfo); ProcessBinary(dirWbInfo, tagOffset, reader, byteCount, false, 2); return(true); case PanasonicRawIfd0Directory.TagWbInfo2: var dirWbInfo2 = new PanasonicRawWbInfo2Directory(); dirWbInfo2.Parent = CurrentDirectory; Directories.Add(dirWbInfo2); ProcessBinary(dirWbInfo2, tagOffset, reader, byteCount, false, 3); return(true); case PanasonicRawIfd0Directory.TagDistortionInfo: var dirDistort = new PanasonicRawDistortionDirectory(); dirDistort.Parent = CurrentDirectory; Directories.Add(dirDistort); ProcessBinary(dirDistort, tagOffset, reader, byteCount); return(true); } } // Panasonic RAW sometimes contains an embedded version of the data as a JPG file. if (tagId == PanasonicRawIfd0Directory.TagJpgFromRaw && CurrentDirectory is PanasonicRawIfd0Directory) { var jpegrawbytes = reader.GetBytes(tagOffset, byteCount); // Extract information from embedded image since it is metadata-rich var jpegmem = new MemoryStream(jpegrawbytes); var jpegDirectory = Jpeg.JpegMetadataReader.ReadMetadata(jpegmem); foreach (var dir in jpegDirectory) { dir.Parent = CurrentDirectory; Directories.Add(dir); } return(true); } return(false); }