Statistics
| Revision:

root / trunk / libraries / libRaster / src / org / gvsig / raster / dataset / RasterDataset.java @ 20866

History | View | Annotate | Download (30 KB)

1
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
2
 *
3
 * Copyright (C) 2006 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.dataset;
20

    
21
import java.awt.geom.AffineTransform;
22
import java.awt.geom.NoninvertibleTransformException;
23
import java.awt.geom.Point2D;
24
import java.io.File;
25
import java.io.IOException;
26
import java.lang.reflect.Constructor;
27
import java.lang.reflect.InvocationTargetException;
28
import java.util.ArrayList;
29
import java.util.Iterator;
30
import java.util.Map;
31
import java.util.Set;
32

    
33
import org.cresques.cts.ICoordTrans;
34
import org.cresques.cts.IProjection;
35
import org.gvsig.raster.RasterLibrary;
36
import org.gvsig.raster.dataset.io.GdalDriver;
37
import org.gvsig.raster.dataset.io.IRegistrableRasterFormat;
38
import org.gvsig.raster.dataset.io.MemoryRasterDriver;
39
import org.gvsig.raster.dataset.io.MemoryRasterDriverParam;
40
import org.gvsig.raster.dataset.io.RasterDriverException;
41
import org.gvsig.raster.dataset.io.rmf.ParsingException;
42
import org.gvsig.raster.dataset.io.rmf.RmfBlocksManager;
43
import org.gvsig.raster.dataset.properties.DatasetColorInterpretation;
44
import org.gvsig.raster.dataset.properties.DatasetHistogram;
45
import org.gvsig.raster.dataset.properties.DatasetMetadata;
46
import org.gvsig.raster.dataset.properties.DatasetStatistics;
47
import org.gvsig.raster.dataset.serializer.ColorInterpretationRmfSerializer;
48
import org.gvsig.raster.dataset.serializer.GeoInfoRmfSerializer;
49
import org.gvsig.raster.dataset.serializer.GeoPointRmfSerializer;
50
import org.gvsig.raster.datastruct.ColorTable;
51
import org.gvsig.raster.datastruct.Extent;
52
import org.gvsig.raster.datastruct.GeoPoint;
53
import org.gvsig.raster.datastruct.Transparency;
54
import org.gvsig.raster.datastruct.serializer.ColorTableRmfSerializer;
55
import org.gvsig.raster.datastruct.serializer.NoDataRmfSerializer;
56
import org.gvsig.raster.datastruct.serializer.NoDataRmfSerializer.NoDataObject;
57
import org.gvsig.raster.util.RasterUtilities;
58
import org.gvsig.raster.util.extensionPoints.ExtensionPoint;
59
import org.gvsig.raster.util.extensionPoints.ExtensionPoints;
60
import org.gvsig.raster.util.extensionPoints.ExtensionPointsSingleton;
61

    
62
/**
63
 * Manejador de ficheros raster georeferenciados.
64
 * 
65
 * Esta clase abstracta es el ancestro de todas las clases que proporcionan
66
 * soporte para ficheros raster georeferenciados.<br>
67
 * Actua tambien como una 'Fabrica', ocultando al cliente la manera en que
68
 * se ha implementado ese manejo. Una clase nueva que soportara un nuevo
69
 * tipo de raster tendr?a que registrar su extensi?n o extensiones usando
70
 * el m?todo @see registerExtension.<br> 
71
 */
