7

I am new to working with Raster in GeoTools-very experienced in java. My goal is to read in a geotiff that has multiple bands, then create a HashMap for each pixel, where the key is simply the lat/lon of the pixel, and the value is a sortedMap in which teh key is the band name, and the value is the real value of the pixel for that band. I am then going to do some fascinating stuff with that map. So in basic terms, I need to read in a tif, get each band, and access then pixel's lat lon in each band. I have a rather pathetic attempt to read in a tiff below, but I can't find any straightforward way online to get each band, and get each pixel.

GridCoverage2D g;// = new GridCoverage2D(null, null);

      GeoTiffReader r = new GeoTiffReader(new File("c;\\temp\\thetiff.tif"));
      GridEnvelope originalGridRange = r.getOriginalGridRange();

UPDATE: So I can now read in the file with the following code:

     public static void main(String[] args) {
        try {
          AbstractGridCoverage2DReader reader = new GeoTiffReader(new FileInputStream(new File("C:\\my.TIF")));//...; // Creating a reader
          String[] coverageNames = reader.getGridCoverageNames();
          // At this point, coverageNames may contain, as an instance, "pressure,temperature,humidity"

          String requestedCoverageName = coverageNames[0]; // e..g, "temperature"

          // Getting the coverage's properties
          final GeneralEnvelope envelope = reader.getOriginalEnvelope();
          final GridEnvelope gridRange = reader.getOriginalGridRange();

          // reading the coverage
//FAILS HERE
          GridCoverage2D coverage = (GridCoverage2D) reader.read(requestedCoverageName, null);
          System.out.println("test");
        } catch (Exception ex) {
          Logger.getLogger(GeoTiffvectorizer.class.getName()).log(Level.SEVERE, null, ex);
        }
      }

problem now is I know the image has 8 bands, but I only got one item in coverageNames[] and I get the following stacktrace error

Error: One factory fails for the operation "ImageRead"
Occurs in: javax.media.jai.ThreadSafeOperationRegistry
java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at javax.media.jai.FactoryCache.invoke(FactoryCache.java:122)
    at javax.media.jai.OperationRegistry.invokeFactory(OperationRegistry.java:1674)
    at javax.media.jai.ThreadSafeOperationRegistry.invokeFactory(ThreadSafeOperationRegistry.java:473)
    at javax.media.jai.registry.RIFRegistry.create(RIFRegistry.java:332)
    at javax.media.jai.RenderedOp.createInstance(RenderedOp.java:819)
    at javax.media.jai.RenderedOp.createRendering(RenderedOp.java:867)
    at javax.media.jai.RenderedOp.getWidth(RenderedOp.java:2179)
    at org.geotools.gce.geotiff.GeoTiffReader.read(GeoTiffReader.java:560)
    at org.geotools.coverage.grid.io.AbstractGridCoverage2DReader.read(AbstractGridCoverage2DReader.java:239)
    at dgi.vectorspaceclustering.GeoTiffvectorizer.main(GeoTiffvectorizer.java:38)
Caused by: java.lang.RuntimeException: javax.imageio.IIOException: I/O error reading header!
    at com.sun.media.jai.imageioimpl.ImageReadCRIF.create(ImageReadCRIF.java:317)
    ... 14 more
Caused by: javax.imageio.IIOException: I/O error reading header!
    at it.geosolutions.imageioimpl.plugins.tiff.TIFFImageReader.readHeader(TIFFImageReader.java:458)
    at it.geosolutions.imageioimpl.plugins.tiff.TIFFImageReader.locateImage(TIFFImageReader.java:465)
    at it.geosolutions.imageioimpl.plugins.tiff.TIFFImageReader.seekToImage(TIFFImageReader.java:589)
    at it.geosolutions.imageioimpl.plugins.tiff.TIFFImageReader.getImageTypes(TIFFImageReader.java:1104)
    at javax.imageio.ImageReader.getRawImageType(ImageReader.java:681)
    at com.sun.media.jai.imageioimpl.ImageReadOpImage.layoutHelper(ImageReadOpImage.java:228)
    at com.sun.media.jai.imageioimpl.ImageReadOpImage.<init>(ImageReadOpImage.java:473)
    at com.sun.media.jai.imageioimpl.ImageReadCRIF.create(ImageReadCRIF.java:309)
    ... 14 more
