I've got a lot of image files (.png or .jpg) that I want to convert from one EPSG defined CRS system to another, e.g. from EPSG:31255 to EPSG:25833, on a server within a Java app.

For each image I know the coordinates (x,y) of the lower left and upper right corner in that specific CRS system.

What I've found so far:

  • QGIS: Is able to do this but I'd have to do it by hand (answer)
  • GDAL: Is able to convert images but it uses C++ (which I can't use on the server)
  • Proj4js: Can only convert coordinates
  • Geotools: I've only found information about converting coordinates or full shapefiles so far.

Can GeoTools convert images too or what other Java/JavaScript library can?


I'm currently using version 22.2 of GeoTools. The dependencies in the pom.xml file are:

  • junit
  • gt-shapefile
  • gt-swing
  • gt-geotiff
  • gt-image (not sure if I need that one)
  • gt-epsg-hsql

The imports in the java file are:

  • import org.geotools.coverage.grid.GridCoverage2D;
  • import org.geotools.coverage.grid.io.AbstractGridCoverage2DReader;
  • import org.geotools.coverage.grid.io.AbstractGridFormat;
  • import org.geotools.coverage.grid.io.GridFormatFinder;
  • import org.geotools.coverage.processing.Operations;
  • import org.geotools.gce.geotiff.GeoTiffFormat;
  • import org.geotools.gce.geotiff.GeoTiffWriter;
  • import org.geotools.referencing.CRS;
  • import org.geotools.util.factory.Hints;
  • import org.opengis.referencing.crs.CoordinateReferenceSystem;
  • are they images or raster data (with a .wld file)? or could you construct a .wld file for them?
    – Ian Turton
    Jan 27, 2020 at 15:45
  • @IanTurton They are images but I can generate the according .jgw/.pgw files if necessary.
    – Neph
    Jan 27, 2020 at 15:49

2 Answers 2


If you have a matching .wld and .prj file then the gt-image module can read and write jpeg and png files.

Once you've read the file in to a GridCoverage you can reproject it and write it out with no difficulty:

AbstractGridFormat format = GridFormatFinder.findFormat(input);
Hints hints = null;
if (format instanceof GeoTiffFormat) {
  hints = new Hints(Hints.FORCE_LONGITUDE_FIRST_AXIS_ORDER, Boolean.TRUE);

AbstractGridCoverage2DReader reader = format.getReader(input, hints);
GridCoverage2D coverage = reader.read(null);
GridCoverage2D coverageTransf = (GridCoverage2D) Operations.DEFAULT.resample(coverage, targetCRS);

GeoTiffFormat outFormat = new GeoTiffFormat();
GridCoverageWriter writer = outFormat.getWriter(destFile, hints);
writer.write(coverageTransf, null);

Assuming your input image is in input, your target CRS is in targetCRS and the output file is in destFile.

PS: see my blog post on how to add a .prj file to a lot of world images if they are missing.

  • Comments are not for extended discussion; this conversation has been moved to chat.
    – Ian Turton
    Jan 28, 2020 at 14:31

Some additional information:

To get the code in Ian Turton's answer (GeoTools 22.2, Java 8) to run properly I had to add the following dependencies to the pom.xml file:



  • gt-geotiff: Used for GeoTiffFormat (Error: GeoTiffFormat cannot be resolved to a type)
  • gt-image: Without you'll get Trying to get a reader from an unknown format. with AbstractGridCoverage2DReader reader = format.getReader(input, hints)
  • gt-epsg-hsql: Otherwise you'll get: org.opengis.referencing.NoSuchAuthorityCodeException: No code "EPSG:25833" from authority "EPSG" found for object of type "EngineeringCRS".
  • I also added gt-coverage at first but the app seems to run fine without it.

I also had to get rid of the Hints.FORCE_LONGITUDE_FIRST_AXIS_ORDER hint, otherwise the output images would all be mirrored and rotated by 90°. This does seem to depend on the used .prj file:

The file (for "EPSG:31255") I downloaded from epsg.io (use the "Well Known Text as HTML" export and rename!) works fine as it includes "TOWGS84". The .prj file I got from spatialreference.org also includes that code but still produces a wrong result (didn't test their "WKT as HTML" version though).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.