svn - r34374 - branches/2.6.x/modules/plugin/imagemosaic/src/main/java/org/geotools/gce/imagemosaic

1 message Options
Embed this post
Permalink
svn_geotools

svn - r34374 - branches/2.6.x/modules/plugin/imagemosaic/src/main/java/org/geotools/gce/imagemosaic

Reply Threaded More More options
Print post
Permalink
Author: danieleromagnoli
Date: 2009-11-13 10:12:21 -0500 (Fri, 13 Nov 2009)
New Revision: 34374

Modified:
   branches/2.6.x/modules/plugin/imagemosaic/src/main/java/org/geotools/gce/imagemosaic/Granule.java
   branches/2.6.x/modules/plugin/imagemosaic/src/main/java/org/geotools/gce/imagemosaic/ImageMosaicFormatFactory.java
   branches/2.6.x/modules/plugin/imagemosaic/src/main/java/org/geotools/gce/imagemosaic/RasterLayerResponse.java
Log:
improving data access when accessing data via Kakadu (Performing subsampled read with subsampling factors as power of 2)

Modified: branches/2.6.x/modules/plugin/imagemosaic/src/main/java/org/geotools/gce/imagemosaic/Granule.java
===================================================================
--- branches/2.6.x/modules/plugin/imagemosaic/src/main/java/org/geotools/gce/imagemosaic/Granule.java 2009-11-12 16:28:58 UTC (rev 34373)
+++ branches/2.6.x/modules/plugin/imagemosaic/src/main/java/org/geotools/gce/imagemosaic/Granule.java 2009-11-13 15:12:21 UTC (rev 34374)
@@ -60,6 +60,12 @@
  */
 class Granule {
 
+ private static final int MAX_SUBSAMPLING_FACTOR = Integer.MAX_VALUE;
+
+ private static final int MAX_LEVELS = 31;
+
+ private static final String DIRECT_KAKADU_PLUGIN="it.geosolutions.imageio.plugins.jp2k.JP2KKakaduImageReader";
+
  /** Logger. */
  private final static Logger LOGGER = org.geotools.util.logging.Logging.getLogger(Granule.class);
   
@@ -336,8 +342,8 @@
  this.granuleUrl = granuleUrl;
 
  // create the base grid to world transformation
- ImageInputStream inStream=null;
- ImageReader reader=null;
+ ImageInputStream inStream = null;
+ ImageReader reader = null;
  try {
  //
  //get info about the raster we have to read
@@ -345,18 +351,18 @@
 
  // get a stream
  inStream = ImageMosaicUtils.getInputStream(granuleUrl);
- if(inStream==null)
+ if(inStream == null)
  throw new IllegalArgumentException("Unable to get an input stream for the provided file "+granuleUrl.toString());
 
  // get a reader and try to cache the relevant SPI
- if(cachedSPI==null){
+ if(cachedSPI == null){
  reader = ImageMosaicUtils.getReader( inStream);
- if(reader!=null)
- cachedSPI=reader.getOriginatingProvider();
+ if(reader != null)
+ cachedSPI = reader.getOriginatingProvider();
  }
  else
- reader=cachedSPI.createReaderInstance();
- if(reader==null)
+ reader = cachedSPI.createReaderInstance();
+ if(reader == null)
  throw new IllegalArgumentException("Unable to get an ImageReader for the provided file "+granuleUrl.toString());
 
  //get selected level and base level dimensions
@@ -367,15 +373,12 @@
  // we do not have such info, hence we assume that it is a simple
  // scale and translate
  final GridToEnvelopeMapper geMapper= new GridToEnvelopeMapper(
- new GridEnvelope2D(originalDimension),
- granuleBBOX
- );
+ new GridEnvelope2D(originalDimension), granuleBBOX);
  geMapper.setPixelAnchor(PixelInCell.CELL_CENTER);//this is the default behavior but it is nice to write it down anyway
- this.baseGridToWorld=geMapper.createAffineTransform();
+ this.baseGridToWorld = geMapper.createAffineTransform();
 
-
  // add the base level
- this.granuleLevels.put(Integer.valueOf(0),new Level(1,1,originalDimension.width,originalDimension.height));
+ this.granuleLevels.put(Integer.valueOf(0), new Level(1, 1, originalDimension.width, originalDimension.height));
 
  } catch (IllegalStateException e) {
  throw new IllegalArgumentException(e);
@@ -385,20 +388,19 @@
  }
  finally{
  try{
- if(inStream!=null)
+ if(inStream != null)
  inStream.close();
  }
  catch (Throwable e) {
  throw new IllegalArgumentException(e);
  }
  finally{
- if(reader!=null)
+ if(reader != null)
  reader.dispose();
  }
  }
  }
 
