/* * Geotoolkit.org - An Open Source Java GIS Toolkit * http://www.geotoolkit.org * * (C) 2002-2012, Open Source Geospatial Foundation (OSGeo) * (C) 2009-2012, Geomatys * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. */ package org.geotoolkit.coverage.grid; import java.util.Random; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; import java.awt.image.WritableRaster; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import org.opengis.referencing.crs.CoordinateReferenceSystem; import org.geotoolkit.factory.Hints; import org.geotoolkit.coverage.Category; import org.geotoolkit.coverage.GridSampleDimension; import org.geotoolkit.coverage.CoverageFactoryFinder; import org.apache.sis.geometry.GeneralEnvelope; import org.apache.sis.referencing.crs.DefaultGeographicCRS; import org.geotoolkit.test.image.ImageTestBase; import org.apache.sis.referencing.CommonCRS; import static org.apache.sis.measure.Units.*; import static org.junit.Assert.*; /** * Base class for grid coverage tests. This class provides a {@link GridCoverage2D} field, * and some convenience methods working on it. * * @author Martin Desruisseaux (IRD) * @version 3.02 * * @since 2.1 */ public abstract strictfp class GridCoverageTestBase extends ImageTestBase { /** * Random number generator for this test. */ private static final Random random = new Random(684673898634768L); /** * The coverage to be tested. An instance can be obtained by * {@link #loadSampleCoverage(SampleCoverage)} or {@link #createRandomCoverage()}. */ protected GridCoverage2D coverage; /** * Creates a new test suite for the given class. * * @param testing The class to be tested. */ protected GridCoverageTestBase(final Class<?> testing) { super(testing); } /** * Loads the given sample coverage. The result is stored in the {@link #coverage} field. * * @param s The enum for the sample grid coverage to load. */ protected final void loadSampleCoverage(final SampleCoverage s) { try { coverage = s.load(); } catch (IOException e) { throw new AssertionError(e); } s.verifyGridGeometry(coverage, 1E-10); } /** * Creates a grid coverage filled with random values. The coordinate * reference system default to {@link DefaultGeographicCRS#WGS84}. */ protected final void createRandomCoverage() { createRandomCoverage(CommonCRS.WGS84.normalizedGeographic()); } /** * Creates a grid coverage filled with random values. * The result is stored in the {@link #coverage} field. * * @param crs The coverage coordinate reference system. */ protected final void createRandomCoverage(final CoordinateReferenceSystem crs) { /* * Some constants used for the construction and tests of the grid coverage. */ final double SCALE = 0.1; // Scale factor for pixel transcoding. final double OFFSET = 5.0; // Offset factor for pixel transcoding. final double PIXEL_SIZE = .25; // Pixel size (in degrees). Used in transformations. final int BEGIN_VALID = 3; // The minimal valid index for quantitative category. /* * Constructs the grid coverage. We will assume that the grid coverage use * (longitude,latitude) coordinates, pixels of 0.25 degrees and a lower * left corner at 10°W 30°N. */ final GridCoverage2D coverage; // The final grid coverage. final BufferedImage image; // The GridCoverage's data. final WritableRaster raster; // The image's data as a raster. final Rectangle2D bounds; // The GridCoverage's envelope. final GridSampleDimension band; // The only image's band. band = new GridSampleDimension("Temperature", new Category[] { new Category("No data", null, 0), new Category("Land", null, 1), new Category("Cloud", null, 2), new Category("Temperature", null, BEGIN_VALID, 256, SCALE, OFFSET) }, CELSIUS); image = new BufferedImage(120, 80, BufferedImage.TYPE_BYTE_INDEXED); raster = image.getRaster(); for (int i=raster.getWidth(); --i>=0;) { for (int j=raster.getHeight(); --j>=0;) { raster.setSample(i,j,0, random.nextInt(256)); } } bounds = new Rectangle2D.Double(-10, 30, PIXEL_SIZE*image.getWidth(), PIXEL_SIZE*image.getHeight()); final GeneralEnvelope envelope = new GeneralEnvelope(crs); envelope.setRange(0, bounds.getMinX(), bounds.getMaxX()); envelope.setRange(1, bounds.getMinY(), bounds.getMaxY()); for (int i=envelope.getDimension(); --i>=2;) { final double min = 10 * i; envelope.setRange(i, min, min + 5); } final Hints hints = new Hints(Hints.TILE_ENCODING, "raw"); final GridCoverageFactory factory = CoverageFactoryFinder.getGridCoverageFactory(hints); coverage = factory.create("Test", image, envelope, new GridSampleDimension[] {band}, null, null); assertEquals("raw", coverage.tileEncoding); /* * Grid coverage construction finished. Now test it. First we test the creation of a * "geophysics" view. This test make sure that the 'view(type)' method does not create * more grid coverages than needed. */ assertSame(coverage.getRenderedImage(), coverage.getRenderableImage(0,1).createDefaultRendering()); assertSame(image.getTile(0,0), coverage.getRenderedImage().getTile(0,0)); GridCoverage2D geophysics = coverage.view(ViewType.GEOPHYSICS); assertSame(coverage, coverage.view(ViewType.PACKED)); assertSame(coverage, geophysics.view(ViewType.PACKED)); assertSame(geophysics, geophysics.view(ViewType.GEOPHYSICS)); assertFalse( coverage.equals(geophysics)); assertFalse( coverage.getSampleDimension(0).getSampleToGeophysics().isIdentity()); assertTrue(geophysics.getSampleDimension(0).getSampleToGeophysics().isIdentity()); /* * Compares data. */ final int bandN = 0; // Band to test. double[] bufferCov = null; double[] bufferGeo = null; final double left = bounds.getMinX() + (0.5*PIXEL_SIZE); // Includes translation to center final double upper = bounds.getMaxY() - (0.5*PIXEL_SIZE); // Includes translation to center final Point2D.Double point = new Point2D.Double(); // Will maps to pixel center. for (int j=raster.getHeight(); --j>=0;) { for (int i=raster.getWidth(); --i>=0;) { point.x = left + PIXEL_SIZE*i; point.y = upper - PIXEL_SIZE*j; double r = raster.getSampleDouble(i,j,bandN); bufferCov = coverage.evaluate(point, bufferCov); bufferGeo = geophysics.evaluate(point, bufferGeo); assertEquals(r, bufferCov[bandN], SAMPLE_TOLERANCE); // Compares transcoded samples. if (r < BEGIN_VALID) { assertTrue(Double.isNaN(bufferGeo[bandN])); } else { assertEquals(OFFSET + SCALE*r, bufferGeo[bandN], SAMPLE_TOLERANCE); } } } this.coverage = coverage; } /** * Tests the serialization of the packed and geophysics views of the * {@linkplain #coverage current coverage}. * * @return The deserialized grid coverage as packed view. * @throws IOException if an I/O operation was needed and failed. * @throws ClassNotFoundException Should never happen. */ protected final GridCoverage2D serialize() throws IOException, ClassNotFoundException { assertNotNull("CoverageTestCase.coverage field is not assigned.", coverage); coverage.tileEncoding = null; /* * The previous line is not something that we should do. * But we want to test the default GridCoverage2D encoding. */ final ByteArrayOutputStream buffer = new ByteArrayOutputStream(); try (ObjectOutputStream out = new ObjectOutputStream(buffer)) { out.writeObject(coverage.view(ViewType.PACKED)); out.writeObject(coverage.view(ViewType.GEOPHYSICS)); } GridCoverage2D read; try (ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(buffer.toByteArray()))) { read = (GridCoverage2D) in.readObject(); assertSame(read, read.view(ViewType.PACKED)); read = (GridCoverage2D) in.readObject(); assertSame(read, read.view(ViewType.GEOPHYSICS)); } final GridCoverage2D view = read.view(ViewType.PACKED); assertNotSame(read, view); return view; } }