docs: public void extract(@NotNull final SequentialReader reader, @NotNull final Metadata metadata, long length, @Nullable Directory parentDirectory)
      {
          IptcDirectory directory = new IptcDirectory();
          metadata.addDirectory(directory);
  
          if (parentDirectory != null)
              directory.setParent(parentDirectory);
  
          int offset = 0;
  
          // for each tag
          while (offset < length) {
  
              // identifies start of a tag
              short startByte;
              try {
                  startByte = reader.getUInt8();
                  offset++;
              } catch (IOException e) {
                  directory.addError("Unable to read starting byte of IPTC tag");
                  return;
              }
  
              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" + Integer.toHexString(IptcMarkerByte) + "' but got '0x" + Integer.toHexString(startByte) + "'.");
                  return;
              }
  
              // 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");
                  return;
              }
  
              int directoryType;
              int tagType;
              int tagByteCount;
              try {
                  directoryType = reader.getUInt8();
                  tagType = reader.getUInt8();
                  tagByteCount = reader.getUInt16();
                  if (tagByteCount > 32767) {
                      // Extended DataSet Tag (see 1.5(c), p14, IPTC-IIMV4.2.pdf)
                      tagByteCount = ((tagByteCount & 0x7FFF) << 16) | reader.getUInt16();
                      offset += 2;
                  }
                  offset += 4;
              } catch (IOException e) {
                  directory.addError("IPTC data segment ended mid-way through tag descriptor");
                  return;
              }
  
              if (offset + tagByteCount > length) {
                  directory.addError("Data for tag extends beyond end of IPTC segment");
                  return;
              }
  
              try {
                  processTag(reader, directory, directoryType, tagType, tagByteCount);
              } catch (IOException e) {
                  directory.addError("Error processing IPTC tag");
                  return;
              }
  
              offset += tagByteCount;
          }
      }