public virtual void Extract(RandomAccessReader reader, Com.Drew.Metadata.Metadata metadata) { PhotoshopDirectory directory = metadata.GetOrCreateDirectory <PhotoshopDirectory>(); int pos; try { pos = reader.GetString(0, 13).Equals("Photoshop 3.0") ? 14 : 0; } catch (IOException) { directory.AddError("Unable to read header"); return; } long length; try { length = reader.GetLength(); } catch (IOException e) { directory.AddError("Unable to read Photoshop data: " + e.Message); return; } while (pos < length) { try { // 4 bytes for the signature. Should always be "8BIM". //String signature = new String(data, pos, 4); pos += 4; // 2 bytes for the resource identifier (tag type). int tagType = reader.GetUInt16(pos); // segment type pos += 2; // A variable number of bytes holding a pascal string (two leading bytes for length). int descriptionLength = reader.GetUInt16(pos); pos += 2; // Some basic bounds checking if (descriptionLength < 0 || descriptionLength + pos > length) { return; } //String description = new String(data, pos, descriptionLength); pos += descriptionLength; // The number of bytes is padded with a trailing zero, if needed, to make the size even. if (pos % 2 != 0) { pos++; } // 4 bytes for the size of the resource data that follows. int byteCount = reader.GetInt32(pos); pos += 4; // The resource data. sbyte[] tagBytes = reader.GetBytes(pos, byteCount); pos += byteCount; // The number of bytes is padded with a trailing zero, if needed, to make the size even. if (pos % 2 != 0) { pos++; } directory.SetByteArray(tagType, tagBytes); // TODO allow rebasing the reader with a new zero-point, rather than copying data here if (tagType == PhotoshopDirectory.TagIptc) { new IptcReader().Extract(new SequentialByteArrayReader(tagBytes), metadata, tagBytes.Length); } if (tagType >= unchecked ((int)(0x0fa0)) && tagType <= unchecked ((int)(0x1387))) { PhotoshopDirectory._tagNameMap.Put(tagType, Sharpen.Extensions.StringFormat("Plug-in %d Data", tagType - unchecked ((int)(0x0fa0)) + 1)); } } catch (IOException ex) { directory.AddError(ex.Message); return; } } }
public virtual void Extract([NotNull] SequentialReader reader, int length, [NotNull] Com.Drew.Metadata.Metadata metadata) { PhotoshopDirectory directory = new PhotoshopDirectory(); metadata.AddDirectory(directory); // Data contains a sequence of Image Resource Blocks (IRBs): // // 4 bytes - Signature "8BIM" // 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 int pos = 0; while (pos < length) { try { // 4 bytes for the signature. Should always be "8BIM". string signature = reader.GetString(4); if (!signature.Equals("8BIM")) { throw new ImageProcessingException("Expecting 8BIM marker"); } pos += 4; // 2 bytes for the resource identifier (tag type). int tagType = reader.GetUInt16(); // segment type pos += 2; // A variable number of bytes holding a pascal string (two leading bytes for length). short descriptionLength = reader.GetUInt8(); pos += 1; // Some basic bounds checking if (descriptionLength < 0 || 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. int byteCount = reader.GetInt32(); pos += 4; // The resource data. sbyte[] 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++; } if (tagType == PhotoshopDirectory.TagIptc) { new IptcReader().Extract(new SequentialByteArrayReader(tagBytes), metadata, tagBytes.Length); } else { if (tagType == PhotoshopDirectory.TagIccProfileBytes) { new IccReader().Extract(new ByteArrayReader(tagBytes), metadata); } else { if (tagType == PhotoshopDirectory.TagExifData1 || tagType == PhotoshopDirectory.TagExifData3) { new ExifReader().Extract(new ByteArrayReader(tagBytes), metadata); } else { if (tagType == PhotoshopDirectory.TagXmpData) { new XmpReader().Extract(tagBytes, metadata); } else { directory.SetByteArray(tagType, tagBytes); } } } } if (tagType >= unchecked((int)(0x0fa0)) && tagType <= unchecked((int)(0x1387))) { PhotoshopDirectory._tagNameMap.Put(tagType, Sharpen.Extensions.StringFormat("Plug-in %d Data", tagType - unchecked((int)(0x0fa0)) + 1)); } } catch (Exception ex) { directory.AddError(ex.Message); return; } } }
public virtual void Extract([NotNull] SequentialReader reader, int length, [NotNull] Com.Drew.Metadata.Metadata metadata) { PhotoshopDirectory directory = new PhotoshopDirectory(); metadata.AddDirectory(directory); // Data contains a sequence of Image Resource Blocks (IRBs): // // 4 bytes - Signature "8BIM" // 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 int pos = 0; while (pos < length) { try { // 4 bytes for the signature. Should always be "8BIM". string signature = reader.GetString(4); if (!signature.Equals("8BIM")) { throw new ImageProcessingException("Expecting 8BIM marker"); } pos += 4; // 2 bytes for the resource identifier (tag type). int tagType = reader.GetUInt16(); // segment type pos += 2; // A variable number of bytes holding a pascal string (two leading bytes for length). short descriptionLength = reader.GetUInt8(); pos += 1; // Some basic bounds checking if (descriptionLength < 0 || 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. int byteCount = reader.GetInt32(); pos += 4; // The resource data. sbyte[] 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++; } if (tagType == PhotoshopDirectory.TagIptc) { new IptcReader().Extract(new SequentialByteArrayReader(tagBytes), metadata, tagBytes.Length); } else { if (tagType == PhotoshopDirectory.TagIccProfileBytes) { new IccReader().Extract(new ByteArrayReader(tagBytes), metadata); } else { if (tagType == PhotoshopDirectory.TagExifData1 || tagType == PhotoshopDirectory.TagExifData3) { new ExifReader().Extract(new ByteArrayReader(tagBytes), metadata); } else { if (tagType == PhotoshopDirectory.TagXmpData) { new XmpReader().Extract(tagBytes, metadata); } else { directory.SetByteArray(tagType, tagBytes); } } } } if (tagType >= unchecked ((int)(0x0fa0)) && tagType <= unchecked ((int)(0x1387))) { PhotoshopDirectory._tagNameMap.Put(tagType, Sharpen.Extensions.StringFormat("Plug-in %d Data", tagType - unchecked ((int)(0x0fa0)) + 1)); } } catch (Exception ex) { directory.AddError(ex.Message); return; } } }