svn-gvsig-desktop / branches / org.gvsig.desktop-2018a / org.gvsig.desktop.compat.cdc / org.gvsig.basicformats / src / main / java / org / gvsig / basicformats / impl / DefaultHDRFile.java @ 43876
History | View | Annotate | Download (18.8 KB)
1 | 43876 | jjdelcerro | package org.gvsig.basicformats.impl; |
---|---|---|---|
2 | |||
3 | |||
4 | import java.io.File; |
||
5 | import java.io.IOException; |
||
6 | import java.nio.ByteOrder; |
||
7 | import java.util.List; |
||
8 | import org.apache.commons.io.FileUtils; |
||
9 | import org.apache.commons.io.FilenameUtils; |
||
10 | import org.apache.commons.lang3.StringUtils; |
||
11 | import org.gvsig.basicformats.HDRFile; |
||
12 | import org.gvsig.fmap.geom.Geometry; |
||
13 | import org.gvsig.fmap.geom.GeometryLocator; |
||
14 | import org.gvsig.fmap.geom.primitive.Envelope; |
||
15 | import org.gvsig.fmap.geom.primitive.Point; |
||
16 | import org.gvsig.raster.lib.buffer.api.BufferManager; |
||
17 | import org.slf4j.Logger; |
||
18 | import org.slf4j.LoggerFactory; |
||
19 | |||
20 | public class DefaultHDRFile implements HDRFile { |
||
21 | |||
22 | // http://resources.esri.com/help/9.3/arcgisdesktop/com/gp_toolref/spatial_analyst_tools/esri_ascii_raster_format.htm
|
||
23 | private static final Logger logger = LoggerFactory.getLogger(DefaultHDRFile.class); |
||
24 | |||
25 | private File source; |
||
26 | private String comments; |
||
27 | |||
28 | private int nrows = NONE; |
||
29 | private int ncols = NONE; |
||
30 | private int nbands = 1; |
||
31 | private int nbits = 8; |
||
32 | private String pixeltype; |
||
33 | private String byteorder_word; |
||
34 | private ByteOrder byteorder = ByteOrder.nativeOrder(); |
||
35 | private String layout = LAYOUT_BIL; |
||
36 | private int skipbytes = 0; |
||
37 | private double ulxmax = Double.NaN; |
||
38 | private double ulymax = Double.NaN; |
||
39 | private double xdim = Double.NaN; |
||
40 | private double ydim = Double.NaN; |
||
41 | private int bandrowbytes = NONE; |
||
42 | private int totalrowbytes = NONE; |
||
43 | private int bandgapbytes = 0; |
||
44 | private boolean valid = false; |
||
45 | private double nodata_value = Double.NaN; |
||
46 | |||
47 | // X coordinate of the origin (by center or lower left corner of the cell).
|
||
48 | private double xllcorner = Double.NaN; |
||
49 | |||
50 | // Y coordinate of the origin (by center or lower left corner of the cell).
|
||
51 | private double yllcorner = Double.NaN; |
||
52 | |||
53 | private int cellsize = NONE; |
||
54 | |||
55 | public DefaultHDRFile() {
|
||
56 | this.source = null; |
||
57 | } |
||
58 | |||
59 | @Override
|
||
60 | public File getFile(File file) { |
||
61 | File f = new File(FilenameUtils.removeExtension(file.getAbsolutePath()) + "." + FILE_EXTENSION); |
||
62 | return f;
|
||
63 | } |
||
64 | |||
65 | @Override
|
||
66 | public File getFile() { |
||
67 | return source;
|
||
68 | } |
||
69 | |||
70 | @Override
|
||
71 | public void read(File file) throws IOException { |
||
72 | File f = this.getFile(file); |
||
73 | if (f.exists()) {
|
||
74 | try {
|
||
75 | List<String> lines = FileUtils.readLines(f); |
||
76 | if (lines != null) { |
||
77 | this.source = f.getAbsoluteFile();
|
||
78 | int lineno = 1; |
||
79 | for (String line : lines) { |
||
80 | String[] words = StringUtils.split(line.trim().toLowerCase()); |
||
81 | try {
|
||
82 | switch (words[0]) { |
||
83 | case "nrows": |
||
84 | this.nrows = Integer.parseInt(words[1]); |
||
85 | break;
|
||
86 | case "ncols": |
||
87 | this.ncols = Integer.parseInt(words[1]); |
||
88 | break;
|
||
89 | case "nbands": |
||
90 | this.nbands = Integer.parseInt(words[1]); |
||
91 | break;
|
||
92 | case "nbits": |
||
93 | this.nbits = Integer.parseInt(words[1]); |
||
94 | break;
|
||
95 | case "pixeltype": |
||
96 | this.pixeltype = words[1]; |
||
97 | break;
|
||
98 | case "byteorder": |
||
99 | this.byteorder_word = words[1]; |
||
100 | break;
|
||
101 | case "layout": |
||
102 | this.layout = words[1]; |
||
103 | break;
|
||
104 | case "skipbytes": |
||
105 | this.skipbytes = Integer.parseInt(words[1]); |
||
106 | break;
|
||
107 | case "nodata_value": |
||
108 | this.nodata_value = Double.parseDouble(words[1]); |
||
109 | break;
|
||
110 | case "cellsize": |
||
111 | this.cellsize = Integer.parseInt(words[1]); |
||
112 | break;
|
||
113 | case "xllcorner": |
||
114 | case "xllcenter": |
||
115 | this.xllcorner = Double.parseDouble(words[1]); |
||
116 | break;
|
||
117 | case "yllcorner": |
||
118 | case "yllcenter": |
||
119 | this.yllcorner = Double.parseDouble(words[1]); |
||
120 | break;
|
||
121 | case "ulxmax": |
||
122 | this.ulxmax = Double.parseDouble(words[1]); |
||
123 | break;
|
||
124 | case "ulymax": |
||
125 | this.ulymax = Double.parseDouble(words[1]); |
||
126 | break;
|
||
127 | case "xdim": |
||
128 | this.xdim = Double.parseDouble(words[1]); |
||
129 | break;
|
||
130 | case "ydim": |
||
131 | this.ydim = Double.parseDouble(words[1]); |
||
132 | break;
|
||
133 | case "bandrowbytes": |
||
134 | this.bandrowbytes = Integer.parseInt(words[1]); |
||
135 | break;
|
||
136 | case "totalrowbytes": |
||
137 | this.totalrowbytes = Integer.parseInt(words[1]); |
||
138 | break;
|
||
139 | case "bandgapbytes": |
||
140 | this.bandgapbytes = Integer.parseInt(words[1]); |
||
141 | break;
|
||
142 | } |
||
143 | } catch (NumberFormatException e) { |
||
144 | logger.warn("Can't parse keyword '" + words[0] |
||
145 | + "' (value='" + words[1] |
||
146 | + "', lineno=+" + lineno
|
||
147 | + ", file=" + f.getAbsoluteFile()
|
||
148 | + ").", e);
|
||
149 | } |
||
150 | lineno++; |
||
151 | } |
||
152 | this.fixValues();
|
||
153 | } |
||
154 | |||
155 | } catch (IOException e) { |
||
156 | logger.warn("Couldn't read " + FILE_EXTENSION + " file (" + f.getAbsoluteFile() + ")", e); |
||
157 | throw e;
|
||
158 | } catch (Exception e) { |
||
159 | String msg = "Couldn't read " + FILE_EXTENSION + " file (" + f.getAbsoluteFile() + ")"; |
||
160 | logger.warn(msg, e); |
||
161 | throw new IOException(msg, e); |
||
162 | } |
||
163 | } |
||
164 | } |
||
165 | |||
166 | private void fixValues() { |
||
167 | @SuppressWarnings("LocalVariableHidesMemberVariable") |
||
168 | boolean valid = true; |
||
169 | |||
170 | if (this.pixeltype != null) { |
||
171 | switch (this.pixeltype) { |
||
172 | case "signedint": |
||
173 | this.nbits = 32; |
||
174 | break;
|
||
175 | case "byte_unsigned": |
||
176 | this.nbits = 8; |
||
177 | break;
|
||
178 | } |
||
179 | } |
||
180 | |||
181 | switch (this.getNbits()) { |
||
182 | case 1: |
||
183 | case 4: |
||
184 | logger.warn("nbits keyword has a non supported value of " + this.getNbits() + " (" + this.source.getAbsolutePath() + ")."); |
||
185 | valid = false;
|
||
186 | break;
|
||
187 | case 8: |
||
188 | case 16: |
||
189 | case 32: |
||
190 | case 64: |
||
191 | break;
|
||
192 | default:
|
||
193 | logger.warn("nbits keyword has an invalid value of " + this.getNbits() + " (" + this.source.getAbsolutePath() + ")."); |
||
194 | this.nbits = 1; |
||
195 | valid = false;
|
||
196 | break;
|
||
197 | } |
||
198 | |||
199 | switch (this.getLayout()) { |
||
200 | case LAYOUT_BIL:
|
||
201 | case LAYOUT_BIP:
|
||
202 | case LAYOUT_BSQ:
|
||
203 | break;
|
||
204 | default:
|
||
205 | logger.warn("layout keyword has an invalid value of '" + this.getLayout() + "' (" + this.source.getAbsolutePath() + ")."); |
||
206 | this.layout = LAYOUT_BIL;
|
||
207 | valid = false;
|
||
208 | break;
|
||
209 | } |
||
210 | |||
211 | if( StringUtils.isEmpty(this.byteorder_word) ) { |
||
212 | this.byteorder = ByteOrder.nativeOrder(); |
||
213 | if( this.byteorder == ByteOrder.BIG_ENDIAN ) { |
||
214 | this.byteorder_word = "msbfirst"; |
||
215 | } else {
|
||
216 | this.byteorder_word = "lsbfirst"; |
||
217 | } |
||
218 | } else {
|
||
219 | switch(this.byteorder_word) { |
||
220 | case "lsbfirst": |
||
221 | case "little_endian": |
||
222 | case "littleendian": |
||
223 | case "intel": |
||
224 | case "i": |
||
225 | this.byteorder = ByteOrder.LITTLE_ENDIAN; |
||
226 | break;
|
||
227 | case "motorola": |
||
228 | case "m": |
||
229 | case "msbfirst": |
||
230 | case "big_endian": |
||
231 | case "bigendian": |
||
232 | this.byteorder = ByteOrder.BIG_ENDIAN; |
||
233 | break;
|
||
234 | default:
|
||
235 | logger.warn("byteorder keyword has an invalid value of '" + this.byteorder_word + "' (" + this.source.getAbsolutePath() + ")."); |
||
236 | this.byteorder = ByteOrder.nativeOrder(); |
||
237 | } |
||
238 | } |
||
239 | if (this.getNrows() == NONE || this.getNcols() == NONE) { |
||
240 | logger.warn("nrows/ncols keywords has an invalid value of '" + this.getNrows() + "/" + this.getNcols() + "' (" + this.source.getAbsolutePath() + ")."); |
||
241 | valid = false;
|
||
242 | } |
||
243 | if (this.getUlymax() == NONE) { |
||
244 | this.ulymax = this.getNrows() - 1; |
||
245 | } |
||
246 | if (this.getBandrowbytes() == NONE) { |
||
247 | this.bandrowbytes = (this.getNcols() * this.getNbits()) / 8; |
||
248 | } |
||
249 | switch (this.getLayout()) { |
||
250 | case LAYOUT_BIL:
|
||
251 | if (this.getTotalrowbytes() == NONE) { |
||
252 | this.totalrowbytes = this.getNbands() * this.getBandrowbytes(); |
||
253 | } |
||
254 | this.bandgapbytes = 0; |
||
255 | break;
|
||
256 | case LAYOUT_BIP:
|
||
257 | if (this.getTotalrowbytes() == NONE) { |
||
258 | this.totalrowbytes = (this.getNcols() * this.getNbands() * this.getNbits()) / 8; |
||
259 | } |
||
260 | this.bandgapbytes = 0; |
||
261 | break;
|
||
262 | case LAYOUT_BSQ:
|
||
263 | if (this.getTotalrowbytes() == NONE) { |
||
264 | this.totalrowbytes = 0; |
||
265 | } |
||
266 | if (this.getBandgapbytes() == NONE) { |
||
267 | this.bandgapbytes = 0; |
||
268 | } |
||
269 | break;
|
||
270 | } |
||
271 | this.valid = valid;
|
||
272 | } |
||
273 | |||
274 | @Override
|
||
275 | public int getDataType() { |
||
276 | if (this.pixeltype != null) { |
||
277 | switch (this.pixeltype) { |
||
278 | case "signedint": |
||
279 | return BufferManager.TYPE_INT;
|
||
280 | case "byte_unsigned": |
||
281 | return BufferManager.TYPE_BYTE;
|
||
282 | } |
||
283 | } |
||
284 | switch (this.getNbits()) { |
||
285 | case 1: |
||
286 | case 4: |
||
287 | default:
|
||
288 | return BufferManager.TYPE_UNDEFINED;
|
||
289 | case 8: |
||
290 | return BufferManager.TYPE_BYTE;
|
||
291 | case 16: |
||
292 | return BufferManager.TYPE_USHORT;
|
||
293 | case 32: |
||
294 | return BufferManager.TYPE_INT;
|
||
295 | case 64: |
||
296 | return BufferManager.TYPE_DOUBLE;
|
||
297 | } |
||
298 | } |
||
299 | |||
300 | @Override
|
||
301 | public void write(File file) throws IOException { |
||
302 | File f = this.getFile(file); |
||
303 | StringBuilder builder = new StringBuilder(); |
||
304 | builder.append("; ").append(this.comments).append("\n"); |
||
305 | builder.append("nrows ").append(this.nrows).append("\n"); |
||
306 | builder.append("ncols ").append(this.ncols).append("\n"); |
||
307 | builder.append("nbands ").append(this.nbands).append("\n"); |
||
308 | builder.append("nbits ").append(this.nbits).append("\n"); |
||
309 | builder.append("layout ").append(LAYOUT_BSQ).append("\n"); |
||
310 | builder.append("byteorder ").append(this.byteorder_word).append("\n"); |
||
311 | builder.append("ulxmax ").append(this.ulxmax).append("\n"); |
||
312 | builder.append("ulymax ").append(this.ulymax).append("\n"); |
||
313 | builder.append("ydim ").append(this.ydim).append("\n"); |
||
314 | builder.append("xdim ").append(this.xdim).append("\n"); |
||
315 | |||
316 | FileUtils.write(file, builder.toString()); |
||
317 | } |
||
318 | |||
319 | @Override
|
||
320 | public void setByteOrder(ByteOrder order) { |
||
321 | this.byteorder = order;
|
||
322 | if( order == ByteOrder.BIG_ENDIAN ) { |
||
323 | this.byteorder_word = "msbfirst"; |
||
324 | } else {
|
||
325 | this.byteorder_word = "lsbfirst"; |
||
326 | } |
||
327 | } |
||
328 | |||
329 | @Override
|
||
330 | public void setNBands(int nbands) { |
||
331 | this.nbands = nbands;
|
||
332 | } |
||
333 | |||
334 | @Override
|
||
335 | public void setDataType(int dataType) { |
||
336 | switch(dataType) {
|
||
337 | case BufferManager.TYPE_BYTE:
|
||
338 | this.nbits = 8; |
||
339 | break;
|
||
340 | case BufferManager.TYPE_USHORT:
|
||
341 | this.nbits = 16; |
||
342 | break;
|
||
343 | case BufferManager.TYPE_INT:
|
||
344 | this.nbits = 32; |
||
345 | break;
|
||
346 | case BufferManager.TYPE_DOUBLE:
|
||
347 | this.nbits = 64; |
||
348 | break;
|
||
349 | default:
|
||
350 | throw new IllegalArgumentException("The data type "+dataType +" is not supported"); |
||
351 | } |
||
352 | |||
353 | } |
||
354 | |||
355 | @Override
|
||
356 | public void setDimensions(int nrows, int ncols, Envelope envelope) { |
||
357 | this.ncols = ncols;
|
||
358 | this.nrows = nrows;
|
||
359 | |||
360 | Point min = envelope.getLowerCorner();
|
||
361 | Point max = envelope.getUpperCorner();
|
||
362 | |||
363 | this.ulxmax = min.getX();
|
||
364 | this.ulymax = max.getY();
|
||
365 | this.ydim = (min.getY() - max.getY()) / this.nrows; |
||
366 | this.xdim = (max.getX() - min.getX()) / this.ncols; |
||
367 | } |
||
368 | |||
369 | @Override
|
||
370 | public Envelope getEnvelope() {
|
||
371 | Envelope envelope = null;
|
||
372 | try {
|
||
373 | if (!Double.isNaN(this.xllcorner) |
||
374 | && !Double.isNaN(this.yllcorner) |
||
375 | && this.cellsize > 0) { |
||
376 | envelope = GeometryLocator.getGeometryManager().createEnvelope( |
||
377 | this.xllcorner,
|
||
378 | this.yllcorner,
|
||
379 | this.xllcorner + (this.ncols * this.cellsize), |
||
380 | this.yllcorner + (this.nrows * this.cellsize), |
||
381 | Geometry.SUBTYPES.GEOM2D); |
||
382 | } |
||
383 | if (envelope == null && !Double.isNaN(this.ulxmax) |
||
384 | && !Double.isNaN(this.ulymax) |
||
385 | && !Double.isNaN(this.xdim) |
||
386 | && !Double.isNaN(this.ydim)) { |
||
387 | envelope = GeometryLocator.getGeometryManager().createEnvelope( |
||
388 | this.ulxmax,
|
||
389 | this.ulymax - (this.nrows * this.ydim), |
||
390 | this.ulxmax + (this.ncols * this.xdim), |
||
391 | this.ulymax,
|
||
392 | Geometry.SUBTYPES.GEOM2D); |
||
393 | } |
||
394 | if (envelope == null && !Double.isNaN(this.xdim) |
||
395 | && !Double.isNaN(this.ydim)) { |
||
396 | envelope = GeometryLocator.getGeometryManager().createEnvelope( |
||
397 | 0,
|
||
398 | 0,
|
||
399 | this.ncols * this.xdim, |
||
400 | this.nrows * this.ydim, |
||
401 | Geometry.SUBTYPES.GEOM2D); |
||
402 | } |
||
403 | if (envelope == null && this.cellsize > 0) { |
||
404 | envelope = GeometryLocator.getGeometryManager().createEnvelope( |
||
405 | 0,
|
||
406 | 0,
|
||
407 | this.ncols * this.cellsize, |
||
408 | this.nrows * this.cellsize, |
||
409 | Geometry.SUBTYPES.GEOM2D); |
||
410 | } |
||
411 | if (envelope == null) { |
||
412 | envelope = GeometryLocator.getGeometryManager().createEnvelope( |
||
413 | 0,
|
||
414 | 0,
|
||
415 | this.ncols,
|
||
416 | this.nrows,
|
||
417 | Geometry.SUBTYPES.GEOM2D); |
||
418 | } |
||
419 | } catch (Exception ex) { |
||
420 | logger.debug("Can't calculate envelope.", ex);
|
||
421 | } |
||
422 | return envelope;
|
||
423 | } |
||
424 | |||
425 | /**
|
||
426 | * @return the nrows
|
||
427 | */
|
||
428 | @Override
|
||
429 | public int getNrows() { |
||
430 | return nrows;
|
||
431 | } |
||
432 | |||
433 | /**
|
||
434 | * @return the ncols
|
||
435 | */
|
||
436 | @Override
|
||
437 | public int getNcols() { |
||
438 | return ncols;
|
||
439 | } |
||
440 | |||
441 | /**
|
||
442 | * @return the nbands
|
||
443 | */
|
||
444 | @Override
|
||
445 | public int getNbands() { |
||
446 | return nbands;
|
||
447 | } |
||
448 | |||
449 | /**
|
||
450 | * @return the nbits
|
||
451 | */
|
||
452 | @Override
|
||
453 | public int getNbits() { |
||
454 | return nbits;
|
||
455 | } |
||
456 | |||
457 | /**
|
||
458 | * @return the byteorder
|
||
459 | */
|
||
460 | @Override
|
||
461 | public ByteOrder getByteorder() { |
||
462 | return byteorder;
|
||
463 | } |
||
464 | |||
465 | /**
|
||
466 | * @return the layout
|
||
467 | */
|
||
468 | @Override
|
||
469 | public String getLayout() { |
||
470 | return layout;
|
||
471 | } |
||
472 | |||
473 | /**
|
||
474 | * @return the skipbytes
|
||
475 | */
|
||
476 | @Override
|
||
477 | public int getSkipbytes() { |
||
478 | return skipbytes;
|
||
479 | } |
||
480 | |||
481 | /**
|
||
482 | * @return the ulxmax
|
||
483 | */
|
||
484 | @Override
|
||
485 | public double getUlxmax() { |
||
486 | return ulxmax;
|
||
487 | } |
||
488 | |||
489 | /**
|
||
490 | * @return the ulymax
|
||
491 | */
|
||
492 | @Override
|
||
493 | public double getUlymax() { |
||
494 | return ulymax;
|
||
495 | } |
||
496 | |||
497 | /**
|
||
498 | * @return the xdim
|
||
499 | */
|
||
500 | @Override
|
||
501 | public double getXdim() { |
||
502 | return xdim;
|
||
503 | } |
||
504 | |||
505 | /**
|
||
506 | * @return the ydim
|
||
507 | */
|
||
508 | @Override
|
||
509 | public double getYdim() { |
||
510 | return ydim;
|
||
511 | } |
||
512 | |||
513 | /**
|
||
514 | * @return the bandrowbytes
|
||
515 | */
|
||
516 | @Override
|
||
517 | public int getBandrowbytes() { |
||
518 | return bandrowbytes;
|
||
519 | } |
||
520 | |||
521 | /**
|
||
522 | * @return the totalrowbytes
|
||
523 | */
|
||
524 | @Override
|
||
525 | public int getTotalrowbytes() { |
||
526 | return totalrowbytes;
|
||
527 | } |
||
528 | |||
529 | /**
|
||
530 | * @return the bandgapbytes
|
||
531 | */
|
||
532 | @Override
|
||
533 | public int getBandgapbytes() { |
||
534 | return bandgapbytes;
|
||
535 | } |
||
536 | |||
537 | /**
|
||
538 | * @return the isValid
|
||
539 | */
|
||
540 | @Override
|
||
541 | public boolean isValid() { |
||
542 | return valid;
|
||
543 | } |
||
544 | |||
545 | /**
|
||
546 | * @return the comments
|
||
547 | */
|
||
548 | @Override
|
||
549 | public String getComments() { |
||
550 | return comments;
|
||
551 | } |
||
552 | |||
553 | /**
|
||
554 | * @param comments the comments to set
|
||
555 | */
|
||
556 | @Override
|
||
557 | public void setComments(String comments) { |
||
558 | this.comments = comments;
|
||
559 | } |
||
560 | |||
561 | /**
|
||
562 | * @return the nodata_value
|
||
563 | */
|
||
564 | @Override
|
||
565 | public double getNodata_value() { |
||
566 | return nodata_value;
|
||
567 | } |
||
568 | |||
569 | /**
|
||
570 | * @return the xllcorner
|
||
571 | */
|
||
572 | @Override
|
||
573 | public double getXllcorner() { |
||
574 | return xllcorner;
|
||
575 | } |
||
576 | |||
577 | /**
|
||
578 | * @return the yllcorner
|
||
579 | */
|
||
580 | @Override
|
||
581 | public double getYllcorner() { |
||
582 | return yllcorner;
|
||
583 | } |
||
584 | |||
585 | /**
|
||
586 | * @return the cellsize
|
||
587 | */
|
||
588 | @Override
|
||
589 | public int getCellsize() { |
||
590 | return cellsize;
|
||
591 | } |
||
592 | |||
593 | @Override
|
||
594 | public int getBandSize() { |
||
595 | return (this.nrows * this.ncols * this.nbits) + this.bandgapbytes; |
||
596 | } |
||
597 | |||
598 | } |