/*
* Geotoolkit.org - An Open Source Java GIS Toolkit
* http://www.geotoolkit.org
*
* (C) 2010-2012, Open Source Geospatial Foundation (OSGeo)
* (C) 2010-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.io;
import java.io.IOException;
import javax.imageio.IIOParam;
import javax.imageio.ImageWriter;
import java.awt.image.RenderedImage;
import java.awt.geom.AffineTransform;
import javax.imageio.metadata.IIOMetadata;
import org.opengis.coverage.grid.GridCoverage;
import org.opengis.coverage.grid.RectifiedGrid;
import org.opengis.referencing.operation.Matrix;
import org.opengis.referencing.operation.MathTransform2D;
import org.geotoolkit.coverage.grid.GridGeometry2D;
import org.geotoolkit.image.io.ImageMetadataException;
import org.geotoolkit.image.io.metadata.MetadataHelper;
import org.geotoolkit.image.io.metadata.SpatialMetadata;
import org.apache.sis.referencing.operation.transform.LinearTransform;
import static org.geotoolkit.test.Assert.*;
import static org.geotoolkit.image.io.MultidimensionalImageStore.*;
/**
* An {@link ImageCoverageWriter} which retains some intermediate computation during the
* writing process.
*
* @author Martin Desruisseaux (Geomatys)
* @version 3.17
*
* @since 3.14
*/
final strictfp class ImageCoverageWriterInspector extends ImageCoverageWriter {
/**
* Small number for comparison of floating point values.
*/
private static final double EPS = 1E-10;
/**
* The caller method.
*/
private final String caller;
/**
* The format name, or {@code null} for auto-detect.
*/
private final String format;
/**
* The difference between the requested grid and the actual grid which is used
* for fetching the pixel values to write.
*/
private MathTransform2D differenceTransform;
/**
* The metadata created by the writer.
*
* @since 3.17
*/
private IIOMetadata metadata;
/**
* Creates a new instance.
*/
ImageCoverageWriterInspector(final String caller) {
this(caller, null);
}
/**
* Creates a new instance which will force the usage of the given format.
*/
ImageCoverageWriterInspector(final String caller, final String format) {
this.caller = caller;
this.format = format;
}
/**
* If the format is unspecified, uses the format given at construction time.
*/
@Override
protected ImageWriter createImageWriter(String formatName,
final Object output, final RenderedImage image) throws IOException
{
if (formatName == null) {
formatName = format;
}
return super.createImageWriter(formatName, output, image);
}
/**
* Delegates to the default implementation and stores the result.
*/
@Override
protected MathTransform2D geodeticToPixelCoordinates(final GridGeometry2D gridGeometry,
final GridCoverageStoreParam geodeticParam, final IIOParam pixelParam,
final boolean isNetcdfHack) // TODO: DEPRECATED: to be removed in Apache SIS.
throws CoverageStoreException
{
final MathTransform2D tr = super.geodeticToPixelCoordinates(gridGeometry, geodeticParam, pixelParam, isNetcdfHack);
differenceTransform = tr;
return tr;
}
/**
* Retains the image metadata (we don't care about the stream metadata for now).
*
* @since 3.17
*/
@Override
protected void completeImageMetadata(IIOMetadata metadata, GridCoverage coverage) throws IOException {
super.completeImageMetadata(metadata, coverage);
if (coverage != null) {
this.metadata = metadata;
}
}
/**
* Asserts that the write operation matched the user request without the need for
* a scaling of translation. Note however that a need for a expanding the bounds
* may still be present.
*/
public void assertNoDifference() {
assertTrue("No scale or translation expected.", isIdentity(differenceTransform));
}
/**
* Asserts that the difference transform contains no translation terms,
* and only the scale terms given to this method.
*/
public void assertDifferenceEqualsScale(final double scaleX, final double scaleY) {
assertFalse("Expected a scale factor.", isIdentity(differenceTransform));
assertTrue(differenceTransform instanceof LinearTransform);
final Matrix m = ((LinearTransform) differenceTransform).getMatrix();
for (int j=m.getNumRow(); --j>=0;) {
for (int i=m.getNumCol(); --i>=0;) {
final double expected;
if (i == j) {
switch (j) {
case X_DIMENSION: expected = scaleX; break;
case Y_DIMENSION: expected = scaleY; break;
default: expected = 1; break;
}
} else {
expected = 0;
}
assertEquals(expected, m.getElement(j, i), EPS);
}
}
}
/**
* Asserts that the difference transform contains no scale terms,
* and only the translation terms given to this method.
*/
public void assertDifferenceEqualsTranslation(final double tx, final double ty) {
assertFalse("Expected translation terms.", isIdentity(differenceTransform));
assertTrue(differenceTransform instanceof LinearTransform);
final Matrix m = ((LinearTransform) differenceTransform).getMatrix();
final int tc = m.getNumCol() - 1;
for (int j=m.getNumRow(); --j>=0;) {
for (int i=m.getNumCol(); --i>=0;) {
final double expected;
if (i == tc) {
switch (j) {
case X_DIMENSION: expected = tx; break;
case Y_DIMENSION: expected = ty; break;
default: expected = 1; break;
}
} else {
expected = (i == j) ? 1 : 0;
}
assertEquals(expected, m.getElement(j, i), EPS);
}
}
}
/**
* Tests that the rectified grid is equals to the given affine transform coefficients.
*
* @since 3.17
*/
public void assertRectifiedGridEquals(final double scaleX, final double scaleY,
final double translateX, final double translateY) throws ImageMetadataException
{
assertInstanceOf("Expected a spatial metadata", SpatialMetadata.class, metadata);
final MetadataHelper helper = new MetadataHelper(null);
final RectifiedGrid rg = ((SpatialMetadata) metadata).getInstanceForType(RectifiedGrid.class);
final AffineTransform tr = helper.getAffineTransform(rg, null);
assertEquals("shearX", 0, tr.getShearX(), EPS);
assertEquals("shearY", 0, tr.getShearY(), EPS);
assertEquals("scaleX", scaleX, tr.getScaleX(), EPS);
assertEquals("scaleY", scaleY, tr.getScaleY(), EPS);
assertEquals("translateX", translateX, tr.getTranslateX(), EPS);
assertEquals("translateY", translateY, tr.getTranslateY(), EPS);
}
/**
* Returns debugging information.
*/
@Override
public String toString() {
final StringBuilder buffer = new StringBuilder("differenceTransform in ");
buffer.append(caller).append(":\n");
Object print = differenceTransform;
if (print instanceof LinearTransform) {
print = ((LinearTransform) differenceTransform).getMatrix();
}
return buffer.append(print).append('\n').toString();
}
}