Caused by: java.io.EOFException
    at javax.imageio.stream.ImageInputStreamImpl.readShort(ImageInputStreamImpl.java:229)
    at javax.imageio.stream.ImageInputStreamImpl.readUnsignedShort(ImageInputStreamImpl.java:242)
    at it.geosolutions.imageioimpl.plugins.tiff.TIFFImageReader.readHeader(TIFFImageReader.java:404)
    ... 21 more
2014-07-14T16:30:36.845-0400  SEVERE  null
javax.media.jai.util.ImagingException: All factories fail for the operation "ImageRead"
    at javax.media.jai.OperationRegistry.invokeFactory(OperationRegistry.java:1687)
    at javax.media.jai.ThreadSafeOperationRegistry.invokeFactory(ThreadSafeOperationRegistry.java:473)
    at javax.media.jai.registry.RIFRegistry.create(RIFRegistry.java:332)
    at javax.media.jai.RenderedOp.createInstance(RenderedOp.java:819)
    at javax.media.jai.RenderedOp.createRendering(RenderedOp.java:867)
    at javax.media.jai.RenderedOp.getWidth(RenderedOp.java:2179)
    at org.geotools.gce.geotiff.GeoTiffReader.read(GeoTiffReader.java:560)
    at org.geotools.coverage.grid.io.AbstractGridCoverage2DReader.read(AbstractGridCoverage2DReader.java:239)
    at dgi.vectorspaceclustering.GeoTiffvectorizer.main(GeoTiffvectorizer.java:38)
Caused by: java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at javax.media.jai.FactoryCache.invoke(FactoryCache.java:122)
    at javax.media.jai.OperationRegistry.invokeFactory(OperationRegistry.java:1674)
    ... 8 more
Caused by: java.lang.RuntimeException: javax.imageio.IIOException: I/O error reading header!
    at com.sun.media.jai.imageioimpl.ImageReadCRIF.create(ImageReadCRIF.java:317)
    ... 14 more
Caused by: javax.imageio.IIOException: I/O error reading header!
    at it.geosolutions.imageioimpl.plugins.tiff.TIFFImageReader.readHeader(TIFFImageReader.java:458)
    at it.geosolutions.imageioimpl.plugins.tiff.TIFFImageReader.locateImage(TIFFImageReader.java:465)
    at it.geosolutions.imageioimpl.plugins.tiff.TIFFImageReader.seekToImage(TIFFImageReader.java:589)
    at it.geosolutions.imageioimpl.plugins.tiff.TIFFImageReader.getImageTypes(TIFFImageReader.java:1104)
    at javax.imageio.ImageReader.getRawImageType(ImageReader.java:681)
    at com.sun.media.jai.imageioimpl.ImageReadOpImage.layoutHelper(ImageReadOpImage.java:228)
    at com.sun.media.jai.imageioimpl.ImageReadOpImage.<init>(ImageReadOpImage.java:473)
    at com.sun.media.jai.imageioimpl.ImageReadCRIF.create(ImageReadCRIF.java:309)
    ... 14 more
Caused by: java.io.EOFException
    at javax.imageio.stream.ImageInputStreamImpl.readShort(ImageInputStreamImpl.java:229)
    at javax.imageio.stream.ImageInputStreamImpl.readUnsignedShort(ImageInputStreamImpl.java:242)
    at it.geosolutions.imageioimpl.plugins.tiff.TIFFImageReader.readHeader(TIFFImageReader.java:404)
    ... 21 more
Caused by:
java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at javax.media.jai.FactoryCache.invoke(FactoryCache.java:122)
    at javax.media.jai.OperationRegistry.invokeFactory(OperationRegistry.java:1674)
    at javax.media.jai.ThreadSafeOperationRegistry.invokeFactory(ThreadSafeOperationRegistry.java:473)
    at javax.media.jai.registry.RIFRegistry.create(RIFRegistry.java:332)
    at javax.media.jai.RenderedOp.createInstance(RenderedOp.java:819)
    at javax.media.jai.RenderedOp.createRendering(RenderedOp.java:867)
    at javax.media.jai.RenderedOp.getWidth(RenderedOp.java:2179)
    at org.geotools.gce.geotiff.GeoTiffReader.read(GeoTiffReader.java:560)
    at org.geotools.coverage.grid.io.AbstractGridCoverage2DReader.read(AbstractGridCoverage2DReader.java:239)
    at dgi.vectorspaceclustering.GeoTiffvectorizer.main(GeoTiffvectorizer.java:38)