-
  public RenderedImage loadRaster(
  final ImageReadParam readParameters,
  final int imageIndex,
@@ -451,7 +453,7 @@
  // level together with the base level grid to world transformation
  MathTransform2D cropWorldToGrid=(MathTransform2D) PixelTranslation.translate(ProjectiveTransform.create(selectedlevel.gridToWorldTransform), PixelInCell.CELL_CENTER, PixelInCell.CELL_CORNER).inverse();
 
- // computing the crop source area which leaves straight into the
+ // computing the crop source area which lives into the
  // selected level raster space, NOTICE that at the end we need to
  // take into account the fact that we might also decimate therefore
  // we cannot just use the crop grid to world but we need to correct
@@ -468,6 +470,18 @@
  LOGGER.fine((new StringBuffer("Loading level ").append(
  imageIndex).append(" with source region ").append(
  sourceArea).toString()));
+
+ // Setting subsampling
+ int newSubSamplingFactor = 0;
+ final String pluginName = cachedSPI.getPluginClassName();
+ if (pluginName != null && pluginName.equals(DIRECT_KAKADU_PLUGIN)){
+ final int ssx = readParameters.getSourceXSubsampling();
+ final int ssy = readParameters.getSourceYSubsampling();
+ newSubSamplingFactor = getSubSamplingFactor2(ssx , ssy);
+ if (newSubSamplingFactor != 0)
+ readParameters.setSourceSubsampling(newSubSamplingFactor, newSubSamplingFactor,0,0);
+ }
+
  // set the source region
  readParameters.setSourceRegion(sourceArea);
  final RenderedImage raster;
@@ -484,7 +498,6 @@
 
  // use fixed source area
  sourceArea.setRect(readParameters.getSourceRegion());
-
 
  //
  // setting new coefficients to define a new affineTransformation
@@ -504,11 +517,9 @@
  // keep into account translation  to work into the selected level raster space
  final AffineTransform afterDecimationTranslateTranform =XAffineTransform.getTranslateInstance(sourceArea.x, sourceArea.y);
 
-
  // now we need to go back to the base level raster space
  final AffineTransform backToBaseLevelScaleTransform =selectedlevel.baseToLevelTransform;
 
-
  // now create the overall transform
  final AffineTransform finalRaster2Model = new AffineTransform(baseGridToWorld);
  finalRaster2Model.concatenate(ImageMosaicUtils.CENTER_TO_CORNER);
@@ -538,9 +549,6 @@
  return null;
  }
 
-
-
-
  // apply the affine transform  conserving indexed color model
  final RenderingHints localHints = new RenderingHints(JAI.KEY_REPLACE_INDEX_COLOR_MODEL, Boolean.FALSE);
  if(XAffineTransform.isIdentity(finalRaster2Model,10E-6))
@@ -589,7 +597,6 @@
  reader.dispose();
  }
  }
-
  }
 
 
@@ -659,11 +666,74 @@
  }
  }
  }
-
  }
  }
 
