/**
   * performs the creation of a <tt>ImageGridCoverage</tt> from the source assigned to this reader.
   *
   * @param parameters
   * @throws IOException
   */
  private GridCoverage performECW(GeneralParameterValueIm[] parameters) throws IOException {

    BufferedImage bi = null;
    CoverageOffering co = null;
    Object[] o = null;

    ECWReader ecwFile = null;
    try {
      String s = ((File) source).getName();
      ecwFile = new ECWReader(s);

      // get the requested dimension in pixels
      int reqWidth = 0;
      int reqHeight = 0;
      for (int i = 0; i < parameters.length; i++) {
        OperationParameterIm op = (OperationParameterIm) parameters[i].getDescriptor();
        String name = op.getName();
        if (name.equalsIgnoreCase("WIDTH")) {
          Object vo = op.getDefaultValue();
          reqWidth = ((Integer) vo).intValue();
        } else if (name.equalsIgnoreCase("HEIGHT")) {
          Object vo = op.getDefaultValue();
          reqHeight = ((Integer) vo).intValue();
        }
      }

      // calculate image region of interest
      o = getECWImageRegion(reqWidth, reqHeight);
      Envelope envl = (Envelope) o[1];

      Rectangle rect = (Rectangle) o[0];
      bi = ecwFile.getBufferedImage(envl, rect.width, rect.height);

      // create a coverage description that matches the sub image (coverage)
      // for this a new LonLatEnvelope must be set
      co = (CoverageOffering) description.clone();
      co.setLonLatEnvelope((LonLatEnvelope) o[2]);

    } catch (Exception e) {
      e.printStackTrace();
      throw new IOException(StringTools.stackTraceToString(e));
    } finally {
      // free the ECW cache memory
      if (ecwFile != null) {
        ecwFile.close();
      }
    }

    return new ImageGridCoverage(co, (Envelope) o[1], bi);
  }
  /**
   * performs the creation of a <tt>ImageGridCoverage</tt> from the source assigned to this reader.
   *
   * @throws IOException
   * @throws ParameterNotFoundException
   */
  private GridCoverage performImage() throws ParameterNotFoundException, IOException {

    BufferedImage bi = readImage();

    // get image rectangle of interrest, envelope and lonlatenvelope
    Object[] o = getImageRegion(bi.getWidth(), bi.getHeight());
    Rectangle rect = (Rectangle) o[0];
    // return null if the result GC would have a width or height of zero
    if (rect.width == 0 || rect.height == 0) {
      return null;
    }
    bi = bi.getSubimage(rect.x, rect.y, rect.width, rect.height);

    // create a coverage description that matches the sub image (coverage)
    // for this a new LonLatEnvelope must be set
    CoverageOffering co = (CoverageOffering) description.clone();
    co.setLonLatEnvelope((LonLatEnvelope) o[2]);

    return new ImageGridCoverage(co, (Envelope) o[1], bi);
  }
  /**
   * validates the passed <tt>GetCoverage</tt> against the passed <tt>WCSCapabilities</tt>
   *
   * @param capabilities
   * @param request
   * @throws InvalidParameterValueException
   */
  private static void validate(WCSCapabilities capabilities, GetCoverage request)
      throws InvalidParameterValueException {
    String coverage = request.getSourceCoverage();
    ContentMetadata cm = capabilities.getContentMetadata();
    // is coverage known by the WCS?
    CoverageOfferingBrief cob = cm.getCoverageOfferingBrief(coverage);
    if (cob == null) {
      throw new InvalidParameterValueException(
          "Coverage: " + coverage + " is not known by the WCS");
    }

    URL url = cob.getConfiguration();
    CoverageDescription cd = null;
    try {
      cd = CoverageDescription.createCoverageDescription(url);
    } catch (Exception e) {
      LOG.logError(e.getMessage(), e);
      throw new InvalidParameterValueException(e.getMessage());
    }
    CoverageOffering co = cd.getCoverageOffering(coverage);
    if (co == null) {
      throw new InvalidParameterValueException(
          "no coverage descrition " + "available for requested coverage: " + coverage);
    }
    // validate requested format
    String format = request.getOutput().getFormat().getCode();
    SupportedFormats sf = co.getSupportedFormats();
    CodeList[] codeList = sf.getFormats();
    if (!validate(codeList, null, format)) {
      throw new InvalidParameterValueException(
          "requested format: " + format + " is not known by the WCS for coverage:" + coverage);
    }
    // validate requested response CRS
    String crs = request.getOutput().getCrs().getCode();
    URI codeSpace = request.getOutput().getCrs().getCodeSpace();
    String space = null;
    if (codeSpace != null) {
      space = codeSpace.toString();
    }

    CodeList[] rrcrs = co.getSupportedCRSs().getRequestResponseSRSs();
    CodeList[] rescrs = co.getSupportedCRSs().getResponseSRSs();
    if (!validate(rrcrs, space, crs) && !validate(rescrs, space, crs)) {
      throw new InvalidParameterValueException(
          "requested response CRS: "
              + crs
              + " is not known by the WCS "
              + "for coverage:"
              + coverage);
    }
    // validate requested CRS
    crs = request.getDomainSubset().getRequestSRS().getCode();
    codeSpace = request.getDomainSubset().getRequestSRS().getCodeSpace();
    if (codeSpace != null) {
      space = codeSpace.toString();
    }
    CodeList[] reqcrs = co.getSupportedCRSs().getRequestSRSs();

    if (!validate(rrcrs, space, crs) && !validate(reqcrs, space, crs)) {
      throw new InvalidParameterValueException(
          "requested request CRS: " + crs + " is not known by the WCS for coverage:" + coverage);
    }
    // validate requested envelope
    Envelope envelope = request.getDomainSubset().getSpatialSubset().getEnvelope();
    LonLatEnvelope llEnv = cob.getLonLatEnvelope();
    Envelope[] domEnvs = co.getDomainSet().getSpatialDomain().getEnvelops();

    try {
      if (!intersects(envelope, request.getDomainSubset().getRequestSRS(), domEnvs, llEnv)) {
        throw new InvalidParameterValueException(
            "requested BBOX: doesn't intersect "
                + " the area of the requested coverage: "
                + coverage);
      }
    } catch (UnknownCRSException e) {
      throw new InvalidParameterValueException(e);
    }
  }