diff --git a/cave/com.raytheon.viz.geotiff/META-INF/MANIFEST.MF b/cave/com.raytheon.viz.geotiff/META-INF/MANIFEST.MF index 74000c81bd..6cf04801fc 100644 --- a/cave/com.raytheon.viz.geotiff/META-INF/MANIFEST.MF +++ b/cave/com.raytheon.viz.geotiff/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Geotiff Plug-in Bundle-SymbolicName: com.raytheon.viz.geotiff;singleton:=true -Bundle-Version: 1.14.0.qualifier +Bundle-Version: 1.14.1.qualifier Bundle-Activator: com.raytheon.viz.geotiff.Activator Bundle-Vendor: Raytheon Require-Bundle: org.eclipse.ui, diff --git a/cave/com.raytheon.viz.geotiff/src/com/raytheon/viz/geotiff/rsc/GeoTiffResource.java b/cave/com.raytheon.viz.geotiff/src/com/raytheon/viz/geotiff/rsc/GeoTiffResource.java index d4ff90a924..b3b46b77d5 100644 --- a/cave/com.raytheon.viz.geotiff/src/com/raytheon/viz/geotiff/rsc/GeoTiffResource.java +++ b/cave/com.raytheon.viz.geotiff/src/com/raytheon/viz/geotiff/rsc/GeoTiffResource.java @@ -20,13 +20,12 @@ package com.raytheon.viz.geotiff.rsc; -import java.awt.image.RenderedImage; import java.io.File; import java.io.IOException; -import javax.imageio.ImageIO; - +import org.geotools.coverage.grid.GeneralGridGeometry; import org.geotools.coverage.grid.GridCoverage2D; +import org.geotools.coverage.grid.GridGeometry2D; import org.geotools.gce.geotiff.GeoTiffFormat; import org.geotools.gce.geotiff.GeoTiffReader; import org.opengis.referencing.crs.CoordinateReferenceSystem; @@ -37,13 +36,13 @@ import com.raytheon.uf.viz.core.exception.VizException; import com.raytheon.uf.viz.core.map.MapDescriptor; import com.raytheon.uf.viz.core.rsc.AbstractVizResource; import com.raytheon.uf.viz.core.rsc.LoadProperties; -import com.raytheon.viz.core.rsc.hdf5.PureMemoryBasedTileSet; +import com.raytheon.uf.viz.core.rsc.capabilities.ImagingCapability; +import com.raytheon.uf.viz.core.tile.TileSetRenderable; +import com.raytheon.uf.viz.core.tile.TileSetRenderable.TileImageCreator; /** * Supports GeoTIFF imagery * - * NOTE: maximum of 2048 height/width in pixels. - * *
  * 
  *     SOFTWARE HISTORY
@@ -51,6 +50,7 @@ import com.raytheon.viz.core.rsc.hdf5.PureMemoryBasedTileSet;
  *     Date         Ticket#     Engineer    Description
  *     ------------   ----------  -----------   --------------------------
  *     8/24/06                    chammack    Initial Creation.
+ *     Aug 14, 2014 3522          bclement    reworked to use TileSetRenderable
  * 
  * 
* @@ -60,11 +60,17 @@ import com.raytheon.viz.core.rsc.hdf5.PureMemoryBasedTileSet; public class GeoTiffResource extends AbstractVizResource { - /** The tiled image */ - private PureMemoryBasedTileSet image; + private static final int TILE_SIZE = 512; + + private TileSetRenderable image; + + private ImageStreamTileCreator tileCreator; private String filePath; + /* true since TileSetRenderable needs reproject() called on it before use */ + private boolean project = true; + protected GeoTiffResource(GeoTiffResourceData data, LoadProperties props) throws VizException, IOException { super(data, props); @@ -78,6 +84,14 @@ public class GeoTiffResource extends */ @Override protected void disposeInternal() { + if (tileCreator != null) { + try { + tileCreator.close(); + } catch (IOException e) { + statusHandler.error( + "Unable to close geotiff tile image stream", e); + } + } if (image != null) { image.dispose(); } @@ -92,28 +106,31 @@ public class GeoTiffResource extends */ @Override protected void initInternal(IGraphicsTarget target) throws VizException { + File imgFile = new File(filePath); + if (!imgFile.canRead()) { + String msg = "Check file permissions."; + if (!imgFile.exists()) { + msg = "File does not exist."; + } + throw new VizException("Unable to open geotiff image: " + + imgFile.getAbsolutePath() + + ". " + msg); + } try { GeoTiffReader gcr = (GeoTiffReader) new GeoTiffFormat() - .getReader(new File(filePath)); - - // Read in the image itself using ImageIO as it is much more - // reliable - RenderedImage img = ImageIO.read(new File(filePath)); + .getReader(imgFile); GridCoverage2D gridCoverage = (GridCoverage2D) gcr.read(null); - image = new PureMemoryBasedTileSet(resourceData.getNameGenerator() - .getName(this), this, gridCoverage.getGridGeometry(), - PureMemoryBasedTileSet.calculateLevels(img), - target.getViewType()); - image.setMapDescriptor(this.descriptor); - image.setImage(img); - image.init(target); + ImagingCapability imaging = getCapability(ImagingCapability.class); + GridGeometry2D tileSetGeometry = gridCoverage.getGridGeometry(); + TileImageCreator tileCreator = new ImageStreamTileCreator(imgFile); + image = new TileSetRenderable(imaging, tileSetGeometry, + tileCreator, 1, TILE_SIZE); gridCoverage = null; - img = null; } catch (Exception e) { - // TODO: Handle exception - e.printStackTrace(); + throw new VizException("Unable to process geotiff image: " + + imgFile.getAbsolutePath(), e); } } @@ -129,6 +146,14 @@ public class GeoTiffResource extends protected void paintInternal(IGraphicsTarget target, PaintProperties paintProps) throws VizException { if (image != null) { + if (project) { + project = false; + GeneralGridGeometry targetGeometry = descriptor + .getGridGeometry(); + if (image.getTargetGeometry() != targetGeometry) { + image.project(targetGeometry); + } + } image.paint(target, paintProps); } } @@ -142,6 +167,6 @@ public class GeoTiffResource extends */ @Override public void project(CoordinateReferenceSystem crs) throws VizException { - image.reproject(); + project = true; } } diff --git a/cave/com.raytheon.viz.geotiff/src/com/raytheon/viz/geotiff/rsc/ImageStreamTileCreator.java b/cave/com.raytheon.viz.geotiff/src/com/raytheon/viz/geotiff/rsc/ImageStreamTileCreator.java new file mode 100644 index 0000000000..57e79d6b21 --- /dev/null +++ b/cave/com.raytheon.viz.geotiff/src/com/raytheon/viz/geotiff/rsc/ImageStreamTileCreator.java @@ -0,0 +1,145 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.viz.geotiff.rsc; + +import java.awt.image.RenderedImage; +import java.io.Closeable; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.Iterator; + +import javax.imageio.ImageIO; +import javax.imageio.ImageReadParam; +import javax.imageio.ImageReader; +import javax.imageio.stream.FileImageInputStream; +import javax.imageio.stream.ImageInputStream; + +import org.geotools.coverage.grid.GeneralGridGeometry; +import org.geotools.coverage.grid.GridEnvelope2D; + +import com.raytheon.uf.viz.core.DrawableImage; +import com.raytheon.uf.viz.core.IGraphicsTarget; +import com.raytheon.uf.viz.core.IMesh; +import com.raytheon.uf.viz.core.PixelCoverage; +import com.raytheon.uf.viz.core.data.IRenderedImageCallback; +import com.raytheon.uf.viz.core.drawables.IImage; +import com.raytheon.uf.viz.core.exception.VizException; +import com.raytheon.uf.viz.core.map.IMapMeshExtension; +import com.raytheon.uf.viz.core.tile.Tile; +import com.raytheon.uf.viz.core.tile.TileSetRenderable.TileImageCreator; + +/** + * Tile image creator that gets tiles from a FileImageInputStream. Must be + * closed after use. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Aug 14, 2014 3522       bclement     Initial creation
+ * 
+ * 
+ * + * @author bclement + * @version 1.0 + */ +public class ImageStreamTileCreator implements TileImageCreator, Closeable { + + private final ImageInputStream imgIn; + + private final ImageReader imgReader; + + /** + * @param in + * @throws IOException + * @see {@link #close()} + */ + public ImageStreamTileCreator(FileImageInputStream in) throws IOException { + this.imgIn = in; + Iterator readers = ImageIO.getImageReaders(imgIn); + if (readers.hasNext()) { + this.imgReader = readers.next(); + imgReader.setInput(imgIn); + } else { + imgIn.close(); + throw new IOException("No image readers found for stream"); + } + } + + /** + * @param imageFile + * @throws FileNotFoundException + * @throws IOException + * @see {@link #close()} + */ + public ImageStreamTileCreator(File imageFile) throws FileNotFoundException, + IOException { + this(new FileImageInputStream(imageFile)); + } + + /* (non-Javadoc) + * @see com.raytheon.uf.viz.core.tile.TileSetRenderable.TileImageCreator#createTileImage(com.raytheon.uf.viz.core.IGraphicsTarget, com.raytheon.uf.viz.core.tile.Tile, org.geotools.coverage.grid.GeneralGridGeometry) + */ + @Override + public DrawableImage createTileImage(IGraphicsTarget target, Tile tile, + GeneralGridGeometry targetGeometry) throws VizException { + if (tile.tileLevel != 0) { + throw new VizException(getClass().getSimpleName() + + " only supports single level tiled data"); + } + final GridEnvelope2D env = tile.tileGeometry.getGridRange2D(); + final ImageReadParam param = imgReader.getDefaultReadParam(); + param.setSourceRegion(env); + IImage img = target.initializeRaster(new IRenderedImageCallback() { + + @Override + public RenderedImage getImage() throws VizException { + try { + synchronized (imgReader) { + return imgReader.read(0, param); + } + } catch (IOException e) { + throw new VizException( + "Unable to read tile from image stream for bounds: " + + env, e); + } + } + }); + + IMesh mesh = target.getExtension(IMapMeshExtension.class) + .constructMesh(tile.tileGeometry, targetGeometry); + return new DrawableImage(img, new PixelCoverage(mesh)); + } + + /* + * (non-Javadoc) + * + * @see java.io.Closeable#close() + */ + @Override + public void close() throws IOException { + imgIn.close(); + imgReader.dispose(); + } + +}