Statistics
| Revision:

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
}