Caused by: java.lang.RuntimeException: javax.imageio.IIOException: I/O error reading header!
    at com.sun.media.jai.imageioimpl.ImageReadCRIF.create(ImageReadCRIF.java:317)
    ... 14 more
Caused by: javax.imageio.IIOException: I/O error reading header!
    at it.geosolutions.imageioimpl.plugins.tiff.TIFFImageReader.readHeader(TIFFImageReader.java:458)
    at it.geosolutions.imageioimpl.plugins.tiff.TIFFImageReader.locateImage(TIFFImageReader.java:465)
    at it.geosolutions.imageioimpl.plugins.tiff.TIFFImageReader.seekToImage(TIFFImageReader.java:589)
    at it.geosolutions.imageioimpl.plugins.tiff.TIFFImageReader.getImageTypes(TIFFImageReader.java:1104)
    at javax.imageio.ImageReader.getRawImageType(ImageReader.java:681)
    at com.sun.media.jai.imageioimpl.ImageReadOpImage.layoutHelper(ImageReadOpImage.java:228)
    at com.sun.media.jai.imageioimpl.ImageReadOpImage.<init>(ImageReadOpImage.java:473)
    at com.sun.media.jai.imageioimpl.ImageReadCRIF.create(ImageReadCRIF.java:309)
    ... 14 more
Caused by: java.io.EOFException
    at javax.imageio.stream.ImageInputStreamImpl.readShort(ImageInputStreamImpl.java:229)
    at javax.imageio.stream.ImageInputStreamImpl.readUnsignedShort(ImageInputStreamImpl.java:242)
    at it.geosolutions.imageioimpl.plugins.tiff.TIFFImageReader.readHeader(TIFFImageReader.java:404)
    ... 21 more
6

Mark's answer is great! It really helped me out.

Here's a slightly modified version of Mark's code. The major difference is that this code does not rely on the java.awt.image package to compute the image size, number of bands, or pixel values. Instead, it uses the GeoTools Coverage API.

import org.geotools.coverage.grid.io.GridCoverage2DReader;
import org.geotools.gce.geotiff.GeoTiffReader;
import org.geotools.coverage.grid.*;
import org.opengis.coverage.grid.*;
import org.opengis.parameter.GeneralParameterValue;
import org.opengis.parameter.ParameterValue;
import org.geotools.coverage.grid.io.AbstractGridFormat;
import org.geotools.coverage.grid.io.OverviewPolicy;


public class Test {
    public static void test(java.io.File file) throws Exception {

        ParameterValue<OverviewPolicy> policy = AbstractGridFormat.OVERVIEW_POLICY.createValue();
        policy.setValue(OverviewPolicy.IGNORE);

        //this will basically read 4 tiles worth of data at once from the disk...
        ParameterValue<String> gridsize = AbstractGridFormat.SUGGESTED_TILE_SIZE.createValue();

        //Setting read type: use JAI ImageRead (true) or ImageReaders read methods (false)
        ParameterValue<Boolean> useJaiRead = AbstractGridFormat.USE_JAI_IMAGEREAD.createValue();
        useJaiRead.setValue(true);


        GridCoverage2DReader reader = new GeoTiffReader(file);
        GridEnvelope dimensions = reader.getOriginalGridRange();
        GridCoordinates maxDimensions = dimensions.getHigh();
        int w = maxDimensions.getCoordinateValue(0)+1;
        int h = maxDimensions.getCoordinateValue(1)+1;
        int numBands = reader.getGridCoverageCount();

        GridCoverage2D coverage = reader.read(
            new GeneralParameterValue[]{policy, gridsize, useJaiRead}
        );
        GridGeometry2D geometry = coverage.getGridGeometry();


        for (int i=0; i<w; i++) {
            for (int j=0; j<h; j++) {

                org.geotools.geometry.Envelope2D pixelEnvelop =
                geometry.gridToWorld(new GridEnvelope2D(i, j, 1, 1));

                double lat = pixelEnvelop.getCenterY();
                double lon = pixelEnvelop.getCenterX();

                double[] vals = new double[numBands];
                coverage.evaluate(new GridCoordinates2D(i, j), vals);

                //Do something!

            }
        }

    }
}
  • How to convert to EPSG:4326? – Mr. P Aug 31 '16 at 11:26
  • 351399.0450625 showing expeceted 22 and 69 – Mr. P Aug 31 '16 at 11:54
  • This can be simplified a bit by calling geometry.gridToWorld(new GridCoordinates2D(i, j)), returning a DirectPosition that can be passed on to coverage.evaluate. – dbaston Apr 24 '18 at 1:26
  • 'numBands' is evaluated to 1, no-matter if it is an ARGB or greyscaled geotiff. How do I determine if the band has 1 (greyscale), 4(argb), or another number of color components? – MojioMS Nov 7 '18 at 11:19
