public static HashMap<String, Double> getRegionParamsFromGridCoverage( GridCoverage2D gridCoverage) { HashMap<String, Double> envelopeParams = new HashMap<String, Double>(); Envelope envelope = gridCoverage.getEnvelope(); DirectPosition lowerCorner = envelope.getLowerCorner(); double[] westSouth = lowerCorner.getCoordinate(); DirectPosition upperCorner = envelope.getUpperCorner(); double[] eastNorth = upperCorner.getCoordinate(); GridGeometry2D gridGeometry = gridCoverage.getGridGeometry(); GridEnvelope2D gridRange = gridGeometry.getGridRange2D(); int height = gridRange.height; int width = gridRange.width; AffineTransform gridToCRS = (AffineTransform) gridGeometry.getGridToCRS(); double xRes = XAffineTransform.getScaleX0(gridToCRS); double yRes = XAffineTransform.getScaleY0(gridToCRS); envelopeParams.put(NORTH, eastNorth[1]); envelopeParams.put(SOUTH, westSouth[1]); envelopeParams.put(WEST, westSouth[0]); envelopeParams.put(EAST, eastNorth[0]); envelopeParams.put(XRES, xRes); envelopeParams.put(YRES, yRes); envelopeParams.put(ROWS, (double) height); envelopeParams.put(COLS, (double) width); return envelopeParams; }
/** * Tests the {@link OverviewsController} with support for different resolutions/different number * of overviews. * * <p>world_a.tif => Pixel Size = (0.833333333333333,-0.833333333333333); 4 overviews world_b.tif * => Pixel Size = (1.406250000000000,-1.406250000000000); 2 overviews * * @throws IOException * @throws MismatchedDimensionException * @throws FactoryException * @throws TransformException */ @Test public void testHeterogeneousGranules() throws IOException, MismatchedDimensionException, FactoryException, TransformException { final CoordinateReferenceSystem WGS84 = CRS.decode("EPSG:4326", true); final ReferencedEnvelope TEST_BBOX_A = new ReferencedEnvelope(-180, 0, -90, 90, WGS84); final ReferencedEnvelope TEST_BBOX_B = new ReferencedEnvelope(0, 180, 0, 90, WGS84); URL heterogeneousGranulesURL = TestData.url(this, "heterogeneous"); // // // // Initialize mosaic variables // // // final Hints hints = new Hints(Hints.DEFAULT_COORDINATE_REFERENCE_SYSTEM, WGS84); final AbstractGridFormat format = (AbstractGridFormat) GridFormatFinder.findFormat(heterogeneousGranulesURL, hints); Assert.assertNotNull(format); Assert.assertFalse("UknownFormat", format instanceof UnknownFormat); final ImageMosaicReader reader = (ImageMosaicReader) format.getReader(heterogeneousGranulesURL, hints); Assert.assertNotNull(reader); final int nOv = reader.getNumberOfOvervies(); final double[] hRes = reader.getHighestRes(); final RasterManager rasterManager = new RasterManager(reader); // // // // Initialize granules related variables // // // final File g1File = new File(DataUtilities.urlToFile(heterogeneousGranulesURL), "world_a.tif"); final File g2File = new File(DataUtilities.urlToFile(heterogeneousGranulesURL), "world_b.tif"); final ImageReadParam readParamsG1 = new ImageReadParam(); final ImageReadParam readParamsG2 = new ImageReadParam(); int imageIndexG1 = 0; int imageIndexG2 = 0; final GranuleDescriptor granuleDescriptor1 = new GranuleDescriptor(g1File.getAbsolutePath(), TEST_BBOX_A, spi, (Geometry) null, true); final GranuleDescriptor granuleDescriptor2 = new GranuleDescriptor(g2File.getAbsolutePath(), TEST_BBOX_B, spi, (Geometry) null, true); assertNotNull(granuleDescriptor1.toString()); assertNotNull(granuleDescriptor2.toString()); final OverviewsController ovControllerG1 = granuleDescriptor1.overviewsController; final OverviewsController ovControllerG2 = granuleDescriptor2.overviewsController; // // // // Initializing read request // // // final GeneralEnvelope envelope = reader.getOriginalEnvelope(); final GridEnvelope originalRange = reader.getOriginalGridRange(); final Rectangle rasterArea = new Rectangle( 0, 0, (int) Math.ceil(originalRange.getSpan(0) / 9.0), (int) Math.ceil(originalRange.getSpan(1) / 9.0)); final GridEnvelope2D range = new GridEnvelope2D(rasterArea); final GridToEnvelopeMapper geMapper = new GridToEnvelopeMapper(range, envelope); geMapper.setPixelAnchor(PixelInCell.CELL_CENTER); final AffineTransform gridToWorld = geMapper.createAffineTransform(); final double requestedResolution[] = new double[] { XAffineTransform.getScaleX0(gridToWorld), XAffineTransform.getScaleY0(gridToWorld) }; TestSet at = null; if (nOv == 4 && Math.abs(hRes[0] - 0.833333333333) <= THRESHOLD) { at = at1; } else if (nOv == 2 && Math.abs(hRes[0] - 1.40625) <= THRESHOLD) { at = at2; } else { return; } // // // // Starting OverviewsController tests // // // final OverviewPolicy[] ovPolicies = new OverviewPolicy[] { OverviewPolicy.QUALITY, OverviewPolicy.SPEED, OverviewPolicy.NEAREST, OverviewPolicy.IGNORE }; for (int i = 0; i < ovPolicies.length; i++) { OverviewPolicy ovPolicy = ovPolicies[i]; LOGGER.info("Testing with OverviewPolicy = " + ovPolicy.toString()); imageIndexG1 = ReadParamsController.setReadParams( requestedResolution, ovPolicy, DecimationPolicy.ALLOW, readParamsG1, rasterManager, ovControllerG1); imageIndexG2 = ReadParamsController.setReadParams( requestedResolution, ovPolicy, DecimationPolicy.ALLOW, readParamsG2, rasterManager, ovControllerG2); assertSame(at.ot[i].g1.imageIndex, imageIndexG1); assertSame(at.ot[i].g2.imageIndex, imageIndexG2); assertSame(at.ot[i].g1.ssx, readParamsG1.getSourceXSubsampling()); assertSame(at.ot[i].g1.ssy, readParamsG1.getSourceYSubsampling()); assertSame(at.ot[i].g2.ssx, readParamsG2.getSourceXSubsampling()); assertSame(at.ot[i].g2.ssy, readParamsG2.getSourceYSubsampling()); } }
/** * Collect georeferencing information about this geotiff. * * @param hints * @throws DataSourceException */ private void getHRInfo(Hints hints) throws DataSourceException { ImageReader reader = null; ImageReader ovrReader = null; ImageInputStream ovrStream = null; try { // // // // Get a reader for this format // // // reader = READER_SPI.createReaderInstance(); // // // // get the METADATA // // // inStream.mark(); reader.setInput(inStream); final IIOMetadata iioMetadata = reader.getImageMetadata(0); final GeoTiffIIOMetadataDecoder metadata = new GeoTiffIIOMetadataDecoder(iioMetadata); gtcs = new GeoTiffMetadata2CRSAdapter(hints); // // // // get the CRS INFO // // // final Object tempCRS = this.hints.get(Hints.DEFAULT_COORDINATE_REFERENCE_SYSTEM); if (tempCRS != null) { this.crs = (CoordinateReferenceSystem) tempCRS; if (LOGGER.isLoggable(Level.FINE)) LOGGER.log(Level.FINE, "Using forced coordinate reference system"); } else { // check external prj first crs = getCRS(source); // now, if we did not want to override the inner CRS or we did not have any external PRJ at // hand // let's look inside the geotiff if (!OVERRIDE_INNER_CRS || crs == null) { if (metadata.hasGeoKey() && gtcs != null) { crs = gtcs.createCoordinateSystem(metadata); } } } // // No data // if (metadata.hasNoData()) { noData = metadata.getNoData(); } // // parse and set layout // setLayout(reader); // // // // get the dimension of the hr image and build the model as well as // computing the resolution // // numOverviews = reader.getNumImages(true) - 1; int hrWidth = reader.getWidth(0); int hrHeight = reader.getHeight(0); final Rectangle actualDim = new Rectangle(0, 0, hrWidth, hrHeight); originalGridRange = new GridEnvelope2D(actualDim); if (gtcs != null && metadata != null && (metadata.hasModelTrasformation() || (metadata.hasPixelScales() && metadata.hasTiePoints()))) { this.raster2Model = GeoTiffMetadata2CRSAdapter.getRasterToModel(metadata); } else { // world file this.raster2Model = parseWorldFile(source); // now world file --> mapinfo? if (raster2Model == null) { MapInfoFileReader mifReader = parseMapInfoFile(source); if (mifReader != null) { raster2Model = mifReader.getTransform(); crs = mifReader.getCRS(); } } } if (crs == null) { if (LOGGER.isLoggable(Level.WARNING)) { LOGGER.warning("Coordinate Reference System is not available"); } crs = AbstractGridFormat.getDefaultCRS(); } if (this.raster2Model == null) { TiePoint[] modelTiePoints = metadata.getModelTiePoints(); if (modelTiePoints != null && modelTiePoints.length > 1) { // use a unit transform and expose the GCPs gcps = new GroundControlPoints(Arrays.asList(modelTiePoints), crs); raster2Model = ProjectiveTransform.create(new AffineTransform()); crs = AbstractGridFormat.getDefaultCRS(); } else { throw new DataSourceException("Raster to Model Transformation is not available"); } } // create envelope using corner transformation final AffineTransform tempTransform = new AffineTransform((AffineTransform) raster2Model); tempTransform.concatenate(CoverageUtilities.CENTER_TO_CORNER); originalEnvelope = CRS.transform(ProjectiveTransform.create(tempTransform), new GeneralEnvelope(actualDim)); originalEnvelope.setCoordinateReferenceSystem(crs); // /// // // setting the higher resolution available for this coverage // // /// highestRes = new double[2]; highestRes[0] = XAffineTransform.getScaleX0(tempTransform); highestRes[1] = XAffineTransform.getScaleY0(tempTransform); if (ovrInStreamSPI != null) { ovrReader = READER_SPI.createReaderInstance(); ovrStream = ovrInStreamSPI.createInputStreamInstance( ovrSource, ImageIO.getUseCache(), ImageIO.getCacheDirectory()); ovrReader.setInput(ovrStream); // this includes the real image as this is a image index, we need to add one. extOvrImgChoice = numOverviews + 1; numOverviews = numOverviews + ovrReader.getNumImages(true); if (numOverviews < extOvrImgChoice) extOvrImgChoice = -1; } // // // // get information for the successive images // // // if (numOverviews >= 1) { overViewResolutions = new double[numOverviews][2]; // Internal overviews start at 1, so lastInternalOverview matches numOverviews if no // external. int firstExternalOverview = extOvrImgChoice == -1 ? numOverviews : extOvrImgChoice - 1; double spanRes0 = highestRes[0] * this.originalGridRange.getSpan(0); double spanRes1 = highestRes[1] * this.originalGridRange.getSpan(1); for (int i = 0; i < firstExternalOverview; i++) { overViewResolutions[i][0] = spanRes0 / reader.getWidth(i + 1); overViewResolutions[i][1] = spanRes1 / reader.getHeight(i + 1); } for (int i = firstExternalOverview; i < numOverviews; i++) { overViewResolutions[i][0] = spanRes0 / ovrReader.getWidth(i - firstExternalOverview); overViewResolutions[i][1] = spanRes1 / ovrReader.getHeight(i - firstExternalOverview); } } else overViewResolutions = null; } catch (Throwable e) { throw new DataSourceException(e); } finally { if (reader != null) try { reader.dispose(); } catch (Throwable t) { } if (ovrReader != null) try { ovrReader.dispose(); } catch (Throwable t) { } if (ovrStream != null) try { ovrStream.close(); } catch (Throwable t) { } if (inStream != null) try { inStream.reset(); } catch (Throwable t) { } } }
/** * Computes the requested resolution which is going to be used for selecting overviews and or * deciding decimation factors on the target coverage. * * <p>In case the requested envelope is in the same {@link CoordinateReferenceSystem} of the * coverage we compute the resolution using the requested {@link MathTransform}. Notice that it * must be a {@link LinearTransform} or else we fail. * * <p>In case the requested envelope is not in the same {@link CoordinateReferenceSystem} of the * coverage we * * @throws DataSourceException in case something bad happens during reprojections and/or * intersections. */ private void computeRequestedResolution() throws DataSourceException { try { // let's try to get the resolution from the requested gridToWorld if (requestedGridToWorld instanceof LinearTransform) { // // the crs of the request and the one of the coverage are NOT the // same and the conversion is not , we can get the resolution from envelope + raster // directly // if (destinationToSourceTransform != null && !destinationToSourceTransform.isIdentity()) { // // compute the approximated resolution in the request crs, notice that we are // assuming a reprojection that keeps the raster area unchanged hence // the effect is a degradation of quality, but we might take that into account emprically // requestedResolution = null; // // // compute the raster that correspond to the crop bbox at the highest resolution // final Rectangle sourceRasterArea = new GeneralGridEnvelope( // CRS.transform( // PixelTranslation.translate(rasterManager.getRaster2Model(),PixelInCell.CELL_CENTER,PixelInCell.CELL_CORNER).inverse(), // cropBBox),PixelInCell.CELL_CORNER,false).toRectangle(); // XRectangle2D.intersect(sourceRasterArea, // rasterManager.spatialDomainManager.coverageRasterArea, sourceRasterArea); // if(sourceRasterArea.isEmpty()) // throw new DataSourceException("The request source raster area is empty"); final GridToEnvelopeMapper geMapper = new GridToEnvelopeMapper(new GridEnvelope2D(destinationRasterArea), cropBBox); final AffineTransform tempTransform = geMapper.createAffineTransform(); // final double scaleX=XAffineTransform.getScaleX0((AffineTransform) // requestedGridToWorld)/XAffineTransform.getScaleX0(tempTransform); // final double scaleY=XAffineTransform.getScaleY0((AffineTransform) // requestedGridToWorld)/XAffineTransform.getScaleY0(tempTransform); // // // // empiric adjustment to get a finer resolution to have better quality when // reprojecting // // TODO make it parametric // // // requestedRasterScaleFactors= new double[2]; // requestedRasterScaleFactors[0]=scaleX*1.0; // requestedRasterScaleFactors[1]=scaleY*1.0; requestedResolution = new double[] { XAffineTransform.getScaleX0(tempTransform), XAffineTransform.getScaleY0(tempTransform) }; } else { // the crs of the request and the one of the coverage are the // same, we can get the resolution from the grid to world requestedResolution = new double[] { XAffineTransform.getScaleX0(requestedGridToWorld), XAffineTransform.getScaleY0(requestedGridToWorld) }; } } else // should not happen throw new UnsupportedOperationException( Errors.format(ErrorKeys.UNSUPPORTED_OPERATION_$1, requestedGridToWorld.toString())); // leave return; } catch (Throwable e) { if (LOGGER.isLoggable(Level.INFO)) LOGGER.log(Level.INFO, "Unable to compute requested resolution", e); } // // use the coverage resolution since we cannot compute the requested one // LOGGER.log(Level.WARNING, "Unable to compute requested resolution, using highest available"); requestedResolution = coverageProperties.fullResolution; }