/** * */ package org.geotools.coverage.io.geotiff; import java.awt.Rectangle; import java.io.IOException; import java.util.Collections; import java.util.EnumSet; import java.util.List; import java.util.Map; import java.util.Set; 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.imageio.geotiff.GeoTiffException; import org.geotools.coverage.io.CoverageCapabilities; import org.geotools.coverage.io.CoverageReadRequest; import org.geotools.coverage.io.CoverageResponse; import org.geotools.coverage.io.CoverageSource; import org.geotools.coverage.io.CoverageResponse.Status; import org.geotools.coverage.io.geotiff.GeoTiffAccess.Info; import org.geotools.coverage.io.impl.DefaultCoverageResponseImpl; import org.geotools.coverage.io.metadata.MetadataNode; import org.geotools.coverage.io.range.RangeType; import org.geotools.data.Parameter; import org.geotools.geometry.jts.ReferencedEnvelope; import org.geotools.util.NullProgressListener; import org.omg.CORBA.DomainManager; import org.opengis.feature.type.Name; import org.opengis.geometry.BoundingBox; import org.opengis.geometry.Envelope; import org.opengis.metadata.spatial.PixelOrientation; import org.opengis.parameter.GeneralParameterValue; import org.opengis.parameter.ParameterValue; import org.opengis.referencing.crs.CoordinateReferenceSystem; import org.opengis.referencing.datum.PixelInCell; import org.opengis.referencing.operation.MathTransform2D; import org.opengis.temporal.TemporalGeometricPrimitive; import org.opengis.util.ProgressListener; /** * Source of GeoTiff coverage data; used for read-only access to a GeoTiff file * or stream. * * @author simone * * @source $URL: http://svn.osgeo.org/geotools/branches/2.7.x/build/maven/javadoc/../../../modules/unsupported/coverage-experiment/geotiff/src/main/java/org/geotools/coverage/io/geotiff/GeoTiffSource.java $ */ public class GeoTiffSource implements CoverageSource { /** * CoverageAccess we are working from. * <p> * We will refer to this CoverageAccess from time to time (in particular to * access a "global lock" used to prevent write operations tripping up over * each other). */ protected GeoTiffAccess access; /** Name of the Coverage we are providing */ protected Name name; protected RangeType rangeType; protected EnumSet<CoverageCapabilities> capabilities; /** * */ GeoTiffSource(final GeoTiffAccess geotiffAccess, final Name name) { access = geotiffAccess; this.name = name; capabilities = EnumSet.of( CoverageCapabilities.READ_HORIZONTAL_DOMAIN_SUBSAMBLING, CoverageCapabilities.READ_RANGE_SUBSETTING, CoverageCapabilities.READ_REPROJECTION, CoverageCapabilities.READ_SUBSAMPLING); } /** Used to quickly check if we are disposed. */ protected boolean isDisposed() { return name == null; } protected void ensureNotDisposed() { if (isDisposed()) { throw new IllegalStateException("Disposed"); } } public EnumSet<CoverageCapabilities> getCapabilities() { return EnumSet.copyOf(capabilities); } /* * (non-Javadoc) * * @see org.geotools.coverage.io.CoverageSource#dispose() */ public synchronized void dispose() { this.access = null; this.name = null; } /* * (non-Javadoc) * * @see * org.geotools.coverage.io.CoverageSource#getCoordinateReferenceSystem( * org.opengis.util.ProgressListener) */ public CoordinateReferenceSystem getCoordinateReferenceSystem( ProgressListener listener) throws IOException { ensureNotDisposed(); return getInfo(listener).getCRS(); } /* * (non-Javadoc) * * @see * org.geotools.coverage.io.CoverageSource#getGridToWorldTransform(boolean, * org.opengis.util.ProgressListener) */ public MathTransform2D getGridToWorldTransform(boolean brief, ProgressListener listener) throws IOException { ensureNotDisposed(); return getInfo(listener).getGeometry().getGridToCRS2D( PixelOrientation.CENTER); } /* * (non-Javadoc) * * @see org.geotools.coverage.io.CoverageSource#getHorizontalDomain(boolean, * org.opengis.util.ProgressListener) */ public List<BoundingBox> getHorizontalDomain(boolean global, ProgressListener listener) throws IOException { ensureNotDisposed(); Info info = getInfo( listener ); BoundingBox bbox = info.getBounds(); return Collections.singletonList( bbox); } /* * (non-Javadoc) * * @see org.geotools.coverage.io.CoverageSource#getInfo(org.opengis.util. * ProgressListener) */ public Info getInfo(ProgressListener listener) { ensureNotDisposed(); return access.getInfo( name, listener); } /* * (non-Javadoc) * * @seeorg.geotools.coverage.io.CoverageSource#getName(org.opengis.util. * ProgressListener) */ public Name getName(ProgressListener listener) { ensureNotDisposed(); return this.name; } public RangeType getRangeType(ProgressListener listener) throws IOException { ensureNotDisposed(); return access.rangeType; } /* * (non-Javadoc) * * @see org.geotools.coverage.io.CoverageSource#getRasterDomain(boolean, * org.opengis.util.ProgressListener) */ public List<Rectangle> getRasterDomain(boolean overall, ProgressListener listener) throws IOException { ensureNotDisposed(); Info info = getInfo( listener ); return Collections.singletonList(new Rectangle(info.getGeometry().getGridRange2D())); } /* * (non-Javadoc) * * @see * org.geotools.coverage.io.CoverageSource#getTemporalDomain(org.opengis * .util.ProgressListener) */ public Set<TemporalGeometricPrimitive> getTemporalDomain( ProgressListener listener) throws IOException { ensureNotDisposed(); return Collections.emptySet(); } /* * (non-Javadoc) * * @see org.geotools.coverage.io.CoverageSource#getVerticalDomain(boolean, * org.opengis.util.ProgressListener) */ public Set<Envelope> getVerticalDomain(boolean global, ProgressListener listener) throws IOException { ensureNotDisposed(); return Collections.emptySet(); } public Map<String, Parameter<?>> getReadParameterInfo() { ensureNotDisposed(); // TODO Auto-generated method stub return null; } /* * (non-Javadoc) * * @see * org.geotools.coverage.io.CoverageSource#read(org.geotools.coverage.io * .CoverageRequest, org.opengis.util.ProgressListener) */ public CoverageResponse read(final CoverageReadRequest request, ProgressListener listener) throws IOException { ensureNotDisposed(); final DefaultCoverageResponseImpl response = new DefaultCoverageResponseImpl(); response.setRequest(request); if (listener == null) listener = new NullProgressListener(); listener.started(); try { access.read(new GeoTiffAccess.Read<CoverageResponse>() { public CoverageResponse run(GeoTiffReader reader, GeoTiffAccess access) throws IOException { // get the request elements final BoundingBox bbox = request.getGeographicArea(); final Rectangle rasterArea = request.getRasterArea(); final MathTransform2D g2w = request .getGridToWorldTransform(); final GridCoverage2D coverage; if (g2w != null || rasterArea != null || g2w != null) { final ParameterValue<GridGeometry2D> readParameter = AbstractGridFormat.READ_GRIDGEOMETRY2D .createValue(); if (g2w == null) { if (rasterArea == null) { Info info = getInfo(null ); readParameter.setValue(new GridGeometry2D( info.getGeometry().getGridRange2D(), new ReferencedEnvelope(bbox))); } else { readParameter.setValue(new GridGeometry2D( new GridEnvelope2D(rasterArea), new ReferencedEnvelope(bbox))); } } else { readParameter.setValue(new GridGeometry2D( new GridEnvelope2D(rasterArea), PixelInCell.CELL_CENTER, g2w, bbox .getCoordinateReferenceSystem(), null)); } coverage = (GridCoverage2D) reader .read(new GeneralParameterValue[] { readParameter }); } else { coverage = (GridCoverage2D) reader.read(null); } response.addResult(coverage); response.setStatus(Status.SUCCESS); return response; } }); } catch (Throwable e) { response.addException(new GeoTiffException(null, "IO error", e)); } finally { listener.complete(); } return response; } public MetadataNode getMetadata(String metadataDomain, ProgressListener listener) { ensureNotDisposed(); throw new UnsupportedOperationException(); } public Set<Name> getMetadataDomains() { ensureNotDisposed(); throw new UnsupportedOperationException(); } public DomainManager getDomainManager(ProgressListener listener) throws IOException { // TODO Auto-generated method stub return null; } }