class AreaGridProcess implements RasterProcess {

    @DescribeResult(name = "result", description = "Output raster")
    public GridCoverage2D execute(
            @DescribeParameter(name = "envelope", description = "Bounding box for the computed raster, in WGS84 geographic coordinates.") ReferencedEnvelope bounds,
            @DescribeParameter(name = "width", description = "Width of the output raster in pixels", minValue = 1) int width,
            @DescribeParameter(name = "height", description = "Height of the output raster in pixels", minValue = 1) int height)
            throws ProcessException {

        // basic checks
        if (height <= 0 || width <= 0) {
            throw new ProcessException("height and width parameters must be greater than 0");
        }
        if (bounds.getCoordinateReferenceSystem() == null) {
            throw new ProcessException("Envelope CRS must not be null");
        }
        // build the grid
        GeometryFactory geomFactory = new GeometryFactory();
        try {
            Polygon polygon = null;
            
            CoordinateReferenceSystem sourceCRS = org.geotools.referencing.crs.DefaultGeographicCRS.WGS84;
            CoordinateReferenceSystem targetCRS = CRS.parseWKT(targetCRSWKT);
            MathTransform transform = CRS.findMathTransform(sourceCRS, targetCRS);
            double pX = bounds.getMinX();
            double pY = bounds.getMaxY();
            double stepX = (bounds.getMaxX() - bounds.getMinX()) / width;
            double stepY = (bounds.getMaxY() - bounds.getMinY()) / height;
            float[][] matrix = new float[height][width];
            Coordinate[] tempCoordinates = new Coordinate[5];

            // scroll through every cell (by row and then by col)
            for (int i = 0; i < height; i++) {
                // start of the row
                pX = bounds.getMinX();
                for (int j = 0; j < width; j++) {
                    double nX = pX + stepX;
                    double nY = pY - stepY;

                    if(polygon == null) {
                        tempCoordinates[0] = new Coordinate(pX, pY);
                        tempCoordinates[1] = new Coordinate(nX, pY);
                        tempCoordinates[2] = new Coordinate(nX, nY);
                        tempCoordinates[3] = new Coordinate(pX, nY);
                        tempCoordinates[4] = tempCoordinates[0];
                        LinearRing linearRing = geomFactory.createLinearRing(tempCoordinates);
                        polygon = geomFactory.createPolygon(linearRing, null);
                    } else {
                        tempCoordinates[0].x = pX; tempCoordinates[0].y = pY;  
                        tempCoordinates[1].x = nX; tempCoordinates[1].y = pY;
                        tempCoordinates[2].x = nX; tempCoordinates[2].y = nY;
                        tempCoordinates[3].x = pX; tempCoordinates[3].y = nY;
                        polygon.geometryChanged();
                    }

                    // transform to EckertIV and compute area
                    Geometry targetGeometry = JTS.transform(polygon, transform);
                    matrix[i][j] = (float) targetGeometry.getArea();
                    // move on
                    pX = pX + stepX;
                }
                // move to next row
                pY = pY - stepY;
            }

            // build the grid coverage
            GridCoverageFactory coverageFactory = new GridCoverageFactory();
            GridCoverage2D grid = coverageFactory.create("AreaGridCoverage", matrix, bounds);
            return grid;

        } catch (org.opengis.referencing.FactoryException ef) {
            throw new ProcessException("Unable to create the target CRS", ef);
        } catch (org.opengis.referencing.operation.TransformException et) {
            throw new ProcessException("Unable to tranform the coordinate system", et);
        }

    }

}