class Utilities {

    public static GridCoverage createCoverage(ImageReaderSpi spi, Object input,
            final int imageIndex, ImageReadParam imageReadParam, final boolean useJAI,
            final boolean useMultithreading, final boolean newTransform,
            final GridSampleDimension[] sampleDimensions, final String coverageName,
            GridCoverageFactory coverageFactory, MathTransform raster2Model,
            CoordinateReferenceSystem coordinateReferenceSystem, GeneralEnvelope coverageEnvelope2D)
            throws IOException {
        // ////////////////////////////////////////////////////////////////////
        //
        // Doing an image read for reading the coverage.
        //
        // ////////////////////////////////////////////////////////////////////
        final PlanarImage image = readImage(spi, input, imageIndex, useJAI, imageReadParam,
                useMultithreading);

        // /////////////////////////////////////////////////////////////////////
        //
        // Creating the coverage
        //
        // /////////////////////////////////////////////////////////////////////
        if (newTransform) {
            // I need to calculate a new transformation (raster2Model)
            // between the cropped image and the required envelope
            final int ssWidth = image.getWidth();
            final int ssHeight = image.getHeight();

            // //
            //
            // setting new coefficients to define a new affineTransformation
            // to be applied to the grid to world transformation
            // ------------------------------------------------------
            //
            // With respect to the original envelope, the obtained
            // planarImage needs to be rescaled and translated. The scaling
            // factors are computed as the ratio between the cropped source
            // region sizes and the read image sizes. The translate
            // settings are represented by the offsets of the source region.
            //
            // //
            final Rectangle sourceRegion = imageReadParam.getSourceRegion();
            final double scaleX = sourceRegion.width / (1.0 * ssWidth);
            final double scaleY = sourceRegion.height / (1.0 * ssHeight);
            final double translateX = sourceRegion.x;
            final double translateY = sourceRegion.y;
            return Utilities.createCoverageFromImage(coverageFactory, coverageName, imageIndex,
                    image, ConcatenatedTransform.create(ProjectiveTransform
                            .create(new AffineTransform(scaleX, 0, 0, scaleY, translateX,
                                    translateY)), raster2Model), coordinateReferenceSystem,
                    (GeneralEnvelope) null, sampleDimensions, true);
        } else {
            // In case of no transformation is required (As an instance,
            // when reading the whole image)
            return Utilities.createCoverageFromImage(coverageFactory, coverageName, imageIndex,
                    image, (MathTransform) null, (CoordinateReferenceSystem) null,
                    coverageEnvelope2D, sampleDimensions, true);
        }
    }

    private  Utilities();

}