001: /*
002: * GeoTools - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2003-2006, Geotools Project Managment Committee (PMC)
005: * (C) 2001, Institut de Recherche pour le Développement
006: *
007: * This library is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU Lesser General Public
009: * License as published by the Free Software Foundation; either
010: * version 2.1 of the License, or (at your option) any later version.
011: *
012: * This library is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * This package contains documentation from OpenGIS specifications.
018: * OpenGIS consortium's work is fully acknowledged here.
019: */
020: package org.geotools.coverage.processing.operation;
021:
022: // J2SE dependencies
023: import java.lang.reflect.Array;
024:
025: // JAI dependencies
026: import javax.media.jai.Interpolation;
027:
028: // OpenGIS dependencies
029: import org.opengis.coverage.Coverage;
030: import org.opengis.parameter.ParameterDescriptor;
031: import org.opengis.parameter.ParameterValueGroup;
032:
033: // Geotools dependencies
034: import org.geotools.factory.Hints;
035: import org.geotools.coverage.grid.GridCoverage2D;
036: import org.geotools.coverage.grid.Interpolator2D;
037: import org.geotools.coverage.processing.Operation2D;
038: import org.geotools.metadata.iso.citation.Citations;
039: import org.geotools.parameter.DefaultParameterDescriptor;
040: import org.geotools.parameter.DefaultParameterDescriptorGroup;
041: import org.geotools.resources.image.ImageUtilities;
042:
043: /**
044: * Specifies the interpolation type to be used to interpolate values for points which fall between
045: * grid cells. The default value is nearest neighbor. The new interpolation type operates on all
046: * sample dimensions. Possible values for type are: {@code "NearestNeighbor"}, {@code "Bilinear"}
047: * and {@code "Bicubic"} (the {@code "Optimal"} interpolation type is currently not supported).
048: * <p>
049: * <strong>Geotools extension:</strong><br>
050: * The Geotools implementation provides two extensions to OpenGIS specification: First, it accepts
051: * also an {@link javax.media.jai.Interpolation} argument type, for interoperability with
052: * <A HREF="http://java.sun.com/products/java-media/jai/">Java Advanced Imaging</A>. Second, it
053: * accepts also an array of {@link java.lang.String} or {@link javax.media.jai.Interpolation}
054: * objects. When an array is specified, the first interpolation in the array is applied. If this
055: * interpolation returns a {@code NaN} value, then the second interpolation is tried as a fallback.
056: * If the second interpolation returns also a {@code NaN} value, then the third one is tried and so
057: * on until an interpolation returns a real number or until we reach the end of interpolation list.
058: * This behavior is convenient when processing remote sensing images of geophysics data, for example
059: * <cite>Sea Surface Temperature</cite> (SST), in which clouds may mask many pixels (i.e. set them
060: * to some {@code NaN} values). Because {@code "Bicubic"} interpolation needs 4×4 pixels while
061: * {@code "Bilinear"} interpolation needs only 2x2 pixels, the {@code "Bilinear"} interpolation is
062: * less likely to fails because of clouds ({@code NaN} values) than the {@code "Bicubic"} one
063: * (note: only one {@code NaN} value is enough to make an interpolation fails). One can workaround
064: * the problem by trying a bicubic interpolation first, then a linear interpolation if
065: * {@code "Bicubic"} failed at a particular location, <cite>etc.</cite> This behavior can be
066: * specified with the following {@code "Type"} argument:
067: * <code>new String[]{"Bicubic", "Bilinear", "NearestNeighbor"}</code>.
068: *
069: * <P><STRONG>Name:</STRONG> <CODE>"Interpolate"</CODE><BR>
070: * <STRONG>JAI operator:</STRONG> N/A<BR>
071: * <STRONG>Parameters:</STRONG></P>
072: * <table border='3' cellpadding='6' bgcolor='F4F8FF'>
073: * <tr bgcolor='#B9DCFF'>
074: * <th>Name</th>
075: * <th>Class</th>
076: * <th>Default value</th>
077: * <th>Minimum value</th>
078: * <th>Maximum value</th>
079: * </tr>
080: * <tr>
081: * <td>{@code "Source"}</td>
082: * <td>{@link org.geotools.coverage.grid.GridCoverage2D}</td>
083: * <td align="center">N/A</td>
084: * <td align="center">N/A</td>
085: * <td align="center">N/A</td>
086: * </tr>
087: * <tr>
088: * <td>{@code "Type"}</td>
089: * <td>{@link java.lang.CharSequence}</td>
090: * <td>"NearestNeighbor"</td>
091: * <td align="center">N/A</td>
092: * <td align="center">N/A</td>
093: * </tr>
094: * </table>
095: *
096: * @since 2.2
097: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/coverage/src/main/java/org/geotools/coverage/processing/operation/Interpolate.java $
098: * @version $Id: Interpolate.java 20970 2006-08-11 07:53:22Z jgarnett $
099: * @author Martin Desruisseaux
100: *
101: * @see org.geotools.coverage.processing.Operations#interpolate
102: * @see Interpolator2D
103: */
104: public class Interpolate extends Operation2D {
105: /**
106: * Serial number for interoperability with different versions.
107: */
108: private static final long serialVersionUID = 6742127682733620661L;
109:
110: /**
111: * The parameter descriptor for the interpolation type.
112: */
113: public static final ParameterDescriptor TYPE = new DefaultParameterDescriptor(
114: Citations.OGC, "Type", Object.class, // Value class (mandatory)
115: null, // Array of valid values
116: "NearestNeighbor", // Default value
117: null, // Minimal value
118: null, // Maximal value
119: null, // Unit of measure
120: true); // Parameter is mandatory
121:
122: /**
123: * Constructs an {@code "Interpolate"} operation.
124: */
125: public Interpolate() {
126: super (new DefaultParameterDescriptorGroup(Citations.OGC,
127: "Interpolate", new ParameterDescriptor[] { SOURCE_0,
128: TYPE }));
129: }
130:
131: /**
132: * Applies an interpolation to a grid coverage. This method is invoked
133: * by {@link org.geotools.coverage.processing.DefaultProcessor} for the
134: * {@code "Interpolate"} operation.
135: */
136: public Coverage doOperation(final ParameterValueGroup parameters,
137: final Hints hints) {
138: final GridCoverage2D source = (GridCoverage2D) parameters
139: .parameter("Source").getValue();
140: final Object type = parameters.parameter("Type").getValue();
141: final Interpolation[] interpolations;
142: if (type.getClass().isArray()) {
143: interpolations = new Interpolation[Array.getLength(type)];
144: for (int i = 0; i < interpolations.length; i++) {
145: interpolations[i] = ImageUtilities
146: .toInterpolation(Array.get(type, i));
147: }
148: } else {
149: interpolations = new Interpolation[] { ImageUtilities
150: .toInterpolation(type) };
151: }
152: return Interpolator2D.create(source, interpolations);
153: }
154: }
|