public static IptcDirectory ProcessBytes([NotNull] string filePath) { var bytes = File.ReadAllBytes(filePath); var directory = new IptcReader().Extract(new SequentialByteArrayReader(bytes), bytes.Length); Assert.NotNull(directory); return directory; }
/// <exception cref="System.IO.IOException"/> public override bool CustomProcessTag(int tagOffset, ICollection<int> processedIfdOffsets, int tiffHeaderOffset, IndexedReader reader, int tagId, int byteCount) { // Custom processing for the Makernote tag if (tagId == ExifDirectoryBase.TagMakernote && CurrentDirectory is ExifSubIfdDirectory) { return ProcessMakernote(tagOffset, processedIfdOffsets, tiffHeaderOffset, 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; } return false; }
Extract([NotNull] SequentialReader reader, int length) { var directory = new PhotoshopDirectory(); var directories = new List<Directory> { directory }; // Data contains a sequence of Image Resource Blocks (IRBs): // // 4 bytes - Signature; mostly "8BIM" but "PHUT", "AgHg" and "DCSR" are also found // 2 bytes - Resource identifier // String - Pascal string, padded to make length even // 4 bytes - Size of resource data which follows // Data - The resource data, padded to make size even // // http://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#50577409_pgfId-1037504 var pos = 0; while (pos < length) { try { // 4 bytes for the signature ("8BIM", "PHUT", etc.) var signature = reader.GetString(4); pos += 4; // 2 bytes for the resource identifier (tag type). var tagType = reader.GetUInt16(); pos += 2; // A variable number of bytes holding a pascal string (two leading bytes for length). var descriptionLength = reader.GetByte(); pos += 1; // Some basic bounds checking if (descriptionLength + pos > length) throw new ImageProcessingException("Invalid string length"); // We don't use the string value here reader.Skip(descriptionLength); pos += descriptionLength; // The number of bytes is padded with a trailing zero, if needed, to make the size even. if (pos % 2 != 0) { reader.Skip(1); pos++; } // 4 bytes for the size of the resource data that follows. var byteCount = reader.GetInt32(); pos += 4; // The resource data. var tagBytes = reader.GetBytes(byteCount); pos += byteCount; // The number of bytes is padded with a trailing zero, if needed, to make the size even. if (pos % 2 != 0) { reader.Skip(1); pos++; } // Skip any unsupported IRBs if (signature != "8BIM") continue; switch (tagType) { case PhotoshopDirectory.TagIptc: var iptcDirectory = new IptcReader().Extract(new SequentialByteArrayReader(tagBytes), tagBytes.Length); iptcDirectory.Parent = directory; directories.Add(iptcDirectory); break; case PhotoshopDirectory.TagIccProfileBytes: var iccDirectory = new IccReader().Extract(new ByteArrayReader(tagBytes)); iccDirectory.Parent = directory; directories.Add(iccDirectory); break; case PhotoshopDirectory.TagExifData1: case PhotoshopDirectory.TagExifData3: var exifDirectories = new ExifReader().Extract(new ByteArrayReader(tagBytes)); foreach (var exifDirectory in exifDirectories.Where(d => d.Parent == null)) exifDirectory.Parent = directory; directories.AddRange(exifDirectories); break; case PhotoshopDirectory.TagXmpData: var xmpDirectory = new XmpReader().Extract(tagBytes); xmpDirectory.Parent = directory; directories.Add(xmpDirectory); break; default: directory.Set(tagType, tagBytes); break; } if (tagType >= 0x0fa0 && tagType <= 0x1387) PhotoshopDirectory.TagNameMap[tagType] = $"Plug-in {tagType - 0x0fa0 + 1} Data"; } catch (Exception ex) { directory.AddError(ex.Message); break; } } return directories; }