import java.awt.image.BufferedImage;
import java.io.File;

import javax.imageio.ImageIO;
import javax.media.jai.Interpolation;

import org.geotools.coverage.grid.GridCoverage2D;
import org.geotools.coverage.grid.GridCoverageFactory;
import org.geotools.coverage.grid.GridEnvelope2D;
import org.geotools.coverage.grid.GridGeometry2D;
import org.geotools.coverage.processing.Operations;
import org.geotools.factory.Hints;
import org.geotools.geometry.Envelope2D;
import org.geotools.image.ImageWorker;
import org.geotools.referencing.CRS;
import org.opengis.geometry.Envelope;

public class ReprojectCoverage {

    public static void main(String[] args) throws Exception {
        // disable optimization
        Hints.putSystemDefault(Hints.RESAMPLE_TOLERANCE, 0.0);

        // read coverage
        BufferedImage bi = ImageIO.read(new File("/tmp/earth.jpg"));
        Envelope2D envelope = new Envelope2D(CRS.decode("EPSG:4326", true), -180, -80, 360, 160);
        GridCoverage2D gc2d = new GridCoverageFactory().create("BMImage", bi, envelope);

        final Envelope targetEnvelope = CRS.transform(gc2d.getEnvelope(), CRS.decode("EPSG:3857"));
        final GridEnvelope2D gridRange = new GridEnvelope2D(0, 0, bi.getWidth(), (int) (bi
                .getWidth()
                / targetEnvelope.getSpan(0) * targetEnvelope.getSpan(1)));
        GridGeometry2D targetGG = new GridGeometry2D(gridRange, targetEnvelope);
        GridCoverage2D gc2dProj = (GridCoverage2D) Operations.DEFAULT.resample(gc2d, CRS
                .decode("EPSG:3857"), targetGG, Interpolation
                .getInstance(Interpolation.INTERP_BICUBIC));

        new ImageWorker(gc2dProj.getRenderedImage()).writeJPEG(new File("/tmp/reproject_out.jpeg"),
                "JPEG", 0.75f, false);
    }
}
