class AffineProcess implements RasterProcess {

    @DescribeResult(name = "result", description = "Raster transformed by an Affine transformation")
    public GridCoverage2D execute(
            @DescribeParameter(name = "coverage", description = "Input raster", min = 1) GridCoverage2D coverage,
            @DescribeParameter(name = "scalex", description = "Scale parameter for the X direction", min = 0) Double scaleX,
            @DescribeParameter(name = "scaley", description = "Scale parameter for the Y direction", min = 0) Double scaleY,
            @DescribeParameter(name = "shearx", description = "Shear parameter for the X direction", min = 0) Double shearX,
            @DescribeParameter(name = "sheary", description = "Shear parameter for the Y direction", min = 0) Double shearY,
            @DescribeParameter(name = "translatex", description = "Offset parameter for the X direction", min = 0) Double translateX,
            @DescribeParameter(name = "translatey", description = "Offset parameter for the Y direction", min = 0) Double translateY,
            @DescribeParameter(name = "nodata", description = "Output coverage nodata values", min = 0) double[] nodata,
            @DescribeParameter(name = "interpolation", description = "Interpolation function to use.  Values are NEAREST, BILINEAR, BICUBIC2, BICUBIC", min = 0) Interpolation interp)
            throws ProcessException {

        // //
        //
        // Creation of the Affine transformation
        //
        // //
        double xScale = scaleX != null ? scaleX : 1;
        double yScale = scaleY != null ? scaleY : 1;
        double xShear = shearX != null ? shearX : 0;
        double yShear = shearY != null ? shearY : 0;
        double xTrans = translateX != null ? translateX : 0;
        double yTrans = translateY != null ? translateY : 0;
        AffineTransform transform = new AffineTransform(xScale, yShear, xShear, yScale, xTrans,
                yTrans);

        // //
        //
        // Selection of the Operation parameters
        //
        // //
        final ParameterValueGroup params = AFFINE.getParameters();
        // Setting of the Source Coverage
        params.parameter("Source").setValue(coverage);
        // Setting of the Transformation parameter
        params.parameter("transform").setValue(transform);
        // Setting of the background value to use if present
        if (nodata != null) {
            params.parameter("backgroundValues").setValue(nodata);
        }

        // If interpolation is present then it is added as a parameter
        if (interp != null) {
            params.parameter("interpolation").setValue(interp);
        }

        // //
        //
        // Execution of the Operation
        //
        // //
        return (GridCoverage2D) PROCESSOR.doOperation(params);
    }

}