Statistics
| Revision:

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

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

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

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

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

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

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

    
198
        return 0;
199
    }
200

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

    
245
        case RasterBuffer.TYPE_BYTE:
246
            return new String("Byte");
247

    
248
        case RasterBuffer.TYPE_DOUBLE:
249
            return new String("Double");
250

    
251
        case RasterBuffer.TYPE_FLOAT:
252
            return new String("Float");
253

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

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

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