Statistics
| Revision:

svn-gvsig-desktop / trunk / libraries / libRaster / src / org / gvsig / raster / dataset / RasterDataset.java @ 12281

History | View | Annotate | Download (32.4 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.Point2D;
23
import java.io.BufferedReader;
24
import java.io.File;
25
import java.io.FileInputStream;
26
import java.io.FileNotFoundException;
27
import java.io.FileReader;
28
import java.io.IOException;
29
import java.lang.reflect.Constructor;
30
import java.lang.reflect.InvocationTargetException;
31

    
32
import org.cresques.cts.ICoordTrans;
33
import org.cresques.cts.IProjection;
34
import org.gvsig.i18n.Messages;
35
import org.gvsig.raster.dataset.io.GdalDriver;
36
import org.gvsig.raster.dataset.io.IRegistrableRasterFormat;
37
import org.gvsig.raster.dataset.io.MemoryRasterDriver;
38
import org.gvsig.raster.dataset.io.MemoryRasterDriverParam;
39
import org.gvsig.raster.dataset.io.rmf.ParsingException;
40
import org.gvsig.raster.dataset.io.rmf.RmfBlocksManager;
41
import org.gvsig.raster.dataset.properties.DatasetColorInterpretation;
42
import org.gvsig.raster.dataset.properties.DatasetHistogram;
43
import org.gvsig.raster.dataset.properties.DatasetMetadata;
44
import org.gvsig.raster.dataset.properties.DatasetStatistics;
45
import org.gvsig.raster.shared.ColorTable;
46
import org.gvsig.raster.shared.Extent;
47
import org.gvsig.raster.shared.Transparency;
48
import org.gvsig.raster.util.IHistogramable;
49
import org.gvsig.raster.util.RasterUtilities;
50
import org.gvsig.raster.util.extensionPoints.ExtensionPoint;
51
import org.gvsig.raster.util.extensionPoints.ExtensionPoints;
52
import org.gvsig.raster.util.extensionPoints.ExtensionPointsSingleton;
53
import org.kxml2.io.KXmlParser;
54
import org.xmlpull.v1.XmlPullParserException;
55

    
56
/**
57
 * Manejador de ficheros raster georeferenciados.
58
 * 
59
 * Esta clase abstracta es el ancestro de todas las clases que proporcionan
60
 * soporte para ficheros raster georeferenciados.<br>
61
 * Actua tambien como una 'Fabrica', ocultando al cliente la manera en que
62
 * se ha implementado ese manejo. Una clase nueva que soportara un nuevo
63
 * tipo de raster tendr?a que registrar su extensi?n o extensiones usando
64
 * el m?todo @see registerExtension.<br> 
65
 * @author "Luis W. Sevilla" <sevilla_lui@gva.es>*
66
 */
67

    
68
public abstract class RasterDataset extends GeoInfo {
69
        
70
        public static final int                CANCEL_HISTOGRAM = IHistogramable.CANCEL_HISTOGRAM;
71
        public static final int                CANCEL_READ = 2;
72
        
73
        protected boolean[]                        cancel = new boolean[1];
74
        
75
        /**
76
         * Flag que representa a la banda del Rojo
77
         */
78
        public static final int                                 RED_BAND        = 0x01;
79
        
80
        /**
81
         * Flag que representa a la banda del Verde
82
         */
83
        public static final int                                 GREEN_BAND        = 0x02;
84
        
85
        /**
86
         * Flag que representa a la banda del Azul
87
         */
88
        public static final int                                 BLUE_BAND        = 0x04;
89
        private boolean                                                        verifySize = false;
90
        /**
91
         * Par?metros de transformaci?n del fichero .rmf. Esta ser? distinta
92
         * de la identidad si la funci?n rmfExists() devuelve true.
93
         */
94
        protected AffineTransform                                rmfTransform = new AffineTransform();
95
                        
96
        /**
97
         * Asignaci?n de banda del Rojo a una banda de la imagen
98
         */
99
        protected int                                                         rBandNr = 1;
100
        
101
        /**
102
         * Asignaci?n de banda del Verde a una banda de la imagen
103
         */
104
        protected int                                                         gBandNr = 1;
105
        
106
        /**
107
         * Asignaci?n de banda del Azul a una banda de la imagen
108
         */
109
        protected int                                                         bBandNr = 1;
110
        
111
        /**
112
         * N?mero de bandas de la imagen
113
         */
114
        protected int                                                         bandCount = 1;
115
        private int                                                         dataType = IBuffer.TYPE_BYTE;        
116

    
117
        /**
118
         * Par?metros de transformaci?n del fichero .rmf. Estas variables tendr?n valores distinto
119
         * de 0 si la funci?n rmfExists() devuelve true.
120
         */
121
        protected double                                                 imageWidth = 0D, imageHeight = 0D;
122
        protected DatasetStatistics                        stats = new DatasetStatistics(this);
123
        protected DatasetHistogram                                histogram = null;
124
        protected Object                                                param = null;
125
        protected RmfBlocksManager                                rmfBlocksManager = null;
126
        
127
        static {
128
                Messages.addResourceFamily("org.cresques.translations.text", "org.cresques.ui");
129
        }
130
        
131
        /*
132
         *  (non-Javadoc)
133
         * @see java.lang.Object#clone()
134
         */
135
        public Object clone() {
136
                try {
137
                        RasterDataset dataset = RasterDataset.open(proj, param);
138
                        //Estas van por referencia
139
                        dataset.histogram = histogram;
140
                        dataset.stats = stats;
141
                        dataset.rmfTransform = rmfTransform;
142
                        return dataset;
143
                } catch (NotSupportedExtensionException e) {
144
                        e.printStackTrace();
145
                } catch (RasterDriverException e) {
146
                        e.printStackTrace();
147
                }
148
                return null;
149
        }
150
        
151
        /**
152
         * Factoria para abrir distintos tipos de raster.
153
         * 
154
         * @param proj Proyecci?n en la que est? el raster.
155
         * @param fName Nombre del fichero.
156
         * @return GeoRasterFile, o null si hay problemas.
157
         */
158
        public static RasterDataset open(IProjection proj, Object param) throws NotSupportedExtensionException, RasterDriverException {
159
                String idFormat = null;
160
        
161
                if(param instanceof String)
162
                        idFormat = ((String)param).toLowerCase().substring(((String)param).lastIndexOf('.') + 1);
163
                if(param instanceof IRegistrableRasterFormat)
164
                        idFormat = ((IRegistrableRasterFormat)param).getFormatID();
165
                                
166
                RasterDataset grf = null;
167

    
168
                Class clase = null;
169
                if(param instanceof MemoryRasterDriverParam)
170
                        clase = MemoryRasterDriver.class;
171
                
172
                if(clase == null){
173
                        ExtensionPoints extensionPoints = ExtensionPointsSingleton.getInstance();
174
                        ExtensionPoint extensionPoint = (ExtensionPoint)extensionPoints.get("RasterReader");
175
                        if(extensionPoint == null)
176
                                return null;
177
                        clase = (Class)extensionPoint.get(idFormat);
178
                }
179
                
180
                if(clase == null)
181
                        clase = GdalDriver.class;
182
                
183
                Class [] args = {IProjection.class, Object.class};
184
                try {
185
                        Constructor hazNuevo = clase.getConstructor(args);
186
                        Object [] args2 = {proj, param};
187
                        grf = (RasterDataset) hazNuevo.newInstance(args2);
188
                } catch (SecurityException e) {
189
                        throw new RasterDriverException("Error SecurityException in open");
190
                } catch (NoSuchMethodException e) {
191
                        throw new RasterDriverException("Error NoSuchMethodException in open");
192
                } catch (IllegalArgumentException e) {
193
                        throw new RasterDriverException("Error IllegalArgumentException in open");
194
                } catch (InstantiationException e) {
195
                        throw new RasterDriverException("Error InstantiationException in open");
196
                } catch (IllegalAccessException e) {
197
                        throw new RasterDriverException("Error IllegalAccessException in open");
198
                } catch (InvocationTargetException e) {
199
                        throw new NotSupportedExtensionException("Error in open");
200
                }
201
                return grf;
202
        }
203
                
204
        /**
205
         * Acciones de inicilizaci?n comunes a todos los drivers.
206
         * Este m?todo debe ser llamado explicitamente por el constructor de cada driver.
207
         * Estas son acciones de inicializaci?n que se ejecutan despu?s del constructor de cada driver.
208
         * Las acciones que hayan de ser realizadas antes se definen en el constructor de RasterDataset.
209
         */
210
        protected void init() {
211
                //Creamos el gestor de Rmf
212
                String f = getFName().substring(0, getFName().lastIndexOf("."));
213
                f = f + ".rmf";
214
                rmfBlocksManager = new RmfBlocksManager(f);
215
                
216
                /*try {
217
                        stats.loadFromRmf(rmfBlocksManager);
218
                } catch (ParsingException e) {
219
                        //No se cargan estad?sticas
220
                }*/
221
        }
222
        
223
        /**
224
         * Tipo de fichero soportado.
225
         * Devuelve true si el tipo de fichero (extension) est? soportado, si no
226
         * devuelve false.
227
         * 
228
         * @param fName Fichero raster
229
         * @return  true si est? soportado, si no false.
230
          */
231
        public static boolean fileIsSupported(String fName) {
232
                ExtensionPoints extensionPoints = ExtensionPointsSingleton.getInstance();
233
                ExtensionPoint extensionPoint = (ExtensionPoint)extensionPoints.get("RasterReader");
234
                return (extensionPoint.get(fName.substring(fName.lastIndexOf(".") + 1, fName.length())) == null) ? false : true;
235
        }
236
        
237
        /**
238
         * Constructor
239
         * @param proj        Proyecci?n
240
         * @param name        Nombre del fichero de imagen.
241
         */
242
        public RasterDataset(IProjection proj, Object param) {
243
                super(proj, param);
244
                if(param instanceof String)
245
                        setFileSize(new File(((String)param)).length());
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
         * Obtiene la codificaci?n del fichero XML
261
         * @param file Nombre del fichero XML
262
         * @return Codificaci?n
263
         */
264
        private String readFileEncoding(String file){
265
                FileReader fr;
266
                String encoding = null;
267
                try
268
            {
269
                        fr = new FileReader(file);
270
                    BufferedReader br = new BufferedReader(fr);
271
                    char[] buffer = new char[100];
272
                    br.read(buffer);
273
                    StringBuffer st = new StringBuffer(new String(buffer));
274
                    String searchText = "encoding=\"";
275
                    int index = st.indexOf(searchText);
276
                    if (index>-1) {
277
                            st.delete(0, index+searchText.length());
278
                            encoding = st.substring(0, st.indexOf("\""));
279
                    }
280
                    fr.close();
281
            } catch(FileNotFoundException ex)        {
282
                    ex.printStackTrace();
283
            } catch (IOException e) {
284
                        e.printStackTrace();
285
                }
286
            return encoding;
287
        }
288
        
289
        private double[] parserExtent(KXmlParser parser) throws XmlPullParserException, IOException {                
290
                double originX = 0D, originY = 0D, w = 0D, h = 0D;
291
                double pixelSizeX = 0D, pixelSizeY = 0D;
292
                double shearX = 0D, shearY = 0D;
293
                
294
                boolean end = false;
295
            int tag = parser.next();
296
            while (!end) {
297
                    switch(tag) {
298
                        case KXmlParser.START_TAG:
299
                                if(parser.getName() != null){        
300
                                                if (parser.getName().equals(RasterMetaFileTags.POSX)){
301
                                                        originX = Double.parseDouble(parser.nextText());
302
                                                }else if (parser.getName().equals(RasterMetaFileTags.POSY)){
303
                                                        originY = Double.parseDouble(parser.nextText());
304
                                                }else if (parser.getName().equals(RasterMetaFileTags.PX_SIZE_X)){
305
                                                        pixelSizeX = Double.parseDouble(parser.nextText());
306
                                                }else if (parser.getName().equals(RasterMetaFileTags.PX_SIZE_Y)){
307
                                                        pixelSizeY = Double.parseDouble(parser.nextText());
308
                                                }else if (parser.getName().equals(RasterMetaFileTags.ROTX)){
309
                                                        shearX = Double.parseDouble(parser.nextText());
310
                                                }else if (parser.getName().equals(RasterMetaFileTags.ROTY)){
311
                                                        shearY = Double.parseDouble(parser.nextText());
312
                                                }else if (parser.getName().equals(RasterMetaFileTags.WIDTH)){
313
                                                        w = Double.parseDouble(parser.nextText());
314
                                                }else if (parser.getName().equals(RasterMetaFileTags.HEIGHT)){
315
                                                        h = Double.parseDouble(parser.nextText());
316
                                                }
317
                                        }                                
318
                                        break;
319
                         case KXmlParser.END_TAG:
320
                                 if (parser.getName().equals(RasterMetaFileTags.BBOX))
321
                                         end = true;
322
                                break;
323
                        case KXmlParser.TEXT:
324
                                break;
325
                    }
326
                    tag = parser.next();
327
            }
328
                
329
            double[] values = {originX, originY, w, h, pixelSizeX, pixelSizeY, shearX, shearY};
330
                return values;
331
        }
332
        
333
        /**
334
         * Obtiene la informaci?n de georreferenciaci?n asociada a la imagen en un fichero .rmf. Esta 
335
         * georreferenciaci?n tiene la caracteristica de que tiene prioridad sobre la de la imagen.
336
         * Es almacenada en la clase GeoFile en la variable virtualExtent.
337
         * @param file Fichero de metadatos .rmf
338
         */
339
        protected void readGeoInfo(String file){
340
                String rmf = file.substring(0, file.lastIndexOf(".") + 1) + "rmf";
341
                File rmfFile = new File(rmf);
342
                if(!rmfFile.exists())
343
                        return;
344
                
345
                boolean georefOk = false;
346
                
347
                FileReader fr = null;
348
                String v = null;
349
                try {
350
                        fr = new FileReader(rmf);
351
                        KXmlParser parser = new KXmlParser();
352
                        parser.setInput(new FileInputStream(rmf), readFileEncoding(rmf));
353
                        int tag = parser.nextTag();
354
                        if ( parser.getEventType() != KXmlParser.END_DOCUMENT ){                    
355
                                parser.require(KXmlParser.START_TAG, null, RasterMetaFileTags.MAIN_TAG);                            
356
                                while(tag != KXmlParser.END_DOCUMENT) {
357
                                        switch(tag) {
358
                                                case KXmlParser.START_TAG:
359
                                                        if (parser.getName().equals(RasterMetaFileTags.LAYER)) {
360
                                                                int layerListTag = parser.next();
361
                                                                boolean geoRefEnd = false;
362
                                                                while (!geoRefEnd){
363
                                                                        if(parser.getName() != null){
364
                                                                                if (parser.getName().equals(RasterMetaFileTags.PROJ)){
365
                                                                                        //System.out.println("PROJ:"+parser.nextText());
366
                                                                                } else if (parser.getName().equals(RasterMetaFileTags.BBOX)){
367
                                                                                        double[] values = parserExtent(parser);
368
                                                                                        rmfTransform = new AffineTransform(        values[4], values[7],
369
                                                                                                                                           values[6], values[5],
370
                                                                                                                                                                   values[0], values[1]);
371
                                                                                        georefOk = true;
372
                                                                                } else if (parser.getName().equals(RasterMetaFileTags.DIM)){
373
                                                                                        boolean DimEnd = false;
374
                                                                                        while (!DimEnd){
375
                                                                                                layerListTag = parser.next();
376
                                                                                                if(parser.getName() != null){        
377
                                                                                                        if (parser.getName().equals(RasterMetaFileTags.PX_WIDTH)){
378
                                                                                                                imageWidth = Double.parseDouble(parser.nextText());
379
                                                                                                        }else if (parser.getName().equals(RasterMetaFileTags.PX_HEIGHT)){
380
                                                                                                                imageHeight = Double.parseDouble(parser.nextText());
381
                                                                                                                DimEnd = true;
382
                                                                                                        }                                                                                                        
383
                                                                                                }
384
                                                                                        }
385
                                                                                        geoRefEnd = true;
386
                                                                                }
387
                                                                        }
388
                                                                        layerListTag = parser.next();
389
                                                                }
390
                                                        }
391
                                                        break;
392
                                                case KXmlParser.END_TAG:                                                        
393
                                                        break;
394
                                                case KXmlParser.TEXT:                                                        
395
                                                        break;
396
                                        }
397
                                        tag = parser.next();
398
                                }
399
                                parser.require(KXmlParser.END_DOCUMENT, null, null);
400
                        }
401
                        
402
                        if(georefOk){
403
                                rmfExists = true;
404
                                setExtentTransform(        rmfTransform.getTranslateX(), rmfTransform.getTranslateY(), 
405
                                                                        rmfTransform.getScaleX(), rmfTransform.getScaleY());
406
                                createExtentsFromRMF(        rmfTransform.getTranslateX(), rmfTransform.getTranslateY(), 
407
                                                                                rmfTransform.getScaleX(), rmfTransform.getScaleY(), 
408
                                                                                imageWidth, imageHeight, 
409
                                                                                rmfTransform.getShearX(), rmfTransform.getShearY());
410
                        }
411
                        
412
                } catch (FileNotFoundException fnfEx) {
413
                } catch (XmlPullParserException xmlEx) {
414
                        xmlEx.printStackTrace();
415
                } catch (IOException e) {
416
                } 
417
                try{
418
                        if(fr != null)
419
                                fr.close();
420
                }catch(IOException ioEx){
421
                        //No est? abierto el fichero por lo que no hacemos nada
422
                }
423
        }
424

    
425
        /**
426
         * Asigna una transformaci?n al raster para que se tenga en cuenta en la asignaci?n del setView. 
427
         * Esta asignaci?n recalcula el extent, el requestExtent y asigna el AffineTransform que se 
428
         * usar? para la transformaci?n. Esta transformaci?n ser? considerada como si la imagen tuviera 
429
         * asociado un rmf.
430
         * @param t Transformaci?n af?n a aplicar
431
         */
432
        public void setAffineTransform(AffineTransform t){
433
                rmfExists = true;
434
                rmfTransform = (AffineTransform)t.clone();
435
                setExtentTransform(t.getTranslateX(), t.getTranslateY(), t.getScaleX(), t.getScaleY());
436
                createExtentsFromRMF(        t.getTranslateX(), t.getTranslateY(), t.getScaleX(), t.getScaleY(), 
437
                                                                this.getWidth(), this.getHeight(), 
438
                                                                t.getShearX(), t.getShearY());
439
        }
440
        
441
        /**
442
         * Asigna una transformaci?n al raster para que se tenga en cuenta en la asignaci?n del setView. 
443
         * Esta asignaci?n recalcula el extent, el requestExtent y asigna el AffineTransform que se 
444
         * usar? para la transformaci?n. Esta transformaci?n ser? considerada como si la imagen tuviera 
445
         * asociado un rmf.
446
         * @param originX Coordenada X de origen del raster
447
         * @param originY Coordenada Y de origen del raster
448
         * @param pixelSizeX Tama?o de pixel en X
449
         * @param pixelSizeY Tama?o de pixel en Y
450
         * @param imageWidth Ancho del raster en pixels
451
         * @param imageHeight Alto del raster en pixels
452
         * @param shearX Shearing en X
453
         * @param shearY Shearing en Y
454
         */
455
        public void setAffineTransform(        double originX, double originY, double pixelSizeX, 
456
                                                                                double pixelSizeY, double shearX, double shearY){
457
                rmfExists = true;
458
                rmfTransform.setToTranslation(originX, originY);
459
                rmfTransform.shear(shearX, shearY);
460
                rmfTransform.scale(pixelSizeX, pixelSizeY);
461
                setExtentTransform(originX, originY, pixelSizeX, pixelSizeY);
462
                createExtentsFromRMF(        originX, originY, pixelSizeX, pixelSizeY, 
463
                                                                imageWidth, imageHeight, shearX, shearY);
464
        }
465
        
466
        /**
467
         * Obtiene la matriz de transformaci?n que se aplica sobre la visualizaci?n 
468
         * del raster.
469
         * @return Matriz de transformaci?n.
470
         */
471
        public AffineTransform getAffineTransform(){
472
                return rmfTransform;
473
        }
474
        
475
        /**
476
         * Elimina la matriz de transformaci?n asociada al raster y que se tiene en cuenta para
477
         * el setView. Este reseteo tendr? en cuenta que si el raster tiene asociado un rmf
478
         * esta transformaci?n no ser? eliminada sino que se asignar? la correspondiente al rmf
479
         * existente.  
480
         * @return devuelve true si tiene fichero rmf asociado y false si no lo tiene.
481
         */
482
        public boolean resetAffineTransform(){
483
                rmfExists = false;
484
                rmfTransform.setToIdentity();
485
                
486
                //Crea los extent iniciales
487
                load();
488
                
489
                //Lee y carga el rmf si existe
490
                readGeoInfo(this.getFName());
491
                
492
                if(rmfExists)
493
                        return true;
494
                else
495
                        return false;
496
        }
497
        
498
        /**
499
         * <P>
500
         * Calcula el extent de la imagen a partir del fichero rmf con y sin rotaci?n. El extent con rotaci?n corresponde
501
         * a la variable extent que contiene el extent verdadero marcado por el fichero de georreferenciaci?n .rmf. El extent
502
         * sin rotaci?n requestExtent es utilizado para realizar la petici?n ya que la petici?n al driver no se puede
503
         * hacer con coordenadas rotadas.
504
         * 
505
         * El calculo de la bounding box rotada lo hace con los valores de transformaci?n leidos desde el fichero .rmf.
506
         * </p>
507
         * <P>
508
         * Para el calculo de una esquina aplicamos la formula siguiente:<BR>
509
         * PtoX = originX + pixelSizeX * x + shearX * y;<BR>
510
         * PtoY = originY + shearY * x + pixelSizeY * y;<BR>
511
         * Aplicandolo a las cuatro esquinas sustituimos en cada una de ellas por.
512
         * </P>
513
         * <UL> 
514
         * <LI>Esquina superior izquierda: x = 0; y = 0;</LI>
515
         * <LI>Esquina superior derecha: x = MaxX; y = 0;</LI>
516
         * <LI>Esquina inferior izquierda: x = 0; y = MaxY;</LI>
517
         * <LI>Esquina inferior derecha: x = MaxX; y = MaxY;</LI>
518
         * </UL> 
519
         * <P>
520
         * quedandonos en los cuatro casos:
521
         * </P>
522
         * <UL> 
523
         * <LI>Esquina superior izquierda: originX; originY;</LI>
524
         * <LI>Esquina superior derecha: PtoX = originX + pixelSizeX * x; PtoY = originY + shearY * x;</LI>
525
         * <LI>Esquina inferior izquierda:  PtoX = originX + shearX * y; PtoY = originY + pixelSizeY * y;</LI>
526
         * <LI>Esquina inferior derecha: PtoX = originX + pixelSizeX * x + shearX * y; PtoY = originY + shearY * x + pixelSizeY * y;</LI>
527
         * </UL>
528
         * 
529
         * <P>
530
         * El calculo de la bounding box se realizar? de la misma forma pero anulando los parametros de shearing.
531
         * </P>
532
         * 
533
         * @param originX Coordenada X de origen del raster
534
         * @param originY Coordenada Y de origen del raster
535
         * @param pixelSizeX Tama?o de pixel en X
536
         * @param pixelSizeY Tama?o de pixel en Y
537
         * @param imageWidth Ancho del raster en pixels
538
         * @param imageHeight Alto del raster en pixels
539
         * @param shearX Shearing en X
540
         * @param shearY Shearing en Y
541
         */
542
        private void createExtentsFromRMF(        double originX, double originY, double pixelSizeX, double pixelSizeY, 
543
                                                                                double imageWidth, double imageHeight, double shearX, double shearY){
544
                                
545
                Point2D p1 = new Point2D.Double(originX, originY);
546
                Point2D p2 = new Point2D.Double(originX + shearX * imageHeight, originY + pixelSizeY * imageHeight);
547
                Point2D p3 = new Point2D.Double(originX + pixelSizeX * imageWidth, originY + shearY * imageWidth);
548
                Point2D p4 = new Point2D.Double(originX + pixelSizeX * imageWidth + shearX * imageHeight, originY + pixelSizeY * imageHeight + shearY * imageWidth);
549
                
550
                double minX = Math.min(Math.min(p1.getX(), p2.getX()), Math.min(p3.getX(), p4.getX()));
551
                double minY = Math.min(Math.min(p1.getY(), p2.getY()), Math.min(p3.getY(), p4.getY()));
552
                double maxX = Math.max(Math.max(p1.getX(), p2.getX()), Math.max(p3.getX(), p4.getX()));
553
                double maxY = Math.max(Math.max(p1.getY(), p2.getY()), Math.max(p3.getY(), p4.getY()));
554
                extent = new Extent(minX, minY, maxX, maxY);
555
                requestExtent = new Extent(originX, originY, originX + (pixelSizeX * imageWidth), originY + (pixelSizeY * imageHeight));
556
        }
557
        
558
        /**
559
         * Calcula la transformaci?n que se produce sobre la vista cuando la imagen tiene un fichero .rmf
560
         * asociado. Esta transformaci?n tiene diferencias entre los distintos formatos por lo que debe calcularla
561
         * el driver correspondiente.
562
         * @param originX Origen de la imagen en la coordenada X
563
         * @param originY Origen de la imagen en la coordenada Y
564
         */
565
        abstract public void setExtentTransform(double originX, double originY, double psX, double psY);
566
                        
567
        /**
568
         * Obtiene el ancho de la imagen
569
         * @return Ancho de la imagen
570
         */
571
        abstract public int getWidth();
572
        
573
        /**
574
         * Obtiene el ancho de la imagen
575
         * @return Ancho de la imagen
576
         */
577
        abstract public int getHeight();
578

    
579
        /**
580
         * Reproyecci?n.
581
         * @param rp        Coordenadas de la transformaci?n
582
         */
583
        abstract public void reProject(ICoordTrans rp);
584

    
585
        /**
586
         * Asigna un nuevo Extent 
587
         * @param e        Extent
588
         */
589
        abstract public void setView(Extent e);
590
        
591
        /**
592
         * Obtiene el extent asignado
593
         * @return        Extent
594
         */
595
        abstract public Extent getView();
596
                                
597
        /**
598
         * Obtiene el valor del raster en la coordenada que se le pasa.
599
         * El valor ser? Double, Int, Byte, etc. dependiendo del tipo de
600
         * raster.
601
         * @param x        coordenada X
602
         * @param y coordenada Y
603
         * @return
604
         */
605
        abstract public Object getData(int x, int y, int band)throws InvalidSetViewException, FileNotOpenException, RasterDriverException;
606

    
607
        /**
608
         * Obtiene el n?nero de bandas del fichero
609
         * @return Entero que representa el n?mero de bandas
610
         */
611
        public int getBandCount() { 
612
                return bandCount; 
613
        }
614
                
615
        /**
616
         * @return Returns the dataType.
617
         */
618
        public int getDataType() {
619
                return dataType;
620
        }
621
        
622
        /**
623
         * @param dataType The dataType to set.
624
         */
625
        public void setDataType(int dataType) {
626
                this.dataType = dataType;
627
        }
628
   
629
        /**
630
         * Cosulta si hay que verificar la relaci?n de aspecto de la imagen, es decir comprueba que el ancho/alto
631
         * pasados a updateImage coinciden con el ancho/alto solicitado en setView a la imagen
632
         * @return true si est? verificando la relaci?n de aspecto. 
633
         */
634
        public boolean mustVerifySize() {
635
                return verifySize;
636
        }
637

    
638
        /**
639
         * Asigna el flag que dice si hay que verificar la relaci?n de aspecto de la imagen, es decir 
640
         * comprueba que el ancho/alto pasados a updateImage coinciden con el ancho/alto solicitado 
641
         * en setView a la imagen.
642
         * @return true si est? verificando la relaci?n de aspecto. 
643
         */
644
        public void setMustVerifySize(boolean verifySize) {
645
                this.verifySize = verifySize;
646
        }
647

    
648
        /**
649
         * Obtiene una ventana de datos de la imagen a partir de coordenadas reales. 
650
         * No aplica supersampleo ni subsampleo sino que devuelve una matriz de igual tama?o a los
651
         * pixeles de disco. 
652
         * @param x Posici?n X superior izquierda
653
         * @param y Posici?n Y superior izquierda
654
         * @param w Ancho en coordenadas reales
655
         * @param h Alto en coordenadas reales
656
         * @param rasterBuf        Buffer de datos
657
         * @param bandList
658
         * @param adjustToExtent Flag que dice si el extent solicitado debe ajustarse al extent del raster o no.
659
         * @return Buffer de datos
660
         */
661
        abstract public IBuffer getWindowRaster(double x, double y, double w, double h, BandList bandList, IBuffer rasterBuf, boolean adjustToExtent);
662
        
663
        /**
664
         * Obtiene una ventana de datos de la imagen a partir de coordenadas reales. 
665
         * Se aplica supersampleo o subsampleo dependiendo del tama?o del buffer especificado.
666
         * 
667
         * @param minX Posici?n m?nima X superior izquierda
668
         * @param minY Posici?n m?nima Y superior izquierda
669
         * @param maxX Posici?n m?xima X inferior derecha
670
         * @param maxY Posici?n m?xima Y inferior derecha
671
         * @param bufWidth Ancho del buffer de datos
672
         * @param bufHeight Alto del buffer de datos
673
         * @param rasterBuf        Buffer de datos
674
         * @param adjustToExtent Flag que dice si el extent solicitado debe ajustarse al extent del raster o no.
675
         * @param bandList
676
         * @return Buffer de datos
677
         */
678
        abstract public IBuffer getWindowRaster(double minX, double minY, double maxX, double maxY, int bufWidth, int bufHeight, BandList bandList, IBuffer rasterBuf, boolean adjustToExtent);
679
        
680
        /**
681
         * Obtiene una ventana de datos de la imagen a partir de coordenadas pixel. 
682
         * No aplica supersampleo ni subsampleo sino que devuelve una matriz de igual tama?o a los
683
         * pixeles de disco. 
684
         * @param x Posici?n X superior izquierda
685
         * @param y Posici?n Y superior izquierda
686
         * @param w Ancho en coordenadas reales
687
         * @param h Alto en coordenadas reales
688
         * @param rasterBuf        Buffer de datos
689
         * @param bandList
690
         * @return Buffer de datos
691
         */
692
        abstract public IBuffer getWindowRaster(int x, int y, int w, int h, BandList bandList, IBuffer rasterBuf);
693
        
694
        /**
695
         * Obtiene una ventana de datos de la imagen a partir de coordenadas pixel. 
696
         * Se aplica supersampleo o subsampleo dependiendo del tama?o del buffer especificado.
697
         * 
698
         * @param x Posici?n X superior izquierda
699
         * @param y Posici?n Y superior izquierda
700
         * @param w Ancho en coordenadas reales
701
         * @param h Alto en coordenadas reales
702
         * @param bufWidth Ancho del buffer de datos
703
         * @param bufHeight Alto del buffer de datos
704
         * @param rasterBuf        Buffer de datos
705
         * @param bandList
706
         * @return Buffer de datos
707
         */
708
        abstract public IBuffer getWindowRaster(int x, int y, int w, int h, int bufWidth, int bufHeight, BandList bandList, IBuffer rasterBuf);
709
        
710
        abstract public int getBlockSize();
711
        
712
        /**
713
         * Obtiene el objeto que contiene los metadatos. Este m?todo debe ser redefinido por los
714
         * drivers si necesitan devolver metadatos. 
715
         * @return
716
         */
717
        public DatasetMetadata getMetadata(){
718
                return null;
719
        }
720
        
721
        /**
722
         * Obtiene el objeto que contiene que contiene la interpretaci?n de 
723
         * color por banda
724
         * @return
725
         */
726
        public DatasetColorInterpretation getColorInterpretation(){
727
                return null;
728
        }
729
        
730
        /**
731
         * Asigna un extent temporal que puede coincidir con el de la vista. Esto es 
732
         * util para cargar imagenes sin georreferenciar ya que podemos asignar el extent
733
         * que queramos para ajustarnos a una vista concreta
734
         * @param tempExtent The tempExtent to set.
735
         */
736
        public void setExtent(Extent ext) {
737
                this.extent = ext;
738
        }
739
        
740
        /**
741
         * Dice si el fichero tiene georreferenciaci?n o no.
742
         * @return true si tiene georreferenciaci?n y false si no la tiene
743
         */
744
        public boolean isGeoreferenced(){
745
                return true;
746
        }
747

    
748
        /**
749
         * Obtiene el objeto paleta. Esta paleta es la que tiene adjunta el fichero de disco. Si es
750
         * null este objeto quiere decir que no tiene paleta para su visualizaci?n. 
751
         * @return Palette
752
         */
753
        public ColorTable getColorTable() {
754
                return null;
755
        }
756
        
757
        /**
758
         * M?todo que indica si existe un fichero .rmf asociado al GeoRasterFile.
759
         * @return
760
         */
761
        public boolean rmfExists(){
762
                return this.rmfExists;
763
        }
764
                
765
        /**
766
         * Obtiene los par?metros de la transformaci?n af?n que corresponde con los elementos de
767
         * un fichero tfw.
768
         * <UL> 
769
         * <LI>[1]tama?o de pixel en X</LI>
770
         * <LI>[2]rotaci?n en X</LI>
771
         * <LI>[4]rotaci?n en Y</LI>
772
         * <LI>[5]tama?o de pixel en Y</LI>
773
         * <LI>[0]origen en X</LI>
774
         * <LI>[3]origen en Y</LI>
775
         * </UL>
776
         * Este m?todo debe ser reimplementado por el driver si tiene esta informaci?n. En principio
777
         * Gdal es capaz de proporcionarla de esta forma.
778
         * @return vector de double con los elementos de la transformaci?n af?n.
779
         */
780
        public double[] getTransform(){
781
                return null;
782
        }
783

    
784
        /**
785
         * Obtiene el estado de transparencia de un GeoRasterFile. 
786
         * @return Objeto TransparencyFileStatus
787
         */
788
        public Transparency getTransparencyDatasetStatus() {
789
                return null;
790
        }
791
        
792
        /**
793
         * Dado unas coordenadas reales, un tama?o de buffer y un tama?o de raster. 
794
         * Si el buffer es de mayor tama?o que el raster (supersampleo) quiere decir que 
795
         * por cada pixel de buffer se repiten varios del raster. Esta funci?n calcula el 
796
         * n?mero de pixels de desplazamiento en X e Y que corresponden al primer pixel del
797
         * buffer en la esquina superior izquierda. Esto es necesario porque la coordenada
798
         * solicitada es real y puede no caer sobre un pixel completo. Este calculo es
799
         * util cuando un cliente quiere supersamplear sobre un buffer y que no se lo haga
800
         * el driver autom?ticamente.
801
         * @param dWorldTLX Coordenada real X superior izquierda
802
         * @param dWorldTLY Coordenada real Y superior izquierda
803
         * @param dWorldBRX Coordenada real X inferior derecha
804
         * @param dWorldBRY Coordenada real Y inferior derecha
805
         * @param nWidth Ancho del raster
806
         * @param nHeight Alto del raster
807
         * @param bufWidth Ancho del buffer
808
         * @param bufHeight Alto del buffer
809
         * @return Array de dos elementos con el desplazamiento en X e Y. 
810
         */
811
        public int[] calcSteps(double dWorldTLX, double dWorldTLY, double dWorldBRX, double dWorldBRY, 
812
                        double nWidth, double nHeight, int bufWidth, int bufHeight){
813
                Point2D tl = worldToRaster(new Point2D.Double(dWorldTLX, dWorldTLY));
814
                Point2D br = worldToRaster(new Point2D.Double(dWorldBRX, dWorldBRY));
815
                                
816
        int x = (int) tl.getX();
817
        int y = (int) tl.getY();
818

    
819
                int stpX = (int)(((tl.getX() - x) * bufWidth) / Math.abs(br.getX() - tl.getX()));
820
                int stpY = (int)(((tl.getY() - y) * bufHeight) / Math.abs(br.getY() - tl.getY()));
821
                
822
                return new int[]{stpX, stpY};
823
        }
824
        
825
        /**
826
         * Lee una l?nea completa del raster y devuelve un array del tipo correcto. Esta funci?n es util
827
         * para una lectura rapida de todo el fichero sin necesidad de asignar vista. 
828
         * @param nLine N?mero de l?nea a leer
829
         * @param band Banda requerida
830
         * @return Object que es un array unidimendional del tipo de datos del raster
831
         * @throws InvalidSetViewException
832
         * @throws FileNotOpenException
833
         * @throws RasterDriverException
834
         */
835
        abstract public Object readCompleteLine(int line, int band)throws InvalidSetViewException, FileNotOpenException, RasterDriverException;
836
        
837
        /**
838
         * Lee un bloque completo de datos del raster y devuelve un array tridimensional del tipo correcto. Esta funci?n es util
839
         * para una lectura rapida de todo el fichero sin necesidad de asignar vista. 
840
         * @param pos Posici?n donde se empieza  a leer
841
         * @param blockHeight Altura m?xima del bloque leido
842
         * @return Object que es un array tridimendional del tipo de datos del raster. (Bandas X Filas X Columnas)
843
         * @throws InvalidSetViewException
844
         * @throws FileNotOpenException
845
         * @throws RasterDriverException
846
         */
847
        abstract public Object readBlock(int pos, int blockHeight)throws InvalidSetViewException, FileNotOpenException, RasterDriverException;
848
        
849
        /**
850
         * Convierte un punto desde coordenadas pixel a coordenadas del mundo.
851
         * @param pt Punto a transformar
852
         * @return punto transformado en coordenadas del mundo
853
         */
854
        abstract public Point2D rasterToWorld(Point2D pt);
855
        
856
        /**
857
         * Convierte un punto desde del mundo a coordenadas pixel.
858
         * @param pt Punto a transformar
859
         * @return punto transformado en coordenadas pixel
860
         */
861
        abstract public Point2D worldToRaster(Point2D pt);
862

    
863
        /**
864
         * ASigna el par?metro de inicializaci?n del driver.
865
         */
866
        public void setParam(Object param) {
867
                this.param = param;
868
        }
869
        
870
        /**
871
         * Obtiene las estadisticas asociadas al fichero
872
         * @return Objeto con las estadisticas
873
         */
874
        public DatasetStatistics getStatistics() {
875
                return stats;
876
        }
877
        
878
        /**
879
         * Obtiene el histograma asociado al dataset. Este puede ser obtenido 
880
         * completo o seg?n una lista de clases pasada.
881
         * 
882
         * @return Histograma asociado al dataset.
883
         */
884
        public DatasetHistogram getHistogram() {
885
                if (histogram == null)
886
                        histogram = new DatasetHistogram(this);
887
                return histogram;
888
        }
889
        
890
        public void resetPercent() {
891
                if (histogram != null) histogram.resetPercent();
892
        }
893

    
894
        public int getPercent() {
895
                if (histogram != null) return histogram.getPercent();
896
                return 0;
897
        }
898
        
899
        public void setCanceled(boolean value, int process) {
900
                if(process == CANCEL_HISTOGRAM || process == 0) {
901
                        if (histogram != null) 
902
                                histogram.setCanceled(value, DatasetHistogram.CANCEL_CREATEHISTOGRAM);
903
                }
904
        }
905

    
906
        public boolean isCanceled(int process) {
907
                if(process == CANCEL_HISTOGRAM) {
908
                        if (histogram != null) 
909
                                return histogram.isCanceled(DatasetHistogram.CANCEL_CREATEHISTOGRAM);
910
                }
911
                return false;
912
        }
913

    
914
        /**
915
         * Obtiene el gestor de ficheros RMF
916
         * @return RmfBloksManager
917
         */
918
        public RmfBlocksManager getRmfBlocksManager() {
919
                return rmfBlocksManager;
920
        }
921
        
922
        /**
923
         * Escribe sobre el rmf todos los cambios que haya para salvar, es decir, para cada
924
         * Objeto registrado en el manager volcar? su contenido al fichero rmf. ANtes de salvar realizar?
925
         * una copia de seguridad sobre un fichero rmf de backup .rm~
926
         * @throws IOException
927
         */
928
        public void saveRmfModification() throws IOException {
929
                RasterUtilities.copyFile(rmfBlocksManager.getPath(), rmfBlocksManager.getPath() + "~");
930
                rmfBlocksManager.write();
931
        }
932
                
933
}