Statistics
| Revision:

root / trunk / libraries / libRaster / src / org / gvsig / raster / buffer / RasterBuffer.java @ 11196

History | View | Annotate | Download (16.3 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.RasterUtilities;
32

    
33
/**
34
 * Rectangulo de pixeles. Para cada tipo de datos java hay un buffer distinto donde cada elemento es
35
 * accedido de la siguiente forma: [banda][fila][columna]
36
 * m[1][2][0] = cte;-> Sustituye el elemento de la fila 2 de la banda 1 columna 0
37
 * m[1][0] = array; -> Sustituye la fila 0 de la banda 1 
38
 * m[0] = matriz cuadrada; -> Sustituye la banda entera.
39
 * 
40
 */
41
public abstract class RasterBuffer implements IBuffer {
42
        //Espacio en memoria (en Megas) que hay que sobrepasar para empezar a cachear.
43
        private static int                cacheMemorySize = 25;
44
        //Espacio en memoria (en Megas) que hay que sobrepasar para empezar a cachear en multipagina.
45
        private static int                multicacheMemorySize = 100;
46
        
47
        public double                         noDataValue = -99999;
48

    
49
        protected int                                percent = 0;
50
        protected boolean                canceled = false;
51
        
52
  protected int                         width;
53
  protected int                         height;
54
  protected int                         nBands;
55
  protected int                         dataType;
56
  
57
  /**
58
   * Variable est?tica que si est? a false desactiva el uso de cach?. Puede ser usada por un cliente
59
   * para cargar siempre los datos en memoria. independientemente de su tama?o. 
60
   */
61
  public static boolean        cacheOn = true;
62
  /**
63
   * Fuerza la carga de los datos en cach? independientemente de su tama?o. Su
64
   * uso suele ser util solo para depuraci?n. Su valor por defecto y recomendado
65
   * es siempre false.
66
   */
67
  public static boolean         forceToLoadInCache = false;
68
  /**
69
   * Fuerza la carga de los datos en cach? de solo lectura independientemente de su tama?o. Su
70
   * uso suele ser util solo para depuraci?n. Su valor por defecto y recomendado
71
   * es siempre false.
72
   */
73
  public static boolean         forceToLoadInReadOnlyCache = false;
74
  /**
75
   * Valor con el que se rellena una banda no valida del buffer. Una banda no valida es la que 
76
   * no tiene datos asignados y tampoco puede ser null. Todas las bandas no validas de un buffer
77
   * apuntan por referencia a la misma banda.
78
   */
79
  protected double                notValidValue = 0D;
80

    
81
  /**
82
   * Genera instancias del buffer de datos adecuado al tama?o del raster. Si no hay muchos datos
83
   * (menos de cacheMemorySize) crear? un buffer en memoria. Si hay m?s de esta cantidad
84
   * entonces crearemos un buffer cacheado (RasterCache). A partir de la cantidad se?alada
85
   * por multicacheMemorySize haremos un buffer cacheado donde cada p?gina no ocupa todo
86
   * el ancho del raster ya que este ser? muy grande. La gesti?n de una cache donde cada
87
   * pagina ha de partir una l?nea lleva una complejidad a?adida.
88
   *  
89
   * @param dataType Tipo de dato
90
   * @param width Ancho
91
   * @param height Alto
92
   * @param bandNr Banda
93
   * @param malloc
94
   * @return
95
   * @throws RasterDriverException 
96
   * @throws NotSupportedExtensionException 
97
   * @throws FileNotFoundException 
98
   */
99
  public static RasterBuffer getBuffer(int dataType, int width, int height, int bandNr, boolean malloc, String filePath) 
100
          /*throws FileNotFoundException, NotSupportedExtensionException, RasterDriverException*/{
101
          //Opci?n de cachear siempre activada (Solo DEBUG)
102
          if(forceToLoadInCache)
103
                  return new RasterCache(dataType, width, height, bandNr);
104
          if(forceToLoadInReadOnlyCache && filePath != null){
105
                try {
106
                        return new RasterReadOnlyHugeBuffer(dataType, width, height, bandNr, filePath);
107
                } catch (FileNotFoundException e) {
108
                        //TODO: EXCEPTION: Modificar el lanzamiento de excepciones del RasterBuffer
109
                        e.printStackTrace();
110
                } catch (NotSupportedExtensionException e) {
111
                        e.printStackTrace();
112
                } catch (RasterDriverException e) {
113
                        e.printStackTrace();
114
                }
115
          }
116
                  
117
          if(cacheOn){
118
            long size = (RasterUtilities.getBytesFromRasterBufType(dataType) * width * height * bandNr) / 1024;
119
            long ms1 = cacheMemorySize * 1024;
120
            long ms2 = multicacheMemorySize * 1024;
121
            if(size <= ms1)
122
                    return new RasterMemoryBuffer(dataType, width, height, bandNr, malloc);
123
            else{
124
                    //if(filePath == null)
125
                            return new RasterCache(dataType, width, height, bandNr);
126
                    /*else 
127
                            return new RasterReadOnlyHugeBuffer(dataType, width, height, bandNr, filePath);*/
128
            }        
129
          }else
130
                  return new RasterMemoryBuffer(dataType, width, height, bandNr, malloc);
131
  }
132
  
133
  /**
134
   * Reserva de memoria para el rasterbuf
135
   * @param dataType Tipo de dato
136
   * @param width Ancho
137
   * @param height Alto
138
   * @param bandNr Numero de bandas
139
   * @param orig
140
   */
141
  public abstract void malloc(int dataType, int width, int height, int bandNr);
142
 
143
  /*
144
   *  (non-Javadoc)
145
   * @see org.gvsig.fmap.driver.IBuffer#getWidth()
146
   */
147
  public int getWidth() {
148
      return width;
149
  }
150

    
151
 /*
152
  *  (non-Javadoc)
153
  * @see org.gvsig.fmap.driver.IBuffer#getHeight()
154
  */
155
  public int getHeight() {
156
      return height;
157
  }
158

    
159
  /*
160
   *  (non-Javadoc)
161
   * @see org.gvsig.fmap.driver.IBuffer#getBandCount()
162
   */
163
  public int getBandCount() {
164
      return nBands;
165
  }
166

    
167
  /**
168
   * Obtiene el tipo de dato. Los tipos de dato posibles est?n definidos en IRaster.
169
   * @return tipo de datos
170
   */
171
        public int getDataType() {
172
                return dataType;
173
        }
174
        
175
        /**
176
         * Asigna el tipo de dato. Los tipos de dato posibles est?n definidos en IRaster.
177
         * @param dataType Tipo de dato del buffer
178
         */
179
        public void setDataType(int dataType) {
180
                this.dataType = dataType;
181
        }
182

    
183
  /**
184
   * Obtiene el tama?o del tipo de dato en bytes
185
   * @return Tipo de dato
186
   */
187
  public int getDataSize() {
188
      if (dataType == TYPE_BYTE) {
189
          return 1;
190
      } else if ((dataType == TYPE_SHORT) | (dataType == TYPE_USHORT)) {
191
          return 2;
192
      } else if (dataType == TYPE_INT) {
193
          return 4;
194
      }else if (dataType == TYPE_FLOAT) {
195
          return 8;
196
      }else if (dataType == TYPE_DOUBLE) {
197
          return 16;
198
      }
199

    
200
      return 0;
201
  }
202

    
203
  /**
204
   * Obtiene el tama?o del buffer
205
   * @return tama?o del buffer
206
   */
207
  public long sizeof() {
208
      return getDataSize() * width * height * nBands;
209
  }
210
  
211
  /**
212
   * Replica la banda de una posici?n sobre otra. Si la banda de destino no existe
213
   * se crea nueva. Si la posici?n de la banda de destino est? intercalada entre bandas 
214
   * que ya existen las otras se desplazan hacia abajo, NO se machacan los datos de ninguna.
215
   * Los datos se replican por referencia por lo que al modificar la banda original las
216
   * del resto quedar?n afectadas.
217
   * @param orig. Posici?n de la banda de origen. 
218
   * @param dest. Posici?n de la banda destino
219
   */   
220
  public abstract void replicateBand(int orig, int dest);
221
  
222
  /**
223
   * Cambia bandas de posici?n. Las posiciones deben existir como bandas del raster. 
224
   * Cada elemento del array representa una banda existente en el buffer (de longitud
225
   * rasterBuf.length) y el valor contenido dentro la banda que le corresponde. Por ejemplo
226
   * si pasamos un array {1, 0, 3, 2} significa que el buffer tiene cuatro bandas y que 
227
   * cambiamos la 0 por la 1 y la 2 por la 3. Un array {0, 1, 2, 3} en el mismo 
228
   * caso no producir?a nig?n cambio.
229
   * 
230
   * Si quisieramos asignar en un buffer monobanda su banda a la segunda posici?n habria
231
   * que insertar una vacia, por ejemplo con addBandFloat(0, null) se insertaria una 
232
   * banda nula en la posici?n 0 y la banda que estaba en la 0 pasar?a a la segunda.
233
   * 
234
   */
235
  public abstract void switchBands(int[] bandPosition);
236
          
237
  /**
238
   * Convierte un tipo de dato a cadena
239
   * @param type Tipo de dato
240
   * @return cadena  que representa el tipo de dato
241
   */
242
  public static String typesToString(int type) {
243
      switch (type) {
244
      case RasterBuffer.TYPE_IMAGE:
245
          return new String("Image");
246

    
247
      case RasterBuffer.TYPE_BYTE:
248
          return new String("Byte");
249

    
250
      case RasterBuffer.TYPE_DOUBLE:
251
          return new String("Double");
252

    
253
      case RasterBuffer.TYPE_FLOAT:
254
          return new String("Float");
255

    
256
      case RasterBuffer.TYPE_INT:
257
              return new String("Integer");
258
              
259
      case RasterBuffer.TYPE_USHORT:
260
      case RasterBuffer.TYPE_SHORT:
261
          return new String("Short");
262
      }
263

    
264
      return null;
265
  }
266
  
267
  /**
268
   * Ajusta el raster al ancho y alto solicitado por el vecino m?s cercano. Promedia el valor de dos
269
   * pixeles contiguos.
270
   * @param w Nuevo ancho
271
   * @param h Nuevo alto
272
   */
273
  public abstract RasterBuffer adjustRasterNearestNeighbourInterpolation(int w, int h, int[] bands);
274
  
275
  /**
276
   * Ajusta el raster al ancho y alto solicitado ajustando con una interpolaci?n bilineal. Promedia
277
   * el valor de cuatro pixeles adyacentes.
278
   * @param w Nuevo ancho
279
   * @param h Nuevo alto
280
   */
281
  public abstract RasterBuffer adjustRasterBilinearInterpolation(int w, int h, int[] bands);
282
  
283
  /**
284
   * Ajusta el raster al ancho y alto solicitado ajustando con una interpolaci?n de distancia inversa.
285
   * Asigna el valor de un pixel en funci?n inversa de la distancia.
286
   * 
287
   * @param w Nuevo ancho
288
   * @param h Nuevo alto
289
   */
290
  public abstract RasterBuffer adjustRasterInverseDistanceInterpolation(int w, int h, int[] bands);
291
  
292
  /**
293
   * Ajusta el raster al ancho y alto solicitado ajustando con una interpolaci?n de spline bicubica.
294
   * @param w Nuevo ancho
295
   * @param h Nuevo alto
296
   */
297
  public abstract RasterBuffer adjustRasterBicubicSplineInterpolation(int w, int h, int[] bands);
298
  
299
  /**
300
   * Ajusta el raster al ancho y alto solicitado ajustando con una interpolaci?n BSpline.
301
   * @param w Nuevo ancho
302
   * @param h Nuevo alto
303
   */
304
  public abstract RasterBuffer adjustRasterBSplineInterpolation(int w, int h, int[] bands);
305
  
306
  /*
307
   *  (non-Javadoc)
308
   * @see org.gvsig.fmap.driver.IBuffer#getNoDataValue()
309
   */
310
  public double getNoDataValue(){
311
          return noDataValue;
312
  }
313
  
314
  /*
315
   *  (non-Javadoc)
316
   * @see org.gvsig.fmap.driver.IBuffer#getByteNoDataValue()
317
   */
318
  public byte getByteNoDataValue(){
319
          return (byte)noDataValue;
320
  }
321
  
322
  /*
323
   *  (non-Javadoc)
324
   * @see org.gvsig.fmap.driver.IBuffer#getShortNoDataValue()
325
   */
326
  public short getShortNoDataValue(){
327
          return (short)noDataValue;
328
  }
329
  
330
  /*
331
   *  (non-Javadoc)
332
   * @see org.gvsig.fmap.driver.IBuffer#getIntNoDataValue()
333
   */
334
  public int getIntNoDataValue(){
335
          return (int)noDataValue;
336
  }
337
  
338
  /*
339
   *  (non-Javadoc)
340
   * @see org.gvsig.fmap.driver.IBuffer#getFloatNoDataValue()
341
   */
342
  public float getFloatNoDataValue(){
343
          return (float)noDataValue;
344
  }
345
  
346
  /*
347
   *  (non-Javadoc)
348
   * @see org.gvsig.fmap.driver.IBuffer#setNoDataValue(double)
349
   */
350
  public void setNoDataValue(double nd){
351
          noDataValue = nd;
352
  }
353
  
354
  /*
355
   *  (non-Javadoc)
356
   * @see org.gvsig.fmap.driver.IBuffer#getNotValidValue()
357
   */
358
  public double getNotValidValue(){
359
          return notValidValue;
360
  }
361
  
362
  /*
363
   *  (non-Javadoc)
364
   * @see org.gvsig.fmap.driver.IBuffer#setNotValidValue(java.lang.Object)
365
   */
366
  public void setNotValidValue(double value){
367
          this.notValidValue = value;
368
  }
369
  
370
  /*
371
   *  (non-Javadoc)
372
   * @see org.gvsig.fmap.driver.IBuffer#cloneBuffer()
373
   */
374
  public abstract IBuffer cloneBuffer();
375
  
376
  /**
377
   * Calcula el m?nimo y el m?ximo del histograma previamente.
378
   * @return double[] con el m?nimo y el m?ximo.
379
   */
380
  private double[] getLimits() {
381
          double max = Double.MIN_VALUE;
382
          double min = Double.MAX_VALUE;
383
          double value = 0;
384

    
385
                switch (getDataType()) {
386
                        case IBuffer.TYPE_BYTE:
387
                                for (int i = 0; i < getBandCount(); i++)
388
                                        for (int r = 0; r < getHeight(); r++) {
389
                                                for (int c = 0; c < getWidth(); c++) {
390
                                                        value = (double) (getElemByte(r, c, i) & 0xff);
391
                                                        if (value > max) max = value;
392
                                                        if (value < min) min = value;
393
                                                }
394
                                                if (isCanceled())
395
                                                        return null;
396
                                        }
397
                                break;
398
                        case IBuffer.TYPE_SHORT:
399
                                for (int i = 0; i < getBandCount(); i++)
400
                                        for (int r = 0; r < getHeight(); r++) {
401
                                                for (int c = 0; c < getWidth(); c++) {
402
                                                        value = (double) (getElemShort(r, c, i) & 0xffff);
403
                                                        if (value > max) max = value;
404
                                                        if (value < min) min = value;
405
                                                }
406
                                                if (isCanceled())
407
                                                        return null;
408
                                        }
409
                                break;
410
                        case IBuffer.TYPE_INT:
411
                                for (int i = 0; i < getBandCount(); i++)
412
                                        for (int r = 0; r < getHeight(); r++) {
413
                                                for (int c = 0; c < getWidth(); c++) {
414
                                                        value = (double) (getElemInt(r, c, i) & 0xffffffff);
415
                                                        if (value > max) max = value;
416
                                                        if (value < min) min = value;
417
                                                }
418
                                                if (isCanceled())
419
                                                        return null;
420
                                        }
421
                                break;
422
                        case IBuffer.TYPE_FLOAT:
423
                                for (int i = 0; i < getBandCount(); i++)
424
                                        for (int r = 0; r < getHeight(); r++) {
425
                                                for (int c = 0; c < getWidth(); c++) {
426
                                                        value =  (double) getElemFloat(r, c, i);
427
                                                        if (value > max) max = value;
428
                                                        if (value < min) min = value;
429
                                                }
430
                                                if (isCanceled())
431
                                                        return null;
432
                                        }
433
                                break;
434
                        case IBuffer.TYPE_DOUBLE:
435
                                for (int i = 0; i < getBandCount(); i++)
436
                                        for (int r = 0; r < getHeight(); r++) {
437
                                                for (int c = 0; c < getWidth(); c++) {
438
                                                        value = getElemDouble(r, c, i);
439
                                                        if (value > max) max = value;
440
                                                        if (value < min) min = value;
441
                                                }
442
                                                if (isCanceled())
443
                                                        return null;
444
                                        }
445
                                break;
446
                }
447
                double[] values = new double[2];
448
                values[0] = min;
449
                values[1] = max;
450
          return values;
451
  }
452

    
453
  /*
454
   * (non-Javadoc)
455
   * @see org.gvsig.raster.driver.datasetproperties.IHistogramable#getHistogram()
456
   */
457
        public Histogram getHistogram() throws HistogramException {
458
                percent = 0;
459
                Histogram hist = null;
460
                double[] limits = getLimits();
461

    
462
                if (limits == null)
463
                        return null;
464

    
465
                if (getDataType() == IBuffer.TYPE_BYTE)
466
                        hist = new Histogram(getBandCount(), 255, limits[0], limits[1]);
467
                else
468
                        hist = new Histogram(getBandCount(), RasterLibrary.defaultNumberOfClasses, limits[0], limits[1]);
469
                                
470
                for (int iBand = 0; iBand < getBandCount(); iBand++) {
471
                        for (int row = 0; row < getHeight(); row++) {
472
                                switch(getDataType()) {
473
                                case IBuffer.TYPE_BYTE:
474
                                        for (int col = 0; col < getWidth(); col++) 
475
                                                hist.incrementPxValue(iBand, (double)(getElemByte(row, col, iBand) & 0xff));
476
                                        break;
477
                                case IBuffer.TYPE_SHORT:
478
                                        for (int col = 0; col < getWidth(); col++) 
479
                                                hist.incrementPxValue(iBand, (double)(getElemShort(row, col, iBand) & 0xffff));
480
                                        break;
481
                                case IBuffer.TYPE_INT:
482
                                        for (int col = 0; col < getWidth(); col++) 
483
                                                hist.incrementPxValue(iBand, (double)(getElemInt(row, col, iBand) & 0xffffffff));
484
                                        break;
485
                                case IBuffer.TYPE_FLOAT:
486
                                        for (int col = 0; col < getWidth(); col++) 
487
                                                hist.incrementPxValue(iBand, (double)getElemFloat(row, col, iBand));
488
                                        break;
489
                                case IBuffer.TYPE_DOUBLE:
490
                                        for (int col = 0; col < getWidth(); col++) 
491
                                                hist.incrementPxValue(iBand, getElemDouble(row, col, iBand));
492
                                        break;
493
                                }
494
                                
495
                                if (isCanceled())
496
                                        return null;
497

    
498
                                percent = ((iBand*getHeight() + row) * 100) /(getHeight() * getBandCount());
499
                        }
500
                }
501
                percent = 100;
502
                return hist;
503
        }
504

    
505
        /*
506
         * (non-Javadoc)
507
         * @see org.gvsig.raster.util.IHistogramable#resetPercent()
508
         */
509
        public void resetPercent() {
510
                percent = 0;
511
        }
512

    
513
        /*
514
         * (non-Javadoc)
515
         * @see org.gvsig.raster.util.IHistogramable#getPercent()
516
         */
517
        public int getPercent() {
518
                return percent;
519
        }
520

    
521
        /*
522
         * (non-Javadoc)
523
         * @see org.gvsig.raster.util.ICancellable#isCanceled()
524
         */
525
        public boolean isCanceled() {
526
                return canceled;
527
        }
528
        
529
        /*
530
         * (non-Javadoc)
531
         * @see org.gvsig.raster.util.ICancellable#setCanceled(boolean)
532
         */
533
        public void setCanceled(boolean value) {
534
                canceled = value;
535
        }
536
}