/**
   * Creates a {@link GridCoverage} for the provided {@link PlanarImage} using the {@link
   * #raster2Model} that was provided for this coverage.
   *
   * <p>This method is vital when working with coverages that have a raster to model transformation
   * that is not a simple scale and translate.
   *
   * @param coverageName
   * @param image contains the data for the coverage to create.
   * @param raster2Model is the {@link MathTransform} that maps from the raster space to the model
   *     space.
   * @return a {@link GridCoverage}
   * @throws IOException
   */
  protected final GridCoverage2D createImageCoverage(
      String coverageName, PlanarImage image, MathTransform raster2Model) throws IOException {

    // creating bands
    final SampleModel sm = image.getSampleModel();
    final ColorModel cm = image.getColorModel();
    final int numBands = sm.getNumBands();
    final GridSampleDimension[] bands = new GridSampleDimension[numBands];
    // setting bands names.
    for (int i = 0; i < numBands; i++) {
      final ColorInterpretation colorInterpretation = TypeMap.getColorInterpretation(cm, i);
      if (colorInterpretation == null) throw new IOException("Unrecognized sample dimension type");
      bands[i] = new GridSampleDimension(colorInterpretation.name()).geophysics(true);
    }
    // creating coverage
    if (raster2Model != null) {
      return coverageFactory.create(
          coverageName,
          image,
          getCoordinateReferenceSystem(coverageName),
          raster2Model,
          bands,
          null,
          null);
    }
    return coverageFactory.create(
        coverageName,
        image,
        new GeneralEnvelope(getOriginalEnvelope(coverageName)),
        bands,
        null,
        null);
  }
  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;
  }
  /**
   * Creates a {@link GridCoverage} for the provided {@link PlanarImage} using the {@link
   * #raster2Model} that was provided for this coverage.
   *
   * <p>This method is vital when working with coverages that have a raster to model transformation
   * that is not a simple scale and translate.
   *
   * @param image contains the data for the coverage to create.
   * @param raster2Model is the {@link MathTransform} that maps from the raster space to the model
   *     space.
   * @return a {@link GridCoverage}
   * @throws IOException
   */
  protected final GridCoverage2D createCoverage(PlanarImage image, MathTransform raster2Model)
      throws IOException {

    // creating bands
    final SampleModel sm = image.getSampleModel();
    final ColorModel cm = image.getColorModel();
    final int numBands = sm.getNumBands();
    final GridSampleDimension[] bands = new GridSampleDimension[numBands];
    // setting bands names.

    Category noDataCategory = null;
    final Map<String, Double> properties = new HashMap<String, Double>();
    if (!Double.isNaN(noData)) {
      noDataCategory =
          new Category(
              Vocabulary.formatInternational(VocabularyKeys.NODATA),
              new Color[] {new Color(0, 0, 0, 0)},
              NumberRange.create(noData, noData),
              NumberRange.create(noData, noData));

      properties.put("GC_NODATA", new Double(noData));
    }

    Set<String> bandNames = new HashSet<String>();
    for (int i = 0; i < numBands; i++) {
      final ColorInterpretation colorInterpretation = TypeMap.getColorInterpretation(cm, i);
      if (colorInterpretation == null) throw new IOException("Unrecognized sample dimension type");
      Category[] categories = null;
      if (noDataCategory != null) {
        categories = new Category[] {noDataCategory};
      }
      String bandName = colorInterpretation.name();
      // make sure we create no duplicate band names
      if (colorInterpretation == ColorInterpretation.UNDEFINED || bandNames.contains(bandName)) {
        bandName = "Band" + (i + 1);
      }
      bands[i] = new GridSampleDimension(bandName, categories, null).geophysics(true);
    }
    // creating coverage
    if (raster2Model != null) {
      return coverageFactory.create(
          coverageName, image, crs, raster2Model, bands, null, properties);
    }
    return coverageFactory.create(
        coverageName, image, new GeneralEnvelope(originalEnvelope), bands, null, properties);
  }