001: /*
002: * GeoTools - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2005-2006, Geotools Project Managment Committee (PMC)
005: * (C) 2005, 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: package org.geotools.coverage.processing;
018:
019: // J2SE and JAI dependencies
020: import java.awt.RenderingHints;
021: import java.util.Map;
022: import javax.media.jai.BorderExtender;
023: import javax.media.jai.Interpolation;
024: import javax.media.jai.KernelJAI;
025:
026: // OpenGIS dependencies
027: import org.opengis.coverage.Coverage;
028: import org.opengis.coverage.grid.GridCoverage;
029: import org.opengis.coverage.grid.GridGeometry;
030: import org.opengis.coverage.processing.Operation;
031: import org.opengis.coverage.processing.OperationNotFoundException;
032: import org.opengis.parameter.InvalidParameterNameException;
033: import org.opengis.parameter.ParameterNotFoundException;
034: import org.opengis.parameter.ParameterValueGroup;
035: import org.opengis.referencing.crs.CoordinateReferenceSystem;
036: import org.opengis.geometry.Envelope;
037:
038: // Geotools dependencies
039: import org.geotools.resources.i18n.Errors;
040: import org.geotools.resources.i18n.ErrorKeys;
041:
042: /**
043: * Convenience, type-safe, methods for applying some common operations on
044: * {@linkplain Coverage coverage} objects. All methods wrap their arguments in a
045: * {@linkplain ParameterValueGroup parameter value group} and delegate the work to the processor's
046: * {@link AbstractProcessor#doOperation doOperation} method.
047: * This convenience class do not brings any new functionalities, but brings type-safety when the
048: * operation is know at compile time. For operation unknown at compile time (e.g. for an operation
049: * selected by users in some widget), use the {@linkplain AbstractProcessor processor} directly.
050: *
051: * @since 2.2
052: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/coverage/src/main/java/org/geotools/coverage/processing/Operations.java $
053: * @version $Id: Operations.java 26601 2007-08-19 23:16:35Z desruisseaux $
054: * @author Martin Desruisseaux
055: *
056: * @see org.geotools.coverage.processing.operation
057: */
058: public class Operations {
059: /**
060: * The default instance.
061: */
062: public static final Operations DEFAULT = new Operations(null);
063:
064: /**
065: * The processor to use for applying operations. If null, will be created only when first
066: * needed.
067: *
068: * @todo Uses the GeoAPI's interface instead once it will be ready.
069: */
070: private AbstractProcessor processor;
071:
072: /**
073: * Creates a new instance using the specified hints.
074: *
075: * @param hints The hints, or {@code null} if none.
076: */
077: public Operations(final RenderingHints hints) {
078: if (hints != null && !hints.isEmpty()) {
079: processor = new BufferedProcessor(hints);
080: }
081: // Otherwise, will creates the processor only when first needed.
082: }
083:
084: /////////////////////////////////////////////////////////////////////////////////
085: //////// ////////
086: //////// A R I T H M E T I C O P E R A T I O N S ////////
087: //////// ////////
088: /////////////////////////////////////////////////////////////////////////////////
089:
090: /**
091: * Adds constants (one for each band) to every sample values of the source coverage.
092: *
093: * @param source The source coverage.
094: * @param constants The constants to add to each band.
095: * @throws CoverageProcessingException if the operation can't be applied.
096: *
097: * @see org.geotools.coverage.processing.operation.AddConst
098: */
099: public Coverage add(final Coverage source, final double[] constants)
100: throws CoverageProcessingException {
101: return doOperation("AddConst", source, "constants", constants);
102: }
103:
104: /**
105: * Subtracts constants (one for each band) from every sample values of the source coverage.
106: *
107: * @param source The source coverage.
108: * @param constants The constants to subtract to each band.
109: * @throws CoverageProcessingException if the operation can't be applied.
110: *
111: * @see org.geotools.coverage.processing.operation.SubtractConst
112: */
113: public Coverage subtract(final Coverage source,
114: final double[] constants)
115: throws CoverageProcessingException {
116: return doOperation("SubtractConst", source, "constants",
117: constants);
118: }
119:
120: /**
121: * Subtracts every sample values of the source coverage from constants (one for each band).
122: *
123: * @param source The source coverage.
124: * @param constants The constants to subtract from.
125: * @throws CoverageProcessingException if the operation can't be applied.
126: *
127: * @see org.geotools.coverage.processing.operation.SubtractFromConst
128: */
129: public Coverage subtractFrom(final Coverage source,
130: final double[] constants)
131: throws CoverageProcessingException {
132: return doOperation("SubtractFromConst", source, "constants",
133: constants);
134: }
135:
136: /**
137: * Multiplies every sample values of the source coverage by constants (one for each band).
138: *
139: * @param source The source coverage.
140: * @param constants The constants to multiply to each band.
141: * @throws CoverageProcessingException if the operation can't be applied.
142: *
143: * @see org.geotools.coverage.processing.operation.MultiplyConst
144: */
145: public Coverage multiply(final Coverage source,
146: final double[] constants)
147: throws CoverageProcessingException {
148: return doOperation("MultiplyConst", source, "constants",
149: constants);
150: }
151:
152: /**
153: * Divides every sample values of the source coverage by constants (one for each band).
154: *
155: * @param source The source coverage.
156: * @param constants The constants to divides by.
157: * @throws CoverageProcessingException if the operation can't be applied.
158: *
159: * @see org.geotools.coverage.processing.operation.DivideByConst
160: */
161: public Coverage divideBy(final Coverage source,
162: final double[] constants)
163: throws CoverageProcessingException {
164: return doOperation("DivideByConst", source, "constants",
165: constants);
166: }
167:
168: /**
169: * Maps the sample values of a coverage from one range to another range.
170: *
171: * @param source The source coverage.
172: * @param constants The constants to multiply to each band.
173: * @param offsets The constants to add to each band.
174: * @throws CoverageProcessingException if the operation can't be applied.
175: *
176: * @see org.geotools.coverage.processing.operation.Rescale
177: */
178: public Coverage rescale(final Coverage source,
179: final double[] constants, final double[] offsets)
180: throws CoverageProcessingException {
181: return doOperation("Rescale", source, "constants", constants,
182: "offsets", offsets);
183: }
184:
185: /**
186: * Inverts the sample values of a coverage.
187: *
188: * @param source The source coverage.
189: * @throws CoverageProcessingException if the operation can't be applied.
190: *
191: * @see org.geotools.coverage.processing.operation.Invert
192: */
193: public Coverage invert(final Coverage source)
194: throws CoverageProcessingException {
195: return doOperation("Invert", source);
196: }
197:
198: /**
199: * Computes the mathematical absolute value of each sample value.
200: *
201: * @param source The source coverage.
202: * @throws CoverageProcessingException if the operation can't be applied.
203: *
204: * @see org.geotools.coverage.processing.operation.Absolute
205: */
206: public Coverage absolute(final Coverage source)
207: throws CoverageProcessingException {
208: return doOperation("Absolute", source);
209: }
210:
211: /**
212: * Takes the natural logarithm of the sample values of a coverage.
213: *
214: * @param source The source coverage.
215: * @throws CoverageProcessingException if the operation can't be applied.
216: *
217: * @see org.geotools.coverage.processing.operation.Log
218: */
219: public Coverage log(final Coverage source)
220: throws CoverageProcessingException {
221: return doOperation("Log", source);
222: }
223:
224: /**
225: * Takes the exponential of the sample values of a coverage.
226: *
227: * @param source The source coverage.
228: * @throws CoverageProcessingException if the operation can't be applied.
229: *
230: * @see org.geotools.coverage.processing.operation.Exp
231: */
232: public Coverage exp(final Coverage source)
233: throws CoverageProcessingException {
234: return doOperation("Exp", source);
235: }
236:
237: /**
238: * Replaces {@link Float#NaN NaN} values by the weighted average of neighbors values.
239: * This method uses the default padding and validity threshold.
240: *
241: * @param source The source coverage.
242: * @throws CoverageProcessingException if the operation can't be applied.
243: *
244: * @see org.geotools.coverage.processing.operation.NodataFilter
245: */
246: public GridCoverage nodataFilter(final GridCoverage source)
247: throws CoverageProcessingException {
248: return (GridCoverage) doOperation("NodataFilter", source);
249: }
250:
251: /**
252: * Replaces {@link Float#NaN NaN} values by the weighted average of neighbors values.
253: *
254: * @param source The source coverage.
255: * @param padding The number of pixels above, below, to the left and to the right of central
256: * {@code NaN} pixel to use for computing the average. The default value is 1.
257: * @param validityThreshold The minimal number of valid values required for computing the
258: * average. The {@code NaN} value will be replaced by the average only if the number
259: * of valid value is greater than or equals to this threshold. The default value is 4.
260: * @throws CoverageProcessingException if the operation can't be applied.
261: *
262: * @see org.geotools.coverage.processing.operation.NodataFilter
263: */
264: public GridCoverage nodataFilter(final GridCoverage source,
265: final int padding, final int validityThreshold)
266: throws CoverageProcessingException {
267: return (GridCoverage) doOperation("NodataFilter", source,
268: "padding", new Integer(padding), "validityThreshold",
269: new Integer(validityThreshold));
270: }
271:
272: /**
273: * Specifies the interpolation type to be used to interpolate values for points which fall
274: * between grid cells. The default value is nearest neighbor. The new interpolation type
275: * operates on all sample dimensions.
276: *
277: * @param source The source coverage.
278: * @param type The interpolation type. Possible values are {@code "NearestNeighbor"},
279: * {@code "Bilinear"} and {@code "Bicubic"}.
280: * @throws CoverageProcessingException if the operation can't be applied.
281: *
282: * @see org.geotools.coverage.processing.operation.Interpolate
283: */
284: public GridCoverage interpolate(final GridCoverage source,
285: final String type) throws CoverageProcessingException {
286: return (GridCoverage) doOperation("Interpolate", source,
287: "Type", type);
288: }
289:
290: /**
291: * Specifies the interpolation type to be used to interpolate values for points which fall
292: * between grid cells. The default value is nearest neighbor. The new interpolation type
293: * operates on all sample dimensions.
294: *
295: * @param source The source coverage.
296: * @param type The interpolation type as a JAI interpolation object.
297: * @throws CoverageProcessingException if the operation can't be applied.
298: *
299: * @see org.geotools.coverage.processing.operation.Interpolate
300: */
301: public GridCoverage interpolate(final GridCoverage source,
302: final Interpolation type)
303: throws CoverageProcessingException {
304: return (GridCoverage) doOperation("Interpolate", source,
305: "Type", type);
306: }
307:
308: /**
309: * Specifies the interpolation types to be used to interpolate values for points which fall
310: * between grid cells. The first element in the array is the primary interpolation. All other
311: * elements are fallback to be used if the primary interpolation returns a {@code NaN} value.
312: * See {@link org.geotools.coverage.processing.operation.Interpolate} operation for details.
313: *
314: * @param source The source coverage.
315: * @param types The interpolation types and their fallback.
316: * @throws CoverageProcessingException if the operation can't be applied.
317: *
318: * @see org.geotools.coverage.processing.operation.Interpolate
319: */
320: public GridCoverage interpolate(final GridCoverage source,
321: final Interpolation[] types)
322: throws CoverageProcessingException {
323: return (GridCoverage) doOperation("Interpolate", source,
324: "Type", types);
325: }
326:
327: /**
328: * Recolors a coverage to the specified colormaps.
329: *
330: * @param source The source coverage.
331: * @param colorMaps The color maps to apply.
332: * @throws CoverageProcessingException if the operation can't be applied.
333: *
334: * @see org.geotools.coverage.processing.operation.Recolor
335: *
336: * @since 2.3
337: *
338: * @deprecated Parameter of type {@link Map} is deprecated. Please use the parameter of
339: * type {@link ColorMap} instead.
340: */
341: public GridCoverage recolor(final GridCoverage source,
342: final Map[] colorMaps) throws CoverageProcessingException {
343: return (GridCoverage) doOperation("Recolor", source,
344: "ColorMaps", colorMaps);
345: }
346:
347: /**
348: * Recolors a coverage to the specified color maps.
349: *
350: * @param source The source coverage.
351: * @param colorMaps The color maps to apply.
352: * @throws CoverageProcessingException if the operation can't be applied.
353: *
354: * @see org.geotools.coverage.processing.operation.Recolor
355: *
356: * @since 2.4
357: */
358: public GridCoverage recolor(final GridCoverage source,
359: final ColorMap[] colorMaps)
360: throws CoverageProcessingException {
361: return (GridCoverage) doOperation("Recolor", source,
362: "ColorMaps", colorMaps);
363: }
364:
365: /**
366: * Chooses <var>N</var> {@linkplain org.geotools.coverage.GridSampleDimension sample dimensions}
367: * from a coverage and copies their sample data to the destination grid coverage in the order
368: * specified.
369: *
370: * @param source The source coverage.
371: * @param sampleDimensions The sample dimensions to select.
372: * @throws CoverageProcessingException if the operation can't be applied.
373: *
374: * @see org.geotools.coverage.processing.operation.SelectSampleDimension
375: */
376: public Coverage selectSampleDimension(final Coverage source,
377: final int[] sampleDimensions)
378: throws CoverageProcessingException {
379: return doOperation("SelectSampleDimension", source,
380: "SampleDimensions", sampleDimensions);
381: }
382:
383: /////////////////////////////////////////////////////////////////////////////////
384: //////// ////////
385: //////// R E S A M P L I N G O P E R A T I O N S ////////
386: //////// ////////
387: /////////////////////////////////////////////////////////////////////////////////
388:
389: /**
390: * Resamples a coverage to the specified coordinate reference system.
391: *
392: * @param source The source coverage.
393: * @param crs The target coordinate reference system.
394: * @throws CoverageProcessingException if the operation can't be applied.
395: *
396: * @see org.geotools.coverage.processing.operation.Resample
397: */
398: public Coverage resample(final Coverage source,
399: final CoordinateReferenceSystem crs)
400: throws CoverageProcessingException {
401: return doOperation("Resample", source,
402: "CoordinateReferenceSystem", crs);
403: }
404:
405: /**
406: * Resamples a grid coverage to the specified coordinate reference system and grid geometry.
407: *
408: * @param source The source coverage.
409: * @param crs The target coordinate reference system, or {@code null} for keeping it unchanged.
410: * @param gridGeometry The grid geometry, or {@code null} for a default one.
411: * @param interpolationType The interpolation type, or {@code null} for the default one.
412: * @throws CoverageProcessingException if the operation can't be applied.
413: *
414: * @see org.geotools.coverage.processing.operation.Resample
415: */
416: public Coverage resample(final GridCoverage source,
417: final CoordinateReferenceSystem crs,
418: final GridGeometry gridGeometry,
419: final Interpolation interpolationType)
420: throws CoverageProcessingException {
421: return doOperation("Resample", source,
422: "CoordinateReferenceSystem", crs, "GridGeometry",
423: gridGeometry, "InterpolationType", interpolationType);
424: }
425:
426: /**
427: * Crops the image to a specified rectangular area.
428: *
429: * @param source The source coverage.
430: * @param envelope The rectangular area to keep.
431: * @throws CoverageProcessingException if the operation can't be applied.
432: *
433: * @see org.geotools.coverage.processing.operation.Crop
434: *
435: * @since 2.3
436: */
437: public Coverage crop(final Coverage Source, final Envelope envelope)
438: throws CoverageProcessingException {
439: return doOperation("CoverageCrop", Source, "Envelope", envelope);
440: }
441:
442: /**
443: * Translates and resizes an image.
444: *
445: * @param source The source coverage.
446: * @param xScale The scale factor along the <var>x</var> axis.
447: * @param yScale The scale factor along the <var>y</var> axis.
448: * @param xTrans The translation along the <var>x</var> axis.
449: * @param yTrans The translation along the <var>x</var> axis.
450: * @throws CoverageProcessingException if the operation can't be applied.
451: *
452: * @see org.geotools.coverage.processing.operation.Scale
453: *
454: * @since 2.3
455: */
456: public GridCoverage scale(final GridCoverage source,
457: final double xScale, final double yScale,
458: final double xTrans, final double yTrans)
459: throws CoverageProcessingException {
460: return scale(source, xScale, yScale, xTrans, yTrans, null, null);
461: }
462:
463: /**
464: * Translates and resizes an image.
465: *
466: * @param source The source coverage.
467: * @param xScale The scale factor along the <var>x</var> axis.
468: * @param yScale The scale factor along the <var>y</var> axis.
469: * @param xTrans The translation along the <var>x</var> axis.
470: * @param yTrans The translation along the <var>x</var> axis.
471: * @param interpolation The interpolation to use, or {@code null} for the default.
472: * @throws CoverageProcessingException if the operation can't be applied.
473: *
474: * @see org.geotools.coverage.processing.operation.Scale
475: *
476: * @deprecated Replaced by {@link #scale(GridCoverage,double,double,double,double,
477: * Interpolation,BorderExtender} with a {@code null} border extender.
478: *
479: * @since 2.3
480: */
481: public GridCoverage scale(final GridCoverage source,
482: final double xScale, final double yScale,
483: final double xTrans, final double yTrans,
484: final Interpolation interpolation)
485: throws CoverageProcessingException {
486: return scale(source, xScale, yScale, xTrans, yTrans,
487: interpolation, null);
488: }
489:
490: /**
491: * Translates and resizes an image.
492: *
493: * @todo The two last arguments can also be provided as hints at {@link #Operations(Hints)}
494: * construction time. Investigate which way should be encouraged.
495: *
496: * @param source The source coverage.
497: * @param xScale The scale factor along the <var>x</var> axis.
498: * @param yScale The scale factor along the <var>y</var> axis.
499: * @param xTrans The translation along the <var>x</var> axis.
500: * @param yTrans The translation along the <var>x</var> axis.
501: * @param interpolation The interpolation to use, or {@code null} for the default.
502: * @param be The border extender, or {@code null} for the default.
503: * @throws CoverageProcessingException if the operation can't be applied.
504: *
505: * @see org.geotools.coverage.processing.operation.Scale
506: *
507: * @since 2.3
508: */
509: public GridCoverage scale(final GridCoverage source,
510: final double xScale, final double yScale,
511: final double xTrans, final double yTrans,
512: final Interpolation interpolation,
513: final BorderExtender extender)
514: throws CoverageProcessingException {
515: return (GridCoverage) doOperation("Scale", source, "xScale",
516: new Float(xScale), "yScale", new Float(yScale),
517: "xTrans", new Float(xTrans), "yTrans",
518: new Float(yTrans), "Interpolation", interpolation,
519: "BorderExtender", extender);
520: }
521:
522: /////////////////////////////////////////////////////////////////////////////////
523: //////// ////////
524: //////// F I L T E R O P E R A T I O N S ////////
525: //////// ////////
526: /////////////////////////////////////////////////////////////////////////////////
527:
528: /**
529: * @deprecated Renamed as {@link #subsampleAverage subsampleAverage} (lower case "s").
530: *
531: * @since 2.3
532: */
533: public GridCoverage SubsampleAverage(final GridCoverage source,
534: final double scaleX, final double scaleY,
535: final Interpolation interpolation, final BorderExtender be)
536: throws CoverageProcessingException {
537: return subsampleAverage(source, scaleX, scaleY, interpolation,
538: be);
539: }
540:
541: /**
542: * Subsamples an image by averaging over a moving window
543: *
544: * @todo The two last arguments can also be provided as hints at {@link #Operations(Hints)}
545: * construction time. Investigate which way should be encouraged.
546: *
547: * @param source The source coverage.
548: * @param scaleX The scale factor along the <var>x</var> axis.
549: * @param scaleY The scale factor along the <var>y</var> axis.
550: * @param interpolation The interpolation to use, or {@code null} for the default.
551: * @param be The border extender, or {@code null} for the default.
552: * @throws CoverageProcessingException if the operation can't be applied.
553: *
554: * @see org.geotools.coverage.processing.operation.SubsampleAverage
555: *
556: * @since 2.3
557: */
558: public GridCoverage subsampleAverage(final GridCoverage source,
559: final double scaleX, final double scaleY,
560: final Interpolation interpolation, final BorderExtender be)
561: throws CoverageProcessingException {
562: return (GridCoverage) doOperation("SubsampleAverage", source,
563: "scaleX", new Double(scaleX), "scaleY", new Double(
564: scaleY), "Interpolation", interpolation,
565: "BorderExtender", be);
566: }
567:
568: /**
569: * Subsamples an image using the default values. The scale factor is 2 and the
570: * filter is a quadrant symmetric filter generated from a Gaussian kernel.
571: *
572: * @param source The source coverage.
573: * @throws CoverageProcessingException if the operation can't be applied.
574: *
575: * @see org.geotools.coverage.processing.operation.FilteredSubsample
576: *
577: * @since 2.3
578: */
579: public GridCoverage filteredSubsample(final GridCoverage source)
580: throws CoverageProcessingException {
581: return (GridCoverage) doOperation("FilteredSubsample", source);
582: }
583:
584: /**
585: * Subsamples an image by integral factors.
586: *
587: * @param source The source coverage.
588: * @param scaleX The scale factor along the <var>x</var> axis. The default value is 2.
589: * @param scaleY The scale factor along the <var>y</var> axis. The default value is 2.
590: * @param qsFilter The filter. Default to a quadrant symmetric filter generated from
591: * a Gaussian kernel
592: * @throws CoverageProcessingException if the operation can't be applied.
593: *
594: * @see org.geotools.coverage.processing.operation.FilteredSubsample
595: *
596: * @since 2.3
597: */
598: public GridCoverage filteredSubsample(final GridCoverage source,
599: final int scaleX, final int scaleY, final float[] qsFilter)
600: throws CoverageProcessingException {
601: return filteredSubsample(source, scaleX, scaleY, qsFilter,
602: null, null);
603: }
604:
605: /**
606: * Subsamples an image by integral factors.
607: *
608: * @param source The source coverage.
609: * @param scaleX The scale factor along the <var>x</var> axis. The default value is 2.
610: * @param scaleY The scale factor along the <var>y</var> axis. The default value is 2.
611: * @param qsFilter The filter. Default to a quadrant symmetric filter generated from
612: * a Gaussian kernel
613: * @param interpolation The interpolation to use, or {@code null} for the default.
614: * @throws CoverageProcessingException if the operation can't be applied.
615: *
616: * @see org.geotools.coverage.processing.operation.FilteredSubsample
617: *
618: * @since 2.3
619: *
620: * @deprecated Replaced by {@link #filteredSubsample(GridCoverage,int,int,float[],
621: * Interpolation,BorderExtender} with a {@code null} border extender.
622: */
623: public GridCoverage filteredSubsample(final GridCoverage source,
624: final int scaleX, final int scaleY, final float[] qsFilter,
625: final Interpolation interpolation)
626: throws CoverageProcessingException {
627: return filteredSubsample(source, scaleX, scaleY, qsFilter,
628: interpolation, null);
629: }
630:
631: /**
632: * Subsamples an image by integral factors.
633: *
634: * @todo The two last arguments can also be provided as hints at {@link #Operations(Hints)}
635: * construction time. Investigate which way should be encouraged.
636: *
637: * @param source The source coverage.
638: * @param scaleX The scale factor along the <var>x</var> axis. The default value is 2.
639: * @param scaleY The scale factor along the <var>y</var> axis. The default value is 2.
640: * @param qsFilter The filter. Default to a quadrant symmetric filter generated from a
641: * Gaussian kernel
642: * @param interpolation The interpolation to use, or {@code null} for the default.
643: * @param be The border extender, or {@code null} for the default.
644: * @throws CoverageProcessingException if the operation can't be applied.
645: *
646: * @see org.geotools.coverage.processing.operation.FilteredSubsample
647: *
648: * @since 2.3
649: */
650: public GridCoverage filteredSubsample(final GridCoverage source,
651: final int scaleX, final int scaleY, final float[] qsFilter,
652: final Interpolation interpolation, final BorderExtender be)
653: throws CoverageProcessingException {
654: return (GridCoverage) doOperation("FilteredSubsample", source,
655: "scaleX", new Integer(scaleX), "scaleY", new Integer(
656: scaleY), "qsFilterArray", qsFilter,
657: "Interpolation", interpolation, "BorderExtender", be);
658: }
659:
660: /**
661: * Edge detector which computes the magnitude of the image gradient vector in two orthogonal
662: * directions. The default masks are the Sobel ones.
663: *
664: * @param source The source coverage.
665: * @throws CoverageProcessingException if the operation can't be applied.
666: *
667: * @see org.geotools.coverage.processing.operation.GradientMagnitude
668: */
669: public Coverage gradientMagnitude(final Coverage source)
670: throws CoverageProcessingException {
671: return doOperation("GradientMagnitude", source);
672: }
673:
674: /**
675: * Edge detector which computes the magnitude of the image gradient vector in two orthogonal
676: * directions.
677: *
678: * @param source The source coverage.
679: * @param mask1 The first mask.
680: * @param mask2 The second mask, orthogonal to the first one.
681: * @throws CoverageProcessingException if the operation can't be applied.
682: *
683: * @see org.geotools.coverage.processing.operation.GradientMagnitude
684: */
685: public Coverage gradientMagnitude(final Coverage source,
686: final KernelJAI mask1, final KernelJAI mask2)
687: throws CoverageProcessingException {
688: return doOperation("GradientMagnitude", source, "mask1", mask1,
689: "mask2", mask2);
690: }
691:
692: /////////////////////////////////////////////////////////////////////////////////
693: //////// ////////
694: //////// H E L P E R M E T H O D S ////////
695: //////// ////////
696: /////////////////////////////////////////////////////////////////////////////////
697:
698: /**
699: * Returns the processor, creating one if needed.
700: */
701: private AbstractProcessor getProcessor() {
702: // No need to synchronize.
703: if (processor == null) {
704: processor = AbstractProcessor.getInstance();
705: }
706: return processor;
707: }
708:
709: /**
710: * Applies a process operation with default parameters.
711: * This is a helper method for implementation of various convenience methods in this class.
712: *
713: * @param operationName Name of the operation to be applied to the coverage.
714: * @param source The source coverage.
715: * @return The result as a coverage.
716: * @throws OperationNotFoundException if there is no operation named {@code operationName}.
717: * @throws CoverageProcessingException if the operation can't be applied.
718: */
719: protected final Coverage doOperation(final String operationName,
720: final Coverage source) throws OperationNotFoundException,
721: CoverageProcessingException {
722: final AbstractProcessor processor = getProcessor();
723: final Operation operation = processor
724: .getOperation(operationName);
725: final ParameterValueGroup parameters = operation
726: .getParameters();
727: parameters.parameter("Source").setValue(source);
728: return processor.doOperation(parameters);
729: }
730:
731: /**
732: * Applies a process operation with one parameter.
733: * This is a helper method for implementation of various convenience methods in this class.
734: *
735: * @param operationName Name of the operation to be applied to the coverage.
736: * @param source The source coverage.
737: * @param argumentName1 The name of the first parameter to setParameterValue.
738: * @param argumentValue1 The value for the first parameter.
739: * @return The result as a coverage.
740: * @throws OperationNotFoundException if there is no operation named {@code operationName}.
741: * @throws InvalidParameterNameException if there is no parameter with the specified name.
742: * @throws CoverageProcessingException if the operation can't be applied.
743: */
744: protected final Coverage doOperation(final String operationName,
745: final Coverage source, final String argumentName1,
746: final Object argumentValue1)
747: throws OperationNotFoundException,
748: InvalidParameterNameException, CoverageProcessingException {
749: final AbstractProcessor processor = getProcessor();
750: final Operation operation = processor
751: .getOperation(operationName);
752: final ParameterValueGroup parameters = operation
753: .getParameters();
754: parameters.parameter("Source").setValue(source);
755: setParameterValue(parameters, argumentName1, argumentValue1);
756: return processor.doOperation(parameters);
757: }
758:
759: /**
760: * Applies process operation with two parameters.
761: * This is a helper method for implementation of various convenience methods in this class.
762: *
763: * @param operationName Name of the operation to be applied to the coverage.
764: * @param source The source coverage.
765: * @param argumentName1 The name of the first parameter to setParameterValue.
766: * @param argumentValue1 The value for the first parameter.
767: * @param argumentName2 The name of the second parameter to setParameterValue.
768: * @param argumentValue2 The value for the second parameter.
769: * @return The result as a coverage.
770: * @throws OperationNotFoundException if there is no operation named {@code operationName}.
771: * @throws InvalidParameterNameException if there is no parameter with the specified name.
772: * @throws CoverageProcessingException if the operation can't be applied.
773: */
774: protected final Coverage doOperation(final String operationName,
775: final Coverage source, final String argumentName1,
776: final Object argumentValue1, final String argumentName2,
777: final Object argumentValue2)
778: throws OperationNotFoundException,
779: InvalidParameterNameException, CoverageProcessingException {
780: final AbstractProcessor processor = getProcessor();
781: final Operation operation = processor
782: .getOperation(operationName);
783: final ParameterValueGroup parameters = operation
784: .getParameters();
785: parameters.parameter("Source").setValue(source);
786: setParameterValue(parameters, argumentName1, argumentValue1);
787: setParameterValue(parameters, argumentName2, argumentValue2);
788: return processor.doOperation(parameters);
789: }
790:
791: /**
792: * Applies a process operation with three parameters.
793: * This is a helper method for implementation of various convenience methods in this class.
794: *
795: * @param operationName Name of the operation to be applied to the coverage.
796: * @param source The source coverage.
797: * @param argumentName1 The name of the first parameter to setParameterValue.
798: * @param argumentValue1 The value for the first parameter.
799: * @param argumentName2 The name of the second parameter to setParameterValue.
800: * @param argumentValue2 The value for the second parameter.
801: * @param argumentName3 The name of the third parameter to setParameterValue.
802: * @param argumentValue3 The value for the third parameter.
803: * @return The result as a coverage.
804: * @throws OperationNotFoundException if there is no operation named {@code operationName}.
805: * @throws InvalidParameterNameException if there is no parameter with the specified name.
806: * @throws CoverageProcessingException if the operation can't be applied.
807: */
808: protected final Coverage doOperation(final String operationName,
809: final Coverage source, final String argumentName1,
810: final Object argumentValue1, final String argumentName2,
811: final Object argumentValue2, final String argumentName3,
812: final Object argumentValue3)
813: throws OperationNotFoundException,
814: InvalidParameterNameException, CoverageProcessingException {
815: final AbstractProcessor processor = getProcessor();
816: final Operation operation = processor
817: .getOperation(operationName);
818: final ParameterValueGroup parameters = operation
819: .getParameters();
820: parameters.parameter("Source").setValue(source);
821: setParameterValue(parameters, argumentName1, argumentValue1);
822: setParameterValue(parameters, argumentName2, argumentValue2);
823: setParameterValue(parameters, argumentName3, argumentValue3);
824: return processor.doOperation(parameters);
825: }
826:
827: /**
828: * Applies a process operation with four parameters.
829: * This is a helper method for implementation of various convenience methods in this class.
830: *
831: * @param operationName Name of the operation to be applied to the coverage.
832: * @param source The source coverage.
833: * @return The result as a coverage.
834: * @throws OperationNotFoundException if there is no operation named {@code operationName}.
835: * @throws InvalidParameterNameException if there is no parameter with the specified name.
836: * @throws CoverageProcessingException if the operation can't be applied.
837: *
838: * @since 2.3
839: */
840: protected final Coverage doOperation(final String operationName,
841: final Coverage source, final String argumentName1,
842: final Object argumentValue1, final String argumentName2,
843: final Object argumentValue2, final String argumentName3,
844: final Object argumentValue3, final String argumentName4,
845: final Object argumentValue4)
846: throws OperationNotFoundException,
847: InvalidParameterNameException, CoverageProcessingException {
848: final AbstractProcessor processor = getProcessor();
849: final Operation operation = processor
850: .getOperation(operationName);
851: final ParameterValueGroup parameters = operation
852: .getParameters();
853: parameters.parameter("Source").setValue(source);
854: setParameterValue(parameters, argumentName1, argumentValue1);
855: setParameterValue(parameters, argumentName2, argumentValue2);
856: setParameterValue(parameters, argumentName3, argumentValue3);
857: setParameterValue(parameters, argumentName4, argumentValue4);
858: return processor.doOperation(parameters);
859: }
860:
861: /**
862: * Applies a process operation with five parameters.
863: * This is a helper method for implementation of various convenience methods in this class.
864: *
865: * @param operationName Name of the operation to be applied to the coverage.
866: * @param source The source coverage.
867: * @return The result as a coverage.
868: * @throws OperationNotFoundException if there is no operation named {@code operationName}.
869: * @throws InvalidParameterNameException if there is no parameter with the specified name.
870: * @throws CoverageProcessingException if the operation can't be applied.
871: *
872: * @since 2.3
873: */
874: protected final Coverage doOperation(final String operationName,
875: final Coverage source, final String argumentName1,
876: final Object argumentValue1, final String argumentName2,
877: final Object argumentValue2, final String argumentName3,
878: final Object argumentValue3, final String argumentName4,
879: final Object argumentValue4, final String argumentName5,
880: final Object argumentValue5)
881: throws OperationNotFoundException,
882: InvalidParameterNameException, CoverageProcessingException {
883: final AbstractProcessor processor = getProcessor();
884: final Operation operation = processor
885: .getOperation(operationName);
886: final ParameterValueGroup parameters = operation
887: .getParameters();
888: parameters.parameter("Source").setValue(source);
889: setParameterValue(parameters, argumentName1, argumentValue1);
890: setParameterValue(parameters, argumentName2, argumentValue2);
891: setParameterValue(parameters, argumentName3, argumentValue3);
892: setParameterValue(parameters, argumentName4, argumentValue4);
893: setParameterValue(parameters, argumentName5, argumentValue5);
894: return processor.doOperation(parameters);
895: }
896:
897: /**
898: * Applies a process operation with six parameters.
899: * This is a helper method for implementation of various convenience methods in this class.
900: *
901: * @param operationName Name of the operation to be applied to the coverage.
902: * @param source The source coverage.
903: * @return The result as a coverage.
904: * @throws OperationNotFoundException if there is no operation named {@code operationName}.
905: * @throws InvalidParameterNameException if there is no parameter with the specified name.
906: * @throws CoverageProcessingException if the operation can't be applied.
907: *
908: * @since 2.3
909: */
910: protected final Coverage doOperation(final String operationName,
911: final Coverage source, final String argumentName1,
912: final Object argumentValue1, final String argumentName2,
913: final Object argumentValue2, final String argumentName3,
914: final Object argumentValue3, final String argumentName4,
915: final Object argumentValue4, final String argumentName5,
916: final Object argumentValue5, final String argumentName6,
917: final Object argumentValue6)
918: throws OperationNotFoundException,
919: InvalidParameterNameException, CoverageProcessingException {
920: final AbstractProcessor processor = getProcessor();
921: final Operation operation = processor
922: .getOperation(operationName);
923: final ParameterValueGroup parameters = operation
924: .getParameters();
925: parameters.parameter("Source").setValue(source);
926: setParameterValue(parameters, argumentName1, argumentValue1);
927: setParameterValue(parameters, argumentName2, argumentValue2);
928: setParameterValue(parameters, argumentName3, argumentValue3);
929: setParameterValue(parameters, argumentName4, argumentValue4);
930: setParameterValue(parameters, argumentName5, argumentValue5);
931: setParameterValue(parameters, argumentName6, argumentValue6);
932: return processor.doOperation(parameters);
933: }
934:
935: /**
936: * Set the specified parameter to the specified value, if not null.
937: */
938: private static void setParameterValue(
939: final ParameterValueGroup parameters, String name,
940: Object value) throws InvalidParameterNameException {
941: if (value != null)
942: try {
943: parameters.parameter(name).setValue(value);
944: } catch (ParameterNotFoundException cause) {
945: final InvalidParameterNameException exception = new InvalidParameterNameException(
946: Errors.format(
947: ErrorKeys.UNKNOW_PARAMETER_NAME_$1,
948: name), name);
949: exception.initCause(cause);
950: throw exception;
951: }
952: }
953: }
|