Source Code Cross Referenced for AbstractGridCoverage2DReader.java in  » GIS » GeoTools-2.4.1 » org » geotools » coverage » grid » io » 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.io 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


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;
009:         *    version 2.1 of the License.
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.io;
017:
018:        import java.awt.Color;
019:        import java.awt.Rectangle;
020:        import java.awt.color.ColorSpace;
021:        import java.awt.geom.AffineTransform;
022:        import java.awt.geom.Rectangle2D;
023:        import java.awt.image.ColorModel;
024:        import java.awt.image.DataBuffer;
025:        import java.awt.image.IndexColorModel;
026:        import java.io.IOException;
027:        import java.text.ParseException;
028:        import java.util.HashMap;
029:        import java.util.logging.Level;
030:        import java.util.logging.Logger;
031:
032:        import javax.imageio.ImageReadParam;
033:        import javax.imageio.ImageReader;
034:        import javax.imageio.stream.ImageInputStream;
035:        import javax.media.jai.IHSColorSpace;
036:        import javax.media.jai.PlanarImage;
037:        import javax.units.Unit;
038:        import javax.units.UnitFormat;
039:
040:        import org.geotools.coverage.Category;
041:        import org.geotools.coverage.FactoryFinder;
042:        import org.geotools.coverage.GridSampleDimension;
043:        import org.geotools.coverage.grid.GeneralGridRange;
044:        import org.geotools.coverage.grid.GridCoverage2D;
045:        import org.geotools.coverage.grid.GridCoverageFactory;
046:        import org.geotools.data.DataSourceException;
047:        import org.geotools.factory.Hints;
048:        import org.geotools.geometry.GeneralEnvelope;
049:        import org.geotools.referencing.operation.BufferedCoordinateOperationFactory;
050:        import org.geotools.referencing.operation.transform.LinearTransform1D;
051:        import org.geotools.resources.CRSUtilities;
052:        import org.geotools.util.NumberRange;
053:        import org.geotools.util.logging.Logging;
054:        import org.opengis.coverage.MetadataNameNotFoundException;
055:        import org.opengis.coverage.grid.GridCoverage;
056:        import org.opengis.coverage.grid.GridCoverageReader;
057:        import org.opengis.coverage.grid.GridRange;
058:        import org.opengis.referencing.FactoryException;
059:        import org.opengis.referencing.crs.CoordinateReferenceSystem;
060:        import org.opengis.referencing.operation.CoordinateOperationFactory;
061:        import org.opengis.referencing.operation.MathTransform;
062:        import org.opengis.referencing.operation.TransformException;
063:
064:        /**
065:         * This class is a first attempt for providing a way to get more informations
066:         * out of a single 2D raster datasets (x,y). It is worth to remark that for the
067:         * moment this is thought for 2D rasters not for 3D or 4D rasters (x,y,z,t).
068:         * 
069:         * <p>
070:         * The main drawback I see with the current GeoApi GridCoverageReader interface
071:         * is that there is no way to get real information about a raster source unless
072:         * you instantiate a GridCoverage. As an instance it is impossible to know the
073:         * envelope, the number of overviews, the tile size. This information is needed
074:         * in order to perform decimation on reading or to use built-in overviews<br>
075:         * This really impacts the ability to exploit raster datasets in a desktop
076:         * environment where caching is crucial.
077:         * 
078:         * @author Simone Giannecchini
079:         * @since 2.3
080:         * @version 0.2
081:         */
082:        public abstract class AbstractGridCoverage2DReader implements 
083:                GridCoverageReader {
084:
085:            /** The {@link Logger} for this {@link AbstractGridCoverage2DReader}. */
086:            private final static Logger LOGGER = Logging
087:                    .getLogger("org.geotools.data.coverage.grid");
088:
089:            /** Caches a default GridCoverageFactory for usage in plugins. */
090:            protected final static GridCoverageFactory coverageFactory = FactoryFinder
091:                    .getGridCoverageFactory(null);
092:
093:            protected static final double EPS = 1E-6;
094:
095:            /** Buffered factory for coordinate operations. */
096:            protected final static CoordinateOperationFactory operationFactory = new BufferedCoordinateOperationFactory(
097:                    new Hints(Hints.LENIENT_DATUM_SHIFT, Boolean.TRUE));
098:
099:            /**
100:             * Default color ramp. Preset colors used to generate an Image from the raw
101:             * data
102:             */
103:            protected final static Color[] demColors = new Color[] {
104:                    new Color(5, 90, 5), new Color(150, 200, 150),
105:                    new Color(190, 150, 20), new Color(100, 100, 50),
106:                    new Color(200, 210, 220), Color.WHITE, Color.WHITE,
107:                    Color.WHITE, Color.WHITE };
108:
109:            /**
110:             * This contains the maximum number of grid coverages in the file/stream.
111:             * Until multi-image files are supported, this is going to be 0 or 1.
112:             */
113:            protected volatile int numOverviews = 0;
114:
115:            /** 2DGridToWorld math transform. */
116:            protected MathTransform raster2Model = null;
117:
118:            /** crs for this coverage */
119:            protected CoordinateReferenceSystem crs = null;
120:
121:            /** Envelope read from file */
122:            protected GeneralEnvelope originalEnvelope = null;
123:
124:            /** Coverage name */
125:            protected String coverageName = "geotools_coverage";
126:
127:            /** Source to read from */
128:            protected Object source = null;
129:
130:            /** Hints used by the {@link AbstractGridCoverage2DReader} subclasses. */
131:            protected Hints hints = new Hints(new HashMap(5));
132:
133:            /**
134:             * Highest resolution availaible for this reader.
135:             */
136:            protected double[] highestRes = null;
137:
138:            /** Temp variable used in many readers. */
139:            protected boolean closeMe;
140:
141:            /**
142:             * In case we are trying to read from a GZipped file this will be set to
143:             * true.
144:             */
145:            protected boolean gzipped;
146:
147:            /**
148:             * The original {@link GridRange} for the {@link GridCoverage2D} of this
149:             * reader.
150:             */
151:            protected GeneralGridRange originalGridRange = null;
152:
153:            /**
154:             * Input stream that can be used to initialize subclasses of
155:             * {@link AbstractGridCoverage2DReader}.
156:             */
157:            protected ImageInputStream inStream = null;
158:
159:            /** Resolutions avialaible through an overviews based mechanism. */
160:            protected double[][] overViewResolutions = null;
161:
162:            // -------------------------------------------------------------------------
163:            //
164:            // old support methods
165:            //
166:            // -------------------------------------------------------------------------
167:            /**
168:             * This method is responsible for preparing the read param for doing an
169:             * {@link ImageReader#read(int, ImageReadParam)}.
170:             * 
171:             * 
172:             * <p>
173:             * This method is responsible for preparing the read param for doing an
174:             * {@link ImageReader#read(int, ImageReadParam)}. It sets the passed
175:             * {@link ImageReadParam} in terms of decimation on reading using the
176:             * provided requestedEnvelope and requestedDim to evaluate the needed
177:             * resolution. It also returns and {@link Integer} representing the index of
178:             * the raster to be read when dealing with multipage raster.
179:             * 
180:             * @param readP
181:             *            an instance of {@link ImageReadParam} for setting the
182:             *            subsampling factors.
183:             * @param requestedEnvelope
184:             *            the {@link GeneralEnvelope} we are requesting.
185:             * @param requestedDim
186:             *            the requested dimensions.
187:             * @return the index of the raster to read in the underlying data source.
188:             * @throws IOException
189:             * @throws TransformException
190:             */
191:            protected Integer setReadParams(ImageReadParam readP,
192:                    GeneralEnvelope requestedEnvelope, Rectangle requestedDim)
193:                    throws IOException, TransformException {
194:
195:                readP.setSourceSubsampling(1, 1, 0, 0);// default values for
196:                // subsampling
197:                // //
198:                //
199:                // Default image index 0
200:                //
201:                // //
202:                Integer imageChoice = new Integer(0);
203:
204:                // we are able to handle overviews properly only if the transformation
205:                // is
206:                // an affine transform with pure scale and translation, no rotational
207:                // components
208:                if (raster2Model != null && !isScaleTranslate(raster2Model))
209:                    return imageChoice;
210:
211:                // //
212:                //
213:                // Check Hint to ignore overviews
214:                //
215:                // //
216:                Object o = hints.get(Hints.IGNORE_COVERAGE_OVERVIEW);
217:                if (o != null && ((Boolean) o).booleanValue()) {
218:                    return imageChoice;
219:
220:                }
221:
222:                // //
223:                //
224:                // Am I going to decimate or to use overviews? If this geotiff has only
225:                // one page we use decimation, otherwise we use the best page avalabile.
226:                // Future versions should use both.
227:                //
228:                // //
229:                final boolean decimate = (numOverviews <= 0) ? true : false;
230:
231:                // //
232:                //
233:                // Resolution requested. I am here computing the resolution required by
234:                // the user.
235:                //
236:                // //
237:                double[] requestedRes = getResolution(requestedEnvelope,
238:                        requestedDim, crs);
239:                if (requestedRes == null)
240:                    return imageChoice;
241:
242:                // //
243:                //
244:                // overviews or decimation
245:                //
246:                // //
247:                if (!decimate) {
248:                    // /////////////////////////////////////////////////////////////////////
249:                    // OVERVIEWS
250:                    // /////////////////////////////////////////////////////////////////////
251:                    // Should we leave now? In case the resolution of the first level is
252:                    // already lower than the requested one we should use the first
253:                    // level and leave.
254:                    if (highestRes[0] - requestedRes[0] > EPS
255:                            && highestRes[1] - requestedRes[1] > EPS)
256:                        return imageChoice;
257:
258:                    // Should we leave now? In case the resolution of the first level is
259:                    // already lower than the requested one we should use the first
260:                    // level and leave.
261:                    int axis = 0;
262:                    if (requestedRes[0] - requestedRes[1] > EPS)
263:                        axis = 1;
264:
265:                    // //
266:                    //
267:                    // looking for the overview with the highest lower resolution
268:                    // compared
269:                    // to the requested one.
270:                    // This ensure more speed but less quality. In the future we should
271:                    // provide a hint to control this behaviour.
272:                    //
273:                    // //
274:                    double actRes;
275:                    int i = 0;
276:                    for (; i < numOverviews; i++) {
277:                        actRes = (axis == 0) ? overViewResolutions[i][0]
278:                                : overViewResolutions[i][1];
279:                        // is actual resolution lower than the requested resolution?
280:                        if (actRes - requestedRes[axis] > EPS) {
281:
282:                            i--;
283:                            break;
284:
285:                        }
286:
287:                    }
288:                    // checking that we did not exceeded the maximum number of pages.
289:                    if (i == numOverviews) {
290:                        // int subsamplingFactor=
291:                        imageChoice = new Integer(numOverviews);
292:                    } else
293:                        // keeping the first image at highest resolution into account in
294:                        // order to get the overview wit
295:                        imageChoice = new Integer(i + 1);
296:                }
297:                // /////////////////////////////////////////////////////////////////////
298:                // DECIMATION ON READING
299:                // /////////////////////////////////////////////////////////////////////
300:                decimationOnReadingControl(imageChoice, readP, requestedRes);
301:                return imageChoice;
302:            }
303:
304:            /**
305:             * Checks the transformation is a pure scale/translate instance (using a
306:             * tolerance)
307:             * 
308:             * @param transform
309:             * @return
310:             */
311:            protected final boolean isScaleTranslate(MathTransform transform) {
312:                if (!(transform instanceof  AffineTransform))
313:                    return false;
314:                AffineTransform at = (AffineTransform) transform;
315:                return at.getShearX() < EPS && at.getShearY() < EPS;
316:            }
317:
318:            /**
319:             * This method is responsible for evaluating possible subsampling factors
320:             * once the best resolution level has been found, in case we have support
321:             * for overviews, or starting from the original coverage in case there are
322:             * no overviews availaible.
323:             * 
324:             * Anyhow this methof should not be called directly but subclasses should
325:             * make use of the setReadParams method instead in order to transparently
326:             * look for overviews.
327:             * 
328:             * @param imageChoice
329:             * @param readP
330:             * @param requestedRes
331:             */
332:            protected final void decimationOnReadingControl(
333:                    Integer imageChoice, ImageReadParam readP,
334:                    double[] requestedRes) {
335:                {
336:
337:                    int w, h;
338:                    double selectedRes[] = new double[2];
339:                    final int choice = imageChoice.intValue();
340:                    if (choice == 0) {
341:                        // highest resolution
342:                        w = originalGridRange.getLength(0);
343:                        h = originalGridRange.getLength(1);
344:                        selectedRes[0] = highestRes[0];
345:                        selectedRes[1] = highestRes[1];
346:                    } else {
347:                        // some overview
348:                        selectedRes[0] = overViewResolutions[choice - 1][0];
349:                        selectedRes[1] = overViewResolutions[choice - 1][1];
350:                        w = (int) Math.round(originalEnvelope.getLength(0)
351:                                / selectedRes[0]);
352:                        h = (int) Math.round(originalEnvelope.getLength(1)
353:                                / selectedRes[1]);
354:
355:                    }
356:                    // /////////////////////////////////////////////////////////////////////
357:                    // DECIMATION ON READING
358:                    // Setting subsampling factors with some checkings
359:                    // 1) the subsampling factors cannot be zero
360:                    // 2) the subsampling factors cannot be such that the w or h are
361:                    // zero
362:                    // /////////////////////////////////////////////////////////////////////
363:                    if (requestedRes == null) {
364:                        readP.setSourceSubsampling(1, 1, 0, 0);
365:
366:                    } else {
367:                        int subSamplingFactorX = (int) Math
368:                                .floor(requestedRes[0] / selectedRes[0]);
369:                        subSamplingFactorX = subSamplingFactorX == 0 ? 1
370:                                : subSamplingFactorX;
371:
372:                        while (w / subSamplingFactorX <= 0
373:                                && subSamplingFactorX >= 0)
374:                            subSamplingFactorX--;
375:                        subSamplingFactorX = subSamplingFactorX == 0 ? 1
376:                                : subSamplingFactorX;
377:
378:                        int subSamplingFactorY = (int) Math
379:                                .floor(requestedRes[1] / selectedRes[1]);
380:                        subSamplingFactorY = subSamplingFactorY == 0 ? 1
381:                                : subSamplingFactorY;
382:
383:                        while (h / subSamplingFactorY <= 0
384:                                && subSamplingFactorY >= 0)
385:                            subSamplingFactorY--;
386:                        subSamplingFactorY = subSamplingFactorY == 0 ? 1
387:                                : subSamplingFactorY;
388:
389:                        readP.setSourceSubsampling(subSamplingFactorX,
390:                                subSamplingFactorY, 0, 0);
391:                    }
392:
393:                }
394:            }
395:
396:            /**
397:             * Creates a {@link GridCoverage} for the provided {@link PlanarImage} using
398:             * the {@link #originalEnvelope} that was provided for this coverage.
399:             * 
400:             * @param image
401:             *            contains the data for the coverage to create.
402:             * @return a {@link GridCoverage}
403:             * @throws IOException
404:             */
405:            protected final GridCoverage createImageCoverage(PlanarImage image)
406:                    throws IOException {
407:                return createImageCoverage(image, null);
408:
409:            }
410:
411:            /**
412:             * Creates a {@link GridCoverage} for the provided {@link PlanarImage} using
413:             * the {@link #raster2Model} that was provided for this coverage.
414:             * 
415:             * <p>
416:             * This method is vital when working with coverages that have a raster to
417:             * model transformation that is not a simple scale and translate.
418:             * 
419:             * @param image
420:             *            contains the data for the coverage to create.
421:             * @param raster2Model
422:             *            is the {@link MathTransform} that maps from the raster space
423:             *            to the model space.
424:             * @return a {@link GridCoverage}
425:             * @throws IOException
426:             */
427:            protected final GridCoverage createImageCoverage(PlanarImage image,
428:                    MathTransform raster2Model) throws IOException {
429:
430:                // deciding the number range
431:                NumberRange geophysicRange = null;
432:
433:                switch (image.getSampleModel().getTransferType()) {
434:                case DataBuffer.TYPE_BYTE:
435:                    geophysicRange = new NumberRange(0, 255);
436:
437:                    break;
438:
439:                case DataBuffer.TYPE_USHORT:
440:                    geophysicRange = new NumberRange(0, 65535);
441:
442:                    break;
443:                // going to treat following cases as DEM
444:                case DataBuffer.TYPE_INT:
445:                    geophysicRange = new NumberRange(Integer.MIN_VALUE,
446:                            Integer.MAX_VALUE);
447:                    break;
448:                case DataBuffer.TYPE_SHORT:
449:                    geophysicRange = new NumberRange(Short.MIN_VALUE,
450:                            Short.MAX_VALUE);
451:                    break;
452:                case DataBuffer.TYPE_DOUBLE:
453:
454:                    geophysicRange = new NumberRange(Double.MIN_VALUE,
455:                            Double.MAX_VALUE);
456:                    break;
457:                case DataBuffer.TYPE_FLOAT:
458:                    geophysicRange = new NumberRange(Float.MIN_VALUE,
459:                            Float.MAX_VALUE);
460:                    return createDEMCoverage(image);
461:                default:
462:                    throw new DataSourceException(
463:                            "createImageCoverage:Data buffer type not supported by this world image reader! Use byte, ushort or int");
464:                }
465:
466:                /**
467:                 * Now we shuld be able to create the sample dimensions and the
468:                 * categories for this coverage in a much better and meaningful way
469:                 * using the color model and the color space type.
470:                 * 
471:                 * @todo How do we handle the NoData when it is 0?
472:                 * 
473:                 */
474:                // convenieience category in order to
475:                final Category values = new Category("values",
476:                        new Color[] { Color.BLACK }, geophysicRange,
477:                        LinearTransform1D.IDENTITY);
478:
479:                // creating bands
480:                final int numBands = image.getSampleModel().getNumBands();
481:                final GridSampleDimension[] bands = new GridSampleDimension[numBands];
482:                // checking the names
483:                final ColorModel cm = image.getColorModel();
484:                final String names[] = new String[numBands];
485:                // in case of index color model we are already done.
486:                if (cm instanceof  IndexColorModel) {
487:                    names[0] = "index band";
488:                } else {
489:                    // in case of multiband image we are not done yet.
490:                    final ColorSpace cs = cm.getColorSpace();
491:
492:                    if (cs instanceof  IHSColorSpace) {
493:                        names[0] = "Intensity band";
494:                        names[1] = "Hue band";
495:                        names[2] = "Saturation band";
496:
497:                    } else {
498:                        /**
499:                         * 
500:                         * 
501:                         * @TODO we need to support more types than the ones we have
502:                         *       here.
503:                         * 
504:                         * 
505:                         */
506:                        // not IHS, let's take the type
507:                        final int type = cs.getType();
508:                        switch (type) {
509:                        case ColorSpace.CS_GRAY:
510:                        case ColorSpace.TYPE_GRAY:
511:                            names[0] = "grayscale band";
512:                            break;
513:                        case ColorSpace.CS_sRGB:
514:                        case ColorSpace.CS_LINEAR_RGB:
515:                        case ColorSpace.TYPE_RGB:
516:                            names[0] = "Red band";
517:                            names[1] = "Green band";
518:                            names[2] = "Blue band";
519:                            break;
520:                        case ColorSpace.TYPE_CMY:
521:                            names[0] = "Cyan band";
522:                            names[1] = "Magenta band";
523:                            names[2] = "Yellow band";
524:                            break;
525:                        case ColorSpace.TYPE_CMYK:
526:                            names[0] = "Cyan band";
527:                            names[1] = "Magenta band";
528:                            names[2] = "Yellow band";
529:                            names[3] = "K band";
530:                            break;
531:
532:                        }
533:                    }
534:                }
535:                // setting bands names.
536:                for (int i = 0; i < numBands; i++) {
537:
538:                    bands[i] = new GridSampleDimension(names[i],
539:                            new Category[] { values }, null).geophysics(true);
540:                }
541:
542:                // creating coverage
543:                if (raster2Model != null) {
544:                    return coverageFactory.create(coverageName, image, crs,
545:                            raster2Model, bands, null, null);
546:                }
547:
548:                return coverageFactory.create(coverageName, image,
549:                        new GeneralEnvelope(originalEnvelope), bands, null,
550:                        null);
551:
552:            }
553:
554:            /**
555:             * Creates a {@link GridCoverage} for a coverage that is not a simple image
556:             * but that contains complex dadta from measurements.
557:             * 
558:             * 
559:             * <p>
560:             * This usually means that the original {@link DataBuffer#getDataType()} is
561:             * of one of the following types:
562:             * 
563:             * <ul>
564:             * <li>{@link DataBuffer#TYPE_FLOAT}</li>
565:             * <li>{@link DataBuffer#TYPE_DOUBLE}</li>
566:             * <li>{@link DataBuffer#TYPE_INT}</li>
567:             * <li>{@link DataBuffer#TYPE_SHORT}</li>
568:             * </ul>
569:             * 
570:             * and it implies that we have to prepare a transformation from geophysics
571:             * values to non-geophysics values.
572:             * 
573:             * @param coverage
574:             *            a {@link PlanarImage} containing the source coverage.
575:             * @return a {@link GridCoverage}.
576:             */
577:            private GridCoverage createDEMCoverage(PlanarImage coverage) {
578:                // Create the SampleDimension, with colors and byte transformation
579:                // needed for visualization
580:                final UnitFormat unitFormat = UnitFormat.getStandardInstance();
581:                Unit uom = null;
582:
583:                // unit of measure is meter usually, is this a good guess?
584:                try {
585:                    uom = unitFormat.parseUnit("m");
586:                } catch (ParseException e) {
587:                    uom = null;
588:                }
589:
590:                final Category values = new Category("elevation", demColors,
591:                        new NumberRange(2, 10), new NumberRange(-1, 8849));
592:
593:                final GridSampleDimension band = new GridSampleDimension(
594:                        "digital elevation", new Category[] { values }, uom)
595:                        .geophysics(true);
596:
597:                return coverageFactory.create(coverageName, coverage,
598:                        originalEnvelope, new GridSampleDimension[] { band },
599:                        null, null);
600:
601:            }
602:
603:            /**
604:             * This method is responsible for computing the resolutions in for the
605:             * provided grid geometry in the provided crs.
606:             * 
607:             * <P>
608:             * It is worth to note that the returned resolution array is of length of 2
609:             * and it always is lon, lat for the moment.<br>
610:             * It might be worth to remove the axes reordering code when we are
611:             * confident enough with the code to handle the north-up crs.
612:             * <p>
613:             * TODO use orthodromic distance?
614:             * 
615:             * @param envelope
616:             *            the GeneralEnvelope
617:             * @param dim
618:             * @param crs
619:             * @throws DataSourceException
620:             */
621:            protected final double[] getResolution(GeneralEnvelope envelope,
622:                    Rectangle2D dim, CoordinateReferenceSystem crs)
623:                    throws DataSourceException {
624:                double[] requestedRes = null;
625:                try {
626:                    if (dim != null && envelope != null) {
627:                        // do we need to transform the originalEnvelope?
628:                        final CoordinateReferenceSystem crs2D = CRSUtilities
629:                                .getCRS2D(envelope
630:                                        .getCoordinateReferenceSystem());
631:
632:                        if (crs != null
633:                                && !CRSUtilities.equalsIgnoreMetadata(crs,
634:                                        crs2D)) {
635:                            final MathTransform tr = operationFactory
636:                                    .createOperation(crs2D, crs)
637:                                    .getMathTransform();
638:                            if (!tr.isIdentity())
639:                                envelope = CRSUtilities.transform(tr, envelope);
640:                        }
641:                        requestedRes = new double[2];
642:                        requestedRes[0] = envelope.getLength(0)
643:                                / dim.getWidth();
644:                        requestedRes[1] = envelope.getLength(1)
645:                                / dim.getHeight();
646:                    }
647:                    return requestedRes;
648:                } catch (TransformException e) {
649:                    throw new DataSourceException(
650:                            "Unable to get the resolution", e);
651:                } catch (FactoryException e) {
652:                    throw new DataSourceException(
653:                            "Unable to get the resolution", e);
654:                }
655:            }
656:
657:            /**
658:             * Retrieves the {@link CoordinateReferenceSystem} for dataset pointed by
659:             * this {@link AbstractGridCoverage2DReader}.
660:             * 
661:             * @return the {@link CoordinateReferenceSystem} for dataset pointed by this
662:             *         {@link AbstractGridCoverage2DReader}.
663:             */
664:            public final CoordinateReferenceSystem getCrs() {
665:                return crs;
666:            }
667:
668:            /**
669:             * Retrieves the {@link GeneralGridRange} that represents the raster grid
670:             * dimensions of the highest resolution level in this dataset.
671:             * 
672:             * @return the {@link GeneralGridRange} that represents the raster grid
673:             *         dimensions of the highest resolution level in this dataset.
674:             */
675:            public final GeneralGridRange getOriginalGridRange() {
676:                return originalGridRange;
677:            }
678:
679:            /**
680:             * Retrieves the {@link GeneralEnvelope} for this
681:             * {@link AbstractGridCoverage2DReader}.
682:             * 
683:             * @return the {@link GeneralEnvelope} for this
684:             *         {@link AbstractGridCoverage2DReader}.
685:             */
686:            public final GeneralEnvelope getOriginalEnvelope() {
687:                return originalEnvelope;
688:            }
689:
690:            /**
691:             * Retrieves the source for this {@link AbstractGridCoverage2DReader}.
692:             * 
693:             * @return the source for this {@link AbstractGridCoverage2DReader}.
694:             */
695:            public final Object getSource() {
696:                return source;
697:            }
698:
699:            /**
700:             * Disposes this reader.
701:             * 
702:             * <p>
703:             * This method just tries to close the underlying {@link ImageInputStream}.
704:             */
705:            public void dispose() {
706:                if (inStream != null) {
707:                    try {
708:                        inStream.close();
709:                    } catch (IOException e) {
710:                        if (LOGGER.isLoggable(Level.FINE))
711:                            LOGGER.log(Level.FINE, e.getLocalizedMessage(), e);
712:                    }
713:                }
714:
715:            }
716:
717:            /**
718:             * @see org.opengis.coverage.grid.GridCoverageReader#skip()
719:             */
720:            public void skip() {
721:                throw new UnsupportedOperationException("Unsupported opertion.");
722:            }
723:
724:            /**
725:             * @see org.opengis.coverage.grid.GridCoverageReader#hasMoreGridCoverages()
726:             */
727:            public boolean hasMoreGridCoverages() {
728:                throw new UnsupportedOperationException("Unsupported opertion.");
729:            }
730:
731:            /**
732:             * @see org.opengis.coverage.grid.GridCoverageReader#listSubNames()
733:             */
734:            public String[] listSubNames() {
735:                throw new UnsupportedOperationException("Unsupported opertion.");
736:            }
737:
738:            /**
739:             * @see org.opengis.coverage.grid.GridCoverageReader#getCurrentSubname()
740:             */
741:            public String getCurrentSubname() {
742:                throw new UnsupportedOperationException("Unsupported opertion.");
743:            }
744:
745:            /**
746:             * @see org.opengis.coverage.grid.GridCoverageReader#getMetadataNames()
747:             */
748:            public String[] getMetadataNames() {
749:                throw new UnsupportedOperationException("Unsupported opertion.");
750:            }
751:
752:            /**
753:             * @see org.opengis.coverage.grid.GridCoverageReader#getMetadataValue(java.lang.String)
754:             */
755:            public String getMetadataValue(final String name)
756:                    throws MetadataNameNotFoundException {
757:                throw new UnsupportedOperationException("Unsupported opertion.");
758:            }
759:
760:            /**
761:             * @see org.opengis.coverage.grid.GridCoverageReader#getGridCoverageCount()
762:             */
763:            public int getGridCoverageCount() {
764:                throw new UnsupportedOperationException("Unsupported opertion.");
765:            }
766:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.