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;
  }
 @Override
 public ServiceInfo getInfo() {
   if (serviceInfo == null) {
     serviceInfo = new DefaultServiceInfo();
     serviceInfo.setTitle(rasterInfo.getRasterTable());
     serviceInfo.setDescription(rasterInfo.toString());
     Set<String> keywords = new HashSet<String>();
     keywords.add("ArcSDE");
     serviceInfo.setKeywords(keywords);
   }
   return serviceInfo;
 }
  private GridSampleDimension[] getSampleDimensions(final RenderedImage coverageRaster)
      throws IOException {

    GridSampleDimension[] bands = rasterInfo.getGridSampleDimensions();

    // may the image have been promoted? build the correct band info then
    final int imageBands = coverageRaster.getSampleModel().getNumBands();
    if (bands.length == 1 && imageBands > 1) {
      LOGGER.fine(
          coverageName
              + " was promoted from 1 to "
              + coverageRaster.getSampleModel().getNumBands()
              + " bands, returning an appropriate set of GridSampleDimension");
      // stolen from super.createCoverage:
      final ColorModel cm = coverageRaster.getColorModel();
      bands = new GridSampleDimension[imageBands];

      // setting bands names.
      for (int i = 0; i < imageBands; i++) {
        final ColorInterpretation colorInterpretation;
        colorInterpretation = TypeMap.getColorInterpretation(cm, i);
        if (colorInterpretation == null) {
          throw new IOException("Unrecognized sample dimension type");
        }
        bands[i] = new GridSampleDimension(colorInterpretation.name()).geophysics(true);
      }
    }

    return bands;
  }
  /**
   * For each raster: crop->scale->translate->add to mosaic
   *
   * @param queries
   * @param mosaicGeometry
   * @return
   * @throws IOException
   */
  private RenderedImage createMosaic(
      final List<RasterQueryInfo> queries,
      final GridEnvelope mosaicGeometry,
      final LoggingHelper log)
      throws IOException {

    List<RenderedImage> transformed = new ArrayList<RenderedImage>(queries.size());

    /*
     * Do we need to expand to RGB color space and then create a new colormapped image with the
     * whole mosaic?
     */
    boolean expandCM = queries.size() > 1 && rasterInfo.isColorMapped();
    if (expandCM) {
      LOGGER.fine(
          "Creating mosaic out of "
              + queries.size()
              + " colormapped rasters. The mosaic tiles will be expanded to "
              + "\nRGB space and the resulting mosaic reduced to a new IndexColorModel");
    }

    for (RasterQueryInfo query : queries) {
      RenderedImage image = query.getResultImage();
      log.log(image, query.getRasterId(), "01_original");
      if (expandCM) {
        if (LOGGER.isLoggable(Level.FINER)) {
          LOGGER.finer(
              "Creating color expanded version of tile for raster #" + query.getRasterId());
        }

        /*
         * reformat the image as a 4 band rgba backed by byte data
         */
        image = FormatDescriptor.create(image, Integer.valueOf(DataBuffer.TYPE_BYTE), null);

        log.log(image, query.getRasterId(), "04_1_colorExpanded");
      }

      image = cropToRequiredDimension(image, query.getResultGridRange());
      log.log(image, query.getRasterId(), "02_crop");

      // Raster data = image.getData();
      // image = new BufferedImage(image.getColorModel(), (WritableRaster) data, false, null);
      if (queries.size() == 1) {
        return image;
      }
      final GridEnvelope mosaicLocation = query.getMosaicLocation();
      // scale
      Float scaleX = Float.valueOf(((float) mosaicLocation.getSpan(0) / image.getWidth()));
      Float scaleY = Float.valueOf(((float) mosaicLocation.getSpan(1) / image.getHeight()));
      Float translateX = Float.valueOf(0);
      Float translateY = Float.valueOf(0);

      if (!(Float.valueOf(1.0F).equals(scaleX) && Float.valueOf(1.0F).equals(scaleY))) {
        ParameterBlock pb = new ParameterBlock();
        pb.addSource(image);
        pb.add(scaleX);
        pb.add(scaleY);
        pb.add(translateX);
        pb.add(translateY);
        pb.add(new InterpolationNearest());

        image = JAI.create("scale", pb);
        log.log(image, query.getRasterId(), "03_scale");

        int width = image.getWidth();
        int height = image.getHeight();

        assert mosaicLocation.getSpan(0) == width;
        assert mosaicLocation.getSpan(1) == height;
      }

      if (image.getMinX() != mosaicLocation.getLow(0)
          || image.getMinY() != mosaicLocation.getLow(1)) {
        // translate
        ParameterBlock pb = new ParameterBlock();
        pb.addSource(image);
        pb.add(Float.valueOf(mosaicLocation.getLow(0) - image.getMinX()));
        pb.add(Float.valueOf(mosaicLocation.getLow(1) - image.getMinY()));
        pb.add(null);

        image = JAI.create("translate", pb);
        log.log(image, query.getRasterId(), "04_translate");

        assert image.getMinX() == mosaicLocation.getLow(0)
            : image.getMinX() + " != " + mosaicLocation.getLow(0);
        assert image.getMinY() == mosaicLocation.getLow(1)
            : image.getMinY() + " != " + mosaicLocation.getLow(1);
        assert image.getWidth() == mosaicLocation.getSpan(0)
            : image.getWidth() + " != " + mosaicLocation.getSpan(0);
        assert image.getHeight() == mosaicLocation.getSpan(1)
            : image.getHeight() + " != " + mosaicLocation.getSpan(1);
      }

      transformed.add(image);
    }

    final RenderedImage mosaic;
    if (queries.size() == 1) {
      /*
       * This is besides a very slight perf improvement needed because the JAI mosaic
       * operation truncates floating point raster values to 0 and 1. REVISIT: If there's no
       * workaround for that we should prevent raster catalogs made of floating point rasters
       * and throw an exception as we could not really support that.
       */
      mosaic = transformed.get(0);
    } else {
      /*
       * adapted from RasterLayerResponse.java in the imagemosaic module
       */
      ParameterBlockJAI mosaicParams = new ParameterBlockJAI("Mosaic");
      mosaicParams.setParameter("mosaicType", MosaicDescriptor.MOSAIC_TYPE_OVERLAY);

      // set background values to raster's no-data
      double[] backgroundValues;
      if (expandCM) {
        backgroundValues = new double[] {0, 0, 0, 0};
      } else {
        final int numBands = rasterInfo.getNumBands();
        backgroundValues = new double[numBands];
        final int rasterIndex = 0;
        Number noDataValue;
        for (int bn = 0; bn < numBands; bn++) {
          noDataValue = rasterInfo.getNoDataValue(rasterIndex, bn);
          backgroundValues[bn] = noDataValue.doubleValue();
        }
      }
      mosaicParams.setParameter("backgroundValues", backgroundValues);

      final ImageLayout layout =
          new ImageLayout(
              mosaicGeometry.getLow(0),
              mosaicGeometry.getLow(1),
              mosaicGeometry.getSpan(0),
              mosaicGeometry.getSpan(1));
      final int tileWidth = rasterInfo.getTileDimension(0).width;
      final int tileHeight = rasterInfo.getTileDimension(0).height;
      layout.setTileWidth(tileWidth);
      layout.setTileHeight(tileHeight);

      final RenderingHints hints = new RenderingHints(JAI.KEY_IMAGE_LAYOUT, layout);

      for (RenderedImage img : transformed) {
        mosaicParams.addSource(img);
        log.appendLoggingGeometries(LoggingHelper.MOSAIC_RESULT, img);
      }
      log.log(LoggingHelper.MOSAIC_RESULT);

      LOGGER.fine("Creating mosaic out of " + queries.size() + " raster tiles");
      mosaic = JAI.create("Mosaic", mosaicParams, hints);

      log.log(mosaic, 0L, "05_mosaic_result");
    }
    return mosaic;
  }
  public ArcSDEGridCoverage2DReaderJAI(
      final ArcSDERasterFormat parent,
      final RasterReaderFactory rasterReaderFactory,
      final RasterDatasetInfo rasterInfo,
      final Hints hints)
      throws IOException {
    // check it's a supported format
    {
      final int bitsPerSample = rasterInfo.getBand(0, 0).getCellType().getBitsPerSample();
      if (rasterInfo.getNumBands() > 1 && (bitsPerSample == 1 || bitsPerSample == 4)) {
        throw new IllegalArgumentException(
            bitsPerSample + "-bit rasters with more than one band are not supported");
      }
    }
    this.parent = parent;
    this.rasterReaderFactory = rasterReaderFactory;
    this.rasterInfo = rasterInfo;

    super.hints = hints;
    super.coverageFactory = CoverageFactoryFinder.getGridCoverageFactory(this.hints);
    super.crs = rasterInfo.getCoverageCrs();
    super.originalEnvelope = rasterInfo.getOriginalEnvelope(PixelInCell.CELL_CENTER);

    GridEnvelope gridRange = rasterInfo.getOriginalGridRange();
    // super.originalGridRange = new GeneralGridRange(gridRange.toRectangle());
    super.originalGridRange = gridRange;

    super.coverageName = rasterInfo.getRasterTable();
    final int numLevels = rasterInfo.getNumPyramidLevels(0);

    // level 0 is not an overview, but the raster itself
    super.numOverviews = numLevels - 1;

    // ///
    //
    // setting the higher resolution avalaible for this coverage
    //
    // ///
    highestRes =
        super.getResolution(
            originalEnvelope,
            new Rectangle(
                originalGridRange.getLow(0),
                originalGridRange.getLow(1),
                originalGridRange.getSpan(0),
                originalGridRange.getSpan(1)),
            crs);
    // //
    //
    // get information for the successive images
    //
    // //
    // REVISIT may the different rasters in the raster dataset have different pyramid levels? I
    // guess so
    if (numOverviews > 0) {
      overViewResolutions = new double[numOverviews][2];
      for (int pyramidLevel = 1; pyramidLevel <= numOverviews; pyramidLevel++) {
        GridEnvelope levelGridRange = rasterInfo.getGridRange(0, pyramidLevel);
        GeneralEnvelope levelEnvelope = rasterInfo.getGridEnvelope(0, pyramidLevel);

        Rectangle2D levelGridRangeRect =
            new Rectangle2D.Double(
                levelGridRange.getLow(0),
                levelGridRange.getLow(1),
                levelGridRange.getSpan(0),
                levelGridRange.getSpan(1));
        overViewResolutions[pyramidLevel - 1] =
            super.getResolution(levelEnvelope, levelGridRangeRect, crs);
      }
    } else {
      overViewResolutions = null;
    }
  }