001: /*
002: * GeoTools - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 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.processing.operation;
017:
018: // J2SE dependencies
019: import java.awt.RenderingHints;
020: import java.awt.image.IndexColorModel;
021: import java.awt.image.RenderedImage;
022: import java.awt.image.renderable.ParameterBlock;
023:
024: // JAI dependencies
025: import javax.media.jai.ImageLayout;
026: import javax.media.jai.Interpolation;
027: import javax.media.jai.InterpolationNearest;
028: import javax.media.jai.JAI;
029: import javax.media.jai.PlanarImage;
030:
031: // OpenGIS dependencies
032: import org.opengis.coverage.Coverage;
033: import org.geotools.coverage.GridSampleDimension;
034: import org.opengis.coverage.grid.GridCoverage;
035: import org.opengis.parameter.ParameterValueGroup;
036:
037: // Geotools dependencies
038: import org.geotools.coverage.grid.GeneralGridRange;
039: import org.geotools.coverage.grid.GridCoverage2D;
040: import org.geotools.coverage.grid.GridGeometry2D;
041: import org.geotools.coverage.processing.OperationJAI;
042: import org.geotools.factory.Hints;
043: import org.geotools.image.ImageWorker;
044: import org.geotools.resources.coverage.CoverageUtilities;
045: import org.geotools.resources.image.ImageUtilities;
046: import org.opengis.coverage.Coverage;
047: import org.opengis.coverage.grid.GridCoverage;
048: import org.opengis.parameter.ParameterValueGroup;
049: import org.opengis.referencing.operation.MathTransform;
050:
051: /**
052: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/coverage/src/main/java/org/geotools/coverage/processing/operation/FilteredSubsampledGridCoverage2D.java $
053: * @version $Id: FilteredSubsampledGridCoverage2D.java 28130 2007-11-29 11:26:25Z afabiani $
054: * @author Simone Giannecchini
055: */
056: final class FilteredSubsampledGridCoverage2D extends GridCoverage2D {
057: /**
058: * Serial number for cross-version compatibility.
059: */
060: private static final long serialVersionUID = 5274708130300017804L;
061:
062: /**
063: * Creates a filtered subsampled image for the specified source coverage.
064: *
065: * @todo The {@link GridGeometry2D} calculation in this method is wrong!! The calculation
066: * should <strong>always</strong> be performed on {@link MathTransform}, never on
067: * a grid range - envelope pair when the math transform is available.
068: */
069: FilteredSubsampledGridCoverage2D(PlanarImage image,
070: GridCoverage2D sourceCoverage, int actionTaken) {
071: super (
072: sourceCoverage.getName(),
073: image,
074: new GridGeometry2D(new GeneralGridRange(image),
075: sourceCoverage.getEnvelope()),
076: (GridSampleDimension[]) (actionTaken == 1 ? null
077: : sourceCoverage.getSampleDimensions().clone()),
078: new GridCoverage[] { sourceCoverage }, sourceCoverage
079: .getProperties());
080: }
081:
082: /**
083: * Creates a filtered subsampled image from the specified parameters.
084: */
085: static Coverage create(final ParameterValueGroup parameters,
086: final Hints hints) {
087: // /////////////////////////////////////////////////////////////////////
088: //
089: // Getting the input parameters
090: //
091: // /////////////////////////////////////////////////////////////////////
092: final Integer scaleX = (Integer) parameters.parameter("scaleX")
093: .getValue();
094: final Integer scaleY = (Integer) parameters.parameter("scaleY")
095: .getValue();
096: final float qsFilter[] = (float[]) parameters.parameter(
097: "qsFilterArray").getValue();
098: Interpolation interpolation = (Interpolation) parameters
099: .parameter("Interpolation").getValue();
100:
101: // /////////////////////////////////////////////////////////////////////
102: //
103: // Getting the source coverage
104: //
105: // /////////////////////////////////////////////////////////////////////
106: GridCoverage2D sourceCoverage = (GridCoverage2D) parameters
107: .parameter("Source").getValue();
108: RenderedImage sourceImage = sourceCoverage.getRenderedImage();
109:
110: // /////////////////////////////////////////////////////////////////////
111: //
112: // Do we need to explode the Palette to RGB(A)?
113: //
114: // /////////////////////////////////////////////////////////////////////
115: final boolean isFilterPassEverything = qsFilter.length == 1
116: && qsFilter[0] == 1;
117: int actionTaken = CoverageUtilities
118: .prepareSourcesForGCOperation(sourceCoverage,
119: interpolation, !isFilterPassEverything, hints);
120: switch (actionTaken) {
121: case 2:
122: // in this case we need to go back the geophysics view of the
123: // source coverage
124: sourceCoverage = sourceCoverage.geophysics(true);
125: sourceImage = PlanarImage.wrapRenderedImage(sourceCoverage
126: .getRenderedImage());
127:
128: break;
129: case 3:
130: sourceCoverage = sourceCoverage.geophysics(false);
131: sourceImage = sourceCoverage.getRenderedImage();
132: break;
133: }
134:
135: // /////////////////////////////////////////////////////////////////////
136: //
137: // Managing Hints for output coverage's layout purposes
138: //
139: // /////////////////////////////////////////////////////////////////////
140: RenderingHints targetHints = ImageUtilities
141: .getRenderingHints(sourceImage);
142: if (targetHints == null) {
143: targetHints = new RenderingHints(hints);
144: } else if (hints != null) {
145: targetHints.add(hints);
146: }
147: ImageLayout layout = (ImageLayout) targetHints
148: .get(JAI.KEY_IMAGE_LAYOUT);
149: if (layout != null) {
150: layout = (ImageLayout) layout.clone();
151: } else {
152: layout = new ImageLayout(sourceImage);
153: layout.unsetTileLayout();
154: // At this point, only the color model and sample model are left
155: // valids.
156: }
157: if ((layout.getValidMask() & (ImageLayout.TILE_WIDTH_MASK
158: | ImageLayout.TILE_HEIGHT_MASK
159: | ImageLayout.TILE_GRID_X_OFFSET_MASK | ImageLayout.TILE_GRID_Y_OFFSET_MASK)) == 0) {
160: layout.setTileGridXOffset(layout.getMinX(sourceImage));
161: layout.setTileGridYOffset(layout.getMinY(sourceImage));
162: final int width = layout.getWidth(sourceImage);
163: final int height = layout.getHeight(sourceImage);
164: if (layout.getTileWidth(sourceImage) > width)
165: layout.setTileWidth(width);
166: if (layout.getTileHeight(sourceImage) > height)
167: layout.setTileHeight(height);
168: }
169: targetHints.put(JAI.KEY_IMAGE_LAYOUT, layout);
170: // it is crucial to correctly manage the Hints to control the
171: // replacement of IndexColorModel. It is worth to point out that setting
172: // the JAI.KEY_REPLACE_INDEX_COLOR_MODEL hint to true is not enough to
173: // force the operators to do an expansion.
174: // If we explicitly provide an ImageLayout built with the source image
175: // where the CM and the SM are valid. those will be employed overriding
176: // a the possibility to expand the color model.
177: if (actionTaken != 1)
178: targetHints
179: .add(ImageUtilities.DONT_REPLACE_INDEX_COLOR_MODEL);
180: else {
181: targetHints.add(ImageUtilities.REPLACE_INDEX_COLOR_MODEL);
182: layout.unsetValid(ImageLayout.COLOR_MODEL_MASK);
183: layout.unsetValid(ImageLayout.SAMPLE_MODEL_MASK);
184: }
185:
186: // /////////////////////////////////////////////////////////////////////
187: //
188: // preparing the parameters for the scale operation
189: //
190: // /////////////////////////////////////////////////////////////////////
191: final ParameterBlock pbjFilteredSubsample = new ParameterBlock();
192: pbjFilteredSubsample.addSource(sourceImage);
193: pbjFilteredSubsample.add(scaleX).add(scaleY).add(qsFilter).add(
194: interpolation).add(sourceImage);
195:
196: // /////////////////////////////////////////////////////////////////////
197: //
198: // preparing the new gridgeometry
199: //
200: // /////////////////////////////////////////////////////////////////////
201: targetHints.add(new RenderingHints(JAI.KEY_BORDER_EXTENDER,
202: parameters.parameter("BorderExtender").getValue()));
203: targetHints.add(new RenderingHints(JAI.KEY_INTERPOLATION,
204: interpolation));
205: final JAI processor = OperationJAI.getJAI(targetHints);
206:
207: // /////////////////////////////////////////////////////////////////////
208: //
209: // Preparing the resulting coverage
210: //
211: // /////////////////////////////////////////////////////////////////////
212: GridCoverage2D result;
213: if (!processor.equals(JAI.getDefaultInstance()))
214: result = new FilteredSubsampledGridCoverage2D(processor
215: .createNS("FilteredSubsample",
216: pbjFilteredSubsample, targetHints),
217: sourceCoverage, actionTaken);
218: // no supplied processor
219: else
220: result = new FilteredSubsampledGridCoverage2D(JAI.create(
221: "FilteredSubsample", pbjFilteredSubsample,
222: targetHints), sourceCoverage, actionTaken);
223: //now let's see what we need to do in order to clean things up
224: if (actionTaken == 2)
225: return result.geophysics(false);
226: if (actionTaken == 3)
227: return result.geophysics(true);
228: return result;
229: }
230: }
|