4

I finally figured it out... this code assumes that the geotif is in wgs84 (4326) proj, but it works well for getting the lat long for each pixel, and the band values for each pixel (formatted as a csv here). Hope this helps.

import com.spatial4j.core.io.GeohashUtils;
import java.awt.geom.Rectangle2D;
import org.geotools.coverage.grid.GridCoverage2D;
import org.geotools.coverage.grid.GridEnvelope2D;
import org.geotools.coverage.grid.GridGeometry2D;
import org.geotools.coverage.grid.io.AbstractGridFormat;
import org.geotools.coverage.grid.io.OverviewPolicy;
import org.geotools.gce.geotiff.GeoTiffReader;
import org.geotools.geometry.Envelope2D;
import org.opengis.parameter.GeneralParameterValue;
import org.opengis.parameter.ParameterValue;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.cs.CoordinateSystem;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.awt.image.WritableRaster;
import java.io.File;
import java.io.Serializable;


public class PixelExtractor implements Serializable {

  /**
   * returns a pixel as a string with teh following format String outString =
   * geoHash + "@" + name + "@" + date + "@" + originalBands
   *
   * @param f the geotif file
   * @param name the name of the file
   * @param date the date of information (when the image was captured)
   * @param collector
   * @throws Exception
   */
  public void extract(File f, String name, String date) throws Exception {
    ParameterValue<OverviewPolicy> policy = AbstractGridFormat.OVERVIEW_POLICY
            .createValue();
    policy.setValue(OverviewPolicy.IGNORE);

    // this will basically read 4 tiles worth of data at once from the disk...
    ParameterValue<String> gridsize = AbstractGridFormat.SUGGESTED_TILE_SIZE.createValue();
    //gridsize.setValue(512 * 4 + "," + 512);

    // Setting read type: use JAI ImageRead (true) or ImageReaders read methods (false)
    ParameterValue<Boolean> useJaiRead = AbstractGridFormat.USE_JAI_IMAGEREAD.createValue();
    useJaiRead.setValue(true);

    //reader.read(new GeneralParameterValue[] { policy, gridsize, useJaiRead });
    GridCoverage2D image
            = new GeoTiffReader(f).read(new GeneralParameterValue[]{policy, gridsize, useJaiRead});
    Rectangle2D bounds2D = image.getEnvelope2D().getBounds2D();
  bounds2D.getCenterX();
    // calculate zoom level for the image
    GridGeometry2D geometry = image.getGridGeometry();



    BufferedImage img = ImageIO.read(f);
    // ColorModel colorModel = img.getColorModel(      
    WritableRaster raster = img.getRaster();

    int numBands = raster.getNumBands();

    int w = img.getWidth();
    int h = img.getHeight();
    outer:
    for (int i = 0; i < w; i++) {//width...

      for (int j = 0; j < h; j++) {

        double[] latlon = geo(geometry, i, j);
        double lat = latlon[0];
        double lon = latlon[1];

        Double s = 0d;

        String originalBands = "";
        for (int k = 0; k < numBands; k++) {
          double d = raster.getSampleDouble(i, j, k);
          originalBands += d + ",";
          s += d;
        }

        originalBands = originalBands.substring(0, originalBands.length() - 1);
        if (s.compareTo(0d) == 0) {
          continue;
        }
        String geoHash = GeohashUtils.encodeLatLon(lat, lon);
//here do something with the bands, lat, long, geohash, etc....

      }

    }

  }

  private static double[] geo(GridGeometry2D geometry, int x, int y) throws Exception {

    //int zoomlevel = 1;
    Envelope2D pixelEnvelop = geometry.gridToWorld(new GridEnvelope2D(x, y, 1, 1));

    // pixelEnvelop.getCoordinateReferenceSystem().getName().getCodeSpace();
    return new double[]{pixelEnvelop.getCenterY(), pixelEnvelop.getCenterX()};

  }

}
  • This is great- thanks! I posted a slightly modified version of your code that doesn't use the java.awt.image classes. – Peter Jan 10 '15 at 20:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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