Source Code Cross Referenced for Grid2DSampleDimension.java in  » GIS » GeoTools-2.4.1 » org » geotools » coverage » grid » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » GIS » GeoTools 2.4.1 » org.geotools.coverage.grid 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


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:        package org.geotools.coverage.grid;
018:
019:        // J2SE dependencies and extensions
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.Raster;
025:        import java.awt.image.RenderedImage;
026:        import java.awt.image.SampleModel;
027:        import java.util.Arrays;
028:        import javax.units.Unit;
029:
030:        // JAI dependencies
031:        import javax.media.jai.iterator.RectIter;
032:        import javax.media.jai.iterator.RectIterFactory;
033:
034:        // OpenGIS dependencies
035:        import org.opengis.coverage.ColorInterpretation;
036:        import org.opengis.coverage.SampleDimensionType;
037:        import org.opengis.util.InternationalString;
038:
039:        // Geotools dependencies
040:        import org.geotools.coverage.Category;
041:        import org.geotools.coverage.GridSampleDimension;
042:        import org.geotools.coverage.TypeMap;
043:        import org.geotools.factory.Hints;
044:        import org.geotools.referencing.operation.transform.LinearTransform1D;
045:        import org.geotools.resources.ClassChanger;
046:        import org.geotools.resources.i18n.Errors;
047:        import org.geotools.resources.i18n.ErrorKeys;
048:        import org.geotools.util.NumberRange;
049:        import org.geotools.util.SimpleInternationalString;
050:
051:        /**
052:         * Describes the band values for a grid coverage.
053:         *
054:         * @since 2.1
055:         * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/coverage/src/main/java/org/geotools/coverage/grid/Grid2DSampleDimension.java $
056:         * @version $Id: Grid2DSampleDimension.java 22817 2006-11-17 17:24:55Z desruisseaux $
057:         * @author Martin Desruisseaux
058:         */
059:        final class Grid2DSampleDimension extends GridSampleDimension {
060:            /**
061:             * Serial number for interoperability with different versions.
062:             */
063:            private static final long serialVersionUID = 946331925096804779L;
064:
065:            /**
066:             * Band number for this sample dimension.
067:             */
068:            private final int band;
069:
070:            /**
071:             * The number of bands in the {@link GridCoverage} who own this sample dimension.
072:             */
073:            private final int numBands;
074:
075:            /**
076:             * The grid value data type.
077:             */
078:            private final SampleDimensionType type;
079:
080:            /**
081:             * Constructs a sample dimension with a set of categories from an other sample dimension.
082:             *
083:             * @param band  The originating sample dimension.
084:             * @param image The image to be wrapped by {@link GridCoverage}.
085:             * @param bandNumber The band number.
086:             */
087:            private Grid2DSampleDimension(final GridSampleDimension band,
088:                    final RenderedImage image, final int bandNumber) {
089:                super (band);
090:                final SampleModel model = image.getSampleModel();
091:                this .band = bandNumber;
092:                this .numBands = model.getNumBands();
093:                this .type = TypeMap.getSampleDimensionType(model, bandNumber);
094:            }
095:
096:            /**
097:             * Creates a set of sample dimensions for the given image. The array length of both
098:             * arguments must matches the number of bands in the supplied {@code image}.
099:             *
100:             * @param  name  The name for data (e.g. "Elevation").
101:             * @param  image The image for which to create a set of sample dimensions.
102:             * @param  src   User-provided sample dimensions, or {@code null} if none.
103:             * @param  dst   The array where to put sample dimensions.
104:             * @return {@code true} if all sample dimensions are geophysics (quantitative), or
105:             *         {@code false} if all sample dimensions are non-geophysics (qualitative).
106:             * @throws IllegalArgumentException if geophysics and non-geophysics dimensions are mixed.
107:             */
108:            static boolean create(final CharSequence name,
109:                    final RenderedImage image, final GridSampleDimension[] src,
110:                    final GridSampleDimension[] dst) {
111:                final int numBands = image.getSampleModel().getNumBands();
112:                if (src != null && src.length != numBands) {
113:                    throw new IllegalArgumentException(Errors.format(
114:                            ErrorKeys.NUMBER_OF_BANDS_MISMATCH_$3, new Integer(
115:                                    numBands), new Integer(src.length),
116:                            "SampleDimension"));
117:                }
118:                if (dst.length != numBands) {
119:                    throw new IllegalArgumentException(Errors.format(
120:                            ErrorKeys.NUMBER_OF_BANDS_MISMATCH_$3, new Integer(
121:                                    numBands), new Integer(dst.length),
122:                            "SampleDimension"));
123:                }
124:                /*
125:                 * Now, we know that the number of bands and the array length are consistent.
126:                 * Search if there is any null SampleDimension. If any, replace the null value
127:                 * by a default SampleDimension. In all cases, count the number of geophysics
128:                 * and non-geophysics sample dimensions.
129:                 */
130:                int countGeophysics = 0;
131:                int countIndexed = 0;
132:                GridSampleDimension[] defaultSD = null;
133:                for (int i = 0; i < numBands; i++) {
134:                    GridSampleDimension sd = (src != null) ? src[i] : null;
135:                    if (sd == null) {
136:                        /*
137:                         * If the user didn't provided explicitly a SampleDimension, create a default one.
138:                         * We will creates a SampleDimension for all bands in one step, even if only a few
139:                         * of them are required.
140:                         */
141:                        if (defaultSD == null) {
142:                            defaultSD = new GridSampleDimension[numBands];
143:                            create(name, RectIterFactory.create(image, null),
144:                                    image.getSampleModel(), null, null, null,
145:                                    null, defaultSD, null);
146:                        }
147:                        sd = defaultSD[i];
148:                    }
149:                    sd = new Grid2DSampleDimension(sd, image, i);
150:                    dst[i] = sd;
151:                    if (sd.geophysics(true) == sd)
152:                        countGeophysics++;
153:                    if (sd.geophysics(false) == sd)
154:                        countIndexed++;
155:                }
156:                if (countGeophysics == numBands) {
157:                    return true;
158:                }
159:                if (countIndexed == numBands) {
160:                    return false;
161:                }
162:                throw new IllegalArgumentException(Errors
163:                        .format(ErrorKeys.MIXED_CATEGORIES));
164:            }
165:
166:            /**
167:             * Creates a set of sample dimensions for the given raster.
168:             *
169:             * @param  name The name for data (e.g. "Elevation").
170:             * @param  raster The raster.
171:             * @param  min The minimal value for each bands, or {@code null} for computing it automatically.
172:             * @param  max The maximal value for each bands, or {@code null} for computing it automatically.
173:             * @param  units The units of sample values, or {@code null} if unknow.
174:             * @param  colors The colors to use for values from {@code min} to {@code max} for each
175:             *         bands, or {@code null} for a default color palette. If non-null, each arrays
176:             *         {@code colors[b]} may have any length; colors will be interpolated as needed.
177:             * @param  hints An optional set of rendering hints, or {@code null} if none. Those hints will
178:             *         not affect the sample dimensions to be created. However, they may affect the sample
179:             *         dimensions to be returned by <code>{@link #geophysics geophysics}(false)</code>, i.e.
180:             *         the view to be used at rendering time. The optional hint
181:             *         {@link Hints#SAMPLE_DIMENSION_TYPE} specifies the {@link SampleDimensionType}
182:             *         to be used at rendering time, which can be one of
183:             *         {@link SampleDimensionType#UBYTE UBYTE} or
184:             *         {@link SampleDimensionType#USHORT USHORT}.
185:             * @return The sample dimension for the given raster.
186:             */
187:            static GridSampleDimension[] create(final CharSequence name,
188:                    final Raster raster, final double[] min,
189:                    final double[] max, final Unit units,
190:                    final Color[][] colors, final RenderingHints hints) {
191:                final GridSampleDimension[] dst = new GridSampleDimension[raster
192:                        .getNumBands()];
193:                create(name, (min == null || max == null) ? RectIterFactory
194:                        .create(raster, null) : null, raster.getSampleModel(),
195:                        min, max, units, colors, dst, hints);
196:                return dst;
197:            }
198:
199:            /**
200:             * Creates a set of sample dimensions for the data backing the given iterator.
201:             *
202:             * @param  name The name for data (e.g. "Elevation").
203:             * @param  iterator The iterator through the raster data, or {@code null}.
204:             * @param  model The image or raster sample model.
205:             * @param  min The minimal value, or {@code null} for computing it automatically.
206:             * @param  max The maximal value, or {@code null} for computing it automatically.
207:             * @param  units The units of sample values, or {@code null} if unknow.
208:             * @param  colors The colors to use for values from {@code min} to {@code max} for each bands,
209:             *         or {@code null} for a default color palette. If non-null, each arrays
210:             *         {@code colors[b]} may have any length; colors will be interpolated as needed.
211:             * @param  dst The array where to store sample dimensions. The array length must matches
212:             *         the number of bands.
213:             * @param  hints An optional set of rendering hints, or {@code null} if none.
214:             *         Those hints will not affect the sample dimensions to be created. However,
215:             *         they may affect the sample dimensions to be returned by
216:             *         <code>{@link #geophysics geophysics}(false)</code>, i.e.
217:             *         the view to be used at rendering time. The optional hint
218:             *         {@link Hints#SAMPLE_DIMENSION_TYPE} specifies the {@link SampleDimensionType}
219:             *         to be used at rendering time, which can be one of
220:             *         {@link SampleDimensionType#UBYTE UBYTE} or
221:             *         {@link SampleDimensionType#USHORT USHORT}.
222:             */
223:            private static void create(final CharSequence name,
224:                    final RectIter iterator, final SampleModel model,
225:                    double[] min, double[] max, final Unit units,
226:                    final Color[][] colors, final GridSampleDimension[] dst,
227:                    final RenderingHints hints) {
228:                final int numBands = dst.length;
229:                if (min != null && min.length != numBands) {
230:                    throw new IllegalArgumentException(Errors.format(
231:                            ErrorKeys.NUMBER_OF_BANDS_MISMATCH_$3, new Integer(
232:                                    numBands), new Integer(min.length),
233:                            "min[i]"));
234:                }
235:                if (max != null && max.length != numBands) {
236:                    throw new IllegalArgumentException(Errors.format(
237:                            ErrorKeys.NUMBER_OF_BANDS_MISMATCH_$3, new Integer(
238:                                    numBands), new Integer(max.length),
239:                            "max[i]"));
240:                }
241:                if (colors != null && colors.length != numBands) {
242:                    throw new IllegalArgumentException(Errors.format(
243:                            ErrorKeys.NUMBER_OF_BANDS_MISMATCH_$3, new Integer(
244:                                    numBands), new Integer(colors.length),
245:                            "colors[i]"));
246:                }
247:                /*
248:                 * Arguments are know to be valids. We now need to compute two ranges:
249:                 *
250:                 * STEP 1: Range of target (sample) values. This is computed in the following block.
251:                 * STEP 2: Range of source (geophysics) values. It will be computed one block later.
252:                 *
253:                 * The target (sample) values will typically range from 0 to 255 or 0 to 65535, but the
254:                 * general case is handled as well. If the source (geophysics) raster uses floating point
255:                 * numbers, then a "nodata" category may be added in order to handle NaN values. If the
256:                 * source raster use integer numbers instead, then we will rescale samples only if they
257:                 * would not fit in the target data type.
258:                 */
259:                final SampleDimensionType sourceType = TypeMap
260:                        .getSampleDimensionType(model, 0);
261:                final boolean sourceIsFloat = TypeMap
262:                        .isFloatingPoint(sourceType);
263:                SampleDimensionType targetType = null;
264:                if (hints != null) {
265:                    targetType = (SampleDimensionType) hints
266:                            .get(Hints.SAMPLE_DIMENSION_TYPE);
267:                }
268:                if (targetType == null) {
269:                    // Default to TYPE_BYTE for floating point images only; otherwise keep unchanged.
270:                    targetType = sourceIsFloat ? SampleDimensionType.UNSIGNED_8BITS
271:                            : sourceType;
272:                }
273:                // Default setting: no scaling
274:                final boolean targetIsFloat = TypeMap
275:                        .isFloatingPoint(targetType);
276:                NumberRange targetRange = TypeMap.getRange(targetType);
277:                Category[] categories = new Category[1];
278:                final boolean needScaling;
279:                if (targetIsFloat) {
280:                    // Never rescale if the target is floating point numbers.
281:                    needScaling = false;
282:                } else if (sourceIsFloat) {
283:                    // Always rescale for "float to integer" conversions. In addition,
284:                    // Use 0 value as a "no data" category for unsigned data type only.
285:                    needScaling = true;
286:                    if (!TypeMap.isSigned(targetType)) {
287:                        categories = new Category[2];
288:                        categories[1] = Category.NODATA;
289:                        targetRange = TypeMap.getPositiveRange(targetType);
290:                    }
291:                } else {
292:                    // In "integer to integer" conversions, rescale only if
293:                    // the target range is smaller than the source range.
294:                    needScaling = !targetRange.contains(TypeMap
295:                            .getRange(sourceType));
296:                }
297:                /*
298:                 * Computes the minimal and maximal values, if not explicitely provided.
299:                 * This information is required for determining the range of geophysics
300:                 * values.
301:                 */
302:                if (needScaling && (min == null || max == null)) {
303:                    final boolean computeMin;
304:                    final boolean computeMax;
305:                    if (computeMin = (min == null)) {
306:                        min = new double[numBands];
307:                        Arrays.fill(min, Double.POSITIVE_INFINITY);
308:                    }
309:                    if (computeMax = (max == null)) {
310:                        max = new double[numBands];
311:                        Arrays.fill(max, Double.NEGATIVE_INFINITY);
312:                    }
313:                    int b = 0;
314:                    iterator.startBands();
315:                    if (!iterator.finishedBands())
316:                        do {
317:                            iterator.startLines();
318:                            if (!iterator.finishedLines())
319:                                do {
320:                                    iterator.startPixels();
321:                                    if (!iterator.finishedPixels())
322:                                        do {
323:                                            final double z = iterator
324:                                                    .getSampleDouble();
325:                                            if (computeMin && z < min[b])
326:                                                min[b] = z;
327:                                            if (computeMax && z > max[b])
328:                                                max[b] = z;
329:                                        } while (!iterator.nextPixelDone());
330:                                } while (!iterator.nextLineDone());
331:                            if (computeMin && computeMax) {
332:                                if (!(min[b] < max[b])) {
333:                                    min[b] = 0;
334:                                    max[b] = 1;
335:                                }
336:                            }
337:                            b++;
338:                        } while (!iterator.nextBandDone());
339:                }
340:                /*
341:                 * Now, constructs the sample dimensions. We will inconditionnaly provides a "nodata"
342:                 * category for floating point images targeting unsigned integers, since we don't know
343:                 * if the user plan to have NaN values. Even if the current image doesn't have NaN values,
344:                 * it could have NaN later if the image uses a writable raster.
345:                 */
346:                final InternationalString n = SimpleInternationalString
347:                        .wrap(name);
348:                NumberRange sourceRange = TypeMap.getRange(sourceType);
349:                for (int b = 0; b < numBands; b++) {
350:                    final Color[] c = colors != null ? colors[b] : null;
351:                    if (needScaling) {
352:                        sourceRange = new NumberRange(min[b], max[b])
353:                                .castTo(sourceRange.getElementClass());
354:                        categories[0] = new Category(n, c, targetRange,
355:                                sourceRange);
356:                    } else {
357:                        categories[0] = new Category(n, c, targetRange,
358:                                LinearTransform1D.IDENTITY);
359:                    }
360:                    dst[b] = new GridSampleDimension(categories, units)
361:                            .geophysics(true);
362:                }
363:            }
364:
365:            /**
366:             * Returns a code value indicating grid value data type.
367:             * This will also indicate the number of bits for the data type.
368:             *
369:             * @return a code value indicating grid value data type.
370:             */
371:            public SampleDimensionType getSampleDimensionType() {
372:                return type;
373:            }
374:
375:            /**
376:             * Returns the color interpretation of the sample dimension.
377:             */
378:            public ColorInterpretation getColorInterpretation() {
379:                return TypeMap.getColorInterpretation(getColorModel(), band);
380:            }
381:
382:            /**
383:             * Returns a color model for this sample dimension.
384:             */
385:            public ColorModel getColorModel() {
386:                return getColorModel(band, numBands);
387:            }
388:
389:            /**
390:             * Returns the minimum value occurring in this sample dimension.
391:             */
392:            //  public double getMinimumValue()
393:            //  {return getHistogram().getLowValue(band);}
394:            /**
395:             * Returns the maximum value occurring in this sample dimension.
396:             */
397:            //  public double getMaximumValue()
398:            //  {return getHistogram().getHighValue(band);}
399:            /**
400:             * Determine the mode grid value in this sample dimension.
401:             */
402:            //  public double getModeValue()
403:            //  {throw new UnsupportedOperationException("Not implemented");}
404:            /**
405:             * Determine the median grid value in this sample dimension.
406:             */
407:            //  public double getMedianValue()
408:            //  {throw new UnsupportedOperationException("Not implemented");}
409:            /**
410:             * Determine the mean grid value in this sample dimension.
411:             */
412:            //  public double getMeanValue()
413:            //  {return getHistogram().getMean()[band];}
414:            /**
415:             * Determine the standard deviation from the mean
416:             * of the grid values in a sample dimension.
417:             */
418:            //  public double getStandardDeviation()
419:            //  {return getHistogram().getStandardDeviation()[band];}
420:            /**
421:             * Gets the histogram for the underlying grid coverage.
422:             */
423:            //  private Histogram getHistogram()
424:            //  {throw new UnsupportedOperationException("Not implemented");}
425:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.