001: /*
002: * GeoTools - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2005-2006, Geotools Project Managment Committee (PMC)
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation; either
009: * version 2.1 of the License, or (at your option) any later version.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: */
016: package org.geotools.coverage.grid;
017:
018: // J2SE and JAI dependencies
019: import java.util.Map;
020: import java.awt.Color;
021: import java.awt.RenderingHints;
022: import java.awt.image.ColorModel;
023: import java.awt.image.DataBuffer;
024: import java.awt.image.BufferedImage;
025: import java.awt.image.RenderedImage;
026: import java.awt.image.WritableRaster;
027: import java.awt.image.renderable.ParameterBlock;
028: import java.awt.geom.AffineTransform;
029: import javax.media.jai.JAI;
030: import javax.media.jai.PlanarImage;
031: import javax.media.jai.ImageFunction;
032: import javax.media.jai.RasterFactory;
033: import javax.media.jai.util.CaselessStringKey;
034: import javax.units.Unit;
035:
036: // OpenGIS dependencies
037: import org.opengis.coverage.SampleDimensionType;
038: import org.opengis.coverage.grid.GridCoverage;
039: import org.opengis.coverage.grid.GridRange;
040: import org.opengis.referencing.cs.AxisDirection; // For javadoc
041: import org.opengis.referencing.crs.CoordinateReferenceSystem;
042: import org.opengis.referencing.operation.MathTransform;
043: import org.opengis.geometry.Envelope;
044:
045: // Geotools dependencies
046: import org.geotools.factory.Hints;
047: import org.geotools.factory.AbstractFactory;
048: import org.geotools.geometry.GeneralEnvelope;
049: import org.geotools.coverage.GridSampleDimension;
050: import org.geotools.referencing.crs.DefaultGeographicCRS;
051: import org.geotools.resources.i18n.ErrorKeys;
052: import org.geotools.resources.i18n.Errors;
053: import org.geotools.resources.Utilities;
054:
055: /**
056: * A factory for {@linkplain GridCoverage2D grid coverage} objects. This factory expects various
057: * combinaisons of the following informations:
058: * <p>
059: * <ul>
060: * <li>A name as a {@linkplain CharSequence character sequence}.</li>
061: *
062: * <li>A {@linkplain WritableRaster raster}, <strong>or</strong> an {@linkplain RenderedImage image},
063: * <strong>or</strong> an {@linkplain ImageFunction image function}, <strong>or</strong>
064: * a matrix of kind {@code float[][]}.</li>
065: *
066: * <li>A ({@linkplain CoordinateReferenceSystem coordinate reference system} -
067: * {@linkplain MathTransform transform}) pair, <strong>or</strong> an {@linkplain Envelope
068: * envelope}, <strong>or</strong> a {@linkplain GridGeometry2D grid geometry}. The envelope
069: * is easier to use, while the transform provides more control.</li>
070: *
071: * <li>Information about each {@linkplain GridSampleDimension sample dimensions} (often
072: * called <cite>bands</cite> in the particular case of images), <strong>or</strong> minimal
073: * and maximal expected values for each bands.</li>
074: *
075: * <li>Optional properties as a {@linkplain Map map} of <cite>key</cite>-<cite>value</cite> pairs.
076: * "Properties" in <cite>Java Advanced Imaging</cite> are called "Metadata" by OpenGIS.
077: * Keys are {@link String} objects ({@link CaselessStringKey} are accepted as well), while
078: * values may be any {@link Object}.</li>
079: * </ul>
080: *
081: * <p>The {@linkplain CoordinateReferenceSystem coordinate reference system} is inferred from the
082: * supplied {@linkplain Envelope envelope} or {@linkplain GridGeometry2D grid geometry} parameters.
083: * If those parameters do not have CRS information, then this factory fallback on a {@linkplain
084: * #getDefaultCRS default CRS}.</p>
085: *
086: * <p>Every {@code create} methods will ultimately delegate their work to a master
087: * {@link #create(CharSequence, RenderedImage, GridGeometry2D, GridSampleDimension[],
088: * GridCoverage[], Map) create} variant. Developpers can override this method if they
089: * want to intercept the creation of all {@link GridCoverage2D} objects in this factory.</p>
090: *
091: * @since 2.1
092: * @author Martin Desruisseaux
093: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/coverage/src/main/java/org/geotools/coverage/grid/GridCoverageFactory.java $
094: * @version $Id: GridCoverageFactory.java 25449 2007-05-07 12:21:16Z desruisseaux $
095: */
096: public class GridCoverageFactory extends AbstractFactory {
097: /**
098: * Creates a default factory. Users should not need to creates instance of this class
099: * directly. Invoke {@link org.geotools.coverage.FactoryFinder#getGridCoverageFactory}
100: * instead.
101: */
102: public GridCoverageFactory() {
103: this (null);
104: }
105:
106: /**
107: * Creates a factory using the specified set of hints.
108: * The factory recognizes the following hints:
109: * <p>
110: * <ul>
111: * <li>{@link Hints#DEFAULT_COORDINATE_REFERENCE_SYSTEM}</li>
112: * <li>{@link Hints#TILE_ENCODING}</li>
113: * </ul>
114: */
115: public GridCoverageFactory(final Hints userHints) {
116: CoordinateReferenceSystem defaultCRS = null;
117: String tileEncoding = null;
118: if (userHints != null) {
119: defaultCRS = (CoordinateReferenceSystem) userHints
120: .get(Hints.DEFAULT_COORDINATE_REFERENCE_SYSTEM);
121: if (Utilities
122: .equals(defaultCRS, DefaultGeographicCRS.WGS84)
123: || Utilities.equals(defaultCRS,
124: DefaultGeographicCRS.WGS84_3D)) {
125: // Will be handled in a special way by getDefaultCRS(int)
126: defaultCRS = null;
127: }
128: tileEncoding = (String) userHints.get(Hints.TILE_ENCODING);
129: if (tileEncoding != null) {
130: tileEncoding = tileEncoding.trim();
131: if (tileEncoding.length() == 0) {
132: tileEncoding = null;
133: }
134: }
135: }
136: hints
137: .put(Hints.DEFAULT_COORDINATE_REFERENCE_SYSTEM,
138: defaultCRS);
139: hints.put(Hints.TILE_ENCODING, tileEncoding);
140: }
141:
142: /**
143: * Returns the default coordinate reference system to use when no CRS were explicitly
144: * specified by the user. If a {@link Hints#DEFAULT_COORDINATE_REFERENCE_SYSTEM
145: * DEFAULT_COORDINATE_REFERENCE_SYSTEM} hint were provided at factory construction
146: * time, then the specified CRS is returned. Otherwise, the default implementation
147: * returns {@link DefaultGeographicCRS#WGS84} or its 3D variant. Subclasses should
148: * override this method if they want to use different defaults.
149: *
150: * @param dimension The number of dimension expected in the CRS to be returned.
151: *
152: * @since 2.2
153: */
154: protected CoordinateReferenceSystem getDefaultCRS(
155: final int dimension) {
156: final CoordinateReferenceSystem candidate = (CoordinateReferenceSystem) hints
157: .get(Hints.DEFAULT_COORDINATE_REFERENCE_SYSTEM);
158: if (candidate != null) {
159: return candidate;
160: }
161: switch (dimension) {
162: case 2:
163: return DefaultGeographicCRS.WGS84;
164: case 3:
165: return DefaultGeographicCRS.WGS84_3D;
166: default:
167: throw new IllegalArgumentException(Errors.format(
168: ErrorKeys.ILLEGAL_ARGUMENT_$2, "dimension",
169: new Integer(dimension)));
170: }
171: }
172:
173: /**
174: * Constructs a grid coverage from an {@linkplain ImageFunction image function}.
175: *
176: * @param name The grid coverage name.
177: * @param function The image function.
178: * @param gridGeometry The grid geometry. The {@linkplain GridGeometry2D#getGridRange grid
179: * range} must contains the expected image size (width and height).
180: * @param bands Sample dimensions for each image band, or {@code null} for
181: * default sample dimensions.
182: * @param properties The set of properties for this coverage, or {@code null} if there is none.
183: *
184: * @since 2.2
185: */
186: public GridCoverage2D create(final CharSequence name,
187: final ImageFunction function,
188: final GridGeometry2D gridGeometry,
189: final GridSampleDimension[] bands, final Map properties) {
190: final MathTransform transform = gridGeometry.getGridToCRS2D();
191: if (!(transform instanceof AffineTransform)) {
192: throw new IllegalArgumentException(Errors
193: .format(ErrorKeys.NOT_AN_AFFINE_TRANSFORM));
194: }
195: final AffineTransform at = (AffineTransform) transform;
196: if (at.getShearX() != 0 || at.getShearY() != 0) {
197: // TODO: We may support that in a future version.
198: // 1) Create a copy with shear[X/Y] set to 0. Use the copy.
199: // 2) Compute the residu with createInverse() and concatenate().
200: // 3) Apply the residu with JAI.create("Affine").
201: throw new IllegalArgumentException(
202: "Shear and rotation not supported");
203: }
204: final double xScale = at.getScaleX();
205: final double yScale = at.getScaleY();
206: final double xTrans = -at.getTranslateX() / xScale;
207: final double yTrans = -at.getTranslateY() / yScale;
208: final GridRange range = gridGeometry.getGridRange();
209: final ParameterBlock param = new ParameterBlock().add(function)
210: .add(range.getLength(0)) // width
211: .add(range.getLength(1)) // height
212: .add((float) xScale).add((float) yScale).add(
213: (float) xTrans).add((float) yTrans);
214: final PlanarImage image = JAI.create("ImageFunction", param);
215: return create(name, image, gridGeometry, bands, null,
216: properties);
217: }
218:
219: /**
220: * Constructs a grid coverage from the specified matrix and {@linkplain Envelope envelope}.
221: * A default color palette is built from the minimal and maximal values found in the matrix.
222: *
223: * @param name The grid coverage name.
224: * @param matrix The matrix data in a {@code [row][column]} layout.
225: * {@linkplain Float#NaN NaN} values are mapped to a transparent color.
226: * @param envelope The envelope.
227: *
228: * @since 2.2
229: */
230: public GridCoverage2D create(final CharSequence name,
231: final float[][] matrix, final Envelope envelope) {
232: int width = 0;
233: int height = matrix.length;
234: for (int j = 0; j < height; j++) {
235: final float[] row = matrix[j];
236: if (row != null) {
237: if (row.length > width) {
238: width = row.length;
239: }
240: }
241: }
242: final WritableRaster raster;
243: // Need to use JAI raster factory, since WritableRaster
244: // does not supports TYPE_FLOAT as of J2SE 1.5.0_06.
245: raster = RasterFactory.createBandedRaster(
246: DataBuffer.TYPE_FLOAT, width, height, 1, null);
247: for (int j = 0; j < height; j++) {
248: int i = 0;
249: final float[] row = matrix[j];
250: if (row != null) {
251: for (; i < row.length; i++) {
252: raster.setSample(i, j, 0, row[i]);
253: }
254: }
255: for (; i < width; i++) {
256: raster.setSample(i, j, 0, Float.NaN);
257: }
258: }
259: return create(name, raster, envelope);
260: }
261:
262: /**
263: * Constructs a grid coverage from the specified {@linkplain WritableRaster raster} and
264: * {@linkplain Envelope envelope}. A default color palette is built from the minimal and
265: * maximal values found in the raster.
266: *
267: * @param name The grid coverage name.
268: * @param raster The data (may be floating point numbers). {@linkplain Float#NaN NaN}
269: * values are mapped to a transparent color.
270: * @param envelope The envelope.
271: */
272: public GridCoverage2D create(final CharSequence name,
273: final WritableRaster raster, final Envelope envelope) {
274: return create(name, raster, envelope, null, null, null, null,
275: null);
276: }
277:
278: /**
279: * Constructs a grid coverage from the specified {@linkplain WritableRaster raster} and
280: * {@linkplain Envelope envelope}.
281: *
282: * See the {@linkplain #create(CharSequence, RenderedImage, Envelope, GridSampleDimension[],
283: * GridCoverage[], Map) rendered image variant} for a note on heuristic rules applied by this
284: * method.
285: *
286: * @param name The grid coverage name.
287: * @param raster The data (may be floating point numbers). {@linkplain Float#NaN NaN}
288: * values are mapped to a transparent color.
289: * @param envelope The grid coverage cordinates and its CRS. This envelope must have at least
290: * two dimensions. The two first dimensions describe the image location along
291: * <var>x</var> and <var>y</var> axis. The other dimensions are optional and
292: * may be used to locate the image on a vertical axis or on the time axis.
293: * @param minValues The minimal value for each band in the raster, or {@code null}
294: * for computing it automatically.
295: * @param maxValues The maximal value for each band in the raster, or {@code null}
296: * for computing it automatically.
297: * @param units The units of sample values, or {@code null} if unknow.
298: * @param colors The colors to use for values from {@code minValues} to {@code maxValues}
299: * for each bands, or {@code null} for a default color palette. If non-null,
300: * each arrays {@code colors[b]} may have any length; colors will be
301: * interpolated as needed.
302: * @param hints An optional set of rendering hints, or {@code null} if none. Those hints
303: * will not affect the grid coverage to be created. However, they may affect
304: * the grid coverage to be returned by <code>{@link GridCoverage2D#geophysics
305: * geophysics}(false)</code>, i.e. the view to be used at rendering time. The
306: * optional {@link Hints#SAMPLE_DIMENSION_TYPE SAMPLE_DIMENSION_TYPE} hint
307: * specifies the {@link SampleDimensionType} to be used at rendering time,
308: * which can be one of {@link SampleDimensionType#UNSIGNED_8BITS UNSIGNED_8BITS}
309: * or {@link SampleDimensionType#UNSIGNED_16BITS UNSIGNED_16BITS}.
310: *
311: * @since 2.2
312: */
313: public GridCoverage2D create(final CharSequence name,
314: final WritableRaster raster, final Envelope envelope,
315: final double[] minValues, final double[] maxValues,
316: final Unit units, final Color[][] colors,
317: final RenderingHints hints) {
318: final GridSampleDimension[] bands = Grid2DSampleDimension
319: .create(name, raster, minValues, maxValues, units,
320: colors, hints);
321: final ColorModel model = bands[0]
322: .getColorModel(0, bands.length);
323: final RenderedImage image = new BufferedImage(model, raster,
324: false, null);
325: return create(name, image, envelope, bands, null, null);
326: }
327:
328: /**
329: * Constructs a grid coverage from the specified {@linkplain WritableRaster raster} and
330: * "{@linkplain GridGeometry2D#getGridToCoordinateSystem grid to CRS}" transform.
331: *
332: * @param name The grid coverage name.
333: * @param raster The data (may be floating point numbers). {@linkplain Float#NaN NaN}
334: * values are mapped to a transparent color.
335: * @param crs The coordinate reference system. This specifies the CRS used when
336: * accessing a grid coverage with the {@code evaluate} methods.
337: * @param gridToCRS The math transform from grid to coordinate reference system.
338: * @param minValues The minimal value for each band in the raster, or {@code null}
339: * for computing it automatically.
340: * @param maxValues The maximal value for each band in the raster, or {@code null}
341: * for computing it automatically.
342: * @param units The units of sample values, or {@code null} if unknow.
343: * @param colors The colors to use for values from {@code minValues} to {@code maxValues}
344: * for each bands, or {@code null} for a default color palette. If non-null,
345: * each arrays {@code colors[b]} may have any length; colors will be
346: * interpolated as needed.
347: * @param hints An optional set of rendering hints, or {@code null} if none. Those hints
348: * will not affect the grid coverage to be created. However, they may affect
349: * the grid coverage to be returned by <code>{@link GridCoverage2D#geophysics
350: * geophysics}(false)</code>, i.e. the view to be used at rendering time. The
351: * optional {@link Hints#SAMPLE_DIMENSION_TYPE SAMPLE_DIMENSION_TYPE} hint
352: * specifies the {@link SampleDimensionType} to be used at rendering time,
353: * which can be one of {@link SampleDimensionType#UNSIGNED_8BITS UNSIGNED_8BITS}
354: * or {@link SampleDimensionType#UNSIGNED_16BITS UNSIGNED_16BITS}.
355: */
356: public GridCoverage2D create(final CharSequence name,
357: final WritableRaster raster,
358: final CoordinateReferenceSystem crs,
359: final MathTransform gridToCRS, final double[] minValues,
360: final double[] maxValues, final Unit units,
361: final Color[][] colors, final RenderingHints hints) {
362: final GridSampleDimension[] bands = Grid2DSampleDimension
363: .create(name, raster, minValues, maxValues, units,
364: colors, hints);
365: final ColorModel model = bands[0]
366: .getColorModel(0, bands.length);
367: final RenderedImage image = new BufferedImage(model, raster,
368: false, null);
369: return create(name, image, crs, gridToCRS, bands, null, null);
370: }
371:
372: /**
373: * Constructs a grid coverage from the specified {@linkplain WritableRaster raster}
374: * and {@linkplain Envelope envelope}. This convenience constructor performs the same
375: * assumptions on axis order than the {@linkplain #create(CharSequence, RenderedImage,
376: * Envelope, GridSampleDimension[], GridCoverage[], Map) rendered image variant}.
377: * <p>
378: * The {@linkplain CoordinateReferenceSystem coordinate reference system} is inferred from the
379: * supplied envelope. The envelope must have at least two dimensions. The two first dimensions
380: * describe the image location along <var>x</var> and <var>y</var> axis. The other dimensions
381: * are optional and may be used to locate the image on a vertical axis or on the time axis.
382: *
383: * @param name The grid coverage name.
384: * @param raster The raster.
385: * @param envelope The grid coverage cordinates.
386: * @param bands Sample dimensions for each image band, or {@code null} for default
387: * sample dimensions. If non-null, then this array's length must matches
388: * the number of bands in {@code image}.
389: *
390: * @since 2.2
391: */
392: public GridCoverage2D create(final CharSequence name,
393: final WritableRaster raster, final Envelope envelope,
394: final GridSampleDimension[] bands) {
395: final ColorModel model = bands[0]
396: .getColorModel(0, bands.length);
397: final RenderedImage image = new BufferedImage(model, raster,
398: false, null);
399: return create(name, image, envelope, bands, null, null);
400: }
401:
402: /**
403: * Constructs a grid coverage from the specified {@linkplain WritableRaster raster} and
404: * "{@linkplain GridGeometry2D#getGridToCoordinateSystem grid to CRS}" transform.
405: *
406: * @param name The grid coverage name.
407: * @param raster The raster.
408: * @param crs The coordinate reference system. This specifies the CRS used when
409: * accessing a grid coverage with the {@code evaluate} methods. The
410: * number of dimensions must matches the number of target dimensions
411: * of {@code gridToCRS}.
412: * @param gridToCRS The math transform from grid to coordinate reference system.
413: * @param bands Sample dimensions for each image band, or {@code null} for
414: * default sample dimensions. If non-null, then this array's length
415: * must matches the number of bands in {@code image}.
416: *
417: * @since 2.2
418: */
419: public GridCoverage2D create(final CharSequence name,
420: final WritableRaster raster,
421: final CoordinateReferenceSystem crs,
422: final MathTransform gridToCRS,
423: final GridSampleDimension[] bands) {
424: final ColorModel model = bands[0]
425: .getColorModel(0, bands.length);
426: final RenderedImage image = new BufferedImage(model, raster,
427: false, null);
428: return create(name, image, crs, gridToCRS, bands, null, null);
429: }
430:
431: /**
432: * Constructs a grid coverage from the specified {@linkplain RenderedImage image} and
433: * {@linkplain Envelope envelope}. A default set of {@linkplain GridSampleDimension sample
434: * dimensions} is used. The {@linkplain CoordinateReferenceSystem coordinate reference system}
435: * is inferred from the supplied envelope.
436: * <p>
437: * The envelope must have at least two dimensions. The two first dimensions describe the image
438: * location along <var>x</var> and <var>y</var> axis. The other dimensions are optional and may
439: * be used to locate the image on a vertical axis or on the time axis.
440: *
441: * @param name The grid coverage name.
442: * @param image The image.
443: * @param envelope The grid coverage cordinates.
444: *
445: * @since 2.2
446: */
447: public GridCoverage2D create(final CharSequence name,
448: final RenderedImage image, final Envelope envelope) {
449: return create(name, image, envelope, null, null, null);
450: }
451:
452: /**
453: * Constructs a grid coverage from the specified {@linkplain RenderedImage image} and
454: * {@linkplain Envelope envelope}. An {@linkplain AffineTransform affine transform} will
455: * be computed automatically from the specified envelope using heuristic rules described below.
456: * <p>
457: * This convenience constructor assumes that axis order in the supplied image matches exactly
458: * axis order in the supplied envelope. In other words, in the usual case where axis order in
459: * the image is (<var>column</var>, <var>row</var>), then the envelope should probably have a
460: * (<var>longitude</var>, <var>latitude</var>) or (<var>easting</var>, <var>northing</var>)
461: * axis order.
462: * <p>
463: * An exception to the above rule applies for CRS using exactly the following axis order:
464: * ({@link AxisDirection#NORTH NORTH}|{@link AxisDirection#SOUTH SOUTH},
465: * {@link AxisDirection#EAST EAST}|{@link AxisDirection#WEST WEST}).
466: * An example of such CRS is {@code EPSG:4326}. This convenience constructor will
467: * interchange automatically the (<var>y</var>,<var>x</var>) axis for such CRS.
468: * <p>
469: * If more control on axis order and direction reversal is wanted, use the {@linkplain
470: * #create(CharSequence, RenderedImage, CoordinateReferenceSystem, MathTransform,
471: * GridSampleDimension[], GridCoverage[], Map) constructor variant expecting an explicit
472: * transform}.
473: *
474: * @param name The grid coverage name.
475: * @param image The image.
476: * @param envelope The grid coverage cordinates. This envelope must have at least two
477: * dimensions. The two first dimensions describe the image location
478: * along <var>x</var> and <var>y</var> axis. The other dimensions are
479: * optional and may be used to locate the image on a vertical axis or
480: * on the time axis.
481: * @param bands Sample dimensions for each image band, or {@code null} for default
482: * sample dimensions. If non-null, then this array's length must matches
483: * the number of bands in {@code image}.
484: * @param sources The sources for this grid coverage, or {@code null} if none.
485: * @param properties The set of properties for this coverage, or {@code null} if there is none.
486: *
487: * @since 2.2
488: */
489: public GridCoverage2D create(final CharSequence name,
490: final RenderedImage image, Envelope envelope,
491: final GridSampleDimension[] bands,
492: final GridCoverage[] sources, final Map properties) {
493: /*
494: * Makes sure that the specified envelope has a CRS.
495: * If no CRS were specified, a default one is used.
496: */
497: if (envelope.getCoordinateReferenceSystem() == null) {
498: final GeneralEnvelope e = new GeneralEnvelope(envelope);
499: e.setCoordinateReferenceSystem(getDefaultCRS(e
500: .getDimension()));
501: envelope = e;
502: }
503: final GridGeometry2D gm = new GridGeometry2D(
504: new GeneralGridRange(image, envelope.getDimension()),
505: envelope);
506: return create(name, image, gm, bands, sources, properties);
507: }
508:
509: /**
510: * Constructs a grid coverage from the specified {@linkplain RenderedImage image} and
511: * "{@linkplain GridGeometry2D#getGridToCoordinateSystem grid to CRS}" transform.
512: *
513: * @param name The grid coverage name.
514: * @param image The image.
515: * @param crs The coordinate reference system. This specifies the CRS used when
516: * accessing a grid coverage with the {@code evaluate} methods. The
517: * number of dimensions must matches the number of target dimensions
518: * of {@code gridToCRS}.
519: * @param gridToCRS The math transform from grid to coordinate reference system.
520: * @param bands Sample dimension for each image band, or {@code null} for default sample
521: * dimensions. If non-null, then this array's length must matches the number
522: * of bands in the {@code image}.
523: * @param sources The sources for this grid coverage, or {@code null} if none.
524: * @param properties The set of properties for this coverage, or {@code null} if there is none.
525: */
526: public GridCoverage2D create(final CharSequence name,
527: final RenderedImage image,
528: final CoordinateReferenceSystem crs,
529: final MathTransform gridToCRS,
530: final GridSampleDimension[] bands,
531: final GridCoverage[] sources, final Map properties) {
532: final GridGeometry2D gm = new GridGeometry2D(
533: new GeneralGridRange(image, crs.getCoordinateSystem()
534: .getDimension()), gridToCRS, crs);
535: return create(name, image, gm, bands, sources, properties);
536: }
537:
538: /**
539: * Constructs a grid coverage from the specified {@linkplain RenderedImage image} and
540: * {@linkplain GridGeometry2D grid geometry}. The {@linkplain Envelope envelope}
541: * (including the {@linkplain CoordinateReferenceSystem coordinate reference system})
542: * is inferred from the grid geometry.
543: * <p>
544: * This is the most general constructor, the one that gives the maximum control
545: * on the grid coverage to be created. Every {@code create} methods will ultimately
546: * delegate their work this master method. Developpers can override this method if they
547: * want to intercept the creation of all {@link GridCoverage2D} objects in this factory.
548: *
549: * @param name The grid coverage name.
550: * @param image The image.
551: * @param gridGeometry The grid geometry (must contains an {@linkplain GridGeometry2D#getEnvelope
552: * envelope} with its {@linkplain GridGeometry2D#getCoordinateReferenceSystem
553: * coordinate reference system} and a "{@linkplain
554: * GridGeometry2D#getGridToCoordinateSystem grid to CRS}" transform).
555: * @param bands Sample dimensions for each image band, or {@code null} for default sample
556: * dimensions. If non-null, then this array's length must matches the number
557: * of bands in {@code image}.
558: * @param sources The sources for this grid coverage, or {@code null} if none.
559: * @param properties The set of properties for this coverage, or {@code null} none.
560: *
561: * @since 2.2
562: */
563: public GridCoverage2D create(final CharSequence name,
564: final RenderedImage image, GridGeometry2D gridGeometry,
565: final GridSampleDimension[] bands,
566: final GridCoverage[] sources, final Map properties) {
567: /*
568: * Makes sure that the specified grid geometry has a CRS.
569: * If no CRS were specified, a default one is used.
570: */
571: if (!gridGeometry.isDefined(GridGeometry2D.CRS)) {
572: final int dimension = gridGeometry.getDimension();
573: gridGeometry = new GridGeometry2D(gridGeometry,
574: getDefaultCRS(dimension));
575: }
576: final GridCoverage2D coverage;
577: coverage = new GridCoverage2D(name, PlanarImage
578: .wrapRenderedImage(image), gridGeometry, bands,
579: sources, properties);
580: coverage.tileEncoding = (String) hints.get(Hints.TILE_ENCODING);
581: return coverage;
582: }
583: }
|