001: /*
002: * Geotools2 - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2007, Geotools Project Managment Committee (PMC)
005: * (C) 2007, GeoSolutions S.A.S.
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;
010: * version 2.1 of the License.
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: */
018: package org.geotools.gce.ecw;
019:
020: import it.geosolutions.imageio.gdalframework.GDALCommonIIOImageMetadata;
021: import it.geosolutions.imageio.plugins.ecw.ECWImageReaderSpi;
022: import it.geosolutions.imageio.stream.input.FileImageInputStreamExtImpl;
023:
024: import java.awt.Rectangle;
025: import java.awt.geom.AffineTransform;
026: import java.awt.image.renderable.ParameterBlock;
027: import java.io.File;
028: import java.io.FileInputStream;
029: import java.io.FileNotFoundException;
030: import java.io.IOException;
031: import java.io.InputStream;
032: import java.io.UnsupportedEncodingException;
033: import java.net.URL;
034: import java.net.URLDecoder;
035: import java.util.NoSuchElementException;
036: import java.util.logging.Level;
037: import java.util.logging.Logger;
038:
039: import javax.imageio.ImageIO;
040: import javax.imageio.ImageReadParam;
041: import javax.imageio.ImageReader;
042: import javax.imageio.metadata.IIOMetadata;
043: import javax.imageio.spi.ImageReaderSpi;
044: import javax.imageio.stream.FileCacheImageInputStream;
045: import javax.imageio.stream.ImageInputStream;
046: import javax.imageio.stream.MemoryCacheImageInputStream;
047: import javax.media.jai.JAI;
048: import javax.media.jai.PlanarImage;
049:
050: import org.geotools.coverage.grid.GeneralGridRange;
051: import org.geotools.coverage.grid.GridCoverage2D;
052: import org.geotools.coverage.grid.GridGeometry2D;
053: import org.geotools.coverage.grid.io.AbstractGridCoverage2DReader;
054: import org.geotools.coverage.grid.io.AbstractGridFormat;
055: import org.geotools.data.DataSourceException;
056: import org.geotools.data.PrjFileReader;
057: import org.geotools.data.WorldFileReader;
058: import org.geotools.factory.Hints;
059: import org.geotools.geometry.GeneralEnvelope;
060: import org.geotools.parameter.Parameter;
061: import org.geotools.referencing.CRS;
062: import org.geotools.referencing.operation.builder.GridToEnvelopeMapper;
063: import org.geotools.referencing.operation.transform.ProjectiveTransform;
064: import org.opengis.coverage.grid.Format;
065: import org.opengis.coverage.grid.GridCoverage;
066: import org.opengis.coverage.grid.GridCoverageReader;
067: import org.opengis.geometry.Envelope;
068: import org.opengis.geometry.MismatchedDimensionException;
069: import org.opengis.parameter.GeneralParameterValue;
070: import org.opengis.referencing.FactoryException;
071: import org.opengis.referencing.datum.PixelInCell;
072: import org.opengis.referencing.operation.MathTransform;
073: import org.opengis.referencing.operation.NoninvertibleTransformException;
074: import org.opengis.referencing.operation.TransformException;
075:
076: /**
077: * This class can read a ECW data source and create a {@link GridCoverage2D}
078: * from the data.
079: *
080: * @author Daniele Romagnoli, GeoSolutions
081: * @author Simone Giannecchini, GeoSolutions
082: * @since 2.4.x
083: */
084: public final class ECWReader extends AbstractGridCoverage2DReader
085: implements GridCoverageReader {
086: /** Logger. */
087: private final static Logger LOGGER = org.geotools.util.logging.Logging
088: .getLogger("org.geotools.gce.ecw");
089:
090: /** Caches an <code>ImageReaderSpi</code> for a <code>ECWImageReader</code> */
091: private final static ImageReaderSpi readerSPI = new ECWImageReaderSpi();
092:
093: /** Absolute path to the parent dir for this coverage. */
094: private String parentPath;
095:
096: /**
097: * Creates a new instance of a {@link ECWReader}. I assume nothing about
098: * file extension.
099: *
100: * @param input
101: * Source object for which we want to build an {@link ECWReader}.
102: * @throws DataSourceException
103: * @throws FactoryException
104: * @throws MismatchedDimensionException
105: */
106: public ECWReader(Object input) throws DataSourceException,
107: MismatchedDimensionException {
108: this (input, null);
109: }
110:
111: /**
112: * Creates a new instance of a {@link ECWReader}. I assume nothing about
113: * file extension.
114: *
115: * @param input
116: * Source object for which we want to build an {@link ECWReader}.
117: * @param hints
118: * Hints to be used by this reader throughout his life.
119: * @throws DataSourceException
120: * @throws FactoryException
121: * @throws MismatchedDimensionException
122: */
123: public ECWReader(Object input, final Hints hints)
124: throws DataSourceException, MismatchedDimensionException {
125:
126: // /////////////////////////////////////////////////////////////////////
127: //
128: // Checking input
129: //
130: // /////////////////////////////////////////////////////////////////////
131: coverageName = "ECW";
132: try {
133: // //
134: //
135: // Hints
136: //
137: // //
138: if (hints != null)
139: this .hints.add(hints);
140:
141: // //
142: //
143: // Source management
144: //
145: // //
146: checkSource(input);
147:
148: // Getting a reader for this format
149: final ImageReader reader = readerSPI.createReaderInstance();
150: reader.setInput(inStream);
151:
152: // //
153: //
154: // Setting Envelope, GridRange and CRS
155: //
156: // //
157: setOriginalProperties(reader);
158:
159: // //
160: //
161: // Information about multiple levels and such
162: //
163: // //
164: getResolutionInfo(reader);
165: reader.reset();
166:
167: coverageName = (source instanceof File) ? ((File) source)
168: .getName() : "ECW_coverage";
169: // release the stream if we can.
170: finalStreamPreparation();
171: } catch (IOException e) {
172: if (LOGGER.isLoggable(Level.SEVERE))
173: LOGGER.log(Level.SEVERE, e.getLocalizedMessage(), e);
174: throw new DataSourceException(e);
175: } catch (TransformException e) {
176: if (LOGGER.isLoggable(Level.SEVERE))
177: LOGGER.log(Level.SEVERE, e.getLocalizedMessage(), e);
178: throw new DataSourceException(e);
179: }
180:
181: }
182:
183: /**
184: * Setting Envelope, GridRange and CRS from the given
185: * <code>ImageReader</code>
186: *
187: * @param reader
188: * the <code>ImageReader</code> from which to retrieve metadata
189: * (if available) for setting properties
190: * @throws IOException
191: * @throws IllegalStateException
192: * @throws TransformException
193: * @throws MismatchedDimensionException
194: */
195: private void setOriginalProperties(ImageReader reader)
196: throws IOException, IllegalStateException,
197: TransformException, MismatchedDimensionException {
198:
199: // /////////////////////////////////////////////////////////////////////
200: //
201: // Setting Envelope and CRS
202: //
203: // ////////////////////////////////////////////////////////////////////
204:
205: // //
206: //
207: // Using Common metadata from GDAL
208: //
209: // //
210: IIOMetadata metadata = reader.getImageMetadata(0);
211: if (!(metadata instanceof GDALCommonIIOImageMetadata))
212: throw new DataSourceException(
213: "Unexpected error! Metadata are not of the expected class.");
214: getPropertiesFromCommonMetadata(metadata);
215:
216: // //
217: //
218: // If common metadata don't have sufficient information to set CRS
219: // envelope, try other ways, such as looking for a PRJ
220: //
221: // //
222: if (crs == null)
223: getCoordinateReferenceSystemFromPrj();
224:
225: if (crs == null) {
226: LOGGER.info("crs not found proceeding with EPSG:4326");
227: crs = ECWFormat.getDefaultCRS();
228: }
229:
230: // //
231: //
232: // If common metadata doesn't have sufficient information to set the
233: // envelope, try other ways, such as looking for a WorldFile
234: //
235: // //
236: if (originalEnvelope == null)
237: checkForWorldFile();
238:
239: originalEnvelope.setCoordinateReferenceSystem(crs);
240:
241: }
242:
243: /**
244: * Checks whether a world file is associated with the data source. If found,
245: * set the envelope.
246: *
247: * @throws IllegalStateException
248: * @throws TransformException
249: * @throws IOException
250: */
251: private void checkForWorldFile() throws IllegalStateException,
252: TransformException, IOException {
253:
254: final String worldFilePath = new StringBuffer(this .parentPath)
255: .append(File.separatorChar).append(this .coverageName)
256: .toString();
257:
258: // TODO: Check if "eww" is the right extension of ecw world files.
259: File file2Parse = new File(worldFilePath + ".eww");
260: boolean worldFileExists = file2Parse.exists();
261: if (!worldFileExists) {
262: file2Parse = new File(worldFilePath + ".wld");
263: worldFileExists = file2Parse.exists();
264: }
265: if (worldFileExists) {
266: final WorldFileReader reader = new WorldFileReader(
267: file2Parse);
268: raster2Model = reader.getTransform();
269:
270: // //
271: //
272: // In case we read from a real world file we have together the
273: // envelope
274: //
275: // //
276:
277: final AffineTransform tempTransform = new AffineTransform(
278: (AffineTransform) raster2Model);
279: tempTransform.translate(-0.5, -0.5);
280:
281: originalEnvelope = CRS.transform(ProjectiveTransform
282: .create(tempTransform), new GeneralEnvelope(
283: originalGridRange.toRectangle()));
284: }
285: }
286:
287: /**
288: * Given a <code>IIOMetadata</code> metadata object, retrieves several
289: * properties to properly set envelope, gridrange and crs.
290: *
291: * @param metadata
292: */
293: private void getPropertiesFromCommonMetadata(IIOMetadata metadata) {
294: // casting metadata
295: final GDALCommonIIOImageMetadata commonMetadata = (GDALCommonIIOImageMetadata) metadata;
296:
297: // setting CRS and Envelope directly from GDAL, if available
298: final String wkt = commonMetadata.getProjection();
299:
300: if (wkt != null && !(wkt.equalsIgnoreCase("")))
301: try {
302: crs = CRS.parseWKT(wkt);
303:
304: } catch (FactoryException fe) {
305: // unable to get CRS from WKT
306: if (LOGGER.isLoggable(Level.WARNING))
307: LOGGER.log(Level.WARNING, fe.getLocalizedMessage(),
308: fe);
309: crs = null;
310: }
311:
312: final int hrWidth = commonMetadata.getWidth();
313: final int hrHeight = commonMetadata.getHeight();
314: originalGridRange = new GeneralGridRange(new Rectangle(0, 0,
315: hrWidth, hrHeight));
316:
317: // getting Grid Properties
318: final double geoTransform[] = commonMetadata
319: .getGeoTransformation();
320: if (geoTransform != null && geoTransform.length == 6) {
321: final AffineTransform tempTransform = new AffineTransform(
322: geoTransform[1], geoTransform[4], geoTransform[2],
323: geoTransform[5], geoTransform[0], geoTransform[3]);
324: // attention gdal geotransform does not uses the pixel is centre
325: // convention like world files.
326: // tempTransform.translate(-0.5, -0.5);
327: this .raster2Model = ProjectiveTransform
328: .create(tempTransform);
329: try {
330:
331: // Setting Envelope
332: originalEnvelope = CRS.transform(raster2Model,
333: new GeneralEnvelope(originalGridRange
334: .toRectangle()));
335: } catch (IllegalStateException e) {
336: if (LOGGER.isLoggable(Level.WARNING))
337: LOGGER.log(Level.WARNING, e.getLocalizedMessage(),
338: e);
339: } catch (TransformException e) {
340: if (LOGGER.isLoggable(Level.WARNING))
341: LOGGER.log(Level.WARNING, e.getLocalizedMessage(),
342: e);
343: }
344: }
345: }
346:
347: /**
348: * Close the <code>InStream</code> <code>ImageInputStream</code> if we
349: * open it up on purpose to read header info for this
350: * {@link AbstractGridCoverage2DReader}. If the stream cannot be closed, we
351: * just reset and mark it.
352: *
353: * @throws IOException
354: */
355: private void finalStreamPreparation() throws IOException {
356: if (closeMe)
357: inStream.close();
358: else {
359: inStream.reset();
360: inStream.mark();
361: }
362: }
363:
364: /**
365: * Checks the input provided to this {@link ECWReader} and sets all the
366: * other objects and flags accordingly.
367: *
368: * @param input
369: * provided to this {@link ECWReader}.
370: *
371: * @throws UnsupportedEncodingException
372: * @throws DataSourceException
373: * @throws IOException
374: * @throws FileNotFoundException
375: */
376: private void checkSource(Object input)
377: throws UnsupportedEncodingException, DataSourceException,
378: IOException, FileNotFoundException {
379: if (input == null) {
380: final DataSourceException ex = new DataSourceException(
381: "No source set to read this coverage.");
382: if (LOGGER.isLoggable(Level.SEVERE))
383: LOGGER.log(Level.SEVERE, ex.getLocalizedMessage(), ex);
384: throw ex;
385: }
386: this .source = input;
387: closeMe = true;
388: // //
389: //
390: // URL to FIle
391: //
392: // //
393: // if it is a URL ponting to a File I convert it to a file,
394: // otherwis, later on, I will try to get an inputstream out of it.
395: if (input instanceof URL) {
396: // URL that point to a file
397: final URL sourceURL = ((URL) input);
398: if (sourceURL.getProtocol().compareToIgnoreCase("file") == 0) {
399: this .source = input = new File(URLDecoder.decode(
400: sourceURL.getFile(), "UTF-8"));
401: }
402: }
403:
404: // //
405: //
406: // File
407: //
408: // //
409: if (input instanceof File) {
410: final File sourceFile = (File) input;
411: if (!sourceFile.exists() || sourceFile.isDirectory()
412: || !sourceFile.canRead())
413: throw new DataSourceException(
414: "Provided file does not exist or is a directory or is not readable!");
415: this .parentPath = sourceFile.getParent();
416: this .coverageName = sourceFile.getName();
417: final int dotIndex = coverageName.indexOf(".");
418: coverageName = (dotIndex == -1) ? coverageName
419: : coverageName.substring(0, dotIndex);
420: inStream = new FileImageInputStreamExtImpl(sourceFile);
421: } else
422: // //
423: //
424: // URL
425: //
426: // //
427: if (input instanceof URL) {
428: final URL tempURL = ((URL) input);
429: inStream = ImageIO.createImageInputStream(tempURL
430: .openConnection().getInputStream());
431: } else
432: // //
433: //
434: // InputStream
435: //
436: // //
437: if (input instanceof InputStream) {
438: closeMe = false;
439: if (ImageIO.getUseCache())
440: inStream = new FileCacheImageInputStream(
441: (InputStream) input, null);
442: else
443: inStream = new MemoryCacheImageInputStream(
444: (InputStream) input);
445: // let's mark it
446: inStream.mark();
447: } else
448: // //
449: //
450: // ImageInputStream
451: //
452: // //
453: if (input instanceof ImageInputStream) {
454: closeMe = false;
455: inStream = (ImageInputStream) input;
456: inStream.mark();
457: } else
458: throw new IllegalArgumentException("Unsupported input type");
459:
460: if (inStream == null)
461: throw new DataSourceException(
462: "No input stream for the provided source");
463: }
464:
465: /**
466: * Gets resolution information about the coverage itself.
467: *
468: * @param reader
469: * an {@link ImageReader} to use for getting the resolution
470: * information.
471: * @throws IOException
472: * @throws TransformException
473: */
474: private void getResolutionInfo(ImageReader reader)
475: throws IOException, TransformException {
476:
477: // //
478: //
479: // get the dimension of the hr image and build the model as well as
480: // computing the resolution
481: //
482: // //
483: final Rectangle actualDim = new Rectangle(0, 0, reader
484: .getWidth(0), reader.getHeight(0));
485: originalGridRange = new GeneralGridRange(actualDim);
486:
487: // ///
488: //
489: // setting the higher resolution avalaible for this coverage
490: //
491: // ///
492: highestRes = getResolution(originalEnvelope, actualDim, crs);
493:
494: // ///
495: //
496: // Setting raster to model transformation
497: //
498: // ///
499: final GridToEnvelopeMapper geMapper = new GridToEnvelopeMapper();
500: geMapper.setEnvelope(originalEnvelope);
501: geMapper.setGridRange(originalGridRange);
502: geMapper.setGridType(PixelInCell.CELL_CENTER);
503: this .raster2Model = geMapper.createTransform();
504:
505: }
506:
507: /**
508: * @see org.opengis.coverage.grid.GridCoverageReader#getFormat()
509: */
510: public Format getFormat() {
511: return new ECWFormat();
512: }
513:
514: /**
515: * Reads a {@link GridCoverage2D} possibly matching as close as possible the
516: * resolution computed by using the input params provided by using the
517: * parameters for this {@link #read(GeneralParameterValue[])}.
518: *
519: * <p>
520: * To have an idea about the possible read parameters take a look at
521: * {@link AbstractGridFormat} class and {@link ECWFormat} class.
522: *
523: * @param params
524: * an array of {@link GeneralParameterValue} containing the
525: * parameters to control this read process.
526: *
527: * @return a {@link GridCoverage2D}.
528: *
529: * @see AbstractGridFormat
530: * @see ECWFormat
531: * @see org.opengis.coverage.grid.GridCoverageReader#read(org.opengis.parameter.GeneralParameterValue[])
532: */
533: public GridCoverage read(GeneralParameterValue[] params)
534: throws IllegalArgumentException, IOException {
535: GeneralEnvelope readEnvelope = null;
536: Rectangle requestedDim = null;
537: if (params != null) {
538:
539: final int length = params.length;
540: for (int i = 0; i < length; i++) {
541: Parameter param = (Parameter) params[i];
542: String name = param.getDescriptor().getName().getCode();
543: if (name.equals(AbstractGridFormat.READ_GRIDGEOMETRY2D
544: .getName().toString())) {
545: final GridGeometry2D gg = (GridGeometry2D) param
546: .getValue();
547: if (gg == null)
548: continue;
549: readEnvelope = new GeneralEnvelope((Envelope) gg
550: .getEnvelope2D());
551: requestedDim = gg.getGridRange2D().getBounds();
552: }
553:
554: }
555: }
556: return createCoverage(readEnvelope, requestedDim);
557: }
558:
559: /**
560: * This method creates the GridCoverage2D from the underlying file.
561: *
562: * @param requestedDim
563: * @param readEnvelope
564: *
565: *
566: * @return a GridCoverage
567: *
568: * @throws java.io.IOException
569: */
570: private GridCoverage createCoverage(
571: GeneralEnvelope requestedEnvelope, Rectangle requestedDim)
572: throws IOException {
573:
574: if (!closeMe) {
575: inStream.reset();
576: inStream.mark();
577: }
578: // /////////////////////////////////////////////////////////////////////
579: //
580: // Doing an image read for reading the coverage.
581: //
582: // /////////////////////////////////////////////////////////////////////
583:
584: // //
585: //
586: // Setting subsampling factors with some checkings
587: // 1) the subsampling factors cannot be zero
588: // 2) the subsampling factors cannot be such that the w 7or h are zero
589: //
590: // //
591: final ImageReadParam readP = new ImageReadParam();
592: final Integer imageChoice;
593: try {
594: imageChoice = setReadParams(readP, requestedEnvelope,
595: requestedDim);
596: } catch (IOException e) {
597: if (LOGGER.isLoggable(Level.SEVERE))
598: LOGGER.log(Level.SEVERE, e.getLocalizedMessage(), e);
599: return null;
600: } catch (TransformException e) {
601: if (LOGGER.isLoggable(Level.SEVERE))
602: LOGGER.log(Level.SEVERE, e.getLocalizedMessage(), e);
603: return null;
604: }
605:
606: // /////////////////////////////////////////////////////////////////////
607: //
608: // Check if we have something to load by intersecting the requested
609: // envelope with the bounds of the data set.
610: //
611: // If the requested envelope is not in the same crs of the data set crs
612: // we have to perform a conversion towards the latter crs before
613: // intersecting anything.
614: //
615: // /////////////////////////////////////////////////////////////////////
616: GeneralEnvelope intersectionEnvelope = null;
617: Rectangle sourceRegion = null;
618: if (requestedEnvelope != null) {
619: if (!CRS.equalsIgnoreMetadata(requestedEnvelope
620: .getCoordinateReferenceSystem(), this .crs)) {
621: try {
622: // //
623: //
624: // transforming the envelope back to the dataset crs in
625: // order to interact with the original envelope
626: //
627: // //
628: final MathTransform transform = operationFactory
629: .createOperation(
630: requestedEnvelope
631: .getCoordinateReferenceSystem(),
632: crs).getMathTransform();
633: if (!transform.isIdentity()) {
634: requestedEnvelope = CRS.transform(transform,
635: requestedEnvelope);
636: requestedEnvelope
637: .setCoordinateReferenceSystem(this .crs);
638:
639: if (LOGGER.isLoggable(Level.FINE))
640: LOGGER.fine(new StringBuffer(
641: "Reprojected envelope ").append(
642: requestedEnvelope.toString())
643: .append(" crs ")
644: .append(crs.toWKT()).toString());
645: }
646: } catch (TransformException e) {
647: throw new DataSourceException(
648: "Unable to create a coverage for this source",
649: e);
650: } catch (FactoryException e) {
651: throw new DataSourceException(
652: "Unable to create a coverage for this source",
653: e);
654: }
655: }
656: if (!requestedEnvelope.intersects(this .originalEnvelope,
657: true)) {
658: if (LOGGER.isLoggable(Level.FINE))
659: LOGGER
660: .warning("The requested envelope does not intersect the envelope of this coverage, we will return a null coverage.");
661: return null;
662: }
663: intersectionEnvelope = new GeneralEnvelope(
664: requestedEnvelope);
665: // intersect the requested area with the bounds of this layer
666: intersectionEnvelope.intersect(originalEnvelope);
667: intersectionEnvelope.setCoordinateReferenceSystem(this .crs);
668:
669: // ///
670: //
671: // Crop the sourced region
672: //
673: // ///
674: try {
675: final GeneralGridRange finalRange = new GeneralGridRange(
676: CRS.transform(this .raster2Model.inverse(),
677: intersectionEnvelope));
678: // CROP
679: sourceRegion = finalRange.toRectangle();
680: if (!sourceRegion.intersects(this .originalGridRange
681: .toRectangle()))
682: sourceRegion = null;
683: else
684: sourceRegion = sourceRegion
685: .intersection(this .originalGridRange
686: .toRectangle());
687:
688: } catch (NoninvertibleTransformException e) {
689: if (LOGGER.isLoggable(Level.WARNING))
690: LOGGER.log(Level.WARNING, e.getLocalizedMessage(),
691: e);
692: sourceRegion = null;
693: } catch (TransformException e) {
694: if (LOGGER.isLoggable(Level.WARNING))
695: LOGGER.log(Level.WARNING, e.getLocalizedMessage(),
696: e);
697: sourceRegion = null;
698: }
699: }
700:
701: Object input;
702: if (source instanceof File)
703: input = new FileImageInputStreamExtImpl((File) source);
704: else if (source instanceof ImageInputStream
705: || source instanceof InputStream)
706: input = inStream;
707: else if (source instanceof URL) {
708: input = ImageIO.createImageInputStream(((URL) source)
709: .openConnection().getInputStream());
710: } else
711: throw new IllegalArgumentException();
712:
713: final PlanarImage ecwCoverage;
714: if (sourceRegion != null)
715: readP.setSourceRegion(sourceRegion);
716:
717: // //
718: //
719: // image and metadata
720: //
721: // //
722: final ParameterBlock pbjImageRead = new ParameterBlock();
723: pbjImageRead.add(input);
724: pbjImageRead.add(imageChoice);
725: pbjImageRead.add(Boolean.FALSE);
726: pbjImageRead.add(Boolean.FALSE);
727: pbjImageRead.add(Boolean.FALSE);
728: pbjImageRead.add(null);
729: pbjImageRead.add(null);
730: pbjImageRead.add(readP);
731: pbjImageRead.add(readerSPI.createReaderInstance());
732: ecwCoverage = JAI.create("ImageRead", pbjImageRead, hints);
733:
734: // /////////////////////////////////////////////////////////////////////
735: //
736: // Creating the coverage
737: //
738: // /////////////////////////////////////////////////////////////////////
739: try {
740:
741: if (intersectionEnvelope != null) {
742: // I need to calculate a new transformation (raster2Model)
743: // between the cropped image and the required
744: // intersectionEnvelope
745: final GridToEnvelopeMapper gem = new GridToEnvelopeMapper();
746: gem.setEnvelope(intersectionEnvelope);
747: final int ssWidth = ecwCoverage.getWidth();
748: final int ssHeight = ecwCoverage.getHeight();
749: gem.setGridRange(new GeneralGridRange(new Rectangle(0,
750: 0, ssWidth, ssHeight)));
751: gem.setGridType(PixelInCell.CELL_CENTER);
752: return super .createImageCoverage(ecwCoverage, gem
753: .createTransform());
754: } else {
755: // In case of not intersectionEnvelope (As an instance, when
756: // reading the whole image), I can use the originalEnvelope. So,
757: // no need to specify a raster2model parameter
758: return super .createImageCoverage(ecwCoverage);
759: }
760: } catch (NoSuchElementException e) {
761: if (LOGGER.isLoggable(Level.SEVERE))
762: LOGGER.log(Level.SEVERE, e.getLocalizedMessage(), e);
763: throw new DataSourceException(e);
764: }
765: }
766:
767: /**
768: * Gets the coordinate system that will be associated to the
769: * {@link GridCoverage}. The WGS84 coordinate system is used by default. It
770: * is worth to point out that when reading from a stream which is not
771: * connected to a file, like from an http connection (e.g. from a WCS) we
772: * cannot rely on receiving a prj file too. In this case the exchange of
773: * information about referencing should proceed the exchange of data thus I
774: * rely on this and I ask the user who's invoking the read operation to
775: * provide me a valid crs and envelope through read parameters.
776: *
777: * @throws FactoryException
778: * @throws IOException
779: * @throws FileNotFoundException
780: */
781: private void getCoordinateReferenceSystemFromPrj()
782: throws FileNotFoundException, IOException {
783:
784: String prjPath = null;
785: if (source instanceof File) {
786: crs = null;
787: prjPath = new StringBuffer(this .parentPath).append(
788: File.separatorChar).append(this .coverageName)
789: .append(".prj").toString();
790: // read the prj info from the file
791: PrjFileReader projReader = null;
792: try {
793: final File prj = new File(prjPath);
794: if (prj.exists()) {
795: projReader = new PrjFileReader(new FileInputStream(
796: prj).getChannel());
797: crs = projReader.getCoordinateReferenceSystem();
798: }
799: } catch (FileNotFoundException e) {
800: // warn about the error but proceed, it is not fatal
801: // we have at least the default crs to use
802: LOGGER.log(Level.INFO, e.getLocalizedMessage(), e);
803: } catch (IOException e) {
804: // warn about the error but proceed, it is not fatal
805: // we have at least the default crs to use
806: LOGGER.log(Level.INFO, e.getLocalizedMessage(), e);
807: } catch (FactoryException e) {
808: // warn about the error but proceed, it is not fatal
809: // we have at least the default crs to use
810: LOGGER.log(Level.INFO, e.getLocalizedMessage(), e);
811: } finally {
812: if (projReader != null)
813: try {
814: projReader.close();
815: } catch (IOException e) {
816: // warn about the error but proceed, it is not fatal
817: // we have at least the default crs to use
818: LOGGER.log(Level.INFO, e.getLocalizedMessage(),
819: e);
820: }
821: }
822: }
823: }
824: }
|