|
|
|
svn_geotools
|
Author: groldan
Date: 2009-11-04 14:13:17 -0500 (Wed, 04 Nov 2009) New Revision: 34327 Added: trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/jai/ArcSDETiledRenderedImage.java Modified: trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/gce/ArcSDEGridCoverage2DReaderJAI.java trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/gce/ArcSDERasterFormat.java trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/io/NativeTileReader.java trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/io/PromotingTileReader.java trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/io/TileFetchCommand.java trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/io/TileReader.java trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/jai/ArcSDEImageReader.java trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/raster/gce/ArcSDEGridCoverage2DReaderJAILegacyOnlineTest.java Log: GEOT-2616, random access to tiles for ArcSDERenderedImage.getTile(x, y) Modified: trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/gce/ArcSDEGridCoverage2DReaderJAI.java =================================================================== --- trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/gce/ArcSDEGridCoverage2DReaderJAI.java 2009-11-04 16:32:24 UTC (rev 34326) +++ trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/gce/ArcSDEGridCoverage2DReaderJAI.java 2009-11-04 19:13:17 UTC (rev 34327) @@ -62,7 +62,6 @@ import org.geotools.coverage.grid.io.AbstractGridCoverage2DReader; import org.geotools.coverage.grid.io.AbstractGridFormat; import org.geotools.coverage.grid.io.OverviewPolicy; -import org.geotools.data.DataSourceException; import org.geotools.data.DefaultServiceInfo; import org.geotools.data.ServiceInfo; import org.geotools.factory.Hints; @@ -439,15 +438,6 @@ pb.add(translateY); pb.add(new InterpolationNearest()); - if (queries.size() > 0) { - try { - LOGGER.info("Forcing loading data for mosaic as per GEOT-"); - // image.getData(); - } catch (RuntimeException e) { - throw new DataSourceException("Error fetching arcsde raster", e); - } - } - image = JAI.create("scale", pb); log.log(image, query.getRasterId(), "03_scale"); Modified: trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/gce/ArcSDERasterFormat.java =================================================================== --- trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/gce/ArcSDERasterFormat.java 2009-11-04 16:32:24 UTC (rev 34326) +++ trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/gce/ArcSDERasterFormat.java 2009-11-04 19:13:17 UTC (rev 34327) @@ -20,6 +20,9 @@ import java.io.File; import java.io.IOException; import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; import java.util.HashMap; import java.util.Map; import java.util.WeakHashMap; @@ -310,12 +313,17 @@ LOGGER.fine("connecting to ArcSDE Raster: " + coverageUrl); } } else if (input instanceof File) { + String path = ((File) input).getPath(); + while(path.indexOf('\\') > -1){ + path = path.replace('\\', '/'); + } + URI uri; try { - coverageUrl = ((File) input).toURI().toURL().toExternalForm(); - } catch (MalformedURLException e) { - throw new IllegalArgumentException("Can't create coverage URL out of (file) " - + ((File) input).getAbsolutePath()); - } + uri = new URI(path); + } catch (URISyntaxException e) { + throw new IllegalArgumentException(path); + } + coverageUrl = uri.toString(); if (LOGGER.isLoggable(Level.FINE)) { LOGGER.fine("connectiong via file-hack to ArcSDE Raster: " + coverageUrl); } Modified: trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/io/NativeTileReader.java =================================================================== --- trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/io/NativeTileReader.java 2009-11-04 16:32:24 UTC (rev 34326) +++ trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/io/NativeTileReader.java 2009-11-04 19:13:17 UTC (rev 34327) @@ -19,7 +19,6 @@ import java.awt.Dimension; import java.awt.Rectangle; -import java.io.EOFException; import java.io.IOException; import java.util.logging.Level; import java.util.logging.Logger; @@ -40,7 +39,6 @@ import com.esri.sde.sdk.client.SeRasterConstraint; import com.esri.sde.sdk.client.SeRow; import com.esri.sde.sdk.client.SeSqlConstruct; -import com.esri.sde.sdk.client.SeStreamOp; /** * Offers an iterator like interface to fetch ArcSDE raster tiles. @@ -71,15 +69,6 @@ private TileFetchCommand tileFetchCommand; - /** - * {@link SeStreamOp} held to be closed at {@link #dispose()} - * - * @see #execute() - */ - private SeQuery preparedQuery; - - private TileInfo[] nextTile; - private boolean started; private final int bitmaskDataLength; @@ -262,30 +251,6 @@ } /** - * @see org.geotools.arcsde.raster.io.TileReader#hasNext() - */ - public boolean hasNext() throws IOException { - if (!started) { - execute(); - try { - nextTile = session.issue(tileFetchCommand); - } catch (IOException e) { - dispose(); - throw e; - } catch (RuntimeException e) { - dispose(); - throw e; - } - started = true; - if (nextTile == null) { - dispose(); - LOGGER.fine("No tiles to fetch at all, releasing connection"); - } - } - return nextTile != null; - } - - /** * Creates and executes the {@link SeQuery} that's used to fetch the required tiles from the * specified raster, and stores (as member variables) the {@link SeRow} to fetch the tiles from * and the {@link SeQuery} to be closed at the TileReader's disposal @@ -293,7 +258,12 @@ * @throws IOException */ private void execute() throws IOException { + final Rectangle requestedTiles = this.requestedTiles; + this.tileFetchCommand = execute(requestedTiles); + } + private TileFetchCommand execute(final Rectangle rasterTiles) throws IOException { + final int rasterIndex = rasterInfo.getRasterIndex(rasterId); final int tileWidth = rasterInfo.getTileWidth(rasterId); final int tileHeight = rasterInfo.getTileHeight(rasterId); @@ -312,10 +282,10 @@ bandsToQuery[bandN - 1] = bandN; } - int minTileX = requestedTiles.x; - int minTileY = requestedTiles.y; - int maxTileX = minTileX + requestedTiles.width - 1; - int maxTileY = minTileY + requestedTiles.height - 1; + int minTileX = rasterTiles.x; + int minTileY = rasterTiles.y; + int maxTileX = minTileX + rasterTiles.width - 1; + int maxTileY = minTileY + rasterTiles.height - 1; if (LOGGER.isLoggable(Level.FINE)) { LOGGER.fine("Requesting tiles [x=" + minTileX + "-" + maxTileX + ", y=" + minTileY + "-" + maxTileY + "] from tile range [x=0-" @@ -325,8 +295,8 @@ // SDEPoint tileOrigin = rAttr.getTileOrigin(); if (LOGGER.isLoggable(Level.FINE)) { - Rectangle tiledImageSize = new Rectangle(0, 0, tileWidth * requestedTiles.width, - tileHeight * requestedTiles.height); + Rectangle tiledImageSize = new Rectangle(0, 0, tileWidth * rasterTiles.width, + tileHeight * rasterTiles.height); LOGGER.fine("Tiled image size: " + tiledImageSize); } @@ -346,15 +316,15 @@ * Obtain the ISession this tile reader will work with until exhausted */ try { - // lets share connections as we're going to do read only operations - final boolean transactional = false; - this.session = sessionPool.getSession(transactional); - // System.err.println("----> Using " + session + " to read raster #" + rasterId - // + " on Thread " + Thread.currentThread().getName() + ". Tile set: " - // + requestedTiles); - if (LOGGER.isLoggable(Level.FINER)) { - LOGGER.finer("Using " + session + " to read raster #" + rasterId + " on Thread " - + Thread.currentThread().getName() + ". Tile set: " + requestedTiles); + if (this.session == null) { + // lets share connections as we're going to do read only operations + final boolean transactional = false; + this.session = sessionPool.getSession(transactional); + if (LOGGER.isLoggable(Level.FINER)) { + LOGGER.finer("Using " + session + " to read raster #" + rasterId + + " on Thread " + Thread.currentThread().getName() + ". Tile set: " + + rasterTiles); + } } } catch (UnavailableConnectionException e) { // really bad luck.. @@ -371,22 +341,19 @@ final SeRow row = queryCommand.getSeRow(); final int numberOfBands = getNumberOfBands(); - this.tileFetchCommand = new TileFetchCommand(row, pixelsPerTile, numberOfBands); - this.preparedQuery = queryCommand.getPreparedQuery(); + final SeQuery preparedQuery = queryCommand.getPreparedQuery(); + TileFetchCommand fetchCommand = new TileFetchCommand(preparedQuery, row, pixelsPerTile, + numberOfBands); + return fetchCommand; } /** - * @see org.geotools.arcsde.raster.io.TileReader#next() + * @see org.geotools.arcsde.raster.io.TileReader#getTile(int, int) */ - public TileInfo[] next() throws IOException { - final TileInfo[] bandTiles; - final boolean hasNext = hasNext(); - if (hasNext) { - bandTiles = nextTile(); - } else { - throw new IllegalStateException("There're no more tiles to fetch"); - } + public TileInfo[] getTile(final int tileX, final int tileY) throws IOException { + final TileInfo[] bandTiles = fetchTile(tileX, tileY); + try { final int numberOfBands = getNumberOfBands(); for (int bandN = 0; bandN < numberOfBands; bandN++) { @@ -431,13 +398,79 @@ return bandTiles; } - private TileInfo[] nextTile() throws IOException { - if (nextTile == null) { + private int lastTileX = -1; + + private int lastTileY = -1; + + private TileInfo[] fetchTile(final int tileX, final int tileY) throws IOException { + + TileInfo[] tileInfo = null; + + if (isConsecutive(tileX, tileY)) { + while (lastTileX != tileX || lastTileY != tileY) { + tileInfo = nextTile(); + } + } else { + tileInfo = fetchSingleTile(tileX, tileY); + } + + return tileInfo; + } + + /** + * Executes a separate request to fetch this single tile + * + * @throws IOException + */ + private TileInfo[] fetchSingleTile(final int tileX, final int tileY) throws IOException { + LOGGER.info("fetchSingleTile " + tileX + ", " + tileY); + final int rasterTileX = requestedTiles.x + tileX; + final int rasterTileY = requestedTiles.y + tileY; + final int width = 1; + final int height = 1; + final Rectangle requestTiles = new Rectangle(rasterTileX, rasterTileY, width, height); + + final TileFetchCommand command = execute(requestTiles); + final SeQuery query = command.getQuery(); + final TileInfo[] tile; + try { + tile = session.issue(command); + session.close(query); + } catch (IOException e) { + session.close(query); dispose(); - throw new EOFException("No more tiles to read"); + throw e; + } catch (RuntimeException e) { + session.close(query); + dispose(); + throw e; } - TileInfo[] curr = nextTile; + return tile; + } + + /** + * Determines whether the tile defined by {@code tileX, tileY} is consecutive to the original + * request, whether it is exactly the next in the stream or any other one that follows the last + * tile fetched from the original request. + */ + private boolean isConsecutive(final int tileX, final int tileY) { + if (tileX > lastTileX && tileY >= lastTileY) { + return true; + } + if (tileX <= lastTileX && tileY > lastTileY) { + return true; + } + return false; + } + + private TileInfo[] nextTile() throws IOException { + if (!started) { + execute(); + started = true; + } + + TileInfo[] nextTile; try { nextTile = session.issue(tileFetchCommand); } catch (IOException e) { @@ -449,10 +482,22 @@ } if (nextTile == null) { dispose(); - LOGGER.finer("There're no more tiles to fetch"); + throw new IllegalStateException("There're no more tiles to fetch"); } - return curr; + if (lastTileY == -1) { + lastTileY = 0; + } + lastTileX++; + if (lastTileX == getTilesWide()) { + lastTileX = 0; + lastTileY++; + } + + if (lastTileX == getTilesWide() - 1 && lastTileY == getTilesHigh() - 1) { + dispose(); + } + return nextTile; } /** @@ -466,13 +511,22 @@ LOGGER.finer("TileReader disposing " + session + " on Thread " + Thread.currentThread().getName()); } - try { - session.close(this.preparedQuery); - } catch (Exception e) { - LOGGER.log(Level.WARNING, "Closing tile reader's prepared Query", e); + if (tileFetchCommand != null) { + try { + SeQuery preparedQuery = this.tileFetchCommand.getQuery(); + session.close(preparedQuery); + } catch (Exception e) { + LOGGER.log(Level.WARNING, "Closing tile reader's prepared Query", e); + } } + tileFetchCommand = null; + if (LOGGER.isLoggable(Level.FINER)) { + LOGGER.finer("Disposing " + session + " on thread " + + Thread.currentThread().getName()); + } session.dispose(); session = null; + started = false; } } @@ -487,4 +541,20 @@ protected void finalize() { dispose(); } + + public int getMinTileX() { + return requestedTiles.x; + } + + public int getMinTileY() { + return requestedTiles.y; + } + + public int getPyramidLevel() { + return pyramidLevel; + } + + public long getRasterId() { + return rasterId; + } } Modified: trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/io/PromotingTileReader.java =================================================================== --- trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/io/PromotingTileReader.java 2009-11-04 16:32:24 UTC (rev 34326) +++ trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/io/PromotingTileReader.java 2009-11-04 19:13:17 UTC (rev 34327) @@ -95,16 +95,15 @@ return nativeReader.getTilesWide(); } - public boolean hasNext() throws IOException { - return nativeReader.hasNext(); - } - - public TileInfo[] next() throws IOException { + /** + * @see org.geotools.arcsde.raster.io.TileReader#getTile(int, int) + */ + public TileInfo[] getTile(final int tileX, final int tileY) throws IOException { final int numberOfBands = getNumberOfBands(); final TileInfo[] promotedBandInfo = new TileInfo[numberOfBands]; try { - final TileInfo[] nativeBandInfo = nativeReader.next(); + final TileInfo[] nativeBandInfo = nativeReader.getTile(tileX, tileY); for (int bandN = 0; bandN < numberOfBands; bandN++) { TileInfo nativeData = nativeBandInfo[bandN]; @@ -277,4 +276,20 @@ public void dispose() { this.nativeReader.dispose(); } + + public int getMinTileX() { + return nativeReader.getMinTileX(); + } + + public int getMinTileY() { + return nativeReader.getMinTileY(); + } + + public int getPyramidLevel() { + return nativeReader.getPyramidLevel(); + } + + public long getRasterId() { + return nativeReader.getRasterId(); + } } Modified: trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/io/TileFetchCommand.java =================================================================== --- trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/io/TileFetchCommand.java 2009-11-04 16:32:24 UTC (rev 34326) +++ trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/io/TileFetchCommand.java 2009-11-04 19:13:17 UTC (rev 34327) @@ -9,6 +9,7 @@ import com.esri.sde.sdk.client.SeConnection; import com.esri.sde.sdk.client.SeException; +import com.esri.sde.sdk.client.SeQuery; import com.esri.sde.sdk.client.SeRaster; import com.esri.sde.sdk.client.SeRasterTile; import com.esri.sde.sdk.client.SeRow; @@ -18,24 +19,34 @@ * * @author Gabriel Roldan (OpenGeo) * @since 2.5.8 - * @source $URL$ + * @source $URL: + * http://svn.osgeo.org/geotools/trunk/modules/plugin/arcsde/datastore/src/main/java/org + * /geotools/arcsde/raster/io/TileFetchCommand.java $ */ class TileFetchCommand extends Command<TileInfo[]> { + private final SeQuery preparedQuery; + private final SeRow row; private final int pixelsPerTile; - private int numberOfBands; + private final int numberOfBands; private TileDataFetcher dataFetcher; - public TileFetchCommand(final SeRow row, final int pixelsPerTile, final int numberOfBands) { + public TileFetchCommand(final SeQuery preparedQuery, final SeRow row, final int pixelsPerTile, + final int numberOfBands) { + this.preparedQuery = preparedQuery; this.row = row; this.pixelsPerTile = pixelsPerTile; this.numberOfBands = numberOfBands; } + public SeQuery getQuery() { + return preparedQuery; + } + @Override public TileInfo[] execute(ISession session, SeConnection connection) throws SeException, IOException { Modified: trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/io/TileReader.java =================================================================== --- trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/io/TileReader.java 2009-11-04 16:32:24 UTC (rev 34326) +++ trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/io/TileReader.java 2009-11-04 19:13:17 UTC (rev 34327) @@ -20,7 +20,13 @@ import java.io.IOException; /** - * Offers an iterator like interface to read ArcSDE raster tiles into a {@code byte[]} + * Offers a random access interface to the tile data for a raster request. + * <p> + * Implementations are expected to perform better when the tiles are requested in sequential x/y + * order (e.g., 0,0; 1,0; 2,0; 0,1; 1,1; 2,1 for 3x2 tile set), though they're required to be able + * to return any randomly requested tile, probably by being forced to issue a separate request to + * the server or do some cacheing. + * </p> * * @author Gabriel Roldan (OpenGeo) * @since 2.5.4 @@ -73,12 +79,6 @@ public abstract int getBytesPerTile(); /** - * @return whether there are more tiles to fetch - * @throws IOException - */ - public abstract boolean hasNext() throws IOException; - - /** * Fetches a tile and fills {@code tileData} with its raw pixel data packaged as bytes according * to the number of bits per sample * @@ -91,7 +91,7 @@ * @throws {@link IllegalArgumentException} if tileData is not null and its size is less than * {@link #getBytesPerTile()} */ - public abstract TileInfo[] next() throws IOException; + public abstract TileInfo[] getTile(int tileX, int tileY) throws IOException; /** * Disposes any resource being held by this TileReader, making the TileReader unusable and the @@ -99,4 +99,12 @@ */ public abstract void dispose(); + public abstract long getRasterId(); + + public abstract int getPyramidLevel(); + + public abstract int getMinTileX(); + + public abstract int getMinTileY(); + } \ No newline at end of file Modified: trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/jai/ArcSDEImageReader.java =================================================================== --- trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/jai/ArcSDEImageReader.java 2009-11-04 16:32:24 UTC (rev 34326) +++ trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/jai/ArcSDEImageReader.java 2009-11-04 19:13:17 UTC (rev 34327) @@ -1,12 +1,7 @@ package org.geotools.arcsde.raster.jai; -import java.awt.Point; import java.awt.image.BufferedImage; -import java.awt.image.DataBuffer; -import java.awt.image.Raster; import java.awt.image.RenderedImage; -import java.awt.image.SampleModel; -import java.awt.image.WritableRaster; import java.io.IOException; import java.util.Collections; import java.util.Iterator; @@ -17,10 +12,8 @@ import javax.imageio.metadata.IIOMetadata; import javax.media.jai.PlanarImage; -import org.geotools.arcsde.raster.io.TileInfo; import org.geotools.arcsde.raster.io.TileReader; -import com.sun.media.imageioimpl.common.SimpleRenderedImage; public class ArcSDEImageReader extends ImageReader { @@ -94,95 +87,4 @@ public void setInput(Object input, boolean seekForwardOnly, boolean ignoreMetadata) { this.tileReader = (TileReader) input; } - - @SuppressWarnings("unchecked") - private static class ArcSDETiledRenderedImage extends SimpleRenderedImage { - - private TileReader tileReader; - - public ArcSDETiledRenderedImage(TileReader tileReader, ImageTypeSpecifier typeSpec) { - this.tileReader = tileReader; - super.colorModel = typeSpec.getColorModel(); - super.sampleModel = typeSpec.getSampleModel(); - super.height = tileReader.getTilesHigh() * tileReader.getTileHeight(); - super.width = tileReader.getTilesWide() * tileReader.getTileWidth(); - super.minX = 0; - super.minY = 0; - super.tileGridXOffset = 0; - super.tileGridYOffset = 0; - super.tileHeight = tileReader.getTileHeight(); - super.tileWidth = tileReader.getTileWidth(); - } - - private WritableRaster[][] tileCache = null; - - /** - * @see java.awt.image.RenderedImage#getTile(int, int) - */ - public Raster getTile(final int tileX, final int tileY) { - System.err.printf("getTile(%d, %d) %s\n", tileX, tileY, this.toString()); - if (tileCache == null) { - tileCache = new WritableRaster[tileReader.getTilesWide()][tileReader.getTilesHigh()]; - } - - WritableRaster currentTile = tileCache[tileX][tileY]; - if (currentTile == null) { - final int tilesWide = tileReader.getTilesWide(); - final int tilesHigh = tileReader.getTilesHigh(); - - for (int ty = 0; ty < tilesHigh; ty++) { - for (int tx = 0; tx < tilesWide; tx++) { - - currentTile = tileCache[tx][ty]; - - if (currentTile == null) { - int x = tileXToX(tx); - int y = tileYToY(ty); - // System.err.println("fetching tile " + tx + "," + ty); - currentTile = fetchTile(x, y); - tileCache[tx][ty] = currentTile; - } - if (tx == tileX && ty == tileY) { - return currentTile; - } - } - } - } - // currentTile = tileCache[tileX][tileY]; - return currentTile; - } - - private WritableRaster fetchTile(final int xOrigin, final int yOrigin) { - final int numBands = sampleModel.getNumBands(); - - final SampleModel tileSampleModel = super.sampleModel.createCompatibleSampleModel( - tileWidth, tileHeight); - - DataBuffer dataBuffer = sampleModel.createDataBuffer(); - TileInfo[] tileInfo; - try { - tileInfo = tileReader.next(); - } catch (IOException e) { - throw new RuntimeException(e); - } - - for (int bandN = 0; bandN < numBands; bandN++) { - TileInfo bandData = tileInfo[bandN]; - bandData.fill(dataBuffer, bandN); -// byte[] rawBandData = tileInfo.getTileData(); -// -// final int numPixels = tileWidth * tileHeight; -// for (int pixelN = 0; pixelN < numPixels; pixelN++) { -// int val = rawBandData[2 * pixelN + 1] & 0xFF; -// dataBuffer.setElem(bandN, pixelN, val); -// } - } - - WritableRaster currentTile; - currentTile = Raster.createWritableRaster(tileSampleModel, dataBuffer, new Point( - xOrigin, yOrigin)); - return currentTile; - } - - } } Added: trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/jai/ArcSDETiledRenderedImage.java =================================================================== --- trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/jai/ArcSDETiledRenderedImage.java (rev 0) +++ trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/jai/ArcSDETiledRenderedImage.java 2009-11-04 19:13:17 UTC (rev 34327) @@ -0,0 +1,147 @@ +/** + * + */ +package org.geotools.arcsde.raster.jai; + +import java.awt.Point; +import java.awt.image.DataBuffer; +import java.awt.image.Raster; +import java.awt.image.SampleModel; +import java.awt.image.WritableRaster; +import java.io.IOException; + +import javax.imageio.ImageTypeSpecifier; + +import org.apache.commons.collections.map.LRUMap; +import org.geotools.arcsde.raster.io.TileInfo; +import org.geotools.arcsde.raster.io.TileReader; + +import com.sun.media.imageioimpl.common.SimpleRenderedImage; + +@SuppressWarnings("unchecked") +class ArcSDETiledRenderedImage extends SimpleRenderedImage { + + private TileReader tileReader; + + public ArcSDETiledRenderedImage(final TileReader tileReader, final ImageTypeSpecifier typeSpec) { + this.tileReader = tileReader; + super.colorModel = typeSpec.getColorModel(); + super.sampleModel = typeSpec.getSampleModel(); + super.height = tileReader.getTilesHigh() * tileReader.getTileHeight(); + super.width = tileReader.getTilesWide() * tileReader.getTileWidth(); + super.minX = 0; + super.minY = 0; + super.tileGridXOffset = 0; + super.tileGridYOffset = 0; + super.tileHeight = tileReader.getTileHeight(); + super.tileWidth = tileReader.getTileWidth(); + } + + /** + * @see java.awt.image.RenderedImage#getTile(int, int) + */ + public Raster getTile(final int tileX, final int tileY) { + // System.err.printf("getTile(%d, %d) %s\n", tileX, tileY, this.toString()); + + final TileKey key = newKey(tileX, tileY); + WritableRaster currentTile = getCached(key); + if (currentTile != null) { + return currentTile; + } + + final int xOrigin = tileXToX(tileX); + final int yOrigin = tileYToY(tileY); + + final int numBands = sampleModel.getNumBands(); + + final SampleModel tileSampleModel = super.sampleModel.createCompatibleSampleModel( + tileWidth, tileHeight); + + DataBuffer dataBuffer = sampleModel.createDataBuffer(); + TileInfo[] tileInfo; + try { + tileInfo = tileReader.getTile(tileX, tileY); + } catch (IOException e) { + throw new RuntimeException(e); + } + + for (int bandN = 0; bandN < numBands; bandN++) { + TileInfo bandData = tileInfo[bandN]; + bandData.fill(dataBuffer, bandN); + } + + currentTile = Raster.createWritableRaster(tileSampleModel, dataBuffer, new Point(xOrigin, + yOrigin)); + cache(key, currentTile); + + return currentTile; + } + + private TileKey newKey(final int tileX, final int tileY) { + final long rasterId = tileReader.getRasterId(); + final int pyramidLevel = tileReader.getPyramidLevel(); + final int rasterTileX = tileReader.getMinTileX() + tileX; + final int rasterTileY = tileReader.getMinTileY() + tileY; + + TileKey tileKey = new TileKey(rasterId, pyramidLevel, tileX, tileY, rasterTileX, + rasterTileY); + return tileKey; + } + + private static final LRUMap cache = new LRUMap(5); + + private void cache(TileKey key, WritableRaster tile) { + cache.put(key, tile); + } + + private WritableRaster getCached(TileKey key) { + WritableRaster tile = (WritableRaster) cache.get(key); + return tile; + } + + private static class TileKey { + private int tileX, tileY; + + private long rasterId; + + private int pyramidLevel; + + private int rasterTileX; + + private int rasterTileY; + + public TileKey(long rasterId, int pyramidLevel, int tileX, int tileY, int rasterTileX, + int rasterTileY) { + this.rasterId = rasterId; + this.pyramidLevel = pyramidLevel; + this.tileX = tileX; + this.tileY = tileY; + this.rasterTileX = rasterTileX; + this.rasterTileY = rasterTileY; + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof TileKey)) { + return false; + } + TileKey t = (TileKey) o; + return rasterId == t.rasterId && pyramidLevel == t.pyramidLevel + && rasterTileX == t.rasterTileX && rasterTileY == t.rasterTileY; + } + + @Override + public int hashCode() { + return (17 ^ pyramidLevel) + rasterTileX * rasterTileY; + } + + public int getTileX() { + return tileX; + } + + public int getTileY() { + return tileY; + } + + } +} \ No newline at end of file Property changes on: trunk/modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/raster/jai/ArcSDETiledRenderedImage.java ___________________________________________________________________ Added: svn:mime-type + text/plain Added: svn:keywords + Id URL Added: svn:eol-style + native Modified: trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/raster/gce/ArcSDEGridCoverage2DReaderJAILegacyOnlineTest.java =================================================================== --- trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/raster/gce/ArcSDEGridCoverage2DReaderJAILegacyOnlineTest.java 2009-11-04 16:32:24 UTC (rev 34326) +++ trunk/modules/plugin/arcsde/datastore/src/test/java/org/geotools/arcsde/raster/gce/ArcSDEGridCoverage2DReaderJAILegacyOnlineTest.java 2009-11-04 19:13:17 UTC (rev 34327) @@ -120,7 +120,7 @@ final AbstractGridCoverage2DReader reader = getReader(); assertNotNull("Couldn't obtain a reader for " + tableName, reader); - final int count = 0; + final int count = 10; long time = 0; // warm up _testIMG_USGSQUAD_SGBASE(reader); @@ -239,7 +239,11 @@ assertNotNull("read coverage returned null", coverage); RenderedImage image = coverage.view(ViewType.PHOTOGRAPHIC).getRenderedImage(); + Stopwatch sw = new Stopwatch(); + sw.start(); writeToDisk(image, "testRead_" + tableName); + sw.stop(); + LOGGER.info("wrote in " + sw.getTimeString()); } @Test ------------------------------------------------------------------------------ Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day trial. Simplify your report design, integration and deployment - and focus on what you do best, core application coding. Discover what's new with Crystal Reports now. http://p.sf.net/sfu/bobj-july _______________________________________________ GeoTools-commits mailing list [hidden email] https://lists.sourceforge.net/lists/listinfo/geotools-commits |
||||||||||||||||
| Free Embeddable Forum Powered by Nabble | Help |