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: /*
017: * NOTICE OF RELEASE TO THE PUBLIC DOMAIN
018: *
019: * This work was created by employees of the USDA Forest Service's
020: * Fire Science Lab for internal use. It is therefore ineligible for
021: * copyright under title 17, section 105 of the United States Code. You
022: * may treat it as you would treat any public domain work: it may be used,
023: * changed, copied, or redistributed, with or without permission of the
024: * authors, for free or for compensation. You may not claim exclusive
025: * ownership of this code because it is already owned by everyone. Use this
026: * software entirely at your own risk. No warranty of any kind is given.
027: *
028: * A copy of 17-USC-105 should have accompanied this distribution in the file
029: * 17USC105.html. If not, you may access the law via the US Government's
030: * public websites:
031: * - http://www.copyright.gov/title17/92chap1.html#105
032: * - http://www.gpoaccess.gov/uscode/ (enter "17USC105" in the search box.)
033: */
034: package org.geotools.gce.geotiff;
035:
036: import java.io.File;
037: import java.io.IOException;
038: import java.io.UnsupportedEncodingException;
039: import java.net.URL;
040: import java.net.URLDecoder;
041: import java.util.HashMap;
042: import java.util.logging.Level;
043: import java.util.logging.Logger;
044:
045: import javax.imageio.ImageIO;
046: import javax.imageio.ImageReader;
047: import javax.imageio.metadata.IIOMetadata;
048: import javax.imageio.stream.ImageInputStream;
049:
050: import org.geotools.coverage.grid.io.AbstractGridFormat;
051: import org.geotools.coverage.grid.io.imageio.GeoToolsWriteParams;
052: import org.geotools.data.DataSourceException;
053: import org.geotools.factory.Hints;
054: import org.geotools.gce.geotiff.IIOMetadataAdpaters.GeoTiffIIOMetadataDecoder;
055: import org.geotools.parameter.DefaultParameterDescriptorGroup;
056: import org.geotools.parameter.ParameterGroup;
057: import org.opengis.coverage.grid.Format;
058: import org.opengis.coverage.grid.GridCoverageReader;
059: import org.opengis.coverage.grid.GridCoverageWriter;
060: import org.opengis.parameter.GeneralParameterDescriptor;
061:
062: import com.sun.media.imageioimpl.plugins.tiff.TIFFImageReaderSpi;
063:
064: /**
065: * Provides basic information about the GeoTIFF format IO. This is currently an
066: * extension of the Geotools AbstractGridFormat because the stream and file GCEs
067: * will pick it up if it extends AbstractGridFormat.
068: *
069: * @author Bryce Nordgren, USDA Forest Service
070: * @author Simone Giannecchini
071: * @source $URL:
072: * http://svn.geotools.org/geotools/trunk/gt/plugin/geotiff/src/org/geotools/gce/geotiff/GeoTiffFormat.java $
073: */
074: public final class GeoTiffFormat extends AbstractGridFormat implements
075: Format {
076: private final static TIFFImageReaderSpi spi = new TIFFImageReaderSpi();
077:
078: /** Logger. */
079: private final static Logger LOGGER = org.geotools.util.logging.Logging
080: .getLogger("org.geotools.gce.geotiff");
081:
082: /**
083: * Creates a new instance of GeoTiffFormat
084: */
085: public GeoTiffFormat() {
086: writeParameters = null;
087: mInfo = new HashMap();
088: mInfo.put("name", "GeoTIFF");
089: mInfo.put("description",
090: "Tagged Image File Format with Geographic information");
091: mInfo.put("vendor", "Geotools");
092: mInfo.put("version", "1.1");
093: mInfo
094: .put("docURL",
095: "http://www.remotesensing.org:16080/websites/geotiff/geotiff.html");
096:
097: // reading parameters
098: readParameters = new ParameterGroup(
099: new DefaultParameterDescriptorGroup(
100: mInfo,
101: new GeneralParameterDescriptor[] { READ_GRIDGEOMETRY2D }));
102:
103: // writing parameters
104: writeParameters = new ParameterGroup(
105: new DefaultParameterDescriptorGroup(
106: mInfo,
107: new GeneralParameterDescriptor[] { AbstractGridFormat.GEOTOOLS_WRITE_PARAMS }));
108:
109: }
110:
111: /**
112: * Currently, we only accept files, and we open the file to verify that it
113: * has a GeoKeyDirectory tag. If anything more subtle is wrong with the
114: * file, we deal with that when we try and read it.
115: *
116: * @param o
117: * the source object to test for compatibility with this format.
118: *
119: *
120: * @return true if "o" is a File or a URL that points to a GeoTiff with a
121: * GeoTiff file as a resource.
122: */
123: public boolean accepts(Object o) {
124:
125: //
126: // if (o instanceof CatalogEntry) {
127: // o = ((CatalogEntry) o).resource();
128: // }
129: if (o == null) {
130: return false;
131: }
132: ImageReader reader = null;
133: ImageInputStream inputStream = null;
134: try {
135: if (o instanceof URL) {
136: // /////////////////////////////////////////////////////////////
137: //
138: // URL management
139: // In case the URL points to a file we need to get to the fie
140: // directly and avoid caching. In case it points to http or ftp
141: // or it is an opnen stream we have very small to do and we need
142: // to enable caching.
143: //
144: // /////////////////////////////////////////////////////////////
145: final URL url = (URL) o;
146: if (url.getProtocol().equalsIgnoreCase("file"))
147: o = new File(URLDecoder.decode(url.getFile(),
148: "UTF-8"));
149: else {
150: if (url.getProtocol().equalsIgnoreCase("http")
151: || url.getProtocol()
152: .equalsIgnoreCase("ftp")) {
153: o = ((URL) o).openStream();
154:
155: } else
156: return false;
157: }
158:
159: }
160: // get a stream
161: inputStream = (ImageInputStream) ((o instanceof ImageInputStream) ? o
162: : ImageIO.createImageInputStream(o));
163: if (inputStream == null) {
164: if (LOGGER.isLoggable(Level.FINE))
165: LOGGER.fine("Unable to get an ImageInputStream");
166: return false;
167: }
168:
169: // get a reader
170: inputStream.mark();
171: if (!spi.canDecodeInput(inputStream))
172: return false;
173: reader = spi.createReaderInstance();
174: reader.setInput(inputStream);
175: final IIOMetadata metadata = reader.getImageMetadata(0);
176: try {
177: final GeoTiffIIOMetadataDecoder metadataAdapter = new GeoTiffIIOMetadataDecoder(
178: metadata);
179:
180: if (metadataAdapter.getGeoKeyRevision() != 1) {
181: return false;
182: }
183: } catch (UnsupportedOperationException e) {
184: if (LOGGER.isLoggable(Level.FINE))
185: LOGGER.log(Level.FINE, e.getLocalizedMessage(), e);
186: return false;
187: } finally {
188: if (reader != null) {
189: reader.dispose();
190: }
191: if (inputStream != null) {
192: inputStream.close();
193: }
194: }
195:
196: } catch (IOException e) {
197: if (LOGGER.isLoggable(Level.FINE))
198: LOGGER.log(Level.FINE, e.getLocalizedMessage(), e);
199: return false;
200: }
201: return true;
202:
203: }
204:
205: /**
206: * If <CODE>source</CODE> is a file, this will return a reader object.
207: * This file does not use hints in the construction of the geotiff reader.
208: *
209: * @param source
210: * must be a GeoTiff File
211: *
212: * @return a GeoTiffReader object initialized to the specified File.
213: */
214: public GridCoverageReader getReader(Object source) {
215: return getReader(source, null);
216:
217: }
218:
219: /**
220: * If <CODE>source</CODE> is a file, this will return a reader object.
221: * This file does not use hints in the construction of the geotiff reader.
222: *
223: * @param source
224: * must be a GeoTiff File
225: * @param hints
226: * Hints to pass the hypothetic {@link GridCoverageReader} to
227: * control its behaviour.
228: *
229: * @return a GeoTiffReader object initialized to the specified File.
230: */
231: public GridCoverageReader getReader(Object source, Hints hints) {
232: // if (source instanceof CatalogEntry) {
233: // source = ((CatalogEntry) source).resource();
234: // }
235:
236: if (source instanceof URL) {
237: URL url = (URL) source;
238:
239: try {
240: final String pathname = URLDecoder.decode(
241: url.getFile(), "UTF-8");
242:
243: return new GeoTiffReader(new File(pathname), hints);
244: } catch (UnsupportedEncodingException e) {
245: if (LOGGER.isLoggable(Level.WARNING))
246: LOGGER.log(Level.WARNING, e.getLocalizedMessage(),
247: e);
248: return null;
249: } catch (DataSourceException e) {
250: if (LOGGER.isLoggable(Level.WARNING))
251: LOGGER.log(Level.WARNING, e.getLocalizedMessage(),
252: e);
253: return null;
254: }
255: }
256: try {
257: return new GeoTiffReader(source, hints);
258: } catch (DataSourceException e) {
259: if (LOGGER.isLoggable(Level.WARNING))
260: LOGGER.log(Level.WARNING, e.getLocalizedMessage(), e);
261: return null;
262: }
263:
264: }
265:
266: /**
267: * Retrieves a {@link GeoTiffWriter} or <code>null</code> if the provided
268: * <code>destination</code> is suitable.
269: *
270: * This file does not use hints in the construction of the geotiff reader.
271: *
272: * @param destination
273: * must be a GeoTiff File
274: * @param hints
275: * Hints to pass the hypothetic {@link GridCoverageReader} to
276: * control its behaviour.
277: *
278: * @return a GeoTiffReader object initialized to the specified File.
279: */
280: public GridCoverageWriter getWriter(Object destination, Hints hints) {
281: try {
282: return new GeoTiffWriter(destination, hints);
283: } catch (IOException e) {
284: if (LOGGER.isLoggable(Level.WARNING))
285: LOGGER.log(Level.WARNING, e.getLocalizedMessage(), e);
286: return null;
287: }
288: }
289:
290: /**
291: * Retrieves a {@link GeoTiffWriter} or <code>null</code> if the provided
292: * <code>destination</code> is suitable.
293: *
294: * This file does not use hints in the construction of the geotiff reader.
295: *
296: * @param destination
297: * must be a GeoTiff File
298: *
299: * @return a GeoTiffReader object initialized to the specified File.
300: */
301: public GridCoverageWriter getWriter(Object destination) {
302: try {
303: return new GeoTiffWriter(destination);
304: } catch (IOException e) {
305: if (LOGGER.isLoggable(Level.WARNING))
306: LOGGER.log(Level.WARNING, e.getLocalizedMessage(), e);
307: return null;
308: }
309: }
310:
311: /**
312: * Returns an instance of {@link GeoTiffWriteParams} for controlling an
313: * hypothetic writing process.
314: *
315: * @return an instance of {@link GeoTiffWriteParams}.
316: */
317: public GeoToolsWriteParams getDefaultImageIOWriteParameters() {
318: return new GeoTiffWriteParams();
319: }
320:
321: }
|