/// <summary>Reads IPTC values and returns them in an <see cref="IptcDirectory"/>.</summary> /// <remarks> /// Note that IPTC data does not describe its own length, hence <paramref name="length"/> is required. /// </remarks> public IptcDirectory Extract([NotNull] SequentialReader reader, long length) { var directory = new IptcDirectory(); var offset = 0; // for each tag while (offset < length) { // identifies start of a tag byte startByte; try { startByte = reader.GetByte(); offset++; } catch (IOException) { directory.AddError("Unable to read starting byte of IPTC tag"); break; } if (startByte != IptcMarkerByte) { // NOTE have seen images where there was one extra byte at the end, giving // offset==length at this point, which is not worth logging as an error. if (offset != length) directory.AddError($"Invalid IPTC tag marker at offset {offset - 1}. Expected '0x{IptcMarkerByte:X2}' but got '0x{startByte:X}'."); break; } // we need at least five bytes left to read a tag if (offset + 5 >= length) { directory.AddError("Too few bytes remain for a valid IPTC tag"); break; } int directoryType; int tagType; int tagByteCount; try { directoryType = reader.GetByte(); tagType = reader.GetByte(); // TODO support Extended DataSet Tag (see 1.5(c), p14, IPTC-IIMV4.2.pdf) tagByteCount = reader.GetUInt16(); offset += 4; } catch (IOException) { directory.AddError("IPTC data segment ended mid-way through tag descriptor"); break; } if (offset + tagByteCount > length) { directory.AddError("Data for tag extends beyond end of IPTC segment"); break; } try { ProcessTag(reader, directory, directoryType, tagType, tagByteCount); } catch (IOException) { directory.AddError("Error processing IPTC tag"); break; } offset += tagByteCount; } return directory; }
/// <summary>Reads IPTC values and returns them in an <see cref="IptcDirectory"/>.</summary> /// <remarks> /// Note that IPTC data does not describe its own length, hence <paramref name="length"/> is required. /// </remarks> public IptcDirectory Extract(SequentialReader reader, long length) { var directory = new IptcDirectory(); var offset = 0; // for each tag while (offset < length) { // identifies start of a tag byte startByte; try { startByte = reader.GetByte(); offset++; } catch (IOException) { directory.AddError("Unable to read starting byte of IPTC tag"); break; } if (startByte != IptcMarkerByte) { // NOTE have seen images where there was one extra byte at the end, giving // offset==length at this point, which is not worth logging as an error. if (offset != length) { directory.AddError($"Invalid IPTC tag marker at offset {offset - 1}. Expected '0x{IptcMarkerByte:x2}' but got '0x{startByte:x}'."); } break; } // we need at least four bytes left to read a tag if (offset + 4 > length) { directory.AddError("Too few bytes remain for a valid IPTC tag"); break; } int directoryType; int tagType; int tagByteCount; try { directoryType = reader.GetByte(); tagType = reader.GetByte(); tagByteCount = reader.GetUInt16(); if (tagByteCount > 0x7FFF) { // Extended DataSet Tag (see 1.5(c), p14, IPTC-IIMV4.2.pdf) tagByteCount = ((tagByteCount & 0x7FFF) << 16) | reader.GetUInt16(); offset += 2; } offset += 4; } catch (IOException) { directory.AddError("IPTC data segment ended mid-way through tag descriptor"); break; } if (offset + tagByteCount > length) { directory.AddError("Data for tag extends beyond end of IPTC segment"); break; } try { ProcessTag(reader, directory, directoryType, tagType, tagByteCount); } catch (IOException) { directory.AddError("Error processing IPTC tag"); break; } offset += tagByteCount; } return(directory); }
public IptcDirectoryTests() { _directory = new IptcDirectory(); }