svn-gvsig-desktop / trunk / libraries / libRaster / src / org / gvsig / raster / buffer / RasterBuffer.java @ 11453
History | View | Annotate | Download (29.1 KB)
1 |
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
|
---|---|
2 |
*
|
3 |
* Copyright (C) 2007 IVER T.I. and Generalitat Valenciana.
|
4 |
*
|
5 |
* This program is free software; you can redistribute it and/or
|
6 |
* modify it under the terms of the GNU General Public License
|
7 |
* as published by the Free Software Foundation; either version 2
|
8 |
* of the License, or (at your option) any later version.
|
9 |
*
|
10 |
* This program is distributed in the hope that it will be useful,
|
11 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13 |
* GNU General Public License for more details.
|
14 |
*
|
15 |
* You should have received a copy of the GNU General Public License
|
16 |
* along with this program; if not, write to the Free Software
|
17 |
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,USA.
|
18 |
*/
|
19 |
package org.gvsig.raster.buffer; |
20 |
|
21 |
import java.io.FileNotFoundException; |
22 |
|
23 |
import org.gvsig.raster.RasterLibrary; |
24 |
import org.gvsig.raster.buffer.cache.RasterCache; |
25 |
import org.gvsig.raster.buffer.cache.RasterReadOnlyHugeBuffer; |
26 |
import org.gvsig.raster.dataset.IBuffer; |
27 |
import org.gvsig.raster.dataset.NotSupportedExtensionException; |
28 |
import org.gvsig.raster.dataset.RasterDriverException; |
29 |
import org.gvsig.raster.util.Histogram; |
30 |
import org.gvsig.raster.util.HistogramException; |
31 |
import org.gvsig.raster.util.IHistogramable; |
32 |
import org.gvsig.raster.util.RasterUtilities; |
33 |
|
34 |
/**
|
35 |
* Rectangulo de pixeles. Para cada tipo de datos java hay un buffer distinto donde cada elemento es
|
36 |
* accedido de la siguiente forma: [banda][fila][columna]
|
37 |
* m[1][2][0] = cte;-> Sustituye el elemento de la fila 2 de la banda 1 columna 0
|
38 |
* m[1][0] = array; -> Sustituye la fila 0 de la banda 1
|
39 |
* m[0] = matriz cuadrada; -> Sustituye la banda entera.
|
40 |
*
|
41 |
*/
|
42 |
public abstract class RasterBuffer implements IBuffer { |
43 |
public static final int CANCEL_HISTOGRAM = IHistogramable.CANCEL_HISTOGRAM; |
44 |
protected boolean[] cancel = new boolean[1]; |
45 |
|
46 |
//Espacio en memoria (en Megas) que hay que sobrepasar para empezar a cachear.
|
47 |
private static int cacheMemorySize = 25; |
48 |
//Espacio en memoria (en Megas) que hay que sobrepasar para empezar a cachear en multipagina.
|
49 |
private static int multicacheMemorySize = 100; |
50 |
|
51 |
public double noDataValue = -99999; |
52 |
|
53 |
protected int percent = 0; |
54 |
protected boolean canceled = false; |
55 |
|
56 |
protected int width; |
57 |
protected int height; |
58 |
protected int nBands; |
59 |
protected int dataType; |
60 |
|
61 |
/**
|
62 |
* Variable est?tica que si est? a false desactiva el uso de cach?. Puede ser usada por un cliente
|
63 |
* para cargar siempre los datos en memoria. independientemente de su tama?o.
|
64 |
*/
|
65 |
public static boolean cacheOn = true; |
66 |
/**
|
67 |
* Fuerza la carga de los datos en cach? independientemente de su tama?o. Su
|
68 |
* uso suele ser util solo para depuraci?n. Su valor por defecto y recomendado
|
69 |
* es siempre false.
|
70 |
*/
|
71 |
public static boolean forceToLoadInCache = false; |
72 |
/**
|
73 |
* Fuerza la carga de los datos en cach? de solo lectura independientemente de su tama?o. Su
|
74 |
* uso suele ser util solo para depuraci?n. Su valor por defecto y recomendado
|
75 |
* es siempre false.
|
76 |
*/
|
77 |
public static boolean forceToLoadInReadOnlyCache = false; |
78 |
/**
|
79 |
* Valor con el que se rellena una banda no valida del buffer. Una banda no valida es la que
|
80 |
* no tiene datos asignados y tampoco puede ser null. Todas las bandas no validas de un buffer
|
81 |
* apuntan por referencia a la misma banda.
|
82 |
*/
|
83 |
protected double notValidValue = 0D; |
84 |
|
85 |
/**
|
86 |
* Genera instancias del buffer de datos adecuado al tama?o del raster. Si no hay muchos datos
|
87 |
* (menos de cacheMemorySize) crear? un buffer en memoria. Si hay m?s de esta cantidad
|
88 |
* entonces crearemos un buffer cacheado (RasterCache). A partir de la cantidad se?alada
|
89 |
* por multicacheMemorySize haremos un buffer cacheado donde cada p?gina no ocupa todo
|
90 |
* el ancho del raster ya que este ser? muy grande. La gesti?n de una cache donde cada
|
91 |
* pagina ha de partir una l?nea lleva una complejidad a?adida.
|
92 |
*
|
93 |
* @param dataType Tipo de dato
|
94 |
* @param width Ancho
|
95 |
* @param height Alto
|
96 |
* @param bandNr Banda
|
97 |
* @param flag En caso de buffers de memoria este flag a true significa que se reserva la memoria
|
98 |
* para el buffer de forma normal y si est? a false no se reserva por lo que la reserva deber? ser
|
99 |
* posterior.
|
100 |
* @return Objeto RasterBuffer
|
101 |
* @throws RasterDriverException
|
102 |
* @throws NotSupportedExtensionException
|
103 |
* @throws FileNotFoundException
|
104 |
*/
|
105 |
public static RasterBuffer getBuffer(int dataType, int width, int height, int bandNr, boolean malloc) |
106 |
/*throws FileNotFoundException, NotSupportedExtensionException, RasterDriverException*/{
|
107 |
//Opci?n de cachear siempre activada (Solo DEBUG)
|
108 |
if(forceToLoadInCache)
|
109 |
return new RasterCache(dataType, width, height, bandNr); |
110 |
if(forceToLoadInReadOnlyCache){
|
111 |
try {
|
112 |
return new RasterReadOnlyHugeBuffer(dataType, width, height, bandNr); |
113 |
} catch (FileNotFoundException e) { |
114 |
//TODO: EXCEPTION: Modificar el lanzamiento de excepciones del RasterBuffer
|
115 |
e.printStackTrace(); |
116 |
} catch (NotSupportedExtensionException e) {
|
117 |
e.printStackTrace(); |
118 |
} catch (RasterDriverException e) {
|
119 |
e.printStackTrace(); |
120 |
} |
121 |
} |
122 |
|
123 |
if(cacheOn){
|
124 |
long size = (RasterUtilities.getBytesFromRasterBufType(dataType) * width * height * bandNr) / 1024; |
125 |
long ms1 = cacheMemorySize * 1024; |
126 |
long ms2 = multicacheMemorySize * 1024; |
127 |
if(size <= ms1)
|
128 |
return new RasterMemoryBuffer(dataType, width, height, bandNr, malloc); |
129 |
else{
|
130 |
//if(filePath == null)
|
131 |
return new RasterCache(dataType, width, height, bandNr); |
132 |
/*else
|
133 |
return new RasterReadOnlyHugeBuffer(dataType, width, height, bandNr, filePath);*/
|
134 |
} |
135 |
}else
|
136 |
return new RasterMemoryBuffer(dataType, width, height, bandNr, malloc); |
137 |
} |
138 |
|
139 |
/**
|
140 |
* Reserva de memoria para el rasterbuf
|
141 |
* @param dataType Tipo de dato
|
142 |
* @param width Ancho
|
143 |
* @param height Alto
|
144 |
* @param bandNr Numero de bandas
|
145 |
* @param orig
|
146 |
*/
|
147 |
public abstract void malloc(int dataType, int width, int height, int bandNr); |
148 |
|
149 |
/*
|
150 |
* (non-Javadoc)
|
151 |
* @see org.gvsig.fmap.driver.IBuffer#getWidth()
|
152 |
*/
|
153 |
public int getWidth() { |
154 |
return width;
|
155 |
} |
156 |
|
157 |
/*
|
158 |
* (non-Javadoc)
|
159 |
* @see org.gvsig.fmap.driver.IBuffer#getHeight()
|
160 |
*/
|
161 |
public int getHeight() { |
162 |
return height;
|
163 |
} |
164 |
|
165 |
/*
|
166 |
* (non-Javadoc)
|
167 |
* @see org.gvsig.fmap.driver.IBuffer#getBandCount()
|
168 |
*/
|
169 |
public int getBandCount() { |
170 |
return nBands;
|
171 |
} |
172 |
|
173 |
/**
|
174 |
* Obtiene el tipo de dato. Los tipos de dato posibles est?n definidos en IRaster.
|
175 |
* @return tipo de datos
|
176 |
*/
|
177 |
public int getDataType() { |
178 |
return dataType;
|
179 |
} |
180 |
|
181 |
/**
|
182 |
* Asigna el tipo de dato. Los tipos de dato posibles est?n definidos en IRaster.
|
183 |
* @param dataType Tipo de dato del buffer
|
184 |
*/
|
185 |
public void setDataType(int dataType) { |
186 |
this.dataType = dataType;
|
187 |
} |
188 |
|
189 |
/**
|
190 |
* Obtiene el tama?o del tipo de dato en bytes
|
191 |
* @return Tipo de dato
|
192 |
*/
|
193 |
public int getDataSize() { |
194 |
if (dataType == TYPE_BYTE) {
|
195 |
return 1; |
196 |
} else if ((dataType == TYPE_SHORT) | (dataType == TYPE_USHORT)) { |
197 |
return 2; |
198 |
} else if (dataType == TYPE_INT) { |
199 |
return 4; |
200 |
}else if (dataType == TYPE_FLOAT) { |
201 |
return 8; |
202 |
}else if (dataType == TYPE_DOUBLE) { |
203 |
return 16; |
204 |
} |
205 |
|
206 |
return 0; |
207 |
} |
208 |
|
209 |
/**
|
210 |
* Obtiene el tama?o del buffer
|
211 |
* @return tama?o del buffer
|
212 |
*/
|
213 |
public long sizeof() { |
214 |
return getDataSize() * width * height * nBands;
|
215 |
} |
216 |
|
217 |
/**
|
218 |
* Replica la banda de una posici?n sobre otra. Si la banda de destino no existe
|
219 |
* se crea nueva. Si la posici?n de la banda de destino est? intercalada entre bandas
|
220 |
* que ya existen las otras se desplazan hacia abajo, NO se machacan los datos de ninguna.
|
221 |
* Los datos se replican por referencia por lo que al modificar la banda original las
|
222 |
* del resto quedar?n afectadas.
|
223 |
* @param orig. Posici?n de la banda de origen.
|
224 |
* @param dest. Posici?n de la banda destino
|
225 |
*/
|
226 |
public abstract void replicateBand(int orig, int dest); |
227 |
|
228 |
/**
|
229 |
* Cambia bandas de posici?n. Las posiciones deben existir como bandas del raster.
|
230 |
* Cada elemento del array representa una banda existente en el buffer (de longitud
|
231 |
* rasterBuf.length) y el valor contenido dentro la banda que le corresponde. Por ejemplo
|
232 |
* si pasamos un array {1, 0, 3, 2} significa que el buffer tiene cuatro bandas y que
|
233 |
* cambiamos la 0 por la 1 y la 2 por la 3. Un array {0, 1, 2, 3} en el mismo
|
234 |
* caso no producir?a nig?n cambio.
|
235 |
*
|
236 |
* Si quisieramos asignar en un buffer monobanda su banda a la segunda posici?n habria
|
237 |
* que insertar una vacia, por ejemplo con addBandFloat(0, null) se insertaria una
|
238 |
* banda nula en la posici?n 0 y la banda que estaba en la 0 pasar?a a la segunda.
|
239 |
*
|
240 |
*/
|
241 |
public abstract void switchBands(int[] bandPosition); |
242 |
|
243 |
/**
|
244 |
* Convierte un tipo de dato a cadena
|
245 |
* @param type Tipo de dato
|
246 |
* @return cadena que representa el tipo de dato
|
247 |
*/
|
248 |
public static String typesToString(int type) { |
249 |
switch (type) {
|
250 |
case RasterBuffer.TYPE_IMAGE:
|
251 |
return new String("Image"); |
252 |
|
253 |
case RasterBuffer.TYPE_BYTE:
|
254 |
return new String("Byte"); |
255 |
|
256 |
case RasterBuffer.TYPE_DOUBLE:
|
257 |
return new String("Double"); |
258 |
|
259 |
case RasterBuffer.TYPE_FLOAT:
|
260 |
return new String("Float"); |
261 |
|
262 |
case RasterBuffer.TYPE_INT:
|
263 |
return new String("Integer"); |
264 |
|
265 |
case RasterBuffer.TYPE_USHORT:
|
266 |
case RasterBuffer.TYPE_SHORT:
|
267 |
return new String("Short"); |
268 |
} |
269 |
|
270 |
return null; |
271 |
} |
272 |
|
273 |
/**
|
274 |
* Ajusta el raster al ancho y alto solicitado por el vecino m?s cercano. Promedia el valor de dos
|
275 |
* pixeles contiguos.
|
276 |
* @param w Nuevo ancho
|
277 |
* @param h Nuevo alto
|
278 |
*/
|
279 |
private RasterBuffer adjustRasterNearestNeighbourInterpolation(int w, int h) { |
280 |
double stepX = (double)w / (double)width; |
281 |
double stepY = (double)h / (double)height; |
282 |
RasterBuffer rasterBuf = new RasterMemoryBuffer(getDataType(), w, h, getBandCount(), true); |
283 |
|
284 |
int[] bands = new int[rasterBuf.getBandCount()]; |
285 |
for(int iBand = 0; iBand < rasterBuf.getBandCount(); iBand ++) |
286 |
bands[iBand] = iBand; |
287 |
|
288 |
|
289 |
switch (dataType) {
|
290 |
case RasterBuffer.TYPE_BYTE:
|
291 |
for(int iBand = 0; iBand < bands.length; iBand ++) { |
292 |
if(w <= width) { //submuestreo |
293 |
for(int iRow = 0; iRow < height; iRow ++) |
294 |
for(int iCol = 0; iCol < width; iCol ++) |
295 |
rasterBuf.setElem((int)(iRow * stepY), (int)(iCol * stepX), bands[iBand], getElemByte(iRow, iCol, iBand)); |
296 |
}else{ //supermuestreo |
297 |
for(int iRow = 0; iRow < h; iRow ++) |
298 |
for(int iCol = 0; iCol < w; iCol ++) |
299 |
rasterBuf.setElem(iRow, iCol, bands[iBand], getElemByte((int)(iRow / stepY), (int)(iCol / stepX), iBand)); |
300 |
} |
301 |
} |
302 |
break;
|
303 |
case RasterBuffer.TYPE_DOUBLE:
|
304 |
for(int iBand = 0; iBand < bands.length; iBand ++) { |
305 |
if(w <= width) { //submuestreo |
306 |
for(int iRow = 0; iRow < height; iRow ++) |
307 |
for(int iCol = 0; iCol < width; iCol ++) |
308 |
rasterBuf.setElem((int)(iRow * stepY), (int)(iCol * stepX), bands[iBand], getElemDouble(iRow, iCol, iBand)); |
309 |
}else{ //supermuestreo |
310 |
for(int iRow = 0; iRow < h; iRow ++) |
311 |
for(int iCol = 0; iCol < w; iCol ++) |
312 |
rasterBuf.setElem(iRow, iCol, bands[iBand], getElemDouble((int)(iRow / stepY), (int)(iCol / stepX), iBand)); |
313 |
} |
314 |
} |
315 |
break;
|
316 |
case RasterBuffer.TYPE_FLOAT:
|
317 |
for(int iBand = 0; iBand < bands.length; iBand ++) { |
318 |
if(w <= width) { //submuestreo |
319 |
for(int iRow = 0; iRow < height; iRow ++) |
320 |
for(int iCol = 0; iCol < width; iCol ++) |
321 |
rasterBuf.setElem((int)(iRow * stepY), (int)(iCol * stepX), bands[iBand], getElemFloat(iRow, iCol, iBand)); |
322 |
}else{ //supermuestreo |
323 |
for(int iRow = 0; iRow < h; iRow ++) |
324 |
for(int iCol = 0; iCol < w; iCol ++) |
325 |
rasterBuf.setElem(iRow, iCol, bands[iBand], getElemFloat((int)(iRow / stepY), (int)(iCol / stepX), iBand)); |
326 |
} |
327 |
} |
328 |
break;
|
329 |
case RasterBuffer.TYPE_INT:
|
330 |
for(int iBand = 0; iBand < bands.length; iBand ++) { |
331 |
if(w <= width) { //submuestreo |
332 |
for(int iRow = 0; iRow < height; iRow ++) |
333 |
for(int iCol = 0; iCol < width; iCol ++) |
334 |
rasterBuf.setElem((int)(iRow * stepY), (int)(iCol * stepX), bands[iBand], getElemInt(iRow, iCol, iBand)); |
335 |
}else{ //supermuestreo |
336 |
for(int iRow = 0; iRow < h; iRow ++) |
337 |
for(int iCol = 0; iCol < w; iCol ++) |
338 |
rasterBuf.setElem(iRow, iCol, bands[iBand], getElemInt((int)(iRow / stepY), (int)(iCol / stepX), iBand)); |
339 |
} |
340 |
} |
341 |
break;
|
342 |
case RasterBuffer.TYPE_USHORT:
|
343 |
case RasterBuffer.TYPE_SHORT:
|
344 |
for(int iBand = 0; iBand < bands.length; iBand ++) { |
345 |
if(w <= width) { //submuestreo |
346 |
for(int iRow = 0; iRow < height; iRow ++) |
347 |
for(int iCol = 0; iCol < width; iCol ++) |
348 |
rasterBuf.setElem((int)(iRow * stepY), (int)(iCol * stepX), bands[iBand], getElemShort(iRow, iCol, iBand)); |
349 |
}else{ //supermuestreo |
350 |
for(int iRow = 0; iRow < h; iRow ++) |
351 |
for(int iCol = 0; iCol < w; iCol ++) |
352 |
rasterBuf.setElem(iRow, iCol, bands[iBand], getElemShort((int)(iRow / stepY), (int)(iCol / stepX), iBand)); |
353 |
} |
354 |
} |
355 |
break;
|
356 |
} |
357 |
return rasterBuf;
|
358 |
} |
359 |
|
360 |
/**
|
361 |
* Ajusta el raster al ancho y alto solicitado ajustando con una interpolaci?n bilineal. Promedia
|
362 |
* el valor de cuatro pixeles adyacentes.
|
363 |
* @param w Nuevo ancho
|
364 |
* @param h Nuevo alto
|
365 |
*/
|
366 |
private RasterBuffer adjustRasterBilinearInterpolation(int w, int h) { |
367 |
double pxSize = (double)width / (double)w; |
368 |
RasterBuffer rasterBuf = new RasterMemoryBuffer(getDataType(), w, h, getBandCount(), true); |
369 |
|
370 |
double posX = pxSize / 2D; |
371 |
double posY = posX;
|
372 |
double dx = 0D, dy = 0D; |
373 |
|
374 |
for(int iBand = 0; iBand < getBandCount(); iBand ++) { |
375 |
posY = pxSize / 2D;
|
376 |
switch (dataType) {
|
377 |
case RasterBuffer.TYPE_BYTE:
|
378 |
for(int iRow = 0; iRow < h; iRow ++) { |
379 |
dy = posY - ((int)posY);
|
380 |
posX = pxSize / 2D;
|
381 |
for(int iCol = 0; iCol < w; iCol ++) { |
382 |
dx = posX - ((int)posX);
|
383 |
double[] kernel = getKernelByte(((int)posX), ((int)posY), iBand); |
384 |
double[] nz = getBilinearNZ(dx, dy, kernel); |
385 |
double b = 0; |
386 |
if(nz[0] > 0.0) |
387 |
b = (nz[1] / nz[0]); |
388 |
rasterBuf.setElem(iRow, iCol, iBand, (byte)((byte)b & 0xff)); |
389 |
posX += pxSize; |
390 |
} |
391 |
posY += pxSize; |
392 |
} |
393 |
break;
|
394 |
case RasterBuffer.TYPE_SHORT:
|
395 |
for(int iRow = 0; iRow < h; iRow ++) { |
396 |
dy = posY - ((int)posY);
|
397 |
posX = pxSize / 2D;
|
398 |
for(int iCol = 0; iCol < w; iCol ++) { |
399 |
dx = posX - ((int)posX);
|
400 |
double[] kernel = getKernelShort(((int)posX), ((int)posY), iBand); |
401 |
double[] nz = getBilinearNZ(dx, dy, kernel); |
402 |
double b = 0; |
403 |
if(nz[0] > 0.0) |
404 |
b = (nz[1] / nz[0]); |
405 |
rasterBuf.setElem(iRow, iCol, iBand, (short)((short)b & 0xffff)); |
406 |
posX += pxSize; |
407 |
} |
408 |
posY += pxSize; |
409 |
} |
410 |
break;
|
411 |
case RasterBuffer.TYPE_INT:
|
412 |
for(int iRow = 0; iRow < h; iRow ++) { |
413 |
dy = posY - ((int)posY);
|
414 |
posX = pxSize / 2D;
|
415 |
for(int iCol = 0; iCol < w; iCol ++) { |
416 |
dx = posX - ((int)posX);
|
417 |
double[] kernel = getKernelInt(((int)posX), ((int)posY), iBand); |
418 |
double[] nz = getBilinearNZ(dx, dy, kernel); |
419 |
double b = 0; |
420 |
if(nz[0] > 0.0) |
421 |
b = (nz[1] / nz[0]); |
422 |
rasterBuf.setElem(iRow, iCol, iBand, (int)((int)b & 0xff)); |
423 |
posX += pxSize; |
424 |
} |
425 |
posY += pxSize; |
426 |
} |
427 |
break;
|
428 |
case RasterBuffer.TYPE_FLOAT:
|
429 |
for(int iRow = 0; iRow < h; iRow ++) { |
430 |
dy = posY - ((int)posY);
|
431 |
posX = pxSize / 2D;
|
432 |
for(int iCol = 0; iCol < w; iCol ++) { |
433 |
dx = posX - ((int)posX);
|
434 |
double[] kernel = getKernelFloat(((int)posX), ((int)posY), iBand); |
435 |
double[] nz = getBilinearNZ(dx, dy, kernel); |
436 |
double b = 0; |
437 |
if(nz[0] > 0.0) |
438 |
b = (nz[1] / nz[0]); |
439 |
rasterBuf.setElem(iRow, iCol, iBand, (float)b);
|
440 |
posX += pxSize; |
441 |
} |
442 |
posY += pxSize; |
443 |
} |
444 |
break;
|
445 |
case RasterBuffer.TYPE_DOUBLE:
|
446 |
for(int iRow = 0; iRow < h; iRow ++) { |
447 |
dy = posY - ((int)posY);
|
448 |
posX = pxSize / 2D;
|
449 |
for(int iCol = 0; iCol < w; iCol ++) { |
450 |
dx = posX - ((int)posX);
|
451 |
double[] kernel = getKernelDouble(((int)posX), ((int)posY), iBand); |
452 |
double[] nz = getBilinearNZ(dx, dy, kernel); |
453 |
double b = 0; |
454 |
if(nz[0] > 0.0) |
455 |
b = (nz[1] / nz[0]); |
456 |
rasterBuf.setElem(iRow, iCol, iBand, (double)b);
|
457 |
posX += pxSize; |
458 |
} |
459 |
posY += pxSize; |
460 |
} |
461 |
break;
|
462 |
} |
463 |
|
464 |
} |
465 |
|
466 |
return rasterBuf;
|
467 |
} |
468 |
|
469 |
/**
|
470 |
* Calcula los valores N y Z para el m?todo bilinear
|
471 |
* @param dx
|
472 |
* @param dy
|
473 |
* @param kernel
|
474 |
* @return
|
475 |
*/
|
476 |
private double[] getBilinearNZ(double dx, double dy, double[] kernel) { |
477 |
double z = 0.0, n = 0.0, d; |
478 |
d = (1.0 - dx) * (1.0 - dy); |
479 |
z += d * kernel[0];
|
480 |
n += d; |
481 |
|
482 |
d = dx * (1.0 - dy);
|
483 |
z += d * kernel[1];
|
484 |
n += d; |
485 |
|
486 |
d = (1.0 - dx) * dy;
|
487 |
z += d * kernel[2];
|
488 |
n += d; |
489 |
|
490 |
d = dx * dy; |
491 |
z += d * kernel[3];
|
492 |
n += d; |
493 |
return new double[]{n, z}; |
494 |
} |
495 |
|
496 |
/**
|
497 |
* Obtiene un kernel de cuatro elemento que corresponden a los pixeles (x, y), (x + 1, y),
|
498 |
* (x, y + 1), (x + 1, y + 1). Si los pixeles x + 1 o y + 1 se salen del raster de origen
|
499 |
* se tomar? x e y.
|
500 |
* @param x Coordenada X del pixel inicial
|
501 |
* @param y Coordenada Y del pixel inicial
|
502 |
* @param band N?mero de banda.
|
503 |
* @return Kernel solicitado en forma de array.
|
504 |
*/
|
505 |
private double[] getKernelByte(int x, int y, int band) { |
506 |
double[] d = new double[4]; |
507 |
d[0] = (getElemByte(y, x, band) & 0xff); |
508 |
int nextX = ((x + 1) >= getWidth()) ? x : (x + 1); |
509 |
int nextY = ((y + 1) >= getHeight()) ? y : (y + 1); |
510 |
d[1] = (getElemByte(y, nextX, band) & 0xff); |
511 |
d[2] = (getElemByte(nextY, x, band) & 0xff); |
512 |
d[3] = (getElemByte(nextY, nextX, band) & 0xff); |
513 |
return d;
|
514 |
} |
515 |
|
516 |
/**
|
517 |
* Obtiene un kernel de cuatro elemento que corresponden a los pixeles (x, y), (x + 1, y),
|
518 |
* (x, y + 1), (x + 1, y + 1). Si los pixeles x + 1 o y + 1 se salen del raster de origen
|
519 |
* se tomar? x e y.
|
520 |
* @param x Coordenada X del pixel inicial
|
521 |
* @param y Coordenada Y del pixel inicial
|
522 |
* @param band N?mero de banda.
|
523 |
* @return Kernel solicitado en forma de array.
|
524 |
*/
|
525 |
private double[] getKernelShort(int x, int y, int band) { |
526 |
double[] d = new double[4]; |
527 |
d[0] = (getElemShort(y, x, band) & 0xffff); |
528 |
int nextX = ((x + 1) >= getWidth()) ? x : (x + 1); |
529 |
int nextY = ((y + 1) >= getHeight()) ? y : (y + 1); |
530 |
d[1] = (getElemShort(y, nextX, band) & 0xffff); |
531 |
d[2] = (getElemShort(nextY, x, band) & 0xffff); |
532 |
d[3] = (getElemShort(nextY, nextX, band) & 0xffff); |
533 |
return d;
|
534 |
} |
535 |
|
536 |
/**
|
537 |
* Obtiene un kernel de cuatro elemento que corresponden a los pixeles (x, y), (x + 1, y),
|
538 |
* (x, y + 1), (x + 1, y + 1). Si los pixeles x + 1 o y + 1 se salen del raster de origen
|
539 |
* se tomar? x e y.
|
540 |
* @param x Coordenada X del pixel inicial
|
541 |
* @param y Coordenada Y del pixel inicial
|
542 |
* @param band N?mero de banda.
|
543 |
* @return Kernel solicitado en forma de array.
|
544 |
*/
|
545 |
private double[] getKernelInt(int x, int y, int band) { |
546 |
double[] d = new double[4]; |
547 |
d[0] = (getElemInt(y, x, band) & 0xffffffff); |
548 |
int nextX = ((x + 1) >= getWidth()) ? x : (x + 1); |
549 |
int nextY = ((y + 1) >= getHeight()) ? y : (y + 1); |
550 |
d[1] = (getElemInt(y, nextX, band) & 0xffffffff); |
551 |
d[2] = (getElemInt(nextY, x, band) & 0xffffffff); |
552 |
d[3] = (getElemInt(nextY, nextX, band) & 0xffffffff); |
553 |
return d;
|
554 |
} |
555 |
|
556 |
/**
|
557 |
* Obtiene un kernel de cuatro elemento que corresponden a los pixeles (x, y), (x + 1, y),
|
558 |
* (x, y + 1), (x + 1, y + 1). Si los pixeles x + 1 o y + 1 se salen del raster de origen
|
559 |
* se tomar? x e y.
|
560 |
* @param x Coordenada X del pixel inicial
|
561 |
* @param y Coordenada Y del pixel inicial
|
562 |
* @param band N?mero de banda.
|
563 |
* @return Kernel solicitado en forma de array.
|
564 |
*/
|
565 |
private double[] getKernelFloat(int x, int y, int band) { |
566 |
double[] d = new double[4]; |
567 |
d[0] = getElemFloat(y, x, band);
|
568 |
int nextX = ((x + 1) >= getWidth()) ? x : (x + 1); |
569 |
int nextY = ((y + 1) >= getHeight()) ? y : (y + 1); |
570 |
d[1] = getElemFloat(y, nextX, band);
|
571 |
d[2] = getElemFloat(nextY, x, band);
|
572 |
d[3] = getElemFloat(nextY, nextX, band);
|
573 |
return d;
|
574 |
} |
575 |
|
576 |
/**
|
577 |
* Obtiene un kernel de cuatro elemento que corresponden a los pixeles (x, y), (x + 1, y),
|
578 |
* (x, y + 1), (x + 1, y + 1). Si los pixeles x + 1 o y + 1 se salen del raster de origen
|
579 |
* se tomar? x e y.
|
580 |
* @param x Coordenada X del pixel inicial
|
581 |
* @param y Coordenada Y del pixel inicial
|
582 |
* @param band N?mero de banda.
|
583 |
* @return Kernel solicitado en forma de array.
|
584 |
*/
|
585 |
private double[] getKernelDouble(int x, int y, int band) { |
586 |
double[] d = new double[4]; |
587 |
d[0] = getElemDouble(y, x, band);
|
588 |
int nextX = ((x + 1) >= getWidth()) ? x : (x + 1); |
589 |
int nextY = ((y + 1) >= getHeight()) ? y : (y + 1); |
590 |
d[1] = getElemDouble(y, nextX, band);
|
591 |
d[2] = getElemDouble(nextY, x, band);
|
592 |
d[3] = getElemDouble(nextY, nextX, band);
|
593 |
return d;
|
594 |
} |
595 |
|
596 |
/**
|
597 |
* Ajusta el raster al ancho y alto solicitado ajustando con una interpolaci?n de distancia inversa.
|
598 |
* Asigna el valor de un pixel en funci?n inversa de la distancia.
|
599 |
*
|
600 |
* @param w Nuevo ancho
|
601 |
* @param h Nuevo alto
|
602 |
*/
|
603 |
private RasterBuffer adjustRasterInverseDistanceInterpolation(int w, int h) { |
604 |
return this; |
605 |
} |
606 |
|
607 |
/**
|
608 |
* Ajusta el raster al ancho y alto solicitado ajustando con una interpolaci?n de spline bicubica.
|
609 |
* @param w Nuevo ancho
|
610 |
* @param h Nuevo alto
|
611 |
*/
|
612 |
private RasterBuffer adjustRasterBicubicSplineInterpolation(int w, int h) { |
613 |
return this; |
614 |
} |
615 |
|
616 |
/**
|
617 |
* Ajusta el raster al ancho y alto solicitado ajustando con una interpolaci?n BSpline.
|
618 |
* @param w Nuevo ancho
|
619 |
* @param h Nuevo alto
|
620 |
*/
|
621 |
private RasterBuffer adjustRasterBSplineInterpolation(int w, int h) { |
622 |
return this; |
623 |
} |
624 |
|
625 |
/*
|
626 |
* (non-Javadoc)
|
627 |
* @see org.gvsig.fmap.driver.IBuffer#getNoDataValue()
|
628 |
*/
|
629 |
public double getNoDataValue() { |
630 |
return noDataValue;
|
631 |
} |
632 |
|
633 |
/*
|
634 |
* (non-Javadoc)
|
635 |
* @see org.gvsig.fmap.driver.IBuffer#getByteNoDataValue()
|
636 |
*/
|
637 |
public byte getByteNoDataValue() { |
638 |
return (byte)noDataValue; |
639 |
} |
640 |
|
641 |
/*
|
642 |
* (non-Javadoc)
|
643 |
* @see org.gvsig.fmap.driver.IBuffer#getShortNoDataValue()
|
644 |
*/
|
645 |
public short getShortNoDataValue(){ |
646 |
return (short)noDataValue; |
647 |
} |
648 |
|
649 |
/*
|
650 |
* (non-Javadoc)
|
651 |
* @see org.gvsig.fmap.driver.IBuffer#getIntNoDataValue()
|
652 |
*/
|
653 |
public int getIntNoDataValue(){ |
654 |
return (int)noDataValue; |
655 |
} |
656 |
|
657 |
/*
|
658 |
* (non-Javadoc)
|
659 |
* @see org.gvsig.fmap.driver.IBuffer#getFloatNoDataValue()
|
660 |
*/
|
661 |
public float getFloatNoDataValue(){ |
662 |
return (float)noDataValue; |
663 |
} |
664 |
|
665 |
/*
|
666 |
* (non-Javadoc)
|
667 |
* @see org.gvsig.fmap.driver.IBuffer#setNoDataValue(double)
|
668 |
*/
|
669 |
public void setNoDataValue(double nd){ |
670 |
noDataValue = nd; |
671 |
} |
672 |
|
673 |
/*
|
674 |
* (non-Javadoc)
|
675 |
* @see org.gvsig.fmap.driver.IBuffer#getNotValidValue()
|
676 |
*/
|
677 |
public double getNotValidValue(){ |
678 |
return notValidValue;
|
679 |
} |
680 |
|
681 |
/*
|
682 |
* (non-Javadoc)
|
683 |
* @see org.gvsig.fmap.driver.IBuffer#setNotValidValue(java.lang.Object)
|
684 |
*/
|
685 |
public void setNotValidValue(double value){ |
686 |
this.notValidValue = value;
|
687 |
} |
688 |
|
689 |
/*
|
690 |
* (non-Javadoc)
|
691 |
* @see org.gvsig.fmap.driver.IBuffer#cloneBuffer()
|
692 |
*/
|
693 |
public abstract IBuffer cloneBuffer(); |
694 |
|
695 |
/**
|
696 |
* Ajusta el ?rea del grid a un ancho y un alto dado en pixeles. Este ajuste se har?
|
697 |
* en relaci?n a un m?todo de interpolaci?n definido en el par?metro.
|
698 |
* @param w Ancho de la nueva imagen.
|
699 |
* @param h Alto de la nueva imagen.
|
700 |
* @param interpolation M?todo de interpolaci?n que se usar? en el ajuste.
|
701 |
*/
|
702 |
public RasterBuffer getAdjustedWindow(int w, int h, int interpolationMethod) { |
703 |
if(w == getWidth() && h == getHeight())
|
704 |
return this; |
705 |
RasterBuffer rasterBuf = null;
|
706 |
switch(interpolationMethod) {
|
707 |
case IQueryableRaster.INTERPOLATION_NearestNeighbour:
|
708 |
rasterBuf = adjustRasterNearestNeighbourInterpolation(w, h); |
709 |
break;
|
710 |
case IQueryableRaster.INTERPOLATION_Bilinear:
|
711 |
rasterBuf = adjustRasterBilinearInterpolation(w, h); |
712 |
break;
|
713 |
case IQueryableRaster.INTERPOLATION_InverseDistance:
|
714 |
rasterBuf = adjustRasterInverseDistanceInterpolation(w, h); |
715 |
break;
|
716 |
case IQueryableRaster.INTERPOLATION_BicubicSpline:
|
717 |
rasterBuf = adjustRasterBicubicSplineInterpolation(w, h); |
718 |
break;
|
719 |
case IQueryableRaster.INTERPOLATION_BSpline:
|
720 |
rasterBuf = adjustRasterBSplineInterpolation(w, h); |
721 |
break;
|
722 |
} |
723 |
return rasterBuf;
|
724 |
} |
725 |
|
726 |
/**
|
727 |
* Calcula el m?nimo y el m?ximo del histograma previamente.
|
728 |
* @return double[] con el m?nimo y el m?ximo.
|
729 |
*/
|
730 |
private double[] getLimits() { |
731 |
double max = Double.NEGATIVE_INFINITY; |
732 |
double min = Double.MAX_VALUE; |
733 |
double value = 0; |
734 |
|
735 |
switch (getDataType()) {
|
736 |
case IBuffer.TYPE_BYTE:
|
737 |
for (int i = 0; i < getBandCount(); i++) |
738 |
for (int r = 0; r < getHeight(); r++) { |
739 |
for (int c = 0; c < getWidth(); c++) { |
740 |
value = (double) (getElemByte(r, c, i) & 0xff); |
741 |
if (value > max) max = value;
|
742 |
if (value < min) min = value;
|
743 |
} |
744 |
if (isCanceled(CANCEL_HISTOGRAM))
|
745 |
return null; |
746 |
} |
747 |
break;
|
748 |
case IBuffer.TYPE_SHORT:
|
749 |
for (int i = 0; i < getBandCount(); i++) |
750 |
for (int r = 0; r < getHeight(); r++) { |
751 |
for (int c = 0; c < getWidth(); c++) { |
752 |
value = (double) (getElemShort(r, c, i) & 0xffff); |
753 |
if (value > max) max = value;
|
754 |
if (value < min) min = value;
|
755 |
} |
756 |
if (isCanceled(CANCEL_HISTOGRAM))
|
757 |
return null; |
758 |
} |
759 |
break;
|
760 |
case IBuffer.TYPE_INT:
|
761 |
for (int i = 0; i < getBandCount(); i++) |
762 |
for (int r = 0; r < getHeight(); r++) { |
763 |
for (int c = 0; c < getWidth(); c++) { |
764 |
value = (double) (getElemInt(r, c, i) & 0xffffffff); |
765 |
if (value > max) max = value;
|
766 |
if (value < min) min = value;
|
767 |
} |
768 |
if (isCanceled(CANCEL_HISTOGRAM))
|
769 |
return null; |
770 |
} |
771 |
break;
|
772 |
case IBuffer.TYPE_FLOAT:
|
773 |
for (int i = 0; i < getBandCount(); i++) |
774 |
for (int r = 0; r < getHeight(); r++) { |
775 |
for (int c = 0; c < getWidth(); c++) { |
776 |
value = (double) getElemFloat(r, c, i);
|
777 |
if (value > max) max = value;
|
778 |
if (value < min) min = value;
|
779 |
} |
780 |
if (isCanceled(CANCEL_HISTOGRAM))
|
781 |
return null; |
782 |
} |
783 |
break;
|
784 |
case IBuffer.TYPE_DOUBLE:
|
785 |
for (int i = 0; i < getBandCount(); i++) |
786 |
for (int r = 0; r < getHeight(); r++) { |
787 |
for (int c = 0; c < getWidth(); c++) { |
788 |
value = getElemDouble(r, c, i); |
789 |
if (value > max) max = value;
|
790 |
if (value < min) min = value;
|
791 |
} |
792 |
if (isCanceled(CANCEL_HISTOGRAM))
|
793 |
return null; |
794 |
} |
795 |
break;
|
796 |
} |
797 |
double[] values = new double[2]; |
798 |
values[0] = min;
|
799 |
values[1] = max;
|
800 |
return values;
|
801 |
} |
802 |
|
803 |
/*
|
804 |
* (non-Javadoc)
|
805 |
* @see org.gvsig.raster.driver.datasetproperties.IHistogramable#getHistogram()
|
806 |
*/
|
807 |
public Histogram getHistogram() throws HistogramException { |
808 |
percent = 0;
|
809 |
Histogram hist = null;
|
810 |
double[] limits = getLimits(); |
811 |
|
812 |
if (limits == null) |
813 |
return null; |
814 |
|
815 |
if (getDataType() == IBuffer.TYPE_BYTE)
|
816 |
hist = new Histogram(getBandCount(), 255, limits[0], limits[1]); |
817 |
else
|
818 |
hist = new Histogram(getBandCount(), RasterLibrary.defaultNumberOfClasses, limits[0], limits[1]); |
819 |
|
820 |
for (int iBand = 0; iBand < getBandCount(); iBand++) { |
821 |
for (int row = 0; row < getHeight(); row++) { |
822 |
switch(getDataType()) {
|
823 |
case IBuffer.TYPE_BYTE:
|
824 |
for (int col = 0; col < getWidth(); col++) |
825 |
hist.incrementPxValue(iBand, (double)(getElemByte(row, col, iBand) & 0xff)); |
826 |
break;
|
827 |
case IBuffer.TYPE_SHORT:
|
828 |
for (int col = 0; col < getWidth(); col++) |
829 |
hist.incrementPxValue(iBand, (double)(getElemShort(row, col, iBand) & 0xffff)); |
830 |
break;
|
831 |
case IBuffer.TYPE_INT:
|
832 |
for (int col = 0; col < getWidth(); col++) |
833 |
hist.incrementPxValue(iBand, (double)(getElemInt(row, col, iBand) & 0xffffffff)); |
834 |
break;
|
835 |
case IBuffer.TYPE_FLOAT:
|
836 |
for (int col = 0; col < getWidth(); col++) |
837 |
hist.incrementPxValue(iBand, (double)getElemFloat(row, col, iBand));
|
838 |
break;
|
839 |
case IBuffer.TYPE_DOUBLE:
|
840 |
for (int col = 0; col < getWidth(); col++) |
841 |
hist.incrementPxValue(iBand, getElemDouble(row, col, iBand)); |
842 |
break;
|
843 |
} |
844 |
|
845 |
if (isCanceled(CANCEL_HISTOGRAM))
|
846 |
return null; |
847 |
|
848 |
percent = ((iBand*getHeight() + row) * 100) /(getHeight() * getBandCount());
|
849 |
} |
850 |
} |
851 |
percent = 100;
|
852 |
return hist;
|
853 |
} |
854 |
|
855 |
/*
|
856 |
* (non-Javadoc)
|
857 |
* @see org.gvsig.raster.util.IHistogramable#resetPercent()
|
858 |
*/
|
859 |
public void resetPercent() { |
860 |
percent = 0;
|
861 |
} |
862 |
|
863 |
/*
|
864 |
* (non-Javadoc)
|
865 |
* @see org.gvsig.raster.util.IHistogramable#getPercent()
|
866 |
*/
|
867 |
public int getPercent() { |
868 |
return percent;
|
869 |
} |
870 |
|
871 |
/*
|
872 |
* (non-Javadoc)
|
873 |
* @see org.gvsig.raster.util.ICancellable#isCanceled()
|
874 |
*/
|
875 |
public boolean isCanceled(int process) { |
876 |
if(process == CANCEL_HISTOGRAM)
|
877 |
return cancel[0]; |
878 |
return false; |
879 |
} |
880 |
|
881 |
/*
|
882 |
* (non-Javadoc)
|
883 |
* @see org.gvsig.raster.util.ICancellable#setCanceled(boolean)
|
884 |
*/
|
885 |
public void setCanceled(boolean value, int process) { |
886 |
if(process == CANCEL_HISTOGRAM || process == 0) |
887 |
cancel[0] = value;
|
888 |
} |
889 |
} |