|
|
|
svn_geotools
|
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 |
||||||||||||||||
| Free Embeddable Forum Powered by Nabble | Help |