private void addGeoTiffTags(final Product product) {
    final GeoTIFFMetadata geoTIFFMetadata = ProductUtils.createGeoTIFFMetadata(product);
    if (geoTIFFMetadata == null) {
      return;
    }

    //  for debug purpose
    //        geoTIFFMetadata.dump();

    final int numEntries = geoTIFFMetadata.getNumGeoKeyEntries();
    final TiffShort[] directoryTagValues = new TiffShort[numEntries * 4];
    final ArrayList<TiffDouble> doubleValues = new ArrayList<>();
    final ArrayList<String> asciiValues = new ArrayList<>();
    for (int i = 0; i < numEntries; i++) {
      final GeoTIFFMetadata.KeyEntry entry = geoTIFFMetadata.getGeoKeyEntryAt(i);
      final int[] data = entry.getData();
      for (int j = 0; j < data.length; j++) {
        directoryTagValues[i * 4 + j] = new TiffShort(data[j]);
      }
      if (data[1] == TiffTag.GeoDoubleParamsTag.getValue()) {
        directoryTagValues[i * 4 + 3] = new TiffShort(doubleValues.size());
        final double[] geoDoubleParams = geoTIFFMetadata.getGeoDoubleParams(data[0]);
        for (double geoDoubleParam : geoDoubleParams) {
          doubleValues.add(new TiffDouble(geoDoubleParam));
        }
      }
      if (data[1] == TiffTag.GeoAsciiParamsTag.getValue()) {
        int sizeInBytes = 0;
        for (String asciiValue : asciiValues) {
          sizeInBytes += asciiValue.length() + 1;
        }
        directoryTagValues[i * 4 + 3] = new TiffShort(sizeInBytes);
        asciiValues.add(geoTIFFMetadata.getGeoAsciiParam(data[0]));
      }
    }
    setEntry(new TiffDirectoryEntry(TiffTag.GeoKeyDirectoryTag, directoryTagValues));
    if (!doubleValues.isEmpty()) {
      final TiffDouble[] tiffDoubles = doubleValues.toArray(new TiffDouble[doubleValues.size()]);
      setEntry(new TiffDirectoryEntry(TiffTag.GeoDoubleParamsTag, tiffDoubles));
    }
    if (!asciiValues.isEmpty()) {
      final String[] tiffAsciies = asciiValues.toArray(new String[asciiValues.size()]);
      setEntry(new TiffDirectoryEntry(TiffTag.GeoAsciiParamsTag, new GeoTiffAscii(tiffAsciies)));
    }
    double[] modelTransformation = geoTIFFMetadata.getModelTransformation();
    if (!isZeroArray(modelTransformation)) {
      setEntry(
          new TiffDirectoryEntry(
              TiffTag.ModelTransformationTag, toTiffDoubles(modelTransformation)));
    } else {
      double[] modelPixelScale = geoTIFFMetadata.getModelPixelScale();
      if (!isZeroArray(modelPixelScale)) {
        setEntry(
            new TiffDirectoryEntry(TiffTag.ModelPixelScaleTag, toTiffDoubles(modelPixelScale)));
      }
      final int numModelTiePoints = geoTIFFMetadata.getNumModelTiePoints();
      if (numModelTiePoints > 0) {
        final TiffDouble[] tiePoints = new TiffDouble[numModelTiePoints * 6];
        for (int i = 0; i < numModelTiePoints; i++) {
          final GeoTIFFMetadata.TiePoint modelTiePoint = geoTIFFMetadata.getModelTiePointAt(i);
          final double[] data = modelTiePoint.getData();
          for (int j = 0; j < data.length; j++) {
            tiePoints[i * 6 + j] = new TiffDouble(data[j]);
          }
        }
        setEntry(new TiffDirectoryEntry(TiffTag.ModelTiepointTag, tiePoints));
      }
    }
  }