Statistics
| Revision:

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

History | View | Annotate | Download (15 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.dataaccess.buffer;
20

    
21
import java.io.FileNotFoundException;
22

    
23
import org.gvsig.raster.dataaccess.cache.RasterCache;
24
import org.gvsig.raster.dataaccess.cache.RasterReadOnlyHugeBuffer;
25
import org.gvsig.raster.dataset.IBuffer;
26
import org.gvsig.raster.dataset.NotSupportedExtensionException;
27
import org.gvsig.raster.dataset.RasterDriverException;
28
import org.gvsig.raster.util.DataClassList;
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
     * (non-Javadoc)
378
     * @see org.gvsig.raster.driver.datasetproperties.IHistogramable#getHistogram()
379
     */
380
        public Histogram getHistogram() throws HistogramException {
381
                percent = 0;
382
                if(getDataType() != IBuffer.TYPE_BYTE)
383
                        return null;
384
                Histogram hist = new Histogram(getBandCount(), 256);
385
                for (int iBand = 0; iBand < getBandCount(); iBand++) 
386
                        for (int row = 0; row < getHeight(); row++) {
387
                                for (int col = 0; col < getWidth(); col++) 
388
                                        hist.incrementPxValue(iBand, (getElemByte(row, col, iBand) & 0xff));
389
                                if (isCanceled()) return null;
390
                                percent = ((iBand*getHeight() + row) * 100) /(getHeight() * getBandCount());
391
                        }
392
                percent = 100;
393
                return hist;
394
        }
395

    
396
        /*
397
         * (non-Javadoc)
398
         * @see org.gvsig.raster.driver.datasetproperties.IHistogramable#getHistogramUsingClasses(org.gvsig.raster.shared.DataClassList)
399
          */
400
        public Histogram getHistogramUsingClasses(DataClassList classes) throws HistogramException {
401
                percent = 0;
402
                Histogram hist = new Histogram(getBandCount(), classes.length());
403
                for (int iBand = 0; iBand < getBandCount(); iBand++) { 
404
                        for (int col = 0; col < getHeight(); col++) {
405
                                for (int row = 0; row < getWidth(); row++) {
406
                                        int pixelValue = -1;
407
                                        switch(this.getDataType()){
408
                                        case IBuffer.TYPE_BYTE: pixelValue = classes.getClassPosition((double)(getElemByte(row, col, iBand)  & 0xff)); break;
409
                                        case IBuffer.TYPE_SHORT: pixelValue = classes.getClassPosition((double)(getElemShort(row, col, iBand) & 0xffff)); break;
410
                                        case IBuffer.TYPE_INT: pixelValue = classes.getClassPosition((double)(getElemInt(row, col, iBand) & 0xffffff)); break;
411
                                        case IBuffer.TYPE_FLOAT: pixelValue = classes.getClassPosition((double)getElemFloat(row, col, iBand)); break;
412
                                        case IBuffer.TYPE_DOUBLE: pixelValue = classes.getClassPosition((double)getElemDouble(row, col, iBand)); break;
413
                                        }                 
414
                                        if(pixelValue >= 0)
415
                                                hist.incrementPxValue(iBand, pixelValue);
416
                                }
417
                                if (isCanceled()) return null;
418
                                percent = ((iBand*getHeight() + col) * 100) / (getHeight() * getBandCount());
419
                        }
420
                }
421
                percent = 100;
422
                return hist;
423
        }
424

    
425
        /*
426
         * (non-Javadoc)
427
         * @see org.gvsig.raster.util.IHistogramable#resetPercent()
428
         */
429
        public void resetPercent() {
430
                percent = 0;
431
        }
432

    
433
        /*
434
         * (non-Javadoc)
435
         * @see org.gvsig.raster.util.IHistogramable#getPercent()
436
         */
437
        public int getPercent() {
438
                return percent;
439
        }
440

    
441
        /*
442
         * (non-Javadoc)
443
         * @see org.gvsig.raster.util.ICancellable#isCanceled()
444
         */
445
        public boolean isCanceled() {
446
                return canceled;
447
        }
448
        
449
        /*
450
         * (non-Javadoc)
451
         * @see org.gvsig.raster.util.ICancellable#setCanceled(boolean)
452
         */
453
        public void setCanceled(boolean value) {
454
                canceled = value;
455
        }
456
}