1 |
alfonx |
244 |
/******************************************************************************* |
2 |
|
|
* Copyright (c) 2009 Martin O. J. Schmitz. |
3 |
|
|
* |
4 |
|
|
* This file is part of the SCHMITZM library - a collection of utility |
5 |
alfonx |
256 |
* classes based on Java 1.6, focusing (not only) on Java Swing |
6 |
alfonx |
244 |
* and the Geotools library. |
7 |
|
|
* |
8 |
|
|
* The SCHMITZM project is hosted at: |
9 |
|
|
* http://wald.intevation.org/projects/schmitzm/ |
10 |
|
|
* |
11 |
|
|
* This program is free software; you can redistribute it and/or |
12 |
|
|
* modify it under the terms of the GNU Lesser General Public License |
13 |
|
|
* as published by the Free Software Foundation; either version 3 |
14 |
|
|
* of the License, or (at your option) any later version. |
15 |
|
|
* |
16 |
|
|
* This program is distributed in the hope that it will be useful, |
17 |
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
18 |
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
19 |
|
|
* GNU General Public License for more details. |
20 |
|
|
* |
21 |
|
|
* You should have received a copy of the GNU Lesser General Public License (license.txt) |
22 |
|
|
* along with this program; if not, write to the Free Software |
23 |
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
24 |
|
|
* or try this link: http://www.gnu.org/licenses/lgpl.html |
25 |
|
|
* |
26 |
|
|
* Contributors: |
27 |
|
|
* Martin O. J. Schmitz - initial API and implementation |
28 |
|
|
* Stefan A. Krüger - additional utility classes |
29 |
|
|
******************************************************************************/ |
30 |
|
|
package skrueger.geotools.io; |
31 |
|
|
|
32 |
|
|
import java.awt.geom.Rectangle2D; |
33 |
|
|
import java.awt.image.BufferedImage; |
34 |
alfonx |
382 |
import java.io.File; |
35 |
alfonx |
244 |
import java.io.IOException; |
36 |
alfonx |
382 |
import java.io.InputStream; |
37 |
alfonx |
244 |
import java.net.URL; |
38 |
|
|
|
39 |
|
|
import javax.imageio.IIOException; |
40 |
|
|
import javax.imageio.ImageIO; |
41 |
|
|
|
42 |
|
|
import org.apache.log4j.Logger; |
43 |
|
|
import org.geotools.coverage.grid.GridCoverage2D; |
44 |
|
|
import org.geotools.coverage.grid.GridCoverageFactory; |
45 |
alfonx |
382 |
import org.geotools.data.DataUtilities; |
46 |
alfonx |
244 |
import org.geotools.factory.Hints; |
47 |
|
|
import org.geotools.gce.geotiff.GeoTiffReader; |
48 |
|
|
import org.geotools.geometry.Envelope2D; |
49 |
alfonx |
377 |
import org.opengis.parameter.GeneralParameterValue; |
50 |
alfonx |
244 |
import org.opengis.referencing.crs.CoordinateReferenceSystem; |
51 |
|
|
|
52 |
|
|
import schmitzm.geotools.io.GeoImportUtil; |
53 |
|
|
import schmitzm.io.IOUtil; |
54 |
|
|
|
55 |
|
|
/** |
56 |
alfonx |
377 |
* Erweiterungen von Martin's {@link GeoImportUtil} classe fuer die konsequente |
57 |
|
|
* Benutzung mit {@link URL}s. TODO Diese Klasse sollte vielleicht mit der |
58 |
|
|
* {@link GeoImportUtil} zusammengefuegt werden. |
59 |
|
|
* |
60 |
alfonx |
244 |
* @author <a href="mailto:[email protected]">Stefan Alfons Krüger</a> |
61 |
alfonx |
377 |
* |
62 |
alfonx |
244 |
*/ |
63 |
|
|
public class GeoImportUtilURL extends GeoImportUtil { |
64 |
alfonx |
377 |
final static private Logger LOGGER = Logger |
65 |
|
|
.getLogger(GeoImportUtilURL.class); |
66 |
alfonx |
244 |
|
67 |
|
|
/** |
68 |
alfonx |
377 |
* Read a {@link GridCoverage2D} from an image file. .prj and .wld files are |
69 |
|
|
* usually expected |
70 |
alfonx |
244 |
*/ |
71 |
|
|
public static GridCoverage2D readGridFromImage(URL url) throws IOException { |
72 |
|
|
return readGridFromImage(url, null); |
73 |
|
|
} |
74 |
|
|
|
75 |
|
|
/** |
76 |
alfonx |
377 |
* Read a {@link GridCoverage2D} from an image file. .wld file is usually |
77 |
|
|
* expected also. The CRS can be given as the crs parameter. null is valid. |
78 |
|
|
* |
79 |
|
|
* @author <a href="mailto:[email protected]">Martin Schmitz</a> |
80 |
|
|
* (University of Bonn/Germany) |
81 |
|
|
* @author <a href="mailto:[email protected]">Stefan Alfons |
82 |
|
|
* Krüger</a> |
83 |
alfonx |
244 |
*/ |
84 |
|
|
public static GridCoverage2D readGridFromImage(URL url, |
85 |
|
|
CoordinateReferenceSystem crs) throws IOException { |
86 |
|
|
GridCoverage2D gc = null; |
87 |
|
|
|
88 |
|
|
BufferedImage im = ImageIO.read(url); |
89 |
|
|
if (im == null) |
90 |
|
|
throw new IIOException("No image reader found for this image type!"); |
91 |
|
|
|
92 |
|
|
// World-File einlesen |
93 |
|
|
double[] tfwInfo = null; |
94 |
|
|
|
95 |
alfonx |
377 |
for (WORLD_POSTFIXES pf : WORLD_POSTFIXES.values()) { |
96 |
alfonx |
244 |
if (tfwInfo == null) { |
97 |
|
|
try { |
98 |
alfonx |
377 |
tfwInfo = readWorldFile(IOUtil.changeUrlExt(url, |
99 |
|
|
pf.toString()).openStream()); |
100 |
alfonx |
244 |
} catch (Exception e) { |
101 |
|
|
} |
102 |
|
|
} |
103 |
|
|
} |
104 |
|
|
|
105 |
|
|
if (tfwInfo == null) |
106 |
|
|
throw new IllegalArgumentException( |
107 |
|
|
"No georeferencing information found.\n" |
108 |
alfonx |
377 |
+ "Attach a .wld file to " + url + "please."); |
109 |
alfonx |
244 |
|
110 |
|
|
float w = (float) (im.getWidth() * tfwInfo[0]); // reale Breite = |
111 |
|
|
// RasterSpalten * |
112 |
|
|
// hor. Aufloesung |
113 |
|
|
float h = (float) (im.getHeight() * (-tfwInfo[3])); // reale Hoehe = |
114 |
|
|
// RasterZeilen |
115 |
|
|
// * vert. |
116 |
|
|
// Aufloesung |
117 |
|
|
float x = (float) tfwInfo[4]; // Suedwestliche Ecke! |
118 |
|
|
float y = (float) tfwInfo[5] - h; // Suedwestliche Ecke (im |
119 |
|
|
// tfw-File steht die |
120 |
|
|
// Nordwestliche!) |
121 |
|
|
// ggf. Projektion einlesen |
122 |
|
|
if (crs == null) { |
123 |
alfonx |
377 |
crs = determineProjection(IOUtil.changeUrlExt(url, "prj")); |
124 |
alfonx |
244 |
} |
125 |
|
|
Envelope2D envelope = new Envelope2D(crs, new Rectangle2D.Float(x, y, |
126 |
|
|
w, h)); |
127 |
|
|
// WICHTIG: Name des Rasters sollte Leer-String sein, da ansonsten |
128 |
|
|
// das |
129 |
|
|
// Coloring des Rasters nicht klappt. |
130 |
alfonx |
377 |
// --> Name der Categories und ColorMapEntries-Labels muss (warum auch |
131 |
|
|
// immer) mit dem Namen |
132 |
alfonx |
244 |
// des Rasters uebereinstimmen!!! |
133 |
|
|
gc = new GridCoverageFactory().create("", im, envelope); |
134 |
|
|
|
135 |
|
|
return gc; |
136 |
|
|
} |
137 |
|
|
|
138 |
|
|
/** |
139 |
alfonx |
377 |
* @param input |
140 |
|
|
* URL, File oder InputStream to a GeoTIFF-File |
141 |
alfonx |
244 |
* @param crs |
142 |
|
|
* erzwungenes CoordinateReferenceSystem fuer das Raster (kann |
143 |
|
|
* {@code null} sein) |
144 |
alfonx |
377 |
* |
145 |
alfonx |
244 |
* @author <a href="mailto:[email protected]">Martin Schmitz</a> |
146 |
|
|
* (University of Bonn/Germany) |
147 |
alfonx |
377 |
* @author <a href="mailto:[email protected]">Stefan Alfons |
148 |
|
|
* Krüger</a> |
149 |
|
|
* |
150 |
|
|
* @param readParams |
151 |
|
|
* May be {@link NullPointerException}. Otherwise an array of |
152 |
|
|
* {@link GeneralParameterValue}s |
153 |
alfonx |
244 |
*/ |
154 |
alfonx |
377 |
public static GridCoverage2D readGridFromGeoTiff(Object input, |
155 |
|
|
CoordinateReferenceSystem crs, GeneralParameterValue[] readParams) |
156 |
|
|
throws IOException { |
157 |
alfonx |
244 |
GridCoverage2D gc = null; |
158 |
alfonx |
377 |
LOGGER.debug("Loading GeoTiff from URL = " + input + " now."); |
159 |
alfonx |
244 |
|
160 |
|
|
// Versuchen Geo-Information aus Tiff zu lesen |
161 |
|
|
|
162 |
alfonx |
377 |
// Wenn CRS angegeben, dieses durch Hint erzwingen |
163 |
|
|
Hints hints = new Hints(); |
164 |
alfonx |
244 |
|
165 |
alfonx |
377 |
if (crs != null) |
166 |
|
|
hints.put(Hints.DEFAULT_COORDINATE_REFERENCE_SYSTEM, crs); |
167 |
|
|
// Reader (mit Metadaten) erzeugen |
168 |
alfonx |
244 |
|
169 |
alfonx |
377 |
LOGGER.debug("First try to create GeoTiff reader"); |
170 |
alfonx |
244 |
|
171 |
alfonx |
377 |
/** |
172 |
|
|
* Attention, Attention: The GeoTiffReader fails for URLs like: |
173 |
|
|
* |
174 |
|
|
* jar:file:/home/sdsd/ad/atlas/raster_textur00949608497.jar!/ad/data/ |
175 |
|
|
* raster_textur00949608497/textur.tif |
176 |
|
|
* |
177 |
|
|
* It should be converted to something like: |
178 |
|
|
* jar:http:///atlas/raster_textur00949608497 |
179 |
|
|
* .jar!/ad/data/raster_textur00949608497/textur.tif |
180 |
|
|
* jar:http://www.wikisquare |
181 |
|
|
* .de/atlas/raster_textur00949608497.jar!/ad/data |
182 |
|
|
* /raster_textur00949608497/textur.tif |
183 |
|
|
*/ |
184 |
alfonx |
244 |
|
185 |
alfonx |
382 |
try { |
186 |
|
|
|
187 |
|
|
GeoTiffReader reader = new GeoTiffReader(input, hints); |
188 |
|
|
|
189 |
|
|
gc = (GridCoverage2D) reader.read(readParams); |
190 |
|
|
LOGGER.debug("... was successfull!"); |
191 |
|
|
return gc; |
192 |
|
|
} catch (Exception e) { |
193 |
|
|
// keine Geo-Informationen in Tiff |
194 |
|
|
// --> Raster ueber ImageIO einlesen und WorldFile/ProjectionFile |
195 |
|
|
// verwenden |
196 |
|
|
LOGGER.warn("No geo information found in '" + input |
197 |
|
|
+ "'. Using world- and prj-file..."); |
198 |
|
|
|
199 |
|
|
BufferedImage im = null; |
200 |
|
|
double[] tfwInfo = null ; |
201 |
|
|
if (input instanceof File) { |
202 |
|
|
im = ImageIO.read((File) input); |
203 |
|
|
tfwInfo = readWorldFile(IOUtil.changeFileExt((File)input, "tfw")); |
204 |
|
|
if (crs == null) |
205 |
|
|
crs = determineProjection((File)input); |
206 |
|
|
} else if (input instanceof URL) { |
207 |
|
|
tfwInfo = readWorldFile(IOUtil.changeUrlExt((URL)input, "tfw").openStream()); |
208 |
|
|
im = ImageIO.read((URL) input); |
209 |
|
|
if (crs == null) |
210 |
|
|
crs = determineProjection((URL)input); |
211 |
|
|
} |
212 |
|
|
|
213 |
|
|
if (im == null) |
214 |
|
|
throw new IIOException( |
215 |
|
|
"No image reader found for this image type!"); |
216 |
|
|
// World-File einlesen |
217 |
|
|
|
218 |
|
|
float w = (float) (im.getWidth() * tfwInfo[0]); // reale Breite = |
219 |
|
|
// RasterSpalten * hor. |
220 |
|
|
// Aufloesung |
221 |
|
|
float h = (float) (im.getHeight() * (-tfwInfo[3])); // reale Hoehe = |
222 |
|
|
// RasterZeilen * |
223 |
|
|
// vert. Aufloesung |
224 |
|
|
float x = (float) tfwInfo[4]; // Suedwestliche Ecke! |
225 |
|
|
float y = (float) tfwInfo[5] - h; // Suedwestliche Ecke (im tfw-File |
226 |
|
|
// steht die Nordwestliche!) |
227 |
|
|
// ggf. Projektion einlesen |
228 |
|
|
Envelope2D envelope = new Envelope2D(crs, new Rectangle2D.Float(x, |
229 |
|
|
y, w, h)); |
230 |
|
|
// WICHTIG: Name des Rasters sollte Leer-String sein, da ansonsten |
231 |
|
|
// das |
232 |
|
|
// Coloring des Rasters nicht klappt. |
233 |
|
|
// --> Name der Categories muss (warum auch immer) mit dem Namen |
234 |
|
|
// des Rasters uebereinstimmen!!! |
235 |
|
|
gc = new GridCoverageFactory().create("", im.copyData(null), |
236 |
|
|
envelope); |
237 |
|
|
return gc; |
238 |
|
|
} |
239 |
alfonx |
244 |
} |
240 |
|
|
|
241 |
alfonx |
377 |
// |
242 |
|
|
// ArcGridRaster reader = new ArcGridRaster(new BufferedReader( |
243 |
|
|
// new InputStreamReader(url.openStream())), false); |
244 |
|
|
// WritableRaster raster = reader.readRaster(); |
245 |
|
|
// if (crs == null) |
246 |
|
|
// crs = determineProjection(IOUtil.changeUrlExt(url, "prj")); |
247 |
|
|
// |
248 |
|
|
// LOGGER.debug("Position " + reader.getXlCorner() + " / " |
249 |
|
|
// + reader.getYlCorner()); |
250 |
|
|
// LOGGER.debug("Size " + reader.getNCols() + " / " |
251 |
|
|
// + reader.getNRows()); |
252 |
|
|
// LOGGER.debug("Min/Max " + reader.getMinValue() + " / " |
253 |
|
|
// + reader.getMaxValue()); |
254 |
|
|
// LOGGER.debug("NoData " + reader.getNoData()); |
255 |
|
|
// LOGGER.debug("CellSize " + reader.getCellSize()); |
256 |
|
|
// |
257 |
|
|
// Double x = reader.getXlCorner(); // Suedwestliche Ecke! |
258 |
|
|
// Double y = reader.getYlCorner(); // Suedwestliche Ecke! |
259 |
|
|
// if (y.isNaN() || x.isNaN()) { |
260 |
|
|
// throw new IllegalArgumentException( |
261 |
|
|
// "The parameters xlCorner and/or ylCorner could not be read. Hint: Check if the file defines 'xlcenter' instead of 'xlcorner'. If so, just replace all 'center' with 'corner' and try again."); |
262 |
|
|
// } |
263 |
|
|
// |
264 |
|
|
// Double w = (reader.getNCols() * reader.getCellSize()); // reale Breite = |
265 |
|
|
// // RasterSpalten |
266 |
|
|
// // * Aufloesung |
267 |
|
|
// Double h = (reader.getNRows() * reader.getCellSize()); // reale Hoehe = |
268 |
|
|
// // RasterZeilen |
269 |
|
|
// // * Aufloesung |
270 |
|
|
// Envelope2D envelope = new Envelope2D(crs, new Rectangle2D.Double(x, y, |
271 |
|
|
// w, h)); |
272 |
|
|
// |
273 |
|
|
// // WICHTIG: Name des Rasters sollte Leer-String sein, da ansonsten das |
274 |
|
|
// // Coloring des Rasters nicht klappt. |
275 |
|
|
// // --> Name der Categories muss (warum auch immer) mit dem Namen |
276 |
|
|
// // des Rasters uebereinstimmen!!! |
277 |
|
|
// return new GridCoverageFactory().create("", raster, envelope); |
278 |
|
|
// // |
279 |
|
|
// // === OHNE ArcGridRaster === |
280 |
|
|
// // // ArcGridReader reader = new ArcGridReader( new BufferedReader( new |
281 |
|
|
// // InputStreamReader( new FileInputStream(file) ) )); |
282 |
|
|
// // ArcGridReader reader = new ArcGridReader( file ); |
283 |
|
|
// // return (GridCoverage2D)reader.read(null); |
284 |
alfonx |
244 |
|
285 |
|
|
} |