72

    
73
public abstract class RasterDataset extends GeoInfo {
74

    
75
        /**
76
         * Flags que representan a las bandas visualizables
77
         */
78
        public static final int                RED_BAND         = 0x01;
79
        public static final int                GREEN_BAND       = 0x02;
80
        public static final int                BLUE_BAND        = 0x04;
81
        public static final int                ALPHA_BAND       = 0x08;
82
        
83
        /**
84
         * N?mero de bandas de la imagen
85
         */
86
        protected int                          bandCount        = 1;
87
        private int[]                          dataType         = null;
88

    
89
        protected DatasetStatistics            stats            = new DatasetStatistics(this);
90
        protected DatasetHistogram             histogram        = null;
91
        protected Object                       param            = null;
92
        protected RmfBlocksManager             rmfBlocksManager = null;
93

    
94
        protected ColorTable                   colorTable       = null;        
95
        protected DatasetColorInterpretation   colorInterpretation = null;
96

    
97
        /**
98
         * Valor del NoData
99
         */
100
        protected double                       noData           = 0;
101

    
102
        /**
103
         * Indica si el valor NoData esta activo
104
         */
105
        protected boolean                      noDataEnabled    = false;
106
        
107
        /*
108
         *  (non-Javadoc)
109
         * @see java.lang.Object#clone()
110
         */
111
        public Object clone() {
112
                try {
113
                        RasterDataset dataset = RasterDataset.open(proj, param);
114
                        //Estas van por referencia
115
                        dataset.histogram = histogram;
116
                        dataset.stats = stats;
117
                        return dataset;
118
                } catch (NotSupportedExtensionException e) {
119
                        e.printStackTrace();
120
                } catch (RasterDriverException e) {
121
                        e.printStackTrace();
122
                }
123
                return null;
124
        }
125
        
126
        /**
127
         * Constructor
128
         */
129
        public RasterDataset() {
130
                
131
        }
132
        
133
        /**
134
         * Factoria para abrir distintos tipos de raster.
135
         * 
136
         * @param proj Proyecci?n en la que est? el raster.
137
         * @param fName Nombre del fichero.
138
         * @return GeoRasterFile, o null si hay problemas.
139
         */
140
        public static RasterDataset open(IProjection proj, Object param) throws NotSupportedExtensionException, RasterDriverException {
141
                String idFormat = null;
142
                
143
                if(param instanceof String)
144
                        idFormat = RasterUtilities.getExtensionFromFileName(((String)param));
145
                if(param instanceof IRegistrableRasterFormat)
146
                        idFormat = ((IRegistrableRasterFormat)param).getFormatID();
147
                                
148
                RasterDataset grf = null;
149

    
150
                Class clase = null;
151
                if(param instanceof MemoryRasterDriverParam)
152
                        clase = MemoryRasterDriver.class;
153
                
154
                if(clase == null){
155
                        ExtensionPoints extensionPoints = ExtensionPointsSingleton.getInstance();
156
                        ExtensionPoint extensionPoint = (ExtensionPoint)extensionPoints.get("RasterReader");
157
                        if(extensionPoint == null)
158
                                return null;
159
                        if(idFormat != null)
160
                                clase = (Class)extensionPoint.get(idFormat);
161
                }
162
                
163
                if(clase == null)
164
                        clase = GdalDriver.class;
165
                
166
                Class [] args = {IProjection.class, Object.class};
167
                try {
168
                        Constructor hazNuevo = clase.getConstructor(args);
169
                        Object [] args2 = {proj, param};
170
                        grf = (RasterDataset) hazNuevo.newInstance(args2);
171
                } catch (SecurityException e) {
172
                        throw new RasterDriverException("Error SecurityException in open");
173
                } catch (NoSuchMethodException e) {
174
                        throw new RasterDriverException("Error NoSuchMethodException in open");
175
                } catch (IllegalArgumentException e) {
176
                        throw new RasterDriverException("Error IllegalArgumentException in open");
177
                } catch (InstantiationException e) {
178
                        throw new RasterDriverException("Error InstantiationException in open");
179
                } catch (IllegalAccessException e) {
180
                        throw new RasterDriverException("Error IllegalAccessException in open");
181
                } catch (InvocationTargetException e) {
182
                        throw new NotSupportedExtensionException("Error in open. Problemas con las librer?as.");
183
                }
184
                return grf;
185
        }
186
                
187
        /**
188
         * Acciones de inicilizaci?n comunes a todos los drivers.
189
         * Este m?todo debe ser llamado explicitamente por el constructor de cada driver.
190
         * Estas son acciones de inicializaci?n que se ejecutan despu?s del constructor de cada driver.
191
         * Las acciones que hayan de ser realizadas antes se definen en el constructor de RasterDataset.
192
         */
193
        protected void init() {
194
                //Creamos el gestor de Rmf
195
                int last =  getFName().lastIndexOf(".");
196
                if(last == -1)
197
                        last = getFName().length();
198
                String f = getFName().substring(0, last);
199
                f = f + ".rmf";
200
                rmfBlocksManager = new RmfBlocksManager(f);
201
        }
202
        
203
        /**
204
         * Tipo de fichero soportado.
205
         * Devuelve true si el tipo de fichero (extension) est? soportado, si no
206
         * devuelve false.
207
         * 
208
         * @param fName Fichero raster
209
         * @return  true si est? soportado, si no false.
210
                */
211
        public static boolean fileIsSupported(String fName) {
212
                ExtensionPoints extensionPoints = ExtensionPointsSingleton.getInstance();
213
                ExtensionPoint extensionPoint = (ExtensionPoint)extensionPoints.get("RasterReader");
214
                return (extensionPoint.get(fName.substring(fName.lastIndexOf(".") + 1, fName.length()).toLowerCase()) == null) ? false : true;
215
        }
216
        
217
                /**
218
                 * Obtiene la lista de extensiones de ficheros soportadas
219
                 * @return Lista de extensiones registradas
220
                 */
221
                public static ArrayList getExtensionsSupported() {
222
                        ExtensionPoints extensionPoints = ExtensionPointsSingleton.getInstance();
223
                        ExtensionPoint extensionPoint = (ExtensionPoint)extensionPoints.get("RasterReader");
224
                if(extensionPoint == null)
225
                        return null;
226
                Set values = extensionPoint.entrySet();
227
                        ArrayList result = new ArrayList();
228
                        for (Iterator it = values.iterator(); it.hasNext(); ) {
229
                                Map.Entry entry = ((Map.Entry)it.next());
230
                                String ext = (String)entry.getKey();
231
                                result.add(ext);
232
                                }
233
                        return result;
234
                }
235
        
236
        /**
237
         * Constructor
238
         * @param proj        Proyecci?n
239
         * @param name        Nombre del fichero de imagen.
240
         */
241
        public RasterDataset(IProjection proj, Object param) {
242
                super(proj, param);
243
                if(param instanceof String)
244
                        setFileSize(new File(getFName()).length());
245
        }
246

    
247
        
248
        /**
249
         * Carga un fichero raster. Puede usarse para calcular el extent e instanciar 
250
         * un objeto de este tipo.
251
         */
252
        abstract public GeoInfo load();
253
        
254
        /**
255
         * Cierra el fichero y libera los recursos.
256
         */
257
        abstract public void close();
258
                
259
        /**
260
         * Carga metadatos desde el fichero Rmf si estos existen
261
         * @param fName Nombre del fichero
262
         * @throws ParsingException 
263
         */
264
        public void loadFromRmf(RmfBlocksManager manager) throws ParsingException {
265
                if (!manager.checkRmf())
266
                        return;
267

    
268
                if (!new File(manager.getPath()).exists())
269
                        return;
270

    
271
                GeoInfoRmfSerializer geoInfoSerializer = new GeoInfoRmfSerializer(this);
272
                ColorTableRmfSerializer colorTableSerializer = new ColorTableRmfSerializer();
273
                NoDataRmfSerializer noDataSerializer = new NoDataRmfSerializer(noData, RasterLibrary.NODATATYPE_LAYER);
274
                ColorInterpretationRmfSerializer colorInterpSerializer = new ColorInterpretationRmfSerializer();
275

    
276
                manager.addClient(geoInfoSerializer);
277
                manager.addClient(colorTableSerializer);
278
                manager.addClient(noDataSerializer);
279
                manager.addClient(colorInterpSerializer);
280

    
281
                manager.read(null);
282

    
283
                manager.removeClient(geoInfoSerializer.getClass());
284
                manager.removeClient(colorTableSerializer.getClass());
285
                manager.removeClient(noDataSerializer.getClass());
286
                manager.removeClient(colorInterpSerializer.getClass());
287

    
288
                if (colorTableSerializer.getResult() != null)
289
                        setColorTable((ColorTable) colorTableSerializer.getResult());
290

    
291
                if (noDataSerializer.getResult() != null) {
292
                        noData = ((NoDataObject) noDataSerializer.getResult()).getValue();
293
                        noDataEnabled = (((NoDataObject) noDataSerializer.getResult()).getType() != RasterLibrary.NODATATYPE_DISABLED);
294
                }
295
                
296
                if(colorInterpSerializer.getResult() != null) {
297
                        DatasetColorInterpretation ci = (DatasetColorInterpretation)colorInterpSerializer.getResult();
298
                        setColorInterpretation(ci);
299
                        if(ci.getBand(DatasetColorInterpretation.ALPHA_BAND) != -1) 
300
                                getTransparencyDatasetStatus().setTransparencyBand(ci.getBand(DatasetColorInterpretation.ALPHA_BAND));
301
                }
302

    
303
        }
304
        
305
        /**
306
         * Salva la georreferenciaci?n a fichero rmf.
307
         * @param fName
308
         * @throws IOException  
309
         */
310
        public void saveToRmf(RmfBlocksManager manager) throws IOException {
311
                GeoInfoRmfSerializer ser = new GeoInfoRmfSerializer(this);
312
                if(!manager.checkRmf())
313
                        return;
314
                manager.addClient(ser);
315
                RasterUtilities.copyFile(manager.getPath(), manager.getPath() + "~");
316
                manager.write();
317
                manager.removeClient(ser.getClass());
318
        }        
319
        
320
        /**
321
         * Salva la georreferenciaci?n a fichero rmf.
322
         * @param fName
323
         * @throws IOException  
324
         */
325
        public void saveGeoToRmf() throws IOException {
326
                saveToRmf(rmfBlocksManager);
327
        }
328
        
329
        /**
330
         * Salva la georreferenciaci?n a fichero rmf.
331
         * @param geoPoints
332
         * @throws IOException  
333
         */
334
        public void saveGeoPointsToRmf(GeoPoint[] geoPoints) throws IOException {
335
                GeoPointRmfSerializer ser = new GeoPointRmfSerializer(geoPoints);
336
                if(!rmfBlocksManager.checkRmf())
337
                        return;
338
                rmfBlocksManager.addClient(ser);
339
                RasterUtilities.copyFile(rmfBlocksManager.getPath(), rmfBlocksManager.getPath() + "~");
340
                rmfBlocksManager.write();
341
                rmfBlocksManager.removeClient(ser.getClass());
342
        }
343
        
344
        /**
345
         * Salva la georreferenciaci?n a fichero rmf.
346
         * @param geoPoints
347
         * @throws IOException  
348
         */
349
        public GeoPoint[] loadGeoPointsFromRmf() throws IOException {
350
                GeoPointRmfSerializer ser = new GeoPointRmfSerializer();
351
                if(!rmfBlocksManager.checkRmf())
352
                        return null;
353
                rmfBlocksManager.addClient(ser);
354
                try {
355
                        rmfBlocksManager.read(null);
356
                } catch (ParsingException e) {
357
                        throw new IOException("Error parseando XML");
358
                }
359
                rmfBlocksManager.removeClient(ser.getClass());
360
                return (GeoPoint[])ser.getResult();
361
        }
362
                                
363
        /**
364
         * Obtiene el ancho de la imagen
365
         * @return Ancho de la imagen
366
         */
367
        abstract public int getWidth();
368
        
369
        /**
370
         * Obtiene el ancho de la imagen
371
         * @return Ancho de la imagen
372
         */
373
        abstract public int getHeight();
374

    
375
        /**
376
         * Reproyecci?n.
377
         * @param rp        Coordenadas de la transformaci?n
378
         */
379
        abstract public void reProject(ICoordTrans rp);
380

    
381
        /**
382
         * Asigna un nuevo Extent 
383
         * @param e        Extent
384
         */
385
        abstract public void setView(Extent e);
386
        
387
        /**
388
         * Obtiene el extent asignado
389
         * @return        Extent
390
         */
391
        abstract public Extent getView();
392
                                
393
        /**
394
         * Obtiene el valor del raster en la coordenada que se le pasa.
395
         * El valor ser? Double, Int, Byte, etc. dependiendo del tipo de
396
         * raster.
397
         * @param x        coordenada X
398
         * @param y coordenada Y
399
         * @return
400
         */
401
        abstract public Object getData(int x, int y, int band)throws InvalidSetViewException, FileNotOpenException, RasterDriverException;
402

    
403
        /**
404
         * Obtiene el n?nero de bandas del fichero
405
         * @return Entero que representa el n?mero de bandas
406
         */
407
        public int getBandCount() { 
408
                return bandCount; 
409
        }
410
                
411
        /**
412
         * @return Returns the dataType.
413
         */
414
        public int[] getDataType() {
415
                return dataType;
416
        }
417
        
418
        /**
419
         * @param dataType The dataType to set.
420
         */
421
        public void setDataType(int[] dataType) {
422
                this.dataType = dataType;
423
        }
424
         
425
        /**
426
         * Obtiene el tama?o de pixel en X
427
         * @return tama?o de pixel en X
428
         */
429
        public double getPixelSizeX() {
430
                return externalTransformation.getScaleX();
431
        }
432
        
433
        /**
434
         * Obtiene el tama?o de pixel en Y
435
         * @return tama?o de pixel en Y
436
         */
437
        public double getPixelSizeY() {
438
                return externalTransformation.getScaleY();
439
        }
440

    
441
        /**
442
         * Obtiene una ventana de datos de la imagen a partir de coordenadas reales. 
443
         * No aplica supersampleo ni subsampleo sino que devuelve una matriz de igual tama?o a los
444
         * pixeles de disco. 
445
         * @param ulx Posici?n X superior izquierda
446
         * @param uly Posici?n Y superior izquierda
447
         * @param lrx Posici?n X inferior derecha
448
         * @param lry Posici?n Y inferior derecha
449
         * @param rasterBuf        Buffer de datos
450
         * @param bandList
451
         * @return Buffer de datos
452
         */
453
        abstract public IBuffer getWindowRaster(double ulx, double uly, double lrx, double lry, BandList bandList, IBuffer rasterBuf)throws InterruptedException, RasterDriverException;
454
        
455
        /**
456
         * Obtiene una ventana de datos de la imagen a partir de coordenadas reales. 
457
         * No aplica supersampleo ni subsampleo sino que devuelve una matriz de igual tama?o a los
458
         * pixeles de disco. 
459
         * @param x Posici?n X superior izquierda
460
         * @param y Posici?n Y superior izquierda
461
         * @param w Ancho en coordenadas reales
462
         * @param h Alto en coordenadas reales
463
         * @param rasterBuf        Buffer de datos
464
         * @param bandList
465
         * @param adjustToExtent Flag que dice si el extent solicitado debe ajustarse al extent del raster o no.
466
         * @return Buffer de datos
467
         */
468
        abstract public IBuffer getWindowRaster(double x, double y, double w, double h, BandList bandList, IBuffer rasterBuf, boolean adjustToExtent)throws InterruptedException, RasterDriverException;
469
        
470
        /**
471
         * Obtiene una ventana de datos de la imagen a partir de coordenadas reales. 
472
         * Se aplica supersampleo o subsampleo dependiendo del tama?o del buffer especificado.
473
         * 
474
         * @param minX Posici?n m?nima X superior izquierda
475
         * @param minY Posici?n m?nima Y superior izquierda
476
         * @param maxX Posici?n m?xima X inferior derecha
477
         * @param maxY Posici?n m?xima Y inferior derecha
478
         * @param bufWidth Ancho del buffer de datos
479
         * @param bufHeight Alto del buffer de datos
480
         * @param rasterBuf        Buffer de datos
481
         * @param adjustToExtent Flag que dice si el extent solicitado debe ajustarse al extent del raster o no.
482
         * @param bandList
483
         * @return Buffer de datos
484
         */
485
        abstract public IBuffer getWindowRaster(double minX, double minY, double maxX, double maxY, int bufWidth, int bufHeight, BandList bandList, IBuffer rasterBuf, boolean adjustToExtent)throws InterruptedException, RasterDriverException;
486
        
487
        /**
488
         * Obtiene una ventana de datos de la imagen a partir de coordenadas pixel. 
489
         * No aplica supersampleo ni subsampleo sino que devuelve una matriz de igual tama?o a los
490
         * pixeles de disco. 
491
         * @param x Posici?n X superior izquierda
492
         * @param y Posici?n Y superior izquierda
493
         * @param w Ancho en coordenadas reales
494
         * @param h Alto en coordenadas reales
495
         * @param rasterBuf        Buffer de datos
496
         * @param bandList
497
         * @return Buffer de datos
498
         */
499
        abstract public IBuffer getWindowRaster(int x, int y, int w, int h, BandList bandList, IBuffer rasterBuf)throws InterruptedException, RasterDriverException;
500
        
501
        /**
502
         * Obtiene una ventana de datos de la imagen a partir de coordenadas pixel. 
503
         * Se aplica supersampleo o subsampleo dependiendo del tama?o del buffer especificado.
504
         * 
505
         * @param x Posici?n X superior izquierda
506
         * @param y Posici?n Y superior izquierda
507
         * @param w Ancho en coordenadas reales
508
         * @param h Alto en coordenadas reales
509
         * @param bufWidth Ancho del buffer de datos
510
         * @param bufHeight Alto del buffer de datos
511
         * @param rasterBuf        Buffer de datos
512
         * @param bandList
513
         * @return Buffer de datos
514
         */
515
        abstract public IBuffer getWindowRaster(int x, int y, int w, int h, int bufWidth, int bufHeight, BandList bandList, IBuffer rasterBuf)throws InterruptedException, RasterDriverException;
516
        
517
        abstract public int getBlockSize();
518
        
519
        /**
520
         * Obtiene el objeto que contiene los metadatos. Este m?todo debe ser redefinido por los
521
         * drivers si necesitan devolver metadatos. 
522
         * @return
523
         */
524
        public DatasetMetadata getMetadata(){
525
                return null;
526
        }
527

    
528
        /**
529
         * Obtiene el valor NoData asociado al raster. Si hay un valor en el fichero
530
         * RMF se devuelve este, sino se buscar? en la cabecera del raster o metadatos de
531
         * este. Si finalmente no encuentra ninguno se devuelve el valor por defecto
532
         * definido en la libreria.
533
         * @return
534
         */
535
        public double getNoDataValue() {
536
                return noData;
537
        }
538

    
539
        /**
540
         * Pone el valor original de noData. Primero lo consulta del valor del metadata
541
         * y luego del RMF.
542
         */
543
        public void resetNoDataValue() {
544
                /**
545
                 * Intentamos recuperar el valor del metadatas, en caso de no encontrarlo le
546
                 * asignamos el noData por defecto
547
                 */
548
                noDataEnabled = false;
549
                do {
550
                        if (getMetadata() == null) {
551
                                noData = RasterLibrary.defaultNoDataValue;
552
                                break;
553
                        }
554

    
555
                        if (getMetadata().getNoDataValue().length == 0) {
556
                                noData = RasterLibrary.defaultNoDataValue;
557
                                break;
558
                        }
559

    
560
                        noData = getMetadata().getNoDataValue()[0];
561
                        noDataEnabled = true;
562
                } while (false);
563

    
564
                /**
565
                 * Miramos a ver si podemos obtener el valor del RMF, en caso de exito se
566
                 * asigna, en caso contrario, no hacemos nada.
567
                 */
568
                RmfBlocksManager manager = getRmfBlocksManager();
569

    
570
                if (!manager.checkRmf())
571
                        return;
572

    
573
                if (!new File(manager.getPath()).exists())
574
                        return;
575

    
576
                NoDataRmfSerializer noDataSerializer = new NoDataRmfSerializer();
577

    
578
                manager.addClient(noDataSerializer);
579

    
580
                try {
581
                        manager.read(null);
582
                } catch (ParsingException e) {
583
                }
584

    
585
                manager.removeClient(noDataSerializer.getClass());
586

    
587
                if (noDataSerializer.getResult() != null) {
588
                        NoDataObject noDataObject = ((NoDataObject) noDataSerializer.getResult());
589
                        noData = noDataObject.getValue();
590
                        noDataEnabled = (noDataObject.getType() > 0);
591
                }
592
        }
593
        
594
        /**
595
         * Establece el valor del NoData
596
         * @param value
597
         */
598
        public void setNoDataValue(double value) {
599
                noData = value;
600
                noDataEnabled = true;
601
        }
602
                
603
        /**
604
         * Obtiene el objeto que contiene que contiene la interpretaci?n de 
605
         * color por banda
606
         * @return
607
         */
608
        public DatasetColorInterpretation getColorInterpretation(){
609
                return colorInterpretation;
610
        }
611
                
612
        /**
613
         * Asigna el objeto que contiene que contiene la interpretaci?n de 
614
         * color por banda
615
         * @param DatasetColorInterpretation
616
         */
617
        public void setColorInterpretation(DatasetColorInterpretation colorInterpretation){
618
                this.colorInterpretation = colorInterpretation;
619
        }
620
        
621
        /**
622
         * Dice si el fichero tiene georreferenciaci?n o no.
623
         * @return true si tiene georreferenciaci?n y false si no la tiene
624
         */
625
        public boolean isGeoreferenced(){
626
                return true;
627
        }
628

    
629
        /**
630
         * Obtiene el objeto paleta. Esta paleta es la que tiene adjunta el fichero de disco. Si es
631
         * null este objeto quiere decir que no tiene paleta para su visualizaci?n. 
632
         * @return Palette
633
         */
634
        public ColorTable getColorTable() {
635
                return colorTable;
636
        }
637

    
638
        /**
639
         * Define el objeto paleta. Si se define null quiere decir que no tiene paleta
640
         * para su visualizaci?n. 
641
         * @param value
642
         */
643
        public void setColorTable(ColorTable value) {
644
                colorTable = value;
645
        }
646
        
647
        /**
648
         * Obtiene el estado de transparencia de un GeoRasterFile. 
649
         * @return Objeto TransparencyFileStatus
650
         */
651
        public Transparency getTransparencyDatasetStatus() {
652
                return null;
653
        }
654
        
655
        /**
656
         * Dado unas coordenadas reales, un tama?o de buffer y un tama?o de raster. 
657
         * Si el buffer es de mayor tama?o que el raster (supersampleo) quiere decir que 
658
         * por cada pixel de buffer se repiten varios del raster. Esta funci?n calcula el 
659
         * n?mero de pixels de desplazamiento en X e Y que corresponden al primer pixel del
660
         * buffer en la esquina superior izquierda. Esto es necesario porque la coordenada
661
         * solicitada es real y puede no caer sobre un pixel completo. Este calculo es
662
         * util cuando un cliente quiere supersamplear sobre un buffer y que no se lo haga
663
         * el driver autom?ticamente.
664
         * @param dWorldTLX Coordenada real X superior izquierda
665
         * @param dWorldTLY Coordenada real Y superior izquierda
666
         * @param dWorldBRX Coordenada real X inferior derecha
667
         * @param dWorldBRY Coordenada real Y inferior derecha
668
         * @param nWidth Ancho del raster
669
         * @param nHeight Alto del raster
670
         * @param bufWidth Ancho del buffer
671
         * @param bufHeight Alto del buffer
672
         * @return Array de dos elementos con el desplazamiento en X e Y. 
673
         */
674
        public double[] calcSteps(double dWorldTLX, double dWorldTLY, double dWorldBRX, double dWorldBRY, 
675
                        double nWidth, double nHeight, int bufWidth, int bufHeight) {
676

    
677
                Point2D p1 = new Point2D.Double(dWorldTLX, dWorldTLY);
678
                Point2D p2 = new Point2D.Double(dWorldBRX, dWorldBRY);
679

    
680
                Point2D tl = worldToRaster(new Point2D.Double(p1.getX(), p1.getY()));
681
                Point2D br = worldToRaster(new Point2D.Double(p2.getX(), p2.getY()));
682
                
683
                double wPx = (bufWidth / Math.abs(br.getX() - tl.getX()));
684
                double hPx = (bufHeight / Math.abs(br.getY() - tl.getY()));
685
                
686
                int x = (int)((tl.getX() > br.getX()) ? Math.floor(br.getX()) : Math.floor(tl.getX()));
687
                int y = (int)((tl.getY() > br.getY()) ? Math.floor(br.getY()) : Math.floor(tl.getY()));
688
                
689
                double a = (tl.getX() > br.getX()) ? (Math.abs(br.getX() - x)) : (Math.abs(tl.getX() - x));
690
                double b = (tl.getY() > br.getY()) ? (Math.abs(br.getY() - y)) : (Math.abs(tl.getY() - y)); 
691

    
692
                                double stpX = (int)((a * bufWidth) / Math.abs(br.getX() - tl.getX()));
693
                double stpY = (int)((b * bufHeight) / Math.abs(br.getY() - tl.getY()));
694
                
695
                return new double[]{stpX, stpY, wPx, hPx};
696
        }
697
        
698
        /**
699
         * Lee una l?nea completa del raster y devuelve un array del tipo correcto. Esta funci?n es util
700
         * para una lectura rapida de todo el fichero sin necesidad de asignar vista. 
701
         * @param nLine N?mero de l?nea a leer
702
         * @param band Banda requerida
703
         * @return Object que es un array unidimendional del tipo de datos del raster
704
         * @throws InvalidSetViewException
705
         * @throws FileNotOpenException
706
         * @throws RasterDriverException
707
         */
708
        abstract public Object readCompleteLine(int line, int band)throws InvalidSetViewException, FileNotOpenException, RasterDriverException;
709
        
710
        /**
711
         * Lee un bloque completo de datos del raster y devuelve un array tridimensional del tipo correcto. Esta funci?n es util
712
         * para una lectura rapida de todo el fichero sin necesidad de asignar vista. 
713
         * @param pos Posici?n donde se empieza  a leer
714
         * @param blockHeight Altura m?xima del bloque leido
715
         * @return Object que es un array tridimendional del tipo de datos del raster. (Bandas X Filas X Columnas)
716
         * @throws InvalidSetViewException
717
         * @throws FileNotOpenException
718
         * @throws RasterDriverException
719
         */
720
        abstract public Object readBlock(int pos, int blockHeight)
721
                throws InvalidSetViewException, FileNotOpenException, RasterDriverException, InterruptedException;
722
        
723
        /**
724
         * Convierte un punto desde coordenadas pixel a coordenadas del mundo.
725
         * @param pt Punto a transformar
726
         * @return punto transformado en coordenadas del mundo
727
         */
728
        public Point2D rasterToWorld(Point2D pt) {
729
                Point2D p = new Point2D.Double();
730
                externalTransformation.transform(pt, p);
731
                return p;
732
        }
733
        
734
        /**
735
         * Convierte un punto desde del mundo a coordenadas pixel.
736
         * @param pt Punto a transformar
737
         * @return punto transformado en coordenadas pixel
738
         */
739
        public Point2D worldToRaster(Point2D pt) {
740
                Point2D p = new Point2D.Double();
741
                try {
742
                        externalTransformation.inverseTransform(pt, p);
743
                } catch (NoninvertibleTransformException e) {
744
                        return pt;
745
                }
746
                return p;
747
        }
748
        
749
        /**
750
         * Calcula el extent en coordenadas del mundo real
751
         * @return Extent
752
         */
753
        public Extent getExtent() {
754
                return new Extent(        rasterToWorld(new Point2D.Double(0, 0)), 
755
                                                        rasterToWorld(new Point2D.Double(getWidth(), getHeight())),
756
                                                        rasterToWorld(new Point2D.Double(getWidth(), 0)),
757
                                                        rasterToWorld(new Point2D.Double(0, getHeight())));
758
        }
759
        
760
        /**
761
         * Calcula el extent en coordenadas del mundo real sin rotaci?n. Solo coordenadas y tama?o de pixel
762
         * @return Extent
763
         */
764
        public Extent getExtentWithoutRot() {
765
                AffineTransform at = new AffineTransform(        externalTransformation.getScaleX(), 0, 
766
                                                                                                        0, externalTransformation.getScaleY(), 
767
                                                                                                        externalTransformation.getTranslateX(), externalTransformation.getTranslateY());
768
                Point2D p1 = new Point2D.Double(0, 0);
769
                Point2D p2 = new Point2D.Double(getWidth(), getHeight());
770
                at.transform(p1, p1);
771
                at.transform(p2, p2);
772
                return new Extent(p1, p2);
773
        }
774
        
775
        /**
776
         * ASigna el par?metro de inicializaci?n del driver.
777
         */
778
        public void setParam(Object param) {
779
                this.param = param;
780
        }
781
        
782
        /**
783
         * Obtiene las estadisticas asociadas al fichero
784
         * @return Objeto con las estadisticas
785
         */
786
        public DatasetStatistics getStatistics() {
787
                return stats;
788
        }
789
        
790
        /**
791
         * Obtiene el n?mero de overviews de una banda
792
         * @return
793
         */
794
        abstract public int getOverviewCount(int band) throws BandAccessException, RasterDriverException;
795

    
796
        /**
797
         * Obtiene el ancho de una overview de una banda
798
         * @return
799
         */
800
        abstract public int getOverviewWidth(int band, int overview) throws BandAccessException, RasterDriverException;
801

    
802
        /**
803
         * Obtiene el alto de una overview de una banda
804
         * @return
805
         */
806
        abstract public int getOverviewHeight(int band, int overview) throws BandAccessException, RasterDriverException;
807
        
808
        /**
809
         * Informa de si el dataset soporta overviews o no.
810
         * @return true si soporta overviews y false si no las soporta.
811
         */
812
        abstract public boolean overviewsSupport();
813
        
814
        /**
815
         * Obtiene el histograma asociado al dataset. Este puede ser obtenido 
816
         * completo o seg?n una lista de clases pasada.
817
         * 
818
         * @return Histograma asociado al dataset.
819
         */
820
        public DatasetHistogram getHistogram() {
821
                if (histogram == null)
822
                        histogram = new DatasetHistogram(this);
823
                return histogram;
824
        }
825
        
826
        /**
827
         * Pone a cero el porcentaje de progreso del proceso de calculo de histograma
828
         */
829
        public void resetPercent() {
830
                if (histogram != null)
831
                        histogram.resetPercent();
832
        }
833

    
834
        /**
835
         * Obtiene el porcentaje de proceso en la construcci?n del histograma,
836
         * @return porcentaje de progreso
837
         */
838
        public int getPercent() {
839
                if (histogram != null) 
840
                        return histogram.getPercent();
841
                return 0;
842
        }
843

    
844
        /**
845
         * Obtiene el gestor de ficheros RMF
846
         * @return RmfBloksManager
847
         */
848
        public RmfBlocksManager getRmfBlocksManager() {
849
                return rmfBlocksManager;
850
        }
851
        
852
        /**
853
         * Escribe sobre el rmf todos los cambios que haya para salvar, es decir, para cada
854
         * Objeto registrado en el manager volcar? su contenido al fichero rmf. ANtes de salvar realizar?
855
         * una copia de seguridad sobre un fichero rmf de backup .rm~
856
         * @throws IOException
857
         */
858
        public void saveRmfModification() throws IOException {
859
                RasterUtilities.copyFile(rmfBlocksManager.getPath(), rmfBlocksManager.getPath() + "~");
860
                GeoInfoRmfSerializer geoInfoSerializer = new GeoInfoRmfSerializer(this);
861
                rmfBlocksManager.addClient(geoInfoSerializer);
862
                rmfBlocksManager.write();
863
                rmfBlocksManager.removeClient(geoInfoSerializer.getClass());
864
        }
865
                
866
        /**
867
         * Informa de si el punto en coordenadas del mundo real pasado por par?metro cae dentro del 
868
         * raster o fuera. Para este calculo cogeremos el punto a averiguar si est? dentro del raster 
869
         * y le aplicaremos la transformaci?n inversa de la transformaci?n af?n aplicada. Una vez hecho 
870
         * esto ya se puede comprobar si est? dentro de los l?mites del extent del raster.
871
         * @param p Punto a comprobar en coordenadas reales
872
         * @return true si el punto est? dentro y false si est? fuera.
873
         */
874
        public boolean isInside(Point2D p){
875
                //Realizamos los calculos solo si el punto est? dentro del extent de la imagen rotada, as? nos ahorramos los calculos
876
                //cuando el puntero est? fuera
877
                
878
                Point2D pt = new Point2D.Double();
879
                try {
880
                        
881
                        getAffineTransform().inverseTransform(p, pt);
882
                        if(        pt.getX() >= 0 && pt.getX() < getWidth() &&
883
                                        pt.getY() >= 0 && pt.getY() < getHeight())
884
                                return true;
885
                } catch (NoninvertibleTransformException e) {
886
                        return false;
887
                }
888
                
889
                return false;
890
        }
891
        
892
        /**
893
         * Consulta de si un raster tiene rotaci?n o no.
894
         * @return true si tiene rotaci?n y false si no la tiene.
895
         */
896
        public boolean isRotated() {
897
                if(externalTransformation.getShearX() != 0 || externalTransformation.getShearY() != 0)
898
                        return true;
899
                return false;
900
        }
901

    
902
        /**
903
         * Devuelve si el RasterDataSet tiene el valor noData activo
904
         * @return the noDataEnabled
905
         */
906
        public boolean isNoDataEnabled() {
907
                return noDataEnabled;
908
        }
909

    
910
        /**
911
         * Define si el RasterDataSet tiene el valor noData activo 
912
         * @param noDataEnabled the noDataEnabled to set
913
         */
914
        public void setNoDataEnabled(boolean noDataEnabled) {
915
                this.noDataEnabled = noDataEnabled;
916
        }
917
}