+ /**
+     * Given a pair of xSubsamplingFactor (xSSF) and ySubsamplingFactor (ySFF),
+     * look for a subsampling factor (SSF) in case xSSF != ySSF or they are not
+     * powers of 2.
+     * In case xSSF == ySSF == 2^N, the method return 0 (No optimal subsampling factor found).
+     *
+     * @param xSubsamplingFactor
+     * @param ySubsamplingFactor
+     * @return
+     *
+     * Note that this function will be made available in the next Imageio-ext release within the
+     * imageio-ext's Utilities.
+     */
+ private static int getSubSamplingFactor2(final int xSubsamplingFactor, final int ySubsamplingFactor) {
+        boolean resamplingIsRequired = false;
+        int newSubSamplingFactor = 0;
 
+        // Preliminar check: Are xSSF and ySSF different?
+        final boolean subSamplingFactorsAreDifferent = (xSubsamplingFactor != ySubsamplingFactor);
+
+        // Let be nSSF the minimum of xSSF and ySSF (They may be equals).
+        newSubSamplingFactor = (xSubsamplingFactor <= ySubsamplingFactor) ? xSubsamplingFactor
+                : ySubsamplingFactor;
+        // if nSSF is greater than the maxSupportedSubSamplingFactor
+        // (MaxSupSSF), it needs to be adjusted.
+        final boolean changedSubSamplingFactors = (newSubSamplingFactor > MAX_SUBSAMPLING_FACTOR);
+        if (newSubSamplingFactor > MAX_SUBSAMPLING_FACTOR)
+            newSubSamplingFactor = MAX_SUBSAMPLING_FACTOR;
+        final int optimalSubsampling = findOptimalSubSampling(newSubSamplingFactor);
+
+        resamplingIsRequired = subSamplingFactorsAreDifferent
+                || changedSubSamplingFactors || optimalSubsampling != newSubSamplingFactor;
+        if (!resamplingIsRequired) {
+            // xSSF and ySSF are equal and they are not greater than MaxSuppSSF
+         newSubSamplingFactor = 0;
+        } else {
+            // xSSF and ySSF are different or they are greater than MaxSuppSFF.
+            // We need to find a new subsampling factor to load a proper region.
+            newSubSamplingFactor = optimalSubsampling;
+        }
+        return newSubSamplingFactor;
+    }
+
+ private static int findOptimalSubSampling(final int newSubSamplingFactor) {
+        int optimalSubSamplingFactor = 1;
+
+        // finding the available subsampling factors from the number of
+        // resolution levels
+        for (int level = 0; level < MAX_LEVELS; level++) {
+            // double the subSamplingFactor until it is lower than the
+            // input subSamplingFactor
+            if (optimalSubSamplingFactor < newSubSamplingFactor)
+                optimalSubSamplingFactor = 1 << level;
+            // if the calculated subSamplingFactor is greater than the input
+            // subSamplingFactor, we need to step back by halving it.
+            else if (optimalSubSamplingFactor > newSubSamplingFactor) {
+                optimalSubSamplingFactor = optimalSubSamplingFactor >> 1;
+                break;
+            } else if (optimalSubSamplingFactor == newSubSamplingFactor) {
+                break;
+            }
+        }
+        return optimalSubSamplingFactor;
+    }
+
  @Override
  public String toString() {
  // build a decent representation for this level

Modified: branches/2.6.x/modules/plugin/imagemosaic/src/main/java/org/geotools/gce/imagemosaic/ImageMosaicFormatFactory.java
===================================================================
--- branches/2.6.x/modules/plugin/imagemosaic/src/main/java/org/geotools/gce/imagemosaic/ImageMosaicFormatFactory.java 2009-11-12 16:28:58 UTC (rev 34373)
+++ branches/2.6.x/modules/plugin/imagemosaic/src/main/java/org/geotools/gce/imagemosaic/ImageMosaicFormatFactory.java 2009-11-13 15:12:21 UTC (rev 34374)
@@ -33,7 +33,6 @@
 import org.geotools.coverageio.gdal.jp2ecw.JP2ECWFormatFactory;
 import org.geotools.coverageio.gdal.jp2kak.JP2KFormatFactory;
 import org.geotools.coverageio.gdal.jp2mrsid.JP2MrSIDFormatFactory;
-import org.opengis.coverage.grid.Format;
 
 import com.sun.media.imageioimpl.common.PackageUtil;
 import com.sun.media.imageioimpl.plugins.jpeg2000.J2KImageReaderCodecLibSpi;
@@ -48,7 +47,6 @@
  * @since 2.3
  */
 
-@SuppressWarnings("deprecation")
 public final class ImageMosaicFormatFactory implements GridFormatFactorySpi {
  /** Logger. */
  private final static Logger LOGGER = org.geotools.util.logging.Logging.getLogger(ImageMosaicFormatFactory.class);

Modified: branches/2.6.x/modules/plugin/imagemosaic/src/main/java/org/geotools/gce/imagemosaic/RasterLayerResponse.java
===================================================================
--- branches/2.6.x/modules/plugin/imagemosaic/src/main/java/org/geotools/gce/imagemosaic/RasterLayerResponse.java 2009-11-12 16:28:58 UTC (rev 34373)
+++ branches/2.6.x/modules/plugin/imagemosaic/src/main/java/org/geotools/gce/imagemosaic/RasterLayerResponse.java 2009-11-13 15:12:21 UTC (rev 34374)
@@ -125,28 +125,23 @@
  return cropBBox;
  }
 
-
  public MathTransform2D getMosaicWorldToGrid() {
  return mosaicWorldToGrid;
  }
 
-
  public Granule getGranule() {
  return granule;
  }
 
-
  public ImageReadParam getReadParameters() {
  return readParameters;
  }
 
-
  public int getImageIndex() {
  return imageIndex;
  }
 
  public RenderedImage call() throws Exception {
-
  return granule.loadRaster(readParameters, imageIndex, cropBBox, mosaicWorldToGrid, request,tilesDimension);
  }
 
@@ -211,7 +206,7 @@
  // load raster data
  //
  //create a granule loader
- final GranuleLoader loader = new GranuleLoader(baseReadParameters, imageChoice, mosaicBBox, finalWorldToGridCorner,granule,request.getTileDimensions());
+ final GranuleLoader loader = new GranuleLoader(baseReadParameters, imageChoice, mosaicBBox, finalWorldToGridCorner, granule, request.getTileDimensions());
  if(!multithreadingAllowed)
  tasks.add(new FutureTask<RenderedImage>(loader));
  else
@@ -433,12 +428,7 @@
  final RasterManager rasterManager) {
  this.request = request;
  inputURL = rasterManager.getInputURL();
-// File tempFile;
-// try {
-// tempFile = new File(this.inputURL.toURI());
-// } catch (URISyntaxException e) {
-// throw new IllegalArgumentException(e);
-// }// TODO improve me
+
  try {
  parentLocation = DataUtilities.getParentUrl(inputURL).toExternalForm();
  } catch (MalformedURLException e) {
@@ -561,7 +551,7 @@
  pbjMosaic = new ParameterBlockJAI("Mosaic");
  pbjMosaic.setParameter("backgroundValues",backgroundValues);
  // It might important to set the mosaic type to blend otherwise
- // sometimes strange results jhttp://developer.yahoo.com/yui/slider/ump in.
+ // sometimes strange results jump in.
  if (request.isBlend())
  pbjMosaic.setParameter("mosaicType",MosaicDescriptor.MOSAIC_TYPE_BLEND);
  else
@@ -577,7 +567,7 @@
  // the other levels can be computed accordingly knowning the scale
  // factors.
  if (request.getRequestedBBox() != null&& request.getRequestedRasterArea() != null)
- imageChoice = setReadParams(request.getOverviewPolicy(), baseReadParameters,request);
+ imageChoice = setReadParams(request.getOverviewPolicy(), baseReadParameters, request);
  else
  imageChoice = 0;
  assert imageChoice>=0;
@@ -721,7 +711,6 @@
  //
  // TRANSPARENT COLOR MANAGEMENT
  //
- //
  if (doTransparentColor) {
  if (LOGGER.isLoggable(Level.FINE))
  LOGGER.fine("Support for alpha on input image number "+ granuleIndex);
@@ -756,34 +745,10 @@
 
  /**
  * Once we reach this method it means that we have loaded all the images
- * which were intersecting the requested nevelope. Next step is to create
+ * which were intersecting the requested envelope. Next step is to create
  * the final mosaic image and cropping it to the exact requested envelope.
  *
- * @param location
- *
- * @param envelope
- * @param requestedEnvelope
- * @param intersectionEnvelope
- * @param res
- * @param mosaicBBOx
- * @param pbjMosaic
- * @param finalTransparentColor
- * @param doAlpha
- * @param doTransparentColor
- * @param loadedRasterArea
- * @param rasterBounds
- * @param currentWorldToGrid
- * @param currentGridToWorld
- * @param outputTransparentColor
- * @param outputTransparentColor
- * @param rasterBounds
- * @param singleImageROI
- * @return
- * @return A {@link GridCoverage}, wewll actually a {@link GridCoverage2D}.
- * @throws IOException
- * @throws IllegalArgumentException
- * @throws FactoryRegistryException
- * @throws DataSourceException
+ * @return A {@link RenderedImage}}.
  */
  private RenderedImage buildMosaic() throws IOException  {
 
@@ -797,7 +762,7 @@
  if(tileDimensions!=null)
  layout.setTileHeight(tileDimensions.width).setTileWidth(tileDimensions.height);
  final RenderingHints hints = new RenderingHints(JAI.KEY_IMAGE_LAYOUT,layout);
- RenderedImage mosaic = JAI.create("Mosaic", pbjMosaic ,hints);
+ RenderedImage mosaic = JAI.create("Mosaic", pbjMosaic, hints);
 
  if (LOGGER.isLoggable(Level.FINE))
  LOGGER.fine(new StringBuffer("Mosaic created ").toString());
@@ -808,8 +773,7 @@
 
  }
 
- private GridCoverage2D prepareCoverage(
- RenderedImage image) throws IOException {
+ private GridCoverage2D prepareCoverage(RenderedImage image) throws IOException {
  // creating bands
         final SampleModel sm=image.getSampleModel();
         final ColorModel cm=image.getColorModel();
@@ -884,11 +848,11 @@
  return imageChoice;
 
  // overviews and decimation
- imageChoice = rasterManager.overviewsController.pickOverviewLevel(overviewPolicy,request);
+ imageChoice = rasterManager.overviewsController.pickOverviewLevel(overviewPolicy, request);
 
 
  // DECIMATION ON READING
- rasterManager.decimationController.performDecimation(imageChoice,readParams, request);
+ rasterManager.decimationController.performDecimation(imageChoice, readParams, request);
  return imageChoice;
 
  }


------------------------------------------------------------------------------
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