public boolean extractTiffMetadata(File tifFile, TiffMeta surface)
      throws UnknownCRSException, FactoryException, TransformException, IOException {

    Preconditions.checkArgument(tifFile != null, "File is null.");

    GeoTiffReader gtr = new GeoTiffReader(tifFile);

    try {

      CoordinateReferenceSystem crs = gtr.getCoordinateReferenceSystem();
      surface.setCRS(crs);
      Integer epsgCode = CRS.lookupEpsgCode(crs, true);

      if (epsgCode == null) {
        ReferenceIdentifier name = crs.getName();
        String crsName = "Unknown";
        if (name != null) {
          crsName = name.toString();
        }
        throw new UnknownCRSException(crsName);
      }

      String srid = "EPSG:" + epsgCode;
      surface.setSrid(srid);

      //
      // extremaOp(surface, gtr.read(null));

      /*
       * Build the envelope and set to WGS84
       */
      GeneralEnvelope origEnv = gtr.getOriginalEnvelope();
      DirectPosition ll = origEnv.getLowerCorner();
      DirectPosition ur = origEnv.getUpperCorner();

      Envelope e = new Envelope();
      e.expandToInclude(ll.getOrdinate(0), ll.getOrdinate(1));
      e.expandToInclude(ur.getOrdinate(0), ur.getOrdinate(1));

      Geometry poly = envelopeToWgs84(epsgCode, e);

      if (poly instanceof Polygon) {
        surface.setEnvelope((Polygon) poly);
      }

      /*
       * Figure out the pixel size
       */
      ImageLayout imageLayout = gtr.getImageLayout();
      int imageWidth = imageLayout.getWidth(null);
      int imageHeight = imageLayout.getHeight(null);

      double pixelSizeX = e.getWidth() / imageWidth;
      double pixelSizeY = e.getHeight() / imageHeight;

      surface.setPixelSizeX(pixelSizeX);
      surface.setPixelSizeY(pixelSizeY);

      surface.setMinVal(0d);
      surface.setMaxVal(100d);

      GridCoverage2D gridCoverage2D = gtr.read(null);

      try {
        int nDims = gridCoverage2D.getNumSampleDimensions();
        surface.setNumSampleDimensions(nDims);

        extremaOp(surface, gridCoverage2D);

      } finally {
        gridCoverage2D.dispose(false);
      }

    } finally {

      gtr.dispose();
    }

    return true;
  }
    /**
     * Encodes the boundedBy element
     *
     * <p>e.g.:
     *
     * <pre>{@code
     * <gml:boundedBy>
     *    <gml:Envelope srsName="http://www.opengis.net/def/crs/EPSG/0/4326" axisLabels="Lat Long" uomLabels="deg deg" srsDimension="2">
     *       <gml:lowerCorner>1 1</gml:lowerCorner>
     *       <gml:upperCorner>5 3</gml:upperCorner>
     *    </gml:Envelope>
     * </gml:boundedBy>
     * }</pre>
     *
     * @param ci
     * @param gc2d
     * @param ePSGCode
     * @param axisSwap
     * @param srsName
     * @param axesNames
     * @param axisLabels
     * @throws IOException
     */
    public void handleBoundedBy(
        final GeneralEnvelope envelope,
        boolean axisSwap,
        String srsName,
        String axisLabels,
        WCSDimensionsHelper dimensionHelper)
        throws IOException {
      final CoordinateReferenceSystem crs = envelope.getCoordinateReferenceSystem();
      final CoordinateSystem cs = crs.getCoordinateSystem();

      // TODO time
      String uomLabels =
          extractUoM(crs, cs.getAxis(axisSwap ? 1 : 0).getUnit())
              + " "
              + extractUoM(crs, cs.getAxis(axisSwap ? 0 : 1).getUnit());

      // time and elevation dimensions management
      boolean hasElevation = false;
      boolean hasTime = false;
      if (dimensionHelper != null) {
        if (dimensionHelper.getElevationDimension() != null) {
          uomLabels = uomLabels + " m"; // TODO: Check elevation uom
          hasElevation = true;
        }
        if (dimensionHelper.getTimeDimension() != null) {
          uomLabels = uomLabels + " s";
          hasTime = true;
        }
      }
      final int srsDimension = cs.getDimension() + (hasElevation ? 1 : 0);

      // Setting up envelope bounds (including elevation)
      final String lower =
          new StringBuilder()
              .append(envelope.getLowerCorner().getOrdinate(axisSwap ? 1 : 0))
              .append(" ")
              .append(envelope.getLowerCorner().getOrdinate(axisSwap ? 0 : 1))
              .append(hasElevation ? " " + dimensionHelper.getBeginElevation() : "")
              .toString();

      final String upper =
          new StringBuilder()
              .append(envelope.getUpperCorner().getOrdinate(axisSwap ? 1 : 0))
              .append(" ")
              .append(envelope.getUpperCorner().getOrdinate(axisSwap ? 0 : 1))
              .append(hasElevation ? " " + dimensionHelper.getEndElevation() : "")
              .toString();

      // build the fragment
      final AttributesImpl envelopeAttrs = new AttributesImpl();
      envelopeAttrs.addAttribute("", "srsName", "srsName", "", srsName);
      envelopeAttrs.addAttribute("", "axisLabels", "axisLabels", "", axisLabels);
      envelopeAttrs.addAttribute("", "uomLabels", "uomLabels", "", uomLabels);
      envelopeAttrs.addAttribute(
          "", "srsDimension", "srsDimension", "", String.valueOf(srsDimension));
      start("gml:boundedBy");
      String envelopeName;
      if (dimensionHelper != null && (hasTime || hasElevation)) {
        envelopeName = "gml:EnvelopeWithTimePeriod";
      } else {
        envelopeName = "gml:Envelope";
      }
      start(envelopeName, envelopeAttrs);

      element("gml:lowerCorner", lower);
      element("gml:upperCorner", upper);

      if (dimensionHelper != null && hasTime) {
        element("gml:beginPosition", dimensionHelper.getBeginTime());
        element("gml:endPosition", dimensionHelper.getEndTime());
      }

      end(envelopeName);
      end("gml:boundedBy");
    }