Revision 13130
trunk/libraries/libCresques/src/org/cresques/io/data/Metadata.java | ||
---|---|---|
29 | 29 |
|
30 | 30 |
/** |
31 | 31 |
* Guarda en un Array los metadatos de los distintos tipos de imagenes. |
32 |
*
|
|
32 |
* |
|
33 | 33 |
* NODATA_VALUES=255 255 255 1 |
34 | 34 |
* AREA_OR_POINT=Point 4 |
35 | 35 |
* TIFFTAG_XRESOLUTION=72 4 |
36 | 36 |
* TIFFTAG_YRESOLUTION=72 4 |
37 | 37 |
* TIFFTAG_RESOLUTIONUNIT=2 (pixels/inch) 4 |
38 |
*
|
|
38 |
* |
|
39 | 39 |
* STATISTICS_MINIMUM=0 |
40 | 40 |
* STATISTICS_MAXIMUM=221 |
41 | 41 |
* STATISTICS_MEAN=35.910196078431 |
... | ... | |
47 | 47 |
* STATISTICS_HISTOMAX=255 |
48 | 48 |
* LAYER_TYPE=athematic |
49 | 49 |
* STATISTICS_HISTOBINVALUES=30285675|0|0|22050| ... |
50 |
*
|
|
50 |
* |
|
51 | 51 |
* @author Nacho Brodin (brodin_ign@gva.es) |
52 | 52 |
*/ |
53 | 53 |
public class Metadata{ |
... | ... | |
75 | 75 |
* Metadatos |
76 | 76 |
*/ |
77 | 77 |
private String[] metadataString = null; |
78 |
|
|
78 |
|
|
79 | 79 |
public Metadata(String[] metadata){ |
80 | 80 |
metadataString = metadata; |
81 | 81 |
for(int i = 0;i<metadata.length;i++){ |
... | ... | |
84 | 84 |
this.values.add(value[1]); |
85 | 85 |
} |
86 | 86 |
} |
87 |
|
|
87 |
|
|
88 | 88 |
/** |
89 | 89 |
* Crea un objeto TransparencyRange a partir de los rangos de transparencia |
90 | 90 |
* @return |
... | ... | |
93 | 93 |
int bandR = getBand("Red"); |
94 | 94 |
int bandG = getBand("Green"); |
95 | 95 |
int bandB = getBand("Blue"); |
96 |
|
|
96 |
|
|
97 | 97 |
if(bandR < 0 && bandG < 0 && bandB < 0) |
98 | 98 |
return null; |
99 |
|
|
99 |
|
|
100 | 100 |
//Esta comprobaci?n es para los raster con paleta (gif). Cuando se trate la paleta y no se usen como |
101 | 101 |
//imagenes de una banda habr? que cambiar esto |
102 | 102 |
if((colorInterpretation.length == 1) && colorInterpretation[0].equals("Palette")) |
103 | 103 |
return null; |
104 |
|
|
104 |
|
|
105 | 105 |
if(noDataByBand == null) |
106 | 106 |
return null; |
107 |
|
|
108 |
//Si todos los valores nodata por banda son -1 es que no hay ninguno asignado
|
|
107 |
|
|
108 |
//Si todos los valores nodata por banda son -1 es que no hay ninguno asignado |
|
109 | 109 |
int count =0; |
110 | 110 |
for(int i = 0; i < noDataByBand.length; i++) |
111 | 111 |
if(noDataByBand[i] < 0) |
112 | 112 |
count ++; |
113 |
|
|
113 |
|
|
114 | 114 |
if(count == noDataByBand.length) |
115 | 115 |
return null; |
116 |
|
|
116 |
|
|
117 | 117 |
TransparencyRange tr = new TransparencyRange(); |
118 | 118 |
int[] red = new int[2]; |
119 | 119 |
int[] green = new int[2]; |
120 | 120 |
int[] blue = new int[2]; |
121 |
|
|
121 |
|
|
122 | 122 |
if(bandR >= 0){ |
123 | 123 |
red[0] = red[1] = (int)noDataByBand[bandR]; |
124 | 124 |
tr.setRed(red); |
... | ... | |
131 | 131 |
blue[0] = blue[1] = (int)noDataByBand[bandB]; |
132 | 132 |
tr.setBlue(blue); |
133 | 133 |
} |
134 |
|
|
134 |
|
|
135 | 135 |
tr.setAnd(true); |
136 | 136 |
tr.loadStrEntryFromValues(); |
137 |
|
|
137 |
|
|
138 | 138 |
return tr; |
139 | 139 |
} |
140 |
|
|
140 |
|
|
141 | 141 |
/** |
142 |
* Parsea los metadatos NODATA_VALUES si existe alguno y devuelve un objeto TransparencyRange.
|
|
142 |
* Parsea los metadatos NODATA_VALUES si existe alguno y devuelve un objeto TransparencyRange. |
|
143 | 143 |
* @param nodata |
144 | 144 |
* @return Vector de enteros con los valores RGBA o null si no tiene este metadato o no es parseable |
145 | 145 |
* en este formato. |
... | ... | |
149 | 149 |
//imagenes de una banda habr? que cambiar esto |
150 | 150 |
if((colorInterpretation.length == 1) && colorInterpretation[0].equals("Palette")) |
151 | 151 |
return null; |
152 |
|
|
152 |
|
|
153 | 153 |
int count = 0; |
154 | 154 |
for(int i = 0; i < metadata.size(); i++){ |
155 | 155 |
if(((String)metadata.get(i)).equals("NODATA_VALUES")) |
... | ... | |
157 | 157 |
} |
158 | 158 |
if(count == 0) |
159 | 159 |
return null; |
160 |
|
|
160 |
|
|
161 | 161 |
TransparencyRange[] trList = new TransparencyRange[count]; |
162 |
|
|
162 |
|
|
163 | 163 |
count = 0; |
164 | 164 |
for(int i = 0; i < metadata.size(); i++){ |
165 | 165 |
TransparencyRange tr = new TransparencyRange(); |
166 | 166 |
int[] red = new int[2]; |
167 | 167 |
int[] green = new int[2]; |
168 | 168 |
int[] blue = new int[2]; |
169 |
|
|
169 |
|
|
170 | 170 |
if(((String)metadata.get(i)).equals("NODATA_VALUES")){ |
171 | 171 |
String data = (String)values.get(i); |
172 | 172 |
String[] dataValues = data.split(" "); |
173 |
int[] values = new int[dataValues.length]; |
|
174 | 173 |
try{ |
175 | 174 |
red[0] = red[1] = Integer.parseInt(dataValues[0]); |
176 | 175 |
green[0] = green[1] = Integer.parseInt(dataValues[1]); |
... | ... | |
187 | 186 |
trList[count] = tr; |
188 | 187 |
count ++; |
189 | 188 |
} |
190 |
|
|
189 |
|
|
191 | 190 |
return trList; |
192 | 191 |
} |
193 |
|
|
192 |
|
|
194 | 193 |
/** |
195 |
* Inicializa el vector de cadenas que contendr?n el nombre de la interpretaci?n
|
|
194 |
* Inicializa el vector de cadenas que contendr?n el nombre de la interpretaci?n |
|
196 | 195 |
* de color asignada a cada banda. Este valor es el devuelto por la imagen. |
197 | 196 |
* @param values N?mero de valores |
198 | 197 |
*/ |
199 | 198 |
public void initColorInterpretation(int values){ |
200 | 199 |
colorInterpretation = new String[values]; |
201 | 200 |
} |
202 |
|
|
201 |
|
|
203 | 202 |
/** |
204 | 203 |
* Asigna un valor para la interpretaci?n de color de una banda |
205 |
* @param band Banda
|
|
204 |
* @param band Banda |
|
206 | 205 |
* @param value valor |
207 | 206 |
*/ |
208 | 207 |
public void setColorInterpValue(int band, String value){ |
... | ... | |
214 | 213 |
//No asignamos el elemento |
215 | 214 |
} |
216 | 215 |
} |
217 |
|
|
216 |
|
|
218 | 217 |
/** |
219 |
* Obtiene la posici?n de la banda que contiene el identificador pasado por par?metro
|
|
218 |
* Obtiene la posici?n de la banda que contiene el identificador pasado por par?metro |
|
220 | 219 |
* o -1 si no tiene dicho identificador. |
221 | 220 |
* @return Posici?n de la banda que contiene el identificador o -1 si no lo tiene. |
222 | 221 |
*/ |
... | ... | |
236 | 235 |
public boolean isAlphaBand() { |
237 | 236 |
return isAlphaBand; |
238 | 237 |
} |
239 |
|
|
238 |
|
|
240 | 239 |
/** |
241 | 240 |
* Inicializa los valores no data; |
242 | 241 |
* @param values |
... | ... | |
246 | 245 |
for(int i = 0; i < values; i++) |
247 | 246 |
noDataByBand[i] = -1; |
248 | 247 |
} |
249 |
|
|
248 |
|
|
250 | 249 |
/** |
251 | 250 |
* Asigna un valor para el valor noData por banda |
252 |
* @param band Banda
|
|
251 |
* @param band Banda |
|
253 | 252 |
* @param value valor |
254 | 253 |
*/ |
255 | 254 |
public void setNoDataValue(int band, double value){ |
... | ... | |
267 | 266 |
public String[] getMetadataString() { |
268 | 267 |
return metadataString; |
269 | 268 |
} |
270 |
|
|
269 |
|
|
271 | 270 |
} |
trunk/libraries/libCresques/src/org/cresques/io/GeoRasterFile.java | ||
---|---|---|
1 | 1 |
/* |
2 | 2 |
* Cresques Mapping Suite. Graphic Library for constructing mapping applications. |
3 |
* |
|
4 |
* Copyright (C) 2004-5. |
|
5 | 3 |
* |
4 |
* Copyright (C) 2004-5. |
|
5 |
* |
|
6 | 6 |
* This program is free software; you can redistribute it and/or |
7 | 7 |
* modify it under the terms of the GNU General Public License |
8 | 8 |
* as published by the Free Software Foundation; either version 2 |
... | ... | |
18 | 18 |
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,USA. |
19 | 19 |
* |
20 | 20 |
* For more information, contact: |
21 |
*
|
|
21 |
* |
|
22 | 22 |
* cresques@gmail.com |
23 | 23 |
*/ |
24 | 24 |
package org.cresques.io; |
... | ... | |
55 | 55 |
|
56 | 56 |
/** |
57 | 57 |
* Manejador de ficheros raster georeferenciados. |
58 |
*
|
|
58 |
* |
|
59 | 59 |
* Esta clase abstracta es el ancestro de todas las clases que proporcionan |
60 | 60 |
* soporte para ficheros raster georeferenciados.<br> |
61 | 61 |
* Actua tambien como una 'Fabrica', ocultando al cliente la manera en que |
62 | 62 |
* se ha implementado ese manejo. Una clase nueva que soportara un nuevo |
63 | 63 |
* tipo de raster tendr?a que registrar su extensi?n o extensiones usando |
64 |
* el m?todo @see registerExtension.<br>
|
|
64 |
* el m?todo @see registerExtension.<br> |
|
65 | 65 |
* @author "Luis W. Sevilla" <sevilla_lui@gva.es>* |
66 | 66 |
*/ |
67 | 67 |
|
68 | 68 |
public abstract class GeoRasterFile extends GeoFile { |
69 |
|
|
69 |
|
|
70 | 70 |
/** |
71 | 71 |
* Flag que representa a la banda del Rojo |
72 | 72 |
*/ |
73 | 73 |
public static final int RED_BAND = 0x01; |
74 |
|
|
74 |
|
|
75 | 75 |
/** |
76 | 76 |
* Flag que representa a la banda del Verde |
77 | 77 |
*/ |
78 | 78 |
public static final int GREEN_BAND = 0x02; |
79 |
|
|
79 |
|
|
80 | 80 |
/** |
81 | 81 |
* Flag que representa a la banda del Azul |
82 | 82 |
*/ |
... | ... | |
90 | 90 |
* de la identidad si la funci?n rmfExists() devuelve true. |
91 | 91 |
*/ |
92 | 92 |
protected AffineTransform rmfTransform = new AffineTransform(); |
93 |
|
|
93 |
|
|
94 | 94 |
/** |
95 | 95 |
* Filtro para raster. |
96 | 96 |
* Permite eliminar la franja inutil alrededor de un raster girado o de |
97 | 97 |
* un mosaico de borde irregular. |
98 |
*
|
|
98 |
* |
|
99 | 99 |
* Funciona bien solo con raster en tonos de gris, porque se basa que |
100 | 100 |
* el valor del pixel no supere un determinado valor 'umbral' que se |
101 | 101 |
* le pasa al constructor. |
102 |
*
|
|
102 |
* |
|
103 | 103 |
* Desarrollado para 'limpiar' los bordes de los mosaicos del SIG |
104 | 104 |
* Oleicola. Para ese caso los par?metros del constructo son: |
105 | 105 |
* PixelFilter(0x10ffff00, 0xff000000, 0xf0f0f0); |
106 | 106 |
*/ |
107 | 107 |
protected PixelFilter tFilter = null; |
108 |
|
|
108 |
|
|
109 | 109 |
/** |
110 | 110 |
* Asignaci?n de banda del Rojo a una banda de la imagen |
111 | 111 |
*/ |
112 | 112 |
protected int rBandNr = 1; |
113 |
|
|
113 |
|
|
114 | 114 |
/** |
115 | 115 |
* Asignaci?n de banda del Verde a una banda de la imagen |
116 | 116 |
*/ |
117 | 117 |
protected int gBandNr = 1; |
118 |
|
|
118 |
|
|
119 | 119 |
/** |
120 | 120 |
* Asignaci?n de banda del Azul a una banda de la imagen |
121 | 121 |
*/ |
122 | 122 |
protected int bBandNr = 1; |
123 |
|
|
123 |
|
|
124 | 124 |
/** |
125 | 125 |
* N?mero de bandas de la imagen |
126 | 126 |
*/ |
... | ... | |
139 | 139 |
supportedExtensions = new TreeMap(); |
140 | 140 |
supportedExtensions.put("ecw", EcwFile.class); |
141 | 141 |
supportedExtensions.put("jp2", EcwFile.class); |
142 |
|
|
142 |
|
|
143 | 143 |
supportedExtensions.put("sid", MrSidFile.class); |
144 | 144 |
|
145 | 145 |
supportedExtensions.put("bmp", GdalFile.class); |
... | ... | |
153 | 153 |
//supportedExtensions.put("png", TifGeoRefFile.class); |
154 | 154 |
//supportedExtensions.put("dat", GdalFile.class); |
155 | 155 |
} |
156 |
|
|
156 |
|
|
157 | 157 |
/** |
158 | 158 |
* Factoria para abrir distintos tipos de raster. |
159 |
*
|
|
159 |
* |
|
160 | 160 |
* @param proj Proyecci?n en la que est? el raster. |
161 | 161 |
* @param fName Nombre del fichero. |
162 | 162 |
* @return GeoRasterFile, o null si hay problemas. |
... | ... | |
187 | 187 |
} catch (InvocationTargetException e) { |
188 | 188 |
e.printStackTrace(); |
189 | 189 |
} |
190 |
|
|
190 |
|
|
191 | 191 |
return grf; |
192 | 192 |
} |
193 |
|
|
193 |
|
|
194 | 194 |
/** |
195 | 195 |
* Registra una clase que soporta una extensi?n raster. |
196 | 196 |
* @param ext extensi?n soportada. |
... | ... | |
201 | 201 |
System.out.println("RASTER: extension '"+ext+"' supported."); |
202 | 202 |
supportedExtensions.put(ext, clase); |
203 | 203 |
} |
204 |
|
|
204 |
|
|
205 | 205 |
/** |
206 | 206 |
* Tipo de fichero soportado. |
207 | 207 |
* Devuelve true si el tipo de fichero (extension) est? soportado, si no |
208 | 208 |
* devuelve false. |
209 |
*
|
|
209 |
* |
|
210 | 210 |
* @param fName Fichero raster |
211 | 211 |
* @return true si est? soportado, si no false. |
212 |
*/
|
|
212 |
*/
|
|
213 | 213 |
public static boolean fileIsSupported(String fName) { |
214 | 214 |
String ext = fName.toLowerCase().substring(fName.lastIndexOf('.')+1); |
215 | 215 |
return supportedExtensions.containsKey(ext); |
216 | 216 |
} |
217 |
|
|
217 |
|
|
218 | 218 |
/** |
219 | 219 |
* Constructor |
220 | 220 |
* @param proj Proyecci?n |
... | ... | |
223 | 223 |
public GeoRasterFile(IProjection proj, String name) { |
224 | 224 |
super(proj, name); |
225 | 225 |
} |
226 |
|
|
226 |
|
|
227 | 227 |
/** |
228 |
* Carga un fichero raster. Puede usarse para calcular el extent e instanciar
|
|
228 |
* Carga un fichero raster. Puede usarse para calcular el extent e instanciar |
|
229 | 229 |
* un objeto de este tipo. |
230 | 230 |
*/ |
231 | 231 |
abstract public GeoFile load(); |
232 |
|
|
232 |
|
|
233 | 233 |
/** |
234 | 234 |
* Cierra el fichero y libera los recursos. |
235 | 235 |
*/ |
236 | 236 |
abstract public void close(); |
237 |
|
|
237 |
|
|
238 | 238 |
/** |
239 | 239 |
* Obtiene la codificaci?n del fichero XML |
240 | 240 |
* @param file Nombre del fichero XML |
... | ... | |
244 | 244 |
FileReader fr; |
245 | 245 |
String encoding = null; |
246 | 246 |
try |
247 |
{
|
|
247 |
{
|
|
248 | 248 |
fr = new FileReader(file); |
249 |
BufferedReader br = new BufferedReader(fr);
|
|
250 |
char[] buffer = new char[100];
|
|
251 |
br.read(buffer);
|
|
252 |
StringBuffer st = new StringBuffer(new String(buffer));
|
|
253 |
String searchText = "encoding=\"";
|
|
254 |
int index = st.indexOf(searchText);
|
|
255 |
if (index>-1) {
|
|
256 |
st.delete(0, index+searchText.length());
|
|
257 |
encoding = st.substring(0, st.indexOf("\""));
|
|
258 |
}
|
|
259 |
fr.close();
|
|
260 |
} catch(FileNotFoundException ex) {
|
|
261 |
ex.printStackTrace();
|
|
262 |
} catch (IOException e) {
|
|
249 |
BufferedReader br = new BufferedReader(fr);
|
|
250 |
char[] buffer = new char[100];
|
|
251 |
br.read(buffer);
|
|
252 |
StringBuffer st = new StringBuffer(new String(buffer));
|
|
253 |
String searchText = "encoding=\"";
|
|
254 |
int index = st.indexOf(searchText);
|
|
255 |
if (index>-1) {
|
|
256 |
st.delete(0, index+searchText.length());
|
|
257 |
encoding = st.substring(0, st.indexOf("\""));
|
|
258 |
}
|
|
259 |
fr.close();
|
|
260 |
} catch(FileNotFoundException ex) {
|
|
261 |
ex.printStackTrace();
|
|
262 |
} catch (IOException e) {
|
|
263 | 263 |
e.printStackTrace(); |
264 | 264 |
} |
265 |
return encoding;
|
|
265 |
return encoding;
|
|
266 | 266 |
} |
267 |
|
|
268 |
private double[] parserExtent(KXmlParser parser) throws XmlPullParserException, IOException {
|
|
267 |
|
|
268 |
private double[] parserExtent(KXmlParser parser) throws XmlPullParserException, IOException { |
|
269 | 269 |
double originX = 0D, originY = 0D, w = 0D, h = 0D; |
270 | 270 |
double pixelSizeX = 0D, pixelSizeY = 0D; |
271 | 271 |
double shearX = 0D, shearY = 0D; |
272 |
|
|
272 |
|
|
273 | 273 |
boolean end = false; |
274 |
int tag = parser.next();
|
|
275 |
while (!end) {
|
|
276 |
switch(tag) {
|
|
277 |
case KXmlParser.START_TAG:
|
|
278 |
if(parser.getName() != null){
|
|
274 |
int tag = parser.next();
|
|
275 |
while (!end) {
|
|
276 |
switch(tag) {
|
|
277 |
case KXmlParser.START_TAG:
|
|
278 |
if(parser.getName() != null){
|
|
279 | 279 |
if (parser.getName().equals(RasterMetaFileTags.POSX)){ |
280 | 280 |
originX = Double.parseDouble(parser.nextText()); |
281 | 281 |
}else if (parser.getName().equals(RasterMetaFileTags.POSY)){ |
... | ... | |
293 | 293 |
}else if (parser.getName().equals(RasterMetaFileTags.HEIGHT)){ |
294 | 294 |
h = Double.parseDouble(parser.nextText()); |
295 | 295 |
} |
296 |
}
|
|
296 |
} |
|
297 | 297 |
break; |
298 |
case KXmlParser.END_TAG:
|
|
299 |
if (parser.getName().equals(RasterMetaFileTags.BBOX))
|
|
300 |
end = true;
|
|
301 |
break;
|
|
302 |
case KXmlParser.TEXT:
|
|
303 |
break;
|
|
304 |
}
|
|
305 |
tag = parser.next();
|
|
306 |
}
|
|
307 |
|
|
308 |
double[] values = {originX, originY, w, h, pixelSizeX, pixelSizeY, shearX, shearY};
|
|
298 |
case KXmlParser.END_TAG:
|
|
299 |
if (parser.getName().equals(RasterMetaFileTags.BBOX))
|
|
300 |
end = true;
|
|
301 |
break;
|
|
302 |
case KXmlParser.TEXT:
|
|
303 |
break;
|
|
304 |
}
|
|
305 |
tag = parser.next();
|
|
306 |
}
|
|
307 |
|
|
308 |
double[] values = {originX, originY, w, h, pixelSizeX, pixelSizeY, shearX, shearY};
|
|
309 | 309 |
return values; |
310 | 310 |
} |
311 |
|
|
311 |
|
|
312 | 312 |
/** |
313 |
* Obtiene la informaci?n de georreferenciaci?n asociada a la imagen en un fichero .rmf. Esta
|
|
313 |
* Obtiene la informaci?n de georreferenciaci?n asociada a la imagen en un fichero .rmf. Esta |
|
314 | 314 |
* georreferenciaci?n tiene la caracteristica de que tiene prioridad sobre la de la imagen. |
315 | 315 |
* Es almacenada en la clase GeoFile en la variable virtualExtent. |
316 | 316 |
* @param file Fichero de metadatos .rmf |
... | ... | |
320 | 320 |
File rmfFile = new File(rmf); |
321 | 321 |
if(!rmfFile.exists()) |
322 | 322 |
return; |
323 |
|
|
323 |
|
|
324 | 324 |
boolean georefOk = false; |
325 |
|
|
325 |
|
|
326 | 326 |
FileReader fr = null; |
327 |
String v = null; |
|
328 | 327 |
try { |
329 | 328 |
fr = new FileReader(rmf); |
330 | 329 |
KXmlParser parser = new KXmlParser(); |
331 | 330 |
parser.setInput(new FileInputStream(rmf), readFileEncoding(rmf)); |
332 | 331 |
int tag = parser.nextTag(); |
333 |
if ( parser.getEventType() != KXmlParser.END_DOCUMENT ){
|
|
334 |
parser.require(KXmlParser.START_TAG, null, RasterMetaFileTags.MAIN_TAG);
|
|
332 |
if ( parser.getEventType() != KXmlParser.END_DOCUMENT ){ |
|
333 |
parser.require(KXmlParser.START_TAG, null, RasterMetaFileTags.MAIN_TAG); |
|
335 | 334 |
while(tag != KXmlParser.END_DOCUMENT) { |
336 | 335 |
switch(tag) { |
337 | 336 |
case KXmlParser.START_TAG: |
338 | 337 |
if (parser.getName().equals(RasterMetaFileTags.LAYER)) { |
339 |
int layerListTag = parser.next();
|
|
338 |
parser.next(); |
|
340 | 339 |
boolean geoRefEnd = false; |
341 | 340 |
while (!geoRefEnd){ |
342 | 341 |
if(parser.getName() != null){ |
... | ... | |
345 | 344 |
} else if (parser.getName().equals(RasterMetaFileTags.BBOX)){ |
346 | 345 |
double[] values = parserExtent(parser); |
347 | 346 |
rmfTransform = new AffineTransform( values[4], values[7], |
348 |
values[6], values[5],
|
|
349 |
values[0], values[1]);
|
|
347 |
values[6], values[5],
|
|
348 |
values[0], values[1]);
|
|
350 | 349 |
georefOk = true; |
351 | 350 |
} else if (parser.getName().equals(RasterMetaFileTags.DIM)){ |
352 | 351 |
boolean DimEnd = false; |
353 | 352 |
while (!DimEnd){ |
354 |
layerListTag = parser.next();
|
|
355 |
if(parser.getName() != null){
|
|
353 |
parser.next(); |
|
354 |
if(parser.getName() != null){ |
|
356 | 355 |
if (parser.getName().equals(RasterMetaFileTags.PX_WIDTH)){ |
357 | 356 |
imageWidth = Double.parseDouble(parser.nextText()); |
358 | 357 |
}else if (parser.getName().equals(RasterMetaFileTags.PX_HEIGHT)){ |
359 | 358 |
imageHeight = Double.parseDouble(parser.nextText()); |
360 | 359 |
DimEnd = true; |
361 |
}
|
|
360 |
} |
|
362 | 361 |
} |
363 | 362 |
} |
364 | 363 |
geoRefEnd = true; |
365 | 364 |
} |
366 | 365 |
} |
367 |
layerListTag = parser.next();
|
|
366 |
parser.next(); |
|
368 | 367 |
} |
369 | 368 |
} |
370 | 369 |
break; |
371 |
case KXmlParser.END_TAG:
|
|
370 |
case KXmlParser.END_TAG: |
|
372 | 371 |
break; |
373 |
case KXmlParser.TEXT:
|
|
372 |
case KXmlParser.TEXT: |
|
374 | 373 |
break; |
375 | 374 |
} |
376 | 375 |
tag = parser.next(); |
377 | 376 |
} |
378 | 377 |
parser.require(KXmlParser.END_DOCUMENT, null, null); |
379 | 378 |
} |
380 |
|
|
379 |
|
|
381 | 380 |
if(georefOk){ |
382 | 381 |
rmfExists = true; |
383 |
setExtentTransform( rmfTransform.getTranslateX(), rmfTransform.getTranslateY(),
|
|
382 |
setExtentTransform( rmfTransform.getTranslateX(), rmfTransform.getTranslateY(), |
|
384 | 383 |
rmfTransform.getScaleX(), rmfTransform.getScaleY()); |
385 |
createExtentsFromRMF( rmfTransform.getTranslateX(), rmfTransform.getTranslateY(),
|
|
386 |
rmfTransform.getScaleX(), rmfTransform.getScaleY(),
|
|
387 |
imageWidth, imageHeight,
|
|
384 |
createExtentsFromRMF( rmfTransform.getTranslateX(), rmfTransform.getTranslateY(), |
|
385 |
rmfTransform.getScaleX(), rmfTransform.getScaleY(), |
|
386 |
imageWidth, imageHeight, |
|
388 | 387 |
rmfTransform.getShearX(), rmfTransform.getShearY()); |
389 | 388 |
} |
390 |
|
|
389 |
|
|
391 | 390 |
} catch (FileNotFoundException fnfEx) { |
392 | 391 |
} catch (XmlPullParserException xmlEx) { |
393 | 392 |
xmlEx.printStackTrace(); |
394 | 393 |
} catch (IOException e) { |
395 |
}
|
|
394 |
} |
|
396 | 395 |
try{ |
397 | 396 |
if(fr != null) |
398 | 397 |
fr.close(); |
... | ... | |
402 | 401 |
} |
403 | 402 |
|
404 | 403 |
/** |
405 |
* Asigna una transformaci?n al raster para que se tenga en cuenta en la asignaci?n del setView.
|
|
406 |
* Esta asignaci?n recalcula el extent, el requestExtent y asigna el AffineTransform que se
|
|
407 |
* usar? para la transformaci?n. Esta transformaci?n ser? considerada como si la imagen tuviera
|
|
404 |
* Asigna una transformaci?n al raster para que se tenga en cuenta en la asignaci?n del setView. |
|
405 |
* Esta asignaci?n recalcula el extent, el requestExtent y asigna el AffineTransform que se |
|
406 |
* usar? para la transformaci?n. Esta transformaci?n ser? considerada como si la imagen tuviera |
|
408 | 407 |
* asociado un rmf. |
409 | 408 |
* @param t Transformaci?n af?n a aplicar |
410 | 409 |
*/ |
... | ... | |
412 | 411 |
rmfExists = true; |
413 | 412 |
rmfTransform = (AffineTransform)t.clone(); |
414 | 413 |
setExtentTransform(t.getTranslateX(), t.getTranslateY(), t.getScaleX(), t.getScaleY()); |
415 |
createExtentsFromRMF( t.getTranslateX(), t.getTranslateY(), t.getScaleX(), t.getScaleY(),
|
|
416 |
this.getWidth(), this.getHeight(),
|
|
414 |
createExtentsFromRMF( t.getTranslateX(), t.getTranslateY(), t.getScaleX(), t.getScaleY(), |
|
415 |
this.getWidth(), this.getHeight(), |
|
417 | 416 |
t.getShearX(), t.getShearY()); |
418 | 417 |
} |
419 |
|
|
418 |
|
|
420 | 419 |
/** |
421 |
* Asigna una transformaci?n al raster para que se tenga en cuenta en la asignaci?n del setView.
|
|
422 |
* Esta asignaci?n recalcula el extent, el requestExtent y asigna el AffineTransform que se
|
|
423 |
* usar? para la transformaci?n. Esta transformaci?n ser? considerada como si la imagen tuviera
|
|
420 |
* Asigna una transformaci?n al raster para que se tenga en cuenta en la asignaci?n del setView. |
|
421 |
* Esta asignaci?n recalcula el extent, el requestExtent y asigna el AffineTransform que se |
|
422 |
* usar? para la transformaci?n. Esta transformaci?n ser? considerada como si la imagen tuviera |
|
424 | 423 |
* asociado un rmf. |
425 | 424 |
* @param originX Coordenada X de origen del raster |
426 | 425 |
* @param originY Coordenada Y de origen del raster |
... | ... | |
431 | 430 |
* @param shearX Shearing en X |
432 | 431 |
* @param shearY Shearing en Y |
433 | 432 |
*/ |
434 |
public void setAffineTransform( double originX, double originY, double pixelSizeX,
|
|
433 |
public void setAffineTransform( double originX, double originY, double pixelSizeX, |
|
435 | 434 |
double pixelSizeY, double shearX, double shearY){ |
436 | 435 |
rmfExists = true; |
437 | 436 |
rmfTransform.setToTranslation(originX, originY); |
438 | 437 |
rmfTransform.shear(shearX, shearY); |
439 | 438 |
rmfTransform.scale(pixelSizeX, pixelSizeY); |
440 | 439 |
setExtentTransform(originX, originY, pixelSizeX, pixelSizeY); |
441 |
createExtentsFromRMF( originX, originY, pixelSizeX, pixelSizeY,
|
|
440 |
createExtentsFromRMF( originX, originY, pixelSizeX, pixelSizeY, |
|
442 | 441 |
imageWidth, imageHeight, shearX, shearY); |
443 | 442 |
} |
444 |
|
|
443 |
|
|
445 | 444 |
/** |
446 |
* Obtiene la matriz de transformaci?n que se aplica sobre la visualizaci?n
|
|
445 |
* Obtiene la matriz de transformaci?n que se aplica sobre la visualizaci?n |
|
447 | 446 |
* del raster. |
448 | 447 |
* @return Matriz de transformaci?n. |
449 | 448 |
*/ |
450 | 449 |
public AffineTransform getAffineTransform(){ |
451 | 450 |
return rmfTransform; |
452 | 451 |
} |
453 |
|
|
452 |
|
|
454 | 453 |
/** |
455 | 454 |
* Elimina la matriz de transformaci?n asociada al raster y que se tiene en cuenta para |
456 | 455 |
* el setView. Este reseteo tendr? en cuenta que si el raster tiene asociado un rmf |
457 | 456 |
* esta transformaci?n no ser? eliminada sino que se asignar? la correspondiente al rmf |
458 |
* existente.
|
|
457 |
* existente. |
|
459 | 458 |
* @return devuelve true si tiene fichero rmf asociado y false si no lo tiene. |
460 | 459 |
*/ |
461 | 460 |
public boolean resetAffineTransform(){ |
462 | 461 |
rmfExists = false; |
463 | 462 |
rmfTransform.setToIdentity(); |
464 |
|
|
463 |
|
|
465 | 464 |
//Crea los extent iniciales |
466 | 465 |
load(); |
467 |
|
|
466 |
|
|
468 | 467 |
//Lee y carga el rmf si existe |
469 | 468 |
readGeoInfo(this.getName()); |
470 |
|
|
469 |
|
|
471 | 470 |
if(rmfExists) |
472 | 471 |
return true; |
473 | 472 |
else |
474 | 473 |
return false; |
475 | 474 |
} |
476 |
|
|
475 |
|
|
477 | 476 |
/** |
478 | 477 |
* <P> |
479 | 478 |
* Calcula el extent de la imagen a partir del fichero rmf con y sin rotaci?n. El extent con rotaci?n corresponde |
480 | 479 |
* a la variable extent que contiene el extent verdadero marcado por el fichero de georreferenciaci?n .rmf. El extent |
481 | 480 |
* sin rotaci?n requestExtent es utilizado para realizar la petici?n ya que la petici?n al driver no se puede |
482 | 481 |
* hacer con coordenadas rotadas. |
483 |
*
|
|
482 |
* |
|
484 | 483 |
* El calculo de la bounding box rotada lo hace con los valores de transformaci?n leidos desde el fichero .rmf. |
485 | 484 |
* </p> |
486 | 485 |
* <P> |
... | ... | |
489 | 488 |
* PtoY = originY + shearY * x + pixelSizeY * y;<BR> |
490 | 489 |
* Aplicandolo a las cuatro esquinas sustituimos en cada una de ellas por. |
491 | 490 |
* </P> |
492 |
* <UL>
|
|
491 |
* <UL> |
|
493 | 492 |
* <LI>Esquina superior izquierda: x = 0; y = 0;</LI> |
494 | 493 |
* <LI>Esquina superior derecha: x = MaxX; y = 0;</LI> |
495 | 494 |
* <LI>Esquina inferior izquierda: x = 0; y = MaxY;</LI> |
496 | 495 |
* <LI>Esquina inferior derecha: x = MaxX; y = MaxY;</LI> |
497 |
* </UL>
|
|
496 |
* </UL> |
|
498 | 497 |
* <P> |
499 | 498 |
* quedandonos en los cuatro casos: |
500 | 499 |
* </P> |
501 |
* <UL>
|
|
500 |
* <UL> |
|
502 | 501 |
* <LI>Esquina superior izquierda: originX; originY;</LI> |
503 | 502 |
* <LI>Esquina superior derecha: PtoX = originX + pixelSizeX * x; PtoY = originY + shearY * x;</LI> |
504 | 503 |
* <LI>Esquina inferior izquierda: PtoX = originX + shearX * y; PtoY = originY + pixelSizeY * y;</LI> |
505 | 504 |
* <LI>Esquina inferior derecha: PtoX = originX + pixelSizeX * x + shearX * y; PtoY = originY + shearY * x + pixelSizeY * y;</LI> |
506 | 505 |
* </UL> |
507 |
*
|
|
506 |
* |
|
508 | 507 |
* <P> |
509 | 508 |
* El calculo de la bounding box se realizar? de la misma forma pero anulando los parametros de shearing. |
510 | 509 |
* </P> |
511 |
*
|
|
510 |
* |
|
512 | 511 |
* @param originX Coordenada X de origen del raster |
513 | 512 |
* @param originY Coordenada Y de origen del raster |
514 | 513 |
* @param pixelSizeX Tama?o de pixel en X |
... | ... | |
518 | 517 |
* @param shearX Shearing en X |
519 | 518 |
* @param shearY Shearing en Y |
520 | 519 |
*/ |
521 |
private void createExtentsFromRMF( double originX, double originY, double pixelSizeX, double pixelSizeY,
|
|
520 |
private void createExtentsFromRMF( double originX, double originY, double pixelSizeX, double pixelSizeY, |
|
522 | 521 |
double imageWidth, double imageHeight, double shearX, double shearY){ |
523 |
|
|
522 |
|
|
524 | 523 |
Point2D p1 = new Point2D.Double(originX, originY); |
525 | 524 |
Point2D p2 = new Point2D.Double(originX + shearX * imageHeight, originY + pixelSizeY * imageHeight); |
526 | 525 |
Point2D p3 = new Point2D.Double(originX + pixelSizeX * imageWidth, originY + shearY * imageWidth); |
527 | 526 |
Point2D p4 = new Point2D.Double(originX + pixelSizeX * imageWidth + shearX * imageHeight, originY + pixelSizeY * imageHeight + shearY * imageWidth); |
528 |
|
|
527 |
|
|
529 | 528 |
double minX = Math.min(Math.min(p1.getX(), p2.getX()), Math.min(p3.getX(), p4.getX())); |
530 | 529 |
double minY = Math.min(Math.min(p1.getY(), p2.getY()), Math.min(p3.getY(), p4.getY())); |
531 | 530 |
double maxX = Math.max(Math.max(p1.getX(), p2.getX()), Math.max(p3.getX(), p4.getX())); |
... | ... | |
533 | 532 |
extent = new Extent(minX, minY, maxX, maxY); |
534 | 533 |
requestExtent = new Extent(originX, originY, originX + (pixelSizeX * imageWidth), originY + (pixelSizeY * imageHeight)); |
535 | 534 |
} |
536 |
|
|
535 |
|
|
537 | 536 |
/** |
538 | 537 |
* Calcula la transformaci?n que se produce sobre la vista cuando la imagen tiene un fichero .rmf |
539 | 538 |
* asociado. Esta transformaci?n tiene diferencias entre los distintos formatos por lo que debe calcularla |
... | ... | |
542 | 541 |
* @param originY Origen de la imagen en la coordenada Y |
543 | 542 |
*/ |
544 | 543 |
abstract public void setExtentTransform(double originX, double originY, double psX, double psY); |
545 |
|
|
544 |
|
|
546 | 545 |
public static PxContour getContour(String fName, String name, IProjection proj) { |
547 | 546 |
PxContour contour = null; |
548 | 547 |
return contour; |
549 | 548 |
} |
550 |
|
|
549 |
|
|
551 | 550 |
/** |
552 | 551 |
* Obtiene el ancho de la imagen |
553 | 552 |
* @return Ancho de la imagen |
554 | 553 |
*/ |
555 | 554 |
abstract public int getWidth(); |
556 |
|
|
555 |
|
|
557 | 556 |
/** |
558 | 557 |
* Obtiene el ancho de la imagen |
559 | 558 |
* @return Ancho de la imagen |
... | ... | |
567 | 566 |
abstract public void reProject(ICoordTrans rp); |
568 | 567 |
|
569 | 568 |
/** |
570 |
* Asigna un nuevo Extent
|
|
569 |
* Asigna un nuevo Extent |
|
571 | 570 |
* @param e Extent |
572 | 571 |
*/ |
573 | 572 |
abstract public void setView(Extent e); |
574 |
|
|
573 |
|
|
575 | 574 |
/** |
576 | 575 |
* Obtiene el extent asignado |
577 | 576 |
* @return Extent |
578 | 577 |
*/ |
579 | 578 |
abstract public Extent getView(); |
580 |
|
|
579 |
|
|
581 | 580 |
public void setTransparency(boolean t) { |
582 | 581 |
doTransparency = t; |
583 | 582 |
tFilter = new PixelFilter(255); |
584 | 583 |
} |
585 |
|
|
584 |
|
|
586 | 585 |
/** |
587 | 586 |
* Asigna un valor de transparencia |
588 | 587 |
* @param t Valor de transparencia |
... | ... | |
591 | 590 |
doTransparency = true; |
592 | 591 |
tFilter = new SimplePixelFilter(255 - t); |
593 | 592 |
} |
594 |
|
|
593 |
|
|
595 | 594 |
public boolean getTransparency() { return doTransparency; } |
596 |
|
|
595 |
|
|
597 | 596 |
public void setAlpha(int alpha) { |
598 | 597 |
if (!doTransparency) setTransparency(255 - alpha); |
599 | 598 |
else tFilter.setAlpha(alpha); |
... | ... | |
603 | 602 |
return 255; |
604 | 603 |
return tFilter.getAlpha(); |
605 | 604 |
} |
606 |
|
|
605 |
|
|
607 | 606 |
public void setUpdatable(Component c) { updatable = c; } |
608 |
|
|
607 |
|
|
609 | 608 |
/** |
610 | 609 |
* Actualiza la imagen |
611 | 610 |
* @param width ancho |
... | ... | |
638 | 637 |
abstract public Image updateImage(int width, int height, ICoordTrans rp, Image img, int origBand, int destBand)throws SupersamplingNotSupportedException; |
639 | 638 |
|
640 | 639 |
public int getBandCount() { return bandCount; } |
641 |
|
|
640 |
|
|
642 | 641 |
/** |
643 | 642 |
* Asocia un colorBand al rojo, verde o azul. |
644 | 643 |
* @param flag cual (o cuales) de las bandas. |
645 | 644 |
* @param nBand que colorBand |
646 | 645 |
*/ |
647 |
|
|
646 |
|
|
648 | 647 |
public void setBand(int flag, int bandNr) { |
649 | 648 |
if ((flag & GeoRasterFile.RED_BAND) == GeoRasterFile.RED_BAND) rBandNr = bandNr; |
650 | 649 |
if ((flag & GeoRasterFile.GREEN_BAND) == GeoRasterFile.GREEN_BAND) gBandNr = bandNr; |
... | ... | |
655 | 654 |
* Devuelve el colorBand activo en la banda especificada. |
656 | 655 |
* @param flag banda. |
657 | 656 |
*/ |
658 |
|
|
657 |
|
|
659 | 658 |
public int getBand(int flag) { |
660 | 659 |
if (flag == GeoRasterFile.RED_BAND) return rBandNr; |
661 | 660 |
if (flag == GeoRasterFile.GREEN_BAND) return gBandNr; |
662 | 661 |
if (flag == GeoRasterFile.BLUE_BAND) return bBandNr; |
663 | 662 |
return -1; |
664 | 663 |
} |
665 |
|
|
664 |
|
|
666 | 665 |
/** |
667 | 666 |
* @return Returns the dataType. |
668 | 667 |
*/ |
669 | 668 |
public int getDataType() { |
670 | 669 |
return dataType; |
671 | 670 |
} |
672 |
|
|
671 |
|
|
673 | 672 |
/** |
674 | 673 |
* @param dataType The dataType to set. |
675 | 674 |
*/ |
... | ... | |
682 | 681 |
IObjList oList = new PxObjList(proj); |
683 | 682 |
return oList; |
684 | 683 |
} |
685 |
|
|
684 |
|
|
686 | 685 |
/** |
687 | 686 |
* Calcula los par?metros de un worl file a partir de las esquinas del raster. |
688 | 687 |
* 1. X pixel size A |
... | ... | |
699 | 698 |
* at the top of the image, the X pixel size will be positive |
700 | 699 |
* and the Y pixel size will be negative. For a south-up image, |
701 | 700 |
* these signs would be reversed. |
702 |
*
|
|
701 |
* |
|
703 | 702 |
* You can calculate the World file parameters yourself based |
704 | 703 |
* on the corner coordinates. The X and Y pixel sizes can be |
705 | 704 |
* determined simply by dividing the distance between two |
706 | 705 |
* adjacent corners by the number of columns or rows in the image. |
707 | 706 |
* The rotation terms are calculated with these equations: |
708 |
*
|
|
707 |
* |
|
709 | 708 |
* # B = (A * number_of_columns + C - lower_right_x') / number_of_rows * -1 |
710 | 709 |
* # D = (E * number_of_rows + F - lower_right_y') / number_of_columns * -1 |
711 |
*
|
|
710 |
* |
|
712 | 711 |
* @param corner (tl, tr, br, bl) |
713 | 712 |
* @return |
714 | 713 |
*/ |
... | ... | |
720 | 719 |
double x4 = esq[3].getX(), y4 = esq[3].getY(); |
721 | 720 |
// A: X-scale |
722 | 721 |
a = Math.abs( Math.sqrt( (x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)) |
723 |
/ size.getWidth());
|
|
722 |
/ size.getWidth());
|
|
724 | 723 |
|
725 | 724 |
// E: negative Y-scale |
726 | 725 |
e = - Math.abs(Math.sqrt((x1-x4)*(x1-x4)+ |
727 |
(y1-y4)*(y1-y4))/size.getHeight());
|
|
726 |
(y1-y4)*(y1-y4))/size.getHeight());
|
|
728 | 727 |
|
729 | 728 |
// C, F: upper-left coordinates |
730 | 729 |
c = x1; |
731 | 730 |
f = y1; |
732 |
|
|
731 |
|
|
733 | 732 |
// B & D: rotation parameters |
734 | 733 |
b = (a * size.getWidth() + c - x3 ) / size.getHeight() * -1; |
735 | 734 |
d = (e * size.getHeight() + f - y3 ) / size.getWidth() * -1; |
736 | 735 |
|
737 |
double [] wf = {a,d,b,e,c,f};
|
|
738 |
return wf;
|
|
736 |
double [] wf = {a,d,b,e,c,f}; |
|
737 |
return wf; |
|
739 | 738 |
} |
740 |
public static String printWF(String fName, Point2D [] esq, Dimension sz) {
|
|
741 |
double [] wf = GeoRasterFile.cornersToWorldFile(esq, sz);
|
|
742 |
System.out.println("wf para "+fName);
|
|
743 |
System.out.println(esq+"\n"+sz);
|
|
744 |
String wfData = "";
|
|
745 |
for (int i=0; i<6; i++)
|
|
746 |
wfData += wf[i]+"\n";
|
|
739 |
public static String printWF(String fName, Point2D [] esq, Dimension sz) {
|
|
740 |
double [] wf = GeoRasterFile.cornersToWorldFile(esq, sz);
|
|
741 |
System.out.println("wf para "+fName);
|
|
742 |
System.out.println(esq+"\n"+sz);
|
|
743 |
String wfData = "";
|
|
744 |
for (int i=0; i<6; i++)
|
|
745 |
wfData += wf[i]+"\n";
|
|
747 | 746 |
System.out.println(wfData); |
748 | 747 |
return wfData; |
749 |
} |
|
750 |
|
|
751 |
public static void saveWF(String fName, String data) throws IOException { |
|
752 |
FileWriter fw = new FileWriter(fName); |
|
753 |
fw.write(data); |
|
754 |
fw.flush(); |
|
755 |
fw.close(); |
|
756 |
} |
|
748 |
} |
|
757 | 749 |
|
750 |
public static void saveWF(String fName, String data) throws IOException { |
|
751 |
FileWriter fw = new FileWriter(fName); |
|
752 |
fw.write(data); |
|
753 |
fw.flush(); |
|
754 |
fw.close(); |
|
755 |
} |
|
756 |
|
|
758 | 757 |
/** |
759 | 758 |
* Cosulta si hay que verificar la relaci?n de aspecto de la imagen, es decir comprueba que el ancho/alto |
760 | 759 |
* pasados a updateImage coinciden con el ancho/alto solicitado en setView a la imagen |
761 |
* @return true si est? verificando la relaci?n de aspecto.
|
|
760 |
* @return true si est? verificando la relaci?n de aspecto. |
|
762 | 761 |
*/ |
763 | 762 |
public boolean mustVerifySize() { |
764 | 763 |
return verifySize; |
765 | 764 |
} |
766 | 765 |
|
767 | 766 |
/** |
768 |
* Asigna el flag que dice si hay que verificar la relaci?n de aspecto de la imagen, es decir
|
|
769 |
* comprueba que el ancho/alto pasados a updateImage coinciden con el ancho/alto solicitado
|
|
767 |
* Asigna el flag que dice si hay que verificar la relaci?n de aspecto de la imagen, es decir |
|
768 |
* comprueba que el ancho/alto pasados a updateImage coinciden con el ancho/alto solicitado |
|
770 | 769 |
* en setView a la imagen. |
771 |
* @return true si est? verificando la relaci?n de aspecto.
|
|
770 |
* @return true si est? verificando la relaci?n de aspecto. |
|
772 | 771 |
*/ |
773 | 772 |
public void setMustVerifySize(boolean verifySize) { |
774 | 773 |
this.verifySize = verifySize; |
... | ... | |
776 | 775 |
|
777 | 776 |
abstract public byte[] getWindow(int ulX, int ulY, int sizeX, int sizeY, int band); |
778 | 777 |
abstract public int getBlockSize(); |
779 |
|
|
778 |
|
|
780 | 779 |
/** |
781 | 780 |
* Obtiene el objeto que contiene los metadatos. Este m?todo debe ser redefinido por los |
782 |
* drivers si necesitan devolver metadatos.
|
|
781 |
* drivers si necesitan devolver metadatos. |
|
783 | 782 |
* @return |
784 | 783 |
*/ |
785 | 784 |
public Metadata getMetadata(){ |
786 | 785 |
return null; |
787 | 786 |
} |
788 |
|
|
787 |
|
|
789 | 788 |
/** |
790 |
* Asigna un extent temporal que puede coincidir con el de la vista. Esto es
|
|
789 |
* Asigna un extent temporal que puede coincidir con el de la vista. Esto es |
|
791 | 790 |
* util para cargar imagenes sin georreferenciar ya que podemos asignar el extent |
792 | 791 |
* que queramos para ajustarnos a una vista concreta |
793 | 792 |
* @param tempExtent The tempExtent to set. |
... | ... | |
795 | 794 |
public void setExtent(Extent ext) { |
796 | 795 |
this.extent = ext; |
797 | 796 |
} |
798 |
|
|
797 |
|
|
799 | 798 |
public boolean isGeoreferenced(){ |
800 | 799 |
return true; |
801 | 800 |
} |
802 |
|
|
801 |
|
|
803 | 802 |
/** |
804 | 803 |
* M?todo que indica si existe un fichero .rmf asociado al GeoRasterFile. |
805 | 804 |
* @return |
... | ... | |
807 | 806 |
public boolean rmfExists(){ |
808 | 807 |
return this.rmfExists; |
809 | 808 |
} |
810 |
|
|
809 |
|
|
811 | 810 |
/** |
812 | 811 |
* Obtiene los par?metros de la transformaci?n af?n que corresponde con los elementos de |
813 | 812 |
* un fichero tfw. |
814 |
* <UL>
|
|
813 |
* <UL> |
|
815 | 814 |
* <LI>[1]tama?o de pixel en X</LI> |
816 | 815 |
* <LI>[2]rotaci?n en X</LI> |
817 | 816 |
* <LI>[4]rotaci?n en Y</LI> |
trunk/libraries/libCresques/src/org/cresques/io/EcwFile.java | ||
---|---|---|
71 | 71 |
* @author "Luis W. Sevilla" <sevilla_lui@gva.es> |
72 | 72 |
*/ |
73 | 73 |
public class EcwFile extends GeoRasterFile implements JNCSProgressiveUpdate { |
74 |
//Lleva la cuenta del n?mero de actualizaciones que se hace de una imagen que corresponde con el |
|
75 |
//n?mero de bandas que tiene. Esto es necesario ya que si una imagen tiene el mustResize a |
|
76 |
//true solo debe llamar a la funci?n resizeImage al actualizar la ?ltima banda, sino al hacer |
|
77 |
//un zoom menor que 1:1 se veria mal |
|
78 |
private static int nUpdate = 0; |
|
79 |
private JNCSFile file = null; |
|
80 |
private boolean bErrorOnOpen = false; |
|
81 |
private String errorMessage = null; |
|
82 |
private boolean multifile = false; |
|
83 |
private Extent v = null; |
|
84 |
|
|
74 |
//Lleva la cuenta del n?mero de actualizaciones que se hace de una imagen que corresponde con el |
|
75 |
//n?mero de bandas que tiene. Esto es necesario ya que si una imagen tiene el mustResize a |
|
76 |
//true solo debe llamar a la funci?n resizeImage al actualizar la ?ltima banda, sino al hacer |
|
77 |
//un zoom menor que 1:1 se veria mal |
|
78 |
private static int nUpdate = 0; |
|
79 |
private JNCSFile file = null; |
|
80 |
private String errorMessage = null; |
|
81 |
private boolean multifile = false; |
|
82 |
private Extent v = null; |
|
85 | 83 |
|
86 |
// Ultimo porcentaje de refresco. Se carga en el update y se |
|
87 |
// actualiza en el refreshUpdate |
|
88 |
private int lastRefreshPercent = 0; |
|
89 | 84 |
|
90 |
public EcwFile(IProjection proj, String fName) { |
|
91 |
super(proj, null); |
|
92 |
fName = DataSource.normalize(fName); |
|
93 |
super.setName(fName); |
|
94 |
extent = new Extent(); |
|
85 |
// Ultimo porcentaje de refresco. Se carga en el update y se |
|
86 |
// actualiza en el refreshUpdate |
|
87 |
private int lastRefreshPercent = 0; |
|
95 | 88 |
|
96 |
try { |
|
97 |
|
|
98 |
if (!new File(fName).exists() && !fName.startsWith("ecwp:")){ |
|
99 |
System.err.println("No se puede abrir el archivo"); |
|
100 |
return; |
|
101 |
} |
|
102 |
|
|
103 |
file = new JNCSFile(fName, false); |
|
104 |
load(); |
|
105 |
//readGeoInfo(fName); |
|
106 |
bandCount = file.numBands; |
|
89 |
public EcwFile(IProjection proj, String fName) { |
|
90 |
super(proj, null); |
|
91 |
fName = DataSource.normalize(fName); |
|
92 |
super.setName(fName); |
|
93 |
extent = new Extent(); |
|
107 | 94 |
|
108 |
if ( bandCount > 2) { |
|
109 |
setBand(RED_BAND, 0); |
|
110 |
setBand(GREEN_BAND, 1); |
|
111 |
setBand(BLUE_BAND, 2); |
|
112 |
} else |
|
113 |
setBand(RED_BAND|GREEN_BAND|BLUE_BAND, 0); |
|
114 |
} catch (Exception e) { |
|
115 |
bErrorOnOpen = true; |
|
116 |
errorMessage = e.getMessage(); |
|
117 |
System.err.println(errorMessage); |
|
118 |
e.printStackTrace(); |
|
119 |
} |
|
120 |
} |
|
95 |
try { |
|
121 | 96 |
|
122 |
/** |
|
123 |
* Carga un ECW. |
|
124 |
* |
|
125 |
* @param fname |
|
126 |
*/ |
|
127 |
public GeoFile load() { |
|
128 |
double minX; |
|
129 |
double minY; |
|
130 |
double maxX; |
|
131 |
double maxY; |
|
97 |
if (!new File(fName).exists() && !fName.startsWith("ecwp:")){ |
|
98 |
System.err.println("No se puede abrir el archivo"); |
|
99 |
return; |
|
100 |
} |
|
132 | 101 |
|
133 |
if(file.cellIncrementY > 0) |
|
134 |
file.cellIncrementY = -file.cellIncrementY; |
|
135 |
|
|
136 |
minX = file.originX; |
|
137 |
maxY = file.originY; |
|
138 |
maxX = file.originX + |
|
139 |
((double) (file.width - 1) * file.cellIncrementX); |
|
140 |
minY = file.originY + |
|
141 |
((double) (file.height - 1) * file.cellIncrementY); |
|
142 |
|
|
143 |
extent = new Extent(minX, minY, maxX, maxY); |
|
144 |
requestExtent = extent; |
|
145 |
return this; |
|
146 |
} |
|
102 |
file = new JNCSFile(fName, false); |
|
103 |
load(); |
|
104 |
//readGeoInfo(fName); |
|
105 |
bandCount = file.numBands; |
|
147 | 106 |
|
148 |
public void close() { |
|
149 |
if(file != null){ |
|
150 |
file.close(true); |
|
151 |
file = null; |
|
152 |
} |
|
153 |
} |
|
107 |
if ( bandCount > 2) { |
|
108 |
setBand(RED_BAND, 0); |
|
109 |
setBand(GREEN_BAND, 1); |
|
110 |
setBand(BLUE_BAND, 2); |
|
111 |
} else |
|
112 |
setBand(RED_BAND|GREEN_BAND|BLUE_BAND, 0); |
|
113 |
} catch (Exception e) { |
|
114 |
errorMessage = e.getMessage(); |
|
115 |
System.err.println(errorMessage); |
|
116 |
e.printStackTrace(); |
|
117 |
} |
|
118 |
} |
|
154 | 119 |
|
155 |
/** |
|
156 |
* Devuelve el ancho de la imagen |
|
157 |
*/ |
|
158 |
public int getWidth() { |
|
159 |
return file.width; |
|
160 |
} |
|
120 |
/** |
|
121 |
* Carga un ECW. |
|
122 |
* |
|
123 |
* @param fname |
|
124 |
*/ |
|
125 |
public GeoFile load() { |
|
126 |
double minX; |
|
127 |
double minY; |
|
128 |
double maxX; |
|
129 |
double maxY; |
|
161 | 130 |
|
162 |
/** |
|
163 |
* Devuelve el alto de la imagen |
|
164 |
*/ |
|
165 |
public int getHeight() { |
|
166 |
return file.height; |
|
167 |
} |
|
131 |
if(file.cellIncrementY > 0) |
|
132 |
file.cellIncrementY = -file.cellIncrementY; |
|
168 | 133 |
|
169 |
/**
|
|
170 |
*
|
|
171 |
*/
|
|
172 |
public void setMultifile(boolean mult) {
|
|
173 |
this.multifile = mult;
|
|
174 |
}
|
|
134 |
minX = file.originX;
|
|
135 |
maxY = file.originY;
|
|
136 |
maxX = file.originX +
|
|
137 |
((double) (file.width - 1) * file.cellIncrementX);
|
|
138 |
minY = file.originY +
|
|
139 |
((double) (file.height - 1) * file.cellIncrementY);
|
|
175 | 140 |
|
176 |
public void setView(Extent e) { |
|
177 |
//Aplicamos la transformaci?n a la vista en caso de que haya un fichero .rmf |
|
178 |
/* |
|
179 |
if(file.cellIncrementY > 0) |
|
180 |
file.cellIncrementY = -file.cellIncrementY; |
|
181 |
if(minX < file.originX) |
|
182 |
minX = file.originX; |
|
183 |
if(maxY > file.originY) |
|
184 |
maxY = file.originY; |
|
185 |
if(maxX > (file.originX + ((double) (file.width - 1) * file.cellIncrementX))) |
|
186 |
maxX = file.originX + ((double) (file.width - 1) * file.cellIncrementX); |
|
187 |
if(minY < file.originY + ((double) (file.height - 1) * file.cellIncrementY)) |
|
188 |
minY = file.originY + ((double) (file.height - 1) * file.cellIncrementY); |
|
189 |
|
|
141 |
extent = new Extent(minX, minY, maxX, maxY); |
|
142 |
requestExtent = extent; |
|
143 |
return this; |
|
144 |
} |
|
145 |
|
|
146 |
public void close() { |
|
147 |
if(file != null){ |
|
148 |
file.close(true); |
|
149 |
file = null; |
|
150 |
} |
|
151 |
} |
|
152 |
|
|
153 |
/** |
|
154 |
* Devuelve el ancho de la imagen |
|
155 |
*/ |
|
156 |
public int getWidth() { |
|
157 |
return file.width; |
|
158 |
} |
|
159 |
|
|
160 |
/** |
|
161 |
* Devuelve el alto de la imagen |
|
162 |
*/ |
|
163 |
public int getHeight() { |
|
164 |
return file.height; |
|
165 |
} |
|
166 |
|
|
167 |
/** |
|
168 |
* |
|
169 |
*/ |
|
170 |
public void setMultifile(boolean mult) { |
|
171 |
this.multifile = mult; |
|
172 |
} |
|
173 |
|
|
174 |
public void setView(Extent e) { |
|
175 |
//Aplicamos la transformaci?n a la vista en caso de que haya un fichero .rmf |
|
176 |
/* |
|
177 |
if(file.cellIncrementY > 0) |
|
178 |
file.cellIncrementY = -file.cellIncrementY; |
|
179 |
if(minX < file.originX) |
|
180 |
minX = file.originX; |
|
181 |
if(maxY > file.originY) |
|
182 |
maxY = file.originY; |
|
183 |
if(maxX > (file.originX + ((double) (file.width - 1) * file.cellIncrementX))) |
|
184 |
maxX = file.originX + ((double) (file.width - 1) * file.cellIncrementX); |
|
185 |
if(minY < file.originY + ((double) (file.height - 1) * file.cellIncrementY)) |
|
186 |
minY = file.originY + ((double) (file.height - 1) * file.cellIncrementY); |
|
187 |
|
|
190 | 188 |
Extent transformView = new Extent( minX, minY, maxX, maxY );*/ |
191 |
v = new Extent(e);
|
|
192 |
}
|
|
189 |
v = new Extent(e);
|
|
190 |
}
|
|
193 | 191 |
|
194 |
public Extent getView() { |
|
195 |
return v; |
|
196 |
} |
|
197 |
|
|
198 |
private void setFileView(int numBands, int [] bandList, ChunkFrame f) |
|
199 |
throws JNCSFileNotOpenException, JNCSInvalidSetViewException { |
|
200 |
file.setView(file.numBands, bandList, f.v.minX(), f.v.maxY(), f.v.maxX(), f.v.minY(), f.width, f.height); |
|
201 |
} |
|
192 |
public Extent getView() { |
|
193 |
return v; |
|
194 |
} |
|
202 | 195 |
|
203 |
/** |
|
204 |
* Obtiene un trozo de imagen (determinado por la vista y los par?metros. |
|
205 |
* |
|
206 |
* @param width |
|
207 |
* @param height |
|
208 |
*/ |
|
209 |
public synchronized Image updateImage(int width, int height, ICoordTrans rp) { |
|
210 |
// TODO reproyectar para devolver el trozo de imagen pedida sobre ... |
|
211 |
// la proyecci?n de destino. |
|
212 |
int line = 0; |
|
213 |
boolean mustResize = false; |
|
214 |
Dimension fullSize = null; |
|
215 |
Image ecwImage = null; |
|
196 |
private void setFileView(int numBands, int [] bandList, ChunkFrame f) |
|
197 |
throws JNCSFileNotOpenException, JNCSInvalidSetViewException { |
|
198 |
file.setView(file.numBands, bandList, f.v.minX(), f.v.maxY(), f.v.maxX(), f.v.minY(), f.width, f.height); |
|
199 |
} |
|
216 | 200 |
|
217 |
if (file == null) { |
|
218 |
return ecwImage; |
|
219 |
} |
|
201 |
/** |
|
202 |
* Obtiene un trozo de imagen (determinado por la vista y los par?metros. |
|
203 |
* |
|
204 |
* @param width |
|
205 |
* @param height |
|
206 |
*/ |
|
207 |
public synchronized Image updateImage(int width, int height, ICoordTrans rp) { |
|
208 |
// TODO reproyectar para devolver el trozo de imagen pedida sobre ... |
|
209 |
// la proyecci?n de destino. |
|
210 |
int line = 0; |
|
211 |
Dimension fullSize = null; |
|
212 |
Image ecwImage = null; |
|
220 | 213 |
|
221 |
try { |
|
222 |
int[] bandlist; |
|
223 |
int[] bandListTriband; |
|
224 |
int[] pRGBArray = null; |
|
214 |
if (file == null) { |
|
215 |
return ecwImage; |
|
216 |
} |
|
225 | 217 |
|
226 |
if(mustVerifySize()){ |
|
227 |
// Work out the correct aspect for the setView call. |
|
228 |
double dFileAspect = (double) v.width() / (double) v.height(); |
|
229 |
double dWindowAspect = (double) width / (double) height; |
|
230 |
|
|
231 |
if (dFileAspect > dWindowAspect) { |
|
232 |
height = (int) ((double) width / dFileAspect); |
|
233 |
} else { |
|
234 |
width = (int) ((double) height * dFileAspect); |
|
235 |
} |
|
236 |
} |
|
237 |
fullSize = new Dimension(width, height); |
|
218 |
try { |
|
219 |
int[] bandlist; |
|
220 |
int[] bandListTriband; |
|
221 |
int[] pRGBArray = null; |
|
238 | 222 |
|
239 |
//System.out.println("fullSize = ("+width+","+height+")"); |
|
240 |
// Peta en los peque?os ... arreglar antes de meter del todo |
|
241 |
ChunkFrame[] frames = ChunkFrame.computeFrames(file, v, fullSize, extent); |
|
223 |
if(mustVerifySize()){ |
|
224 |
// Work out the correct aspect for the setView call. |
|
225 |
double dFileAspect = (double) v.width() / (double) v.height(); |
|
226 |
double dWindowAspect = (double) width / (double) height; |
|
242 | 227 |
|
243 |
if (frames.length == 1) { |
|
244 |
width = frames[0].width; |
|
245 |
height = frames[0].height; |
|
228 |
if (dFileAspect > dWindowAspect) { |
|
229 |
height = (int) ((double) width / dFileAspect); |
|
230 |
} else { |
|
231 |
width = (int) ((double) height * dFileAspect); |
|
232 |
} |
|
233 |
} |
|
234 |
fullSize = new Dimension(width, height); |
|
246 | 235 |
|
247 |
if (width <= 0) {
|
|
248 |
width = 1;
|
|
249 |
}
|
|
236 |
//System.out.println("fullSize = ("+width+","+height+")");
|
|
237 |
// Peta en los peque?os ... arreglar antes de meter del todo
|
|
238 |
ChunkFrame[] frames = ChunkFrame.computeFrames(file, v, fullSize, extent);
|
|
250 | 239 |
|
251 |
if (height <= 0) { |
|
252 |
height = 1; |
|
253 |
} |
|
254 |
} |
|
240 |
if (frames.length == 1) { |
|
241 |
width = frames[0].width; |
|
242 |
height = frames[0].height; |
|
255 | 243 |
|
256 |
/* JNCSDatasetPoint ptMin = file.convertWorldToDataset(v.minX(), v.minY()); |
|
257 |
JNCSDatasetPoint ptMax = file.convertWorldToDataset(v.maxX(), v.maxY()); |
|
258 |
System.out.println("Dataset coords Width = "+(ptMax.x-ptMin.x)+", px width ="+width); |
|
259 |
// BEGIN Cambiando para soportar e < 1:1 |
|
260 |
// TODO Mejorarlo para que los PAN con un zoom muy grande sean correctos |
|
261 |
if ((ptMax.x-ptMin.x)<width) { |
|
262 |
width = ptMax.x-ptMin.x; |
|
263 |
height = ptMin.y-ptMax.y; |
|
264 |
System.out.println("Size=("+width+","+height+")"); |
|
265 |
mustResize = true; |
|
266 |
}*/ |
|
244 |
if (width <= 0) { |
|
245 |
width = 1; |
|
246 |
} |
|
267 | 247 |
|
268 |
// Create an image of the ecw file. |
|
269 |
if (doTransparency) { |
|
270 |
ecwImage = new BufferedImage(width, height, |
|
271 |
BufferedImage.TYPE_INT_ARGB); |
|
272 |
} else { |
|
273 |
ecwImage = new BufferedImage(width, height, |
|
274 |
BufferedImage.TYPE_INT_RGB); |
|
275 |
} |
|
248 |
if (height <= 0) { |
|
249 |
height = 1; |
|
250 |
} |
|
251 |
} |
|
276 | 252 |
|
277 |
pRGBArray = new int[width]; |
|
253 |
/* JNCSDatasetPoint ptMin = file.convertWorldToDataset(v.minX(), v.minY()); |
|
254 |
JNCSDatasetPoint ptMax = file.convertWorldToDataset(v.maxX(), v.maxY()); |
|
255 |
System.out.println("Dataset coords Width = "+(ptMax.x-ptMin.x)+", px width ="+width); |
|
256 |
// BEGIN Cambiando para soportar e < 1:1 |
|
257 |
// TODO Mejorarlo para que los PAN con un zoom muy grande sean correctos |
|
258 |
if ((ptMax.x-ptMin.x)<width) { |
|
259 |
width = ptMax.x-ptMin.x; |
|
260 |
height = ptMin.y-ptMax.y; |
|
261 |
System.out.println("Size=("+width+","+height+")"); |
|
262 |
mustResize = true; |
|
263 |
}*/ |
|
278 | 264 |
|
279 |
// Setup the view parameters for the ecw file. |
|
280 |
bandlist = new int[bandCount]; |
|
281 |
bandListTriband = new int[bandCount]; |
|
265 |
// Create an image of the ecw file. |
|
266 |
if (doTransparency) { |
|
267 |
ecwImage = new BufferedImage(width, height, |
|
268 |
BufferedImage.TYPE_INT_ARGB); |
|
269 |
} else { |
|
270 |
ecwImage = new BufferedImage(width, height, |
|
271 |
BufferedImage.TYPE_INT_RGB); |
|
272 |
} |
|
282 | 273 |
|
283 |
if (bandCount > 2) { |
|
284 |
bandlist[0] = getBand(RED_BAND); |
|
285 |
bandlist[1] = getBand(GREEN_BAND); |
|
286 |
bandlist[2] = getBand(BLUE_BAND); |
|
274 |
pRGBArray = new int[width]; |
|
287 | 275 |
|
288 |
if (bandCount > 3) { |
|
289 |
for (int i = 3; i < bandCount; i++) { |
|
290 |
bandlist[i] = 0; |
|
291 |
} |
|
292 |
} |
|
293 |
} else { |
|
294 |
for (int i = 0; i < bandCount; i++) { |
|
295 |
bandlist[i] = i; |
|
296 |
} |
|
297 |
} |
|
276 |
// Setup the view parameters for the ecw file. |
|
277 |
bandlist = new int[bandCount]; |
|
278 |
bandListTriband = new int[bandCount]; |
|
298 | 279 |
|
299 |
if (bandCount == 3) { |
|
300 |
bandListTriband[0] = 0; |
|
301 |
bandListTriband[1] = 1; |
|
302 |
bandListTriband[2] = 2; |
|
303 |
} |
|
280 |
if (bandCount > 2) { |
|
281 |
bandlist[0] = getBand(RED_BAND); |
|
282 |
bandlist[1] = getBand(GREEN_BAND); |
|
283 |
bandlist[2] = getBand(BLUE_BAND); |
|
304 | 284 |
|
305 |
for (int nChunk = 0; nChunk < frames.length; nChunk++) { |
|
306 |
ChunkFrame f = frames[nChunk]; |
|
285 |
if (bandCount > 3) { |
|
286 |
for (int i = 3; i < bandCount; i++) { |
|
287 |
bandlist[i] = 0; |
|
288 |
} |
|
289 |
} |
|
290 |
} else { |
|
291 |
for (int i = 0; i < bandCount; i++) { |
|
292 |
bandlist[i] = i; |
|
293 |
} |
|
294 |
} |
|
307 | 295 |
|
308 |
// Set the view |
|
309 |
if (bandCount != 3) { |
|
310 |
setFileView(file.numBands, bandlist, f); |
|
311 |
} else { |
|
312 |
setFileView(file.numBands, bandListTriband, f); |
|
313 |
} |
|
296 |
if (bandCount == 3) { |
|
297 |
bandListTriband[0] = 0; |
|
298 |
bandListTriband[1] = 1; |
|
299 |
bandListTriband[2] = 2; |
|
300 |
} |
|
314 | 301 |
|
315 |
/* |
|
316 |
* Esta peli es porque el Ecw no intercambia las bandas con lo que me toca hacerlo |
|
317 |
* a mano. Primero detectamos si se ha alterado el orden de las mismas. Si es as? |
|
318 |
* calculamos mascaras y desplazamientos y hacemos una copia en pRGBArrayCopy |
|
319 |
* con las bandas alteradas de orden |
|
320 |
*/ |
|
321 |
int[] pRGBArrayCopy = null; |
|
322 |
int[] mascara = new int[3]; |
|
323 |
int[] shl = new int[3]; |
|
324 |
int[] shr = new int[3]; |
|
325 |
boolean order = true; |
|
302 |
for (int nChunk = 0; nChunk < frames.length; nChunk++) { |
|
303 |
ChunkFrame f = frames[nChunk]; |
|
326 | 304 |
|
327 |
if (bandCount == 3) { |
|
328 |
for (int i = 0; i < bandCount; i++) |
|
329 |
if (bandlist[i] != i) { |
|
330 |
order = false; |
|
331 |
} |
|
305 |
// Set the view |
|
306 |
if (bandCount != 3) { |
|
307 |
setFileView(file.numBands, bandlist, f); |
Also available in: Unified diff