private GeneralEnvelope getResultEnvelope(
      final List<RasterQueryInfo> queryInfos, final GridEnvelope mosaicGeometry) {

    // use the same queryInfo used by setMosaicLocations
    final RasterQueryInfo baseQueryInfo = RasterUtils.findLowestResolution(queryInfos);

    GeneralEnvelope finalEnvelope = null;
    // if (queryInfos.size() == 1) {
    // finalEnvelope = queryInfos.get(0).getResultEnvelope();
    // } else {
    int rasterIndex = baseQueryInfo.getRasterIndex();
    int pyramidLevel = baseQueryInfo.getPyramidLevel();
    MathTransform rasterToModel = rasterInfo.getRasterToModel(rasterIndex, pyramidLevel);
    CoordinateReferenceSystem coverageCrs = rasterInfo.getCoverageCrs();
    GeneralEnvelope mosaicGeometryEnv = new GeneralEnvelope(coverageCrs);
    mosaicGeometryEnv.setEnvelope(
        mosaicGeometry.getLow(0),
        mosaicGeometry.getLow(1),
        1 + mosaicGeometry.getHigh(0),
        1 + mosaicGeometry.getHigh(1));
    try {
      finalEnvelope = CRS.transform(rasterToModel, mosaicGeometryEnv);
      finalEnvelope.setCoordinateReferenceSystem(coverageCrs);
    } catch (TransformException e) {
      throw new RuntimeException(e);
    }
    // }

    // double[] resolution = baseQueryInfo.getResolution();
    // finalEnvelope = toPixelCenter(resolution, finalEnvelope);
    return finalEnvelope;
  }
  private List<RasterQueryInfo> findMatchingRasters(
      final GeneralEnvelope requestedEnvelope,
      final GridEnvelope requestedDim,
      final OverviewPolicy overviewPolicy) {

    final List<RasterQueryInfo> matchingQueries;
    matchingQueries =
        RasterUtils.findMatchingRasters(
            rasterInfo, requestedEnvelope, requestedDim, overviewPolicy);

    if (matchingQueries.isEmpty()) {
      return matchingQueries;
    }

    for (RasterQueryInfo match : matchingQueries) {
      RasterUtils.fitRequestToRaster(requestedEnvelope, rasterInfo, match);
    }
    return matchingQueries;
  }
  /**
   * @see GridCoverageReader#read(GeneralParameterValue[])
   * @return A new {@linkplain GridCoverage grid coverage} from the input source, or {@code null} if
   *     the requested envelope is outside the data bounds
   */
  public GridCoverage2D read(GeneralParameterValue[] params) throws IOException {
    final GeneralEnvelope requestedEnvelope;
    final GridEnvelope requestedDim;
    final OverviewPolicy overviewPolicy;
    {
      final ReadParameters opParams = parseReadParams(params);
      overviewPolicy = opParams.overviewPolicy;
      requestedEnvelope = opParams.requestedEnvelope;
      requestedDim = opParams.dim;
    }

    /*
     * For each raster in the raster dataset, obtain the tiles, pixel range, and resulting
     * envelope
     */
    final List<RasterQueryInfo> queries;
    queries = findMatchingRasters(requestedEnvelope, requestedDim, overviewPolicy);
    if (queries.isEmpty()) {
      if (requestedEnvelope.intersects(getOriginalEnvelope(), true)) {
        /*
         * No matching rasters but envelopes intersect, meaning it's a raster catalog with
         * irregular coverage and the request lies on an area with no coverage
         */
        ImageTypeSpecifier imageTypeSpecifier;
        imageTypeSpecifier = RasterUtils.createFullImageTypeSpecifier(rasterInfo, 0);
        SampleModel sampleModel = imageTypeSpecifier.getSampleModel();
        Point location = new Point(0, 0);
        WritableRaster raster = Raster.createWritableRaster(sampleModel, location);
        GridCoverage2D emptyCoverage;
        emptyCoverage = coverageFactory.create(coverageName, raster, requestedEnvelope);
        return emptyCoverage;
      }
      /*
       * none of the rasters match the requested envelope.
       */
      return null;
    }

    final LoggingHelper log = new LoggingHelper();

    /*
     * Once we collected the matching rasters and their image subsets, find out where in the
     * overall resulting mosaic they fit. If the rasters does not share the spatial resolution,
     * the QueryInfo.resultDimension and QueryInfo.mosaicLocation width or height won't match
     */
    final GridEnvelope mosaicGeometry;
    mosaicGeometry = RasterUtils.setMosaicLocations(rasterInfo, queries);

    if (mosaicGeometry.getSpan(0) == 0 || mosaicGeometry.getSpan(1) == 0) {
      LOGGER.finer(
          "Mosaic geometry width or height is zero,"
              + " returning fake coverage for pixels "
              + mosaicGeometry);
      return null;
    }
    /*
     * Gather the rendered images for each of the rasters that match the requested envelope
     */
    final TiledRasterReader rasterReader = rasterReaderFactory.create(rasterInfo);

    try {
      readAllTiledRasters(queries, rasterReader, log);
    } finally {
      // rasterReader.dispose();
    }

    log.log(LoggingHelper.REQ_ENV);
    log.log(LoggingHelper.RES_ENV);
    log.log(LoggingHelper.MOSAIC_ENV);
    log.log(LoggingHelper.MOSAIC_EXPECTED);

    final RenderedImage coverageRaster = createMosaic(queries, mosaicGeometry, log);

    assert mosaicGeometry.getSpan(0) == coverageRaster.getWidth();
    assert mosaicGeometry.getSpan(1) == coverageRaster.getHeight();

    /*
     * BUILDING COVERAGE
     */
    GridSampleDimension[] bands = getSampleDimensions(coverageRaster);

    final GeneralEnvelope resultEnvelope = getResultEnvelope(queries, mosaicGeometry);
    log.appendLoggingGeometries(LoggingHelper.REQ_ENV, requestedEnvelope);
    log.appendLoggingGeometries(LoggingHelper.RES_ENV, resultEnvelope);

    GridCoverage2D resultCoverage =
        coverageFactory.create(coverageName, coverageRaster, resultEnvelope, bands, null, null);

    // MathTransform gridToCRS = rasterInfo.getRasterToModel(queries.get(0).getRasterIndex(),
    // queries.get(0).getPyramidLevel());
    //
    // GridGeometry2D gridGeometry = new GridGeometry2D(PixelInCell.CELL_CORNER, gridToCRS,
    // resultEnvelope, hints);
    //
    // GridCoverage[] sources = null;
    // Map<?, ?> properties = null;
    // GridCoverage2D resultCoverage = coverageFactory.create(coverageName, coverageRaster,
    // gridGeometry, bands, sources, properties);
    return resultCoverage;
  }