write method

void write(
  1. OutputBuffer out
)

Implementation

void write(OutputBuffer out) {
  final saveEndian = out.bigEndian;

  out
    ..bigEndian = true
    // Tiff header
    ..writeUint16(0x4d4d) // big endian
    ..writeUint16(0x002a)
    ..writeUint32(8); // offset to first ifd block

  if (directories['ifd0'] == null) {
    directories['ifd0'] = IfdDirectory();
  }

  var dataOffset = 8; // offset to first ifd block, from start of tiff header
  final offsets = <String, int>{};

  for (final name in directories.keys) {
    final ifd = directories[name]!;
    offsets[name] = dataOffset;

    if (ifd.sub.containsKey('exif')) {
      ifd[0x8769] = IfdValueLong(0);
    } else {
      ifd.data.remove(0x8769);
    }

    if (ifd.sub.containsKey('interop')) {
      ifd[0xA005] = IfdValueLong(0);
    } else {
      ifd.data.remove(0xA005);
    }

    if (ifd.sub.containsKey('gps')) {
      ifd[0x8825] = IfdValueLong(0);
    } else {
      ifd.data.remove(0x8825);
    }

    // ifd block size
    dataOffset += 2 + (12 * ifd.values.length) + 4;

    // storage for large tag values
    for (final value in ifd.values) {
      final dataSize = value.dataSize;
      if (dataSize > 4) {
        dataOffset += dataSize;
      }
    }

    // storage for sub-ifd blocks
    for (final subName in ifd.sub.keys) {
      final subIfd = ifd.sub[subName];
      offsets[subName] = dataOffset;
      int subSize = 2 + (12 * subIfd.values.length);
      for (final value in subIfd.values) {
        final dataSize = value.dataSize;
        if (dataSize > 4) {
          subSize += dataSize;
        }
      }
      dataOffset += subSize;
    }
  }

  final numIfd = directories.keys.length;
  for (int i = 0; i < numIfd; ++i) {
    final name = directories.keys.elementAt(i);
    final ifd = directories.values.elementAt(i);

    if (ifd.sub.containsKey('exif')) {
      ifd[0x8769]!.setInt(offsets['exif']!);
    }

    if (ifd.sub.containsKey('interop')) {
      ifd[0xA005]!.setInt(offsets['interop']!);
    }

    if (ifd.sub.containsKey('gps')) {
      ifd[0x8825]!.setInt(offsets['gps']!);
    }

    final ifdOffset = offsets[name]!;
    final dataOffset = ifdOffset + 2 + (12 * ifd.values.length) + 4;

    _writeDirectory(out, ifd, dataOffset);

    if (i == numIfd - 1) {
      out.writeUint32(0);
    } else {
      final nextName = directories.keys.elementAt(i + 1);
      out.writeUint32(offsets[nextName]!);
    }

    _writeDirectoryLargeValues(out, ifd);

    for (final subName in ifd.sub.keys) {
      final subIfd = ifd.sub[subName];
      final subOffset = offsets[subName]!;
      final dataOffset = subOffset + 2 + (12 * subIfd.values.length);
      _writeDirectory(out, subIfd, dataOffset);
      _writeDirectoryLargeValues(out, subIfd);
    }
  }

  out.bigEndian = saveEndian;
}