@Test
  public void testThreeGeoTIFFTagsWithOneAscii() {
    metadata.addGeoShortParam(2300, 4576);
    metadata.addGeoAscii(2400, "String");
    metadata.addGeoShortParam(2401, 3456);

    final List<TIFFField> list = Utils.createGeoTIFFFields(metadata);

    assertNotNull(list);
    assertEquals(2, list.size());

    final TIFFField dirField = list.get(0);
    final TIFFField asciiField = list.get(1);

    assertEquals(GeoTIFFTagSet.TAG_GEO_KEY_DIRECTORY, dirField.getTag());
    assertEquals(GeoTIFFTagSet.TAG_GEO_ASCII_PARAMS, asciiField.getTag());

    assertEquals(TIFFField.TIFF_SHORT, dirField.getType());
    assertEquals(TIFFField.TIFF_ASCII, asciiField.getType());

    assertEquals(16, dirField.getCount());
    assertEquals(1, asciiField.getCount());

    final char[] expected = {
      1, 1, 2, 3,
      2300, 0, 1, 4576,
      2400, GeoTIFFTagSet.TAG_GEO_ASCII_PARAMS, 7, 0,
      2401, 0, 1, 3456
    };
    assertArrayEquals(expected, dirField.getAsChars());
    assertEquals("String|", asciiField.getAsString(0));
  }
  @Test
  public void testVersionAndModelTiePoint() {
    metadata.addModelTiePoint(1, 2, 3, 4, 5, 6);
    metadata.addModelTiePoint(2, 3, 4, 5, 6, 7);
    metadata.addModelTiePoint(3, 4, 5, 6, 7, 8);
    final List<TIFFField> list = Utils.createGeoTIFFFields(metadata);

    assertNotNull(list);
    assertEquals(2, list.size());

    final TIFFField dirField = list.get(0);
    assertEquals(GeoTIFFTagSet.TAG_GEO_KEY_DIRECTORY, dirField.getTag());
    assertEquals(TIFFField.TIFF_SHORT, dirField.getType());
    assertEquals(4, dirField.getCount());
    assertArrayEquals(new char[] {1, 1, 2, 0}, dirField.getAsChars());

    final TIFFField tiePointField = list.get(1);
    assertEquals(GeoTIFFTagSet.TAG_MODEL_TIE_POINT, tiePointField.getTag());
    assertEquals(TIFFField.TIFF_DOUBLE, tiePointField.getType());
    assertEquals(3 * 6, tiePointField.getCount());
    final double[] expected = {
      1, 2, 3, 4, 5, 6,
      2, 3, 4, 5, 6, 7,
      3, 4, 5, 6, 7, 8
    };
    assertEquals(true, Arrays.equals(expected, tiePointField.getAsDoubles()));
  }
  @Test
  public void testThreeGeoTIFFStringTags() {
    metadata.addGeoAscii(2300, "4576");
    metadata.addGeoAscii(2400, "aaaaaaaa");
    metadata.addGeoAscii(2401, "bbbb");

    final List<TIFFField> list = Utils.createGeoTIFFFields(metadata);

    assertNotNull(list);
    assertEquals(2, list.size());

    final TIFFField dirField = list.get(0);
    final TIFFField asciiField = list.get(1);

    assertEquals(GeoTIFFTagSet.TAG_GEO_KEY_DIRECTORY, dirField.getTag());
    assertEquals(GeoTIFFTagSet.TAG_GEO_ASCII_PARAMS, asciiField.getTag());

    assertEquals(TIFFField.TIFF_SHORT, dirField.getType());
    assertEquals(TIFFField.TIFF_ASCII, asciiField.getType());

    assertEquals(16, dirField.getCount());
    assertEquals(3, asciiField.getCount());

    final char[] expected = {
      1, 1, 2, 3,
      2300, GeoTIFFTagSet.TAG_GEO_ASCII_PARAMS, 5, 0,
      2400, GeoTIFFTagSet.TAG_GEO_ASCII_PARAMS, 9, 5,
      2401, GeoTIFFTagSet.TAG_GEO_ASCII_PARAMS, 5, 14
    };
    assertArrayEquals(expected, dirField.getAsChars());
    assertEquals("4576|", asciiField.getAsString(0));
    assertEquals("aaaaaaaa|", asciiField.getAsString(1));
    assertEquals("bbbb|", asciiField.getAsString(2));
  }
  @Test
  public void testThreeGeoTIFFTagsWithOneDouble() {
    metadata.addGeoShortParam(2300, 4576);
    metadata.addGeoDoubleParam(2400, 4.5);
    metadata.addGeoShortParam(2401, 3456);

    final List<TIFFField> list = Utils.createGeoTIFFFields(metadata);

    assertNotNull(list);
    assertEquals(2, list.size());

    final TIFFField dirField = list.get(0);
    final TIFFField doubleField = list.get(1);

    assertEquals(GeoTIFFTagSet.TAG_GEO_KEY_DIRECTORY, dirField.getTag());
    assertEquals(GeoTIFFTagSet.TAG_GEO_DOUBLE_PARAMS, doubleField.getTag());

    assertEquals(TIFFField.TIFF_SHORT, dirField.getType());
    assertEquals(TIFFField.TIFF_DOUBLE, doubleField.getType());

    assertEquals(16, dirField.getCount());
    assertEquals(1, doubleField.getCount());

    final char[] expected = {
      1, 1, 2, 3,
      2300, 0, 1, 4576,
      2400, GeoTIFFTagSet.TAG_GEO_DOUBLE_PARAMS, 1, 0,
      2401, 0, 1, 3456
    };
    assertArrayEquals(expected, dirField.getAsChars());
    assertEquals(true, Arrays.equals(new double[] {4.5}, doubleField.getAsDoubles()));
  }
  @Test
  public void testThreeGeoTIFFShortTags() {
    metadata.addGeoShortParam(2300, 4576);
    metadata.addGeoShortParam(2400, 12);
    metadata.addGeoShortParam(2401, 3456);

    final List<TIFFField> list = Utils.createGeoTIFFFields(metadata);

    assertNotNull(list);
    assertEquals(1, list.size());
    final TIFFField dirField = list.get(0);

    assertEquals(GeoTIFFTagSet.TAG_GEO_KEY_DIRECTORY, dirField.getTag());
    assertEquals(TIFFField.TIFF_SHORT, dirField.getType());
    assertEquals(16, dirField.getCount());
    final char[] expected = {
      1, 1, 2, 3,
      2300, 0, 1, 4576,
      2400, 0, 1, 12,
      2401, 0, 1, 3456
    };
    assertArrayEquals(expected, dirField.getAsChars());
  }
  @Test
  public void testVersionAndModelPixelScale() {
    metadata.setModelPixelScale(1, 2, 3);
    final List<TIFFField> list = Utils.createGeoTIFFFields(metadata);

    assertNotNull(list);
    assertEquals(2, list.size());

    final TIFFField dirField = list.get(0);
    assertEquals(GeoTIFFTagSet.TAG_GEO_KEY_DIRECTORY, dirField.getTag());
    assertEquals(TIFFField.TIFF_SHORT, dirField.getType());
    assertEquals(4, dirField.getCount());
    assertArrayEquals(new char[] {1, 1, 2, 0}, dirField.getAsChars());

    final TIFFField scaleField = list.get(1);
    assertEquals(GeoTIFFTagSet.TAG_MODEL_PIXEL_SCALE, scaleField.getTag());
    assertEquals(TIFFField.TIFF_DOUBLE, scaleField.getType());
    assertEquals(3, scaleField.getCount());
    assertEquals(true, Arrays.equals(new double[] {1, 2, 3}, scaleField.getAsDoubles()));
  }
  @Test
  public void testVersionAndModelTransformation() {
    metadata.setModelTransformation(
        new double[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16});
    final List<TIFFField> list = Utils.createGeoTIFFFields(metadata);

    assertNotNull(list);
    assertEquals(2, list.size());

    final TIFFField dirField = list.get(0);
    assertEquals(GeoTIFFTagSet.TAG_GEO_KEY_DIRECTORY, dirField.getTag());
    assertEquals(TIFFField.TIFF_SHORT, dirField.getType());
    assertEquals(4, dirField.getCount());
    assertArrayEquals(new char[] {1, 1, 2, 0}, dirField.getAsChars());

    final TIFFField transformField = list.get(1);
    assertEquals(GeoTIFFTagSet.TAG_MODEL_TRANSFORMATION, transformField.getTag());
    assertEquals(TIFFField.TIFF_DOUBLE, transformField.getType());
    assertEquals(16, transformField.getCount());
    final double[] expected = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
    assertEquals(true, Arrays.equals(expected, transformField.getAsDoubles()));
  }
  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));
      }
    }
  }