Statistics
| Revision:

root / branches / v10+Piloto / libraries / libCq_CMS_praster / src / org / cresques / io / GeoRasterFile.java @ 10041

History | View | Annotate | Download (32.8 KB)

1
/*
2
 * Cresques Mapping Suite. Graphic Library for constructing mapping applications.
3
 * 
4
 * Copyright (C) 2004-5. 
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 2
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
19
 *
20
 * For more information, contact:
21
 * 
22
 * cresques@gmail.com
23
 */
24
package org.cresques.io;
25

    
26
import java.awt.Component;
27
import java.awt.Dimension;
28
import java.awt.Image;
29
import java.awt.geom.AffineTransform;
30
import java.awt.geom.Point2D;
31
import java.awt.image.DataBuffer;
32
import java.io.BufferedReader;
33
import java.io.File;
34
import java.io.FileInputStream;
35
import java.io.FileNotFoundException;
36
import java.io.FileReader;
37
import java.io.FileWriter;
38
import java.io.IOException;
39
import java.lang.reflect.Constructor;
40
import java.lang.reflect.InvocationTargetException;
41
import java.util.TreeMap;
42

    
43
import org.cresques.cts.ICoordTrans;
44
import org.cresques.cts.IProjection;
45
import org.cresques.filter.PixelFilter;
46
import org.cresques.filter.SimplePixelFilter;
47
import org.cresques.io.data.BandList;
48
import org.cresques.io.data.RasterBuf;
49
import org.cresques.io.data.RasterMetaFileTags;
50
import org.cresques.io.datastruct.Metadata;
51
import org.cresques.io.datastruct.Palette;
52
import org.cresques.io.exceptions.SupersamplingNotSupportedException;
53
import org.cresques.px.Extent;
54
import org.cresques.px.IObjList;
55
import org.cresques.px.PxContour;
56
import org.cresques.px.PxObjList;
57
import org.gvsig.i18n.Messages;
58
import org.kxml2.io.KXmlParser;
59
import org.xmlpull.v1.XmlPullParserException;
60

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

    
73
public abstract class GeoRasterFile extends GeoFile {
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 static TreeMap                 supportedExtensions = null;
90
        protected Component                 updatable = null;
91
        protected boolean                         doTransparency = false;
92
        private boolean                                verifySize = false;
93
        /**
94
         * Par?metros de transformaci?n del fichero .rmf. Esta ser? distinta
95
         * de la identidad si la funci?n rmfExists() devuelve true.
96
         */
97
        protected AffineTransform        rmfTransform = new AffineTransform();
98
        
99
        /**
100
         * Esta variable estar? a true si el driver est? supersampleando en el ?ltimo dibujado.
101
         * Debe tenerse especial cuidado ya que est? consulta no es adecuada desde gvSIG ya que el
102
         * dibujado se realiza asincronamente por lo que el valor puede no coincidir con el ?ltimo
103
         * dibujado.
104
         */
105
        protected boolean                        isSupersampling = false;
106
        /**
107
         * Paso correspondiente al supersampling o subsampling que se est? aplicando en el ?ltimo dibujado.
108
         */
109
        protected int[] stepArrayX = null, stepArrayY = null;
110
        
111
        /**
112
         * Filtro para raster.
113
         * Permite eliminar la franja inutil alrededor de un raster girado o de
114
         * un mosaico de borde irregular.
115
         * 
116
         * Funciona bien solo con raster en tonos de gris, porque se basa que
117
         * el valor del pixel no supere un determinado valor 'umbral' que se
118
         * le pasa al constructor.
119
         * 
120
         * Desarrollado para 'limpiar' los bordes de los mosaicos del SIG
121
         * Oleicola. Para ese caso los par?metros del constructo son:
122
         * PixelFilter(0x10ffff00, 0xff000000, 0xf0f0f0);
123
         */
124
        protected PixelFilter                 tFilter = null;
125
        
126
        /**
127
         * Asignaci?n de banda del Rojo a una banda de la imagen
128
         */
129
        protected int                                 rBandNr = 1;
130
        
131
        /**
132
         * Asignaci?n de banda del Verde a una banda de la imagen
133
         */
134
        protected int                                 gBandNr = 1;
135
        
136
        /**
137
         * Asignaci?n de banda del Azul a una banda de la imagen
138
         */
139
        protected int                                 bBandNr = 1;
140
        
141
        /**
142
         * N?mero de bandas de la imagen
143
         */
144
        protected int                                 bandCount = 1;
145
        private int                                 dataType = DataBuffer.TYPE_BYTE;
146
        protected Palette                        palette = null;
147
        /**
148
         * Par?metros de transformaci?n del fichero .rmf. Estas variables tendr?n valores distinto
149
         * de 0 si la funci?n rmfExists() devuelve true.
150
         */
151
        protected double imageWidth = 0D, imageHeight = 0D;
152
        
153
        static {
154
                Messages.addResourceFamily("org.cresques.translations.text", "org.cresques.ui");
155
                supportedExtensions = new TreeMap();
156
                supportedExtensions.put("ecw",  EcwFile.class);
157
                supportedExtensions.put("jp2",  EcwFile.class);
158
                
159
                supportedExtensions.put("sid",  MrSidFile.class);
160

    
161
                supportedExtensions.put("bmp", GdalFile.class);
162
                supportedExtensions.put("gif", GdalFile.class);
163
                supportedExtensions.put("img", GdalFile.class);
164
                supportedExtensions.put("tif", GdalFile.class);
165
                supportedExtensions.put("tiff", GdalFile.class);
166
                supportedExtensions.put("jpg", GdalFile.class);
167
                supportedExtensions.put("png", GdalFile.class);
168
                supportedExtensions.put("vrt", GdalFile.class);
169
                
170
                supportedExtensions.put("dat",  GdalFile.class); // Envi
171
                supportedExtensions.put("lan",  GdalFile.class); // Erdas
172
                supportedExtensions.put("gis",  GdalFile.class); // Erdas
173
                supportedExtensions.put("pix",  GdalFile.class); // PCI Geomatics
174
                supportedExtensions.put("aux",  GdalFile.class); // PCI Geomatics
175
                supportedExtensions.put("adf",  GdalFile.class); // ESRI Grids
176
                supportedExtensions.put("mpr",  GdalFile.class); // Ilwis
177
                supportedExtensions.put("mpl",  GdalFile.class); // Ilwis
178
                supportedExtensions.put("map",  GdalFile.class); // PC Raster
179
                supportedExtensions.put("asc",  GdalFile.class); // PC Raster
180
        }
181
        
182
        /**
183
         * Factoria para abrir distintos tipos de raster.
184
         * 
185
         * @param proj Proyecci?n en la que est? el raster.
186
         * @param fName Nombre del fichero.
187
         * @return GeoRasterFile, o null si hay problemas.
188
         */
189
        public static GeoRasterFile openFile(IProjection proj, String fName) {
190
                String ext = fName.toLowerCase().substring(fName.lastIndexOf('.')+1);
191
                GeoRasterFile grf = null;
192

    
193
                //if (!supportedExtensions.containsKey(ext)) 
194
                        //return grf;
195
                Class clase = null;
196
                if (supportedExtensions.containsKey(ext))
197
                        clase = (Class) supportedExtensions.get(ext);
198
                else
199
                        clase = GdalFile.class;
200
                        
201
                
202
                Class [] args = {IProjection.class, String.class};
203
                try {
204
                        Constructor hazNuevo = clase.getConstructor(args);
205
                        Object [] args2 = {proj, fName};
206
                        grf = (GeoRasterFile) hazNuevo.newInstance(args2);
207
                        grf.setFileSize(new File(fName).length());
208
                } catch (SecurityException e) {
209
                        e.printStackTrace();
210
                } catch (NoSuchMethodException e) {
211
                        e.printStackTrace();
212
                } catch (IllegalArgumentException e) {
213
                        e.printStackTrace();
214
                } catch (InstantiationException e) {
215
                        e.printStackTrace();
216
                } catch (IllegalAccessException e) {
217
                        e.printStackTrace();
218
                } catch (InvocationTargetException e) {
219
                        System.err.println("Extension not supported!!!");
220
                        return null;
221
                }
222
                return grf;
223
        }
224
        
225
        /**
226
         * Registra una clase que soporta una extensi?n raster.
227
         * @param ext extensi?n soportada.
228
         * @param clase clase que la soporta.
229
         */
230
        public static void registerExtension(String ext, Class clase) {
231
                ext = ext.toLowerCase();
232
                System.out.println("RASTER: extension '"+ext+"' supported.");
233
                supportedExtensions.put(ext, clase);
234
        }
235
        
236
        /**
237
         * Tipo de fichero soportado.
238
         * Devuelve true si el tipo de fichero (extension) est? soportado, si no
239
         * devuelve false.
240
         * 
241
         * @param fName Fichero raster
242
         * @return  true si est? soportado, si no false.
243
          */
244
        public static boolean fileIsSupported(String fName) {
245
                //return true;
246
                String ext = fName.toLowerCase().substring(fName.lastIndexOf('.') + 1);
247
                return supportedExtensions.containsKey(ext);
248
        }
249
        
250
        /**
251
         * Constructor
252
         * @param proj        Proyecci?n
253
         * @param name        Nombre del fichero de imagen.
254
         */
255
        public GeoRasterFile(IProjection proj, String name) {
256
                super(proj, name);
257
        }
258
        
259
        /**
260
         * Carga un fichero raster. Puede usarse para calcular el extent e instanciar 
261
         * un objeto de este tipo.
262
         */
263
        abstract public GeoFile load();
264
        
265
        /**
266
         * Cierra el fichero y libera los recursos.
267
         */
268
        abstract public void close();
269
        
270
        /**
271
         * Obtiene la codificaci?n del fichero XML
272
         * @param file Nombre del fichero XML
273
         * @return Codificaci?n
274
         */
275
        private String readFileEncoding(String file){
276
                FileReader fr;
277
                String encoding = null;
278
                try
279
            {
280
                        fr = new FileReader(file);
281
                    BufferedReader br = new BufferedReader(fr);
282
                    char[] buffer = new char[100];
283
                    br.read(buffer);
284
                    StringBuffer st = new StringBuffer(new String(buffer));
285
                    String searchText = "encoding=\"";
286
                    int index = st.indexOf(searchText);
287
                    if (index>-1) {
288
                            st.delete(0, index+searchText.length());
289
                            encoding = st.substring(0, st.indexOf("\""));
290
                    }
291
                    fr.close();
292
            } catch(FileNotFoundException ex)        {
293
                    ex.printStackTrace();
294
            } catch (IOException e) {
295
                        e.printStackTrace();
296
                }
297
            return encoding;
298
        }
299
        
300
        private double[] parserExtent(KXmlParser parser) throws XmlPullParserException, IOException {                
301
                double originX = 0D, originY = 0D, w = 0D, h = 0D;
302
                double pixelSizeX = 0D, pixelSizeY = 0D;
303
                double shearX = 0D, shearY = 0D;
304
                
305
                boolean end = false;
306
            int tag = parser.next();
307
            while (!end) {
308
                    switch(tag) {
309
                        case KXmlParser.START_TAG:
310
                                if(parser.getName() != null){        
311
                                                if (parser.getName().equals(RasterMetaFileTags.POSX)){
312
                                                        originX = Double.parseDouble(parser.nextText());
313
                                                }else if (parser.getName().equals(RasterMetaFileTags.POSY)){
314
                                                        originY = Double.parseDouble(parser.nextText());
315
                                                }else if (parser.getName().equals(RasterMetaFileTags.PX_SIZE_X)){
316
                                                        pixelSizeX = Double.parseDouble(parser.nextText());
317
                                                }else if (parser.getName().equals(RasterMetaFileTags.PX_SIZE_Y)){
318
                                                        pixelSizeY = Double.parseDouble(parser.nextText());
319
                                                }else if (parser.getName().equals(RasterMetaFileTags.ROTX)){
320
                                                        shearX = Double.parseDouble(parser.nextText());
321
                                                }else if (parser.getName().equals(RasterMetaFileTags.ROTY)){
322
                                                        shearY = Double.parseDouble(parser.nextText());
323
                                                }else if (parser.getName().equals(RasterMetaFileTags.WIDTH)){
324
                                                        w = Double.parseDouble(parser.nextText());
325
                                                }else if (parser.getName().equals(RasterMetaFileTags.HEIGHT)){
326
                                                        h = Double.parseDouble(parser.nextText());
327
                                                }
328
                                        }                                
329
                                        break;
330
                         case KXmlParser.END_TAG:
331
                                 if (parser.getName().equals(RasterMetaFileTags.BBOX))
332
                                         end = true;
333
                                break;
334
                        case KXmlParser.TEXT:
335
                                break;
336
                    }
337
                    tag = parser.next();
338
            }
339
                
340
            double[] values = {originX, originY, w, h, pixelSizeX, pixelSizeY, shearX, shearY};
341
                return values;
342
        }
343
        
344
        /**
345
         * Obtiene la informaci?n de georreferenciaci?n asociada a la imagen en un fichero .rmf. Esta 
346
         * georreferenciaci?n tiene la caracteristica de que tiene prioridad sobre la de la imagen.
347
         * Es almacenada en la clase GeoFile en la variable virtualExtent.
348
         * @param file Fichero de metadatos .rmf
349
         */
350
        protected void readGeoInfo(String file){
351
                String rmf = file.substring(0, file.lastIndexOf(".") + 1) + "rmf";
352
                File rmfFile = new File(rmf);
353
                if(!rmfFile.exists())
354
                        return;
355
                
356
                boolean georefOk = false;
357
                
358
                FileReader fr = null;
359
                String v = null;
360
                try {
361
                        fr = new FileReader(rmf);
362
                        KXmlParser parser = new KXmlParser();
363
                        parser.setInput(new FileInputStream(rmf), readFileEncoding(rmf));
364
                        int tag = parser.nextTag();
365
                        if ( parser.getEventType() != KXmlParser.END_DOCUMENT ){                    
366
                                parser.require(KXmlParser.START_TAG, null, RasterMetaFileTags.MAIN_TAG);                            
367
                                while(tag != KXmlParser.END_DOCUMENT) {
368
                                        switch(tag) {
369
                                                case KXmlParser.START_TAG:
370
                                                        if (parser.getName().equals(RasterMetaFileTags.LAYER)) {
371
                                                                int layerListTag = parser.next();
372
                                                                boolean geoRefEnd = false;
373
                                                                while (!geoRefEnd){
374
                                                                        if(parser.getName() != null){
375
                                                                                if (parser.getName().equals(RasterMetaFileTags.PROJ)){
376
                                                                                        //System.out.println("PROJ:"+parser.nextText());
377
                                                                                } else if (parser.getName().equals(RasterMetaFileTags.BBOX)){
378
                                                                                        double[] values = parserExtent(parser);
379
                                                                                        rmfTransform = new AffineTransform(        values[4], values[7],
380
                                                                                                                                           values[6], values[5],
381
                                                                                                                                                                   values[0], values[1]);
382
                                                                                        georefOk = true;
383
                                                                                } else if (parser.getName().equals(RasterMetaFileTags.DIM)){
384
                                                                                        boolean DimEnd = false;
385
                                                                                        while (!DimEnd){
386
                                                                                                layerListTag = parser.next();
387
                                                                                                if(parser.getName() != null){        
388
                                                                                                        if (parser.getName().equals(RasterMetaFileTags.PX_WIDTH)){
389
                                                                                                                imageWidth = Double.parseDouble(parser.nextText());
390
                                                                                                        }else if (parser.getName().equals(RasterMetaFileTags.PX_HEIGHT)){
391
                                                                                                                imageHeight = Double.parseDouble(parser.nextText());
392
                                                                                                                DimEnd = true;
393
                                                                                                        }                                                                                                        
394
                                                                                                }
395
                                                                                        }
396
                                                                                        geoRefEnd = true;
397
                                                                                }
398
                                                                        }
399
                                                                        layerListTag = parser.next();
400
                                                                }
401
                                                        }
402
                                                        break;
403
                                                case KXmlParser.END_TAG:                                                        
404
                                                        break;
405
                                                case KXmlParser.TEXT:                                                        
406
                                                        break;
407
                                        }
408
                                        tag = parser.next();
409
                                }
410
                                parser.require(KXmlParser.END_DOCUMENT, null, null);
411
                        }
412
                        
413
                        if(georefOk){
414
                                rmfExists = true;
415
                                setExtentTransform(        rmfTransform.getTranslateX(), rmfTransform.getTranslateY(), 
416
                                                                        rmfTransform.getScaleX(), rmfTransform.getScaleY());
417
                                createExtentsFromRMF(        rmfTransform.getTranslateX(), rmfTransform.getTranslateY(), 
418
                                                                                rmfTransform.getScaleX(), rmfTransform.getScaleY(), 
419
                                                                                imageWidth, imageHeight, 
420
                                                                                rmfTransform.getShearX(), rmfTransform.getShearY());
421
                        }
422
                        
423
                } catch (FileNotFoundException fnfEx) {
424
                } catch (XmlPullParserException xmlEx) {
425
                        xmlEx.printStackTrace();
426
                } catch (IOException e) {
427
                } 
428
                try{
429
                        if(fr != null)
430
                                fr.close();
431
                }catch(IOException ioEx){
432
                        //No est? abierto el fichero por lo que no hacemos nada
433
                }
434
        }
435

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

    
595
        /**
596
         * Reproyecci?n.
597
         * @param rp        Coordenadas de la transformaci?n
598
         */
599
        abstract public void reProject(ICoordTrans rp);
600

    
601
        /**
602
         * Asigna un nuevo Extent 
603
         * @param e        Extent
604
         */
605
        abstract public void setView(Extent e);
606
        
607
        /**
608
         * Obtiene el extent asignado
609
         * @return        Extent
610
         */
611
        abstract public Extent getView();
612
        
613
        public void setTransparency(boolean t) {
614
                doTransparency = t;
615
                tFilter = new PixelFilter(255);
616
        }
617
        
618
        /**
619
         * Asigna un valor de transparencia
620
         * @param t        Valor de transparencia
621
         */
622
        public void setTransparency(int t ) {
623
                doTransparency = true;
624
                tFilter = new SimplePixelFilter(255 - t);
625
        }
626
        
627
        public boolean getTransparency() { return doTransparency; }
628
        
629
        public void setAlpha(int alpha) {
630
                if (!doTransparency) setTransparency(255 - alpha);
631
                else tFilter.setAlpha(alpha);
632
        }
633
        public int getAlpha() {
634
                if (tFilter == null)
635
                        return 255;
636
                return tFilter.getAlpha();
637
        }
638
        
639
        public void setUpdatable(Component c) { updatable = c; }
640
        
641
        /**
642
         * Actualiza la imagen
643
         * @param width        ancho
644
         * @param height        alto
645
         * @param rp        Reproyecci?n
646
         * @return        img
647
         */
648
        abstract public Image updateImage(int width, int height, ICoordTrans rp);
649

    
650
        /**
651
         * Obtiene el valor del raster en la coordenada que se le pasa.
652
         * El valor ser? Double, Int, Byte, etc. dependiendo del tipo de
653
         * raster.
654
         * @param x        coordenada X
655
         * @param y coordenada Y
656
         * @return
657
         */
658
        abstract public Object getData(int x, int y, int band);
659

    
660
        /**
661
         * Actualiza la/s banda/s especificadas en la imagen.
662
         * @param width                ancho
663
         * @param height        alto
664
         * @param rp                reproyecci?n
665
         * @param img                imagen
666
         * @param flags                que bandas [ RED_BAND | GREEN_BAND | BLUE_BAND ]
667
         * @return                img
668
         * @throws SupersamplingNotSupportedException
669
         */
670
        abstract public Image updateImage(int width, int height, ICoordTrans rp, Image img, int origBand, int destBand)throws SupersamplingNotSupportedException;
671

    
672
        public int getBandCount() { return bandCount; }
673
        
674
        /**
675
         * Asocia un colorBand al rojo, verde o azul.
676
         * @param flag cual (o cuales) de las bandas.
677
         * @param nBand        que colorBand
678
         */
679
        
680
        public void setBand(int flag, int bandNr) {
681
                if ((flag & GeoRasterFile.RED_BAND) == GeoRasterFile.RED_BAND) rBandNr = bandNr;
682
                if ((flag & GeoRasterFile.GREEN_BAND) == GeoRasterFile.GREEN_BAND) gBandNr = bandNr;
683
                if ((flag & GeoRasterFile.BLUE_BAND) == GeoRasterFile.BLUE_BAND) bBandNr = bandNr;
684
        }
685

    
686
        /**
687
         * Devuelve el colorBand activo en la banda especificada.
688
         * @param flag banda.
689
         */
690
        
691
        public int getBand(int flag) {
692
                if (flag == GeoRasterFile.RED_BAND) return rBandNr;
693
                if (flag == GeoRasterFile.GREEN_BAND) return gBandNr;
694
                if (flag == GeoRasterFile.BLUE_BAND) return bBandNr;
695
                return -1;
696
        }
697
        
698
        /**
699
         * @return Returns the dataType.
700
         */
701
        public int getDataType() {
702
                return dataType;
703
        }
704
        
705
        /**
706
         * @param dataType The dataType to set.
707
         */
708
        public void setDataType(int dataType) {
709
                this.dataType = dataType;
710
        }
711

    
712
        public IObjList getObjects() {
713
                // TODO hay que a?adir el raster a la lista de objetos
714
                IObjList oList = new PxObjList(proj);
715
                return oList;
716
        }
717
        
718
        /**
719
         * Calcula los par?metros de un worl file a partir de las esquinas del raster.
720
         *    1. X pixel size A
721
         *    2. X rotation term D
722
         *    3. Y rotation term B
723
         *    4. Y pixel size E
724
         *    5. X coordinate of upper left corner C
725
         *    6. Y coordinate of upper left corner F
726
         * where the real-world coordinates x',y' can be calculated from
727
         * the image coordinates x,y with the equations
728
         *  x' = Ax + By + C and y' = Dx + Ey + F.
729
         *  The signs of the first 4 parameters depend on the orientation
730
         *  of the image. In the usual case where north is more or less
731
         *  at the top of the image, the X pixel size will be positive
732
         *  and the Y pixel size will be negative. For a south-up image,
733
         *  these signs would be reversed.
734
         * 
735
         * You can calculate the World file parameters yourself based
736
         * on the corner coordinates. The X and Y pixel sizes can be
737
         *  determined simply by dividing the distance between two
738
         *  adjacent corners by the number of columns or rows in the image.
739
         *  The rotation terms are calculated with these equations:
740
         * 
741
         *  # B = (A * number_of_columns + C - lower_right_x') / number_of_rows * -1
742
         *  # D = (E * number_of_rows + F - lower_right_y') / number_of_columns * -1
743
         * 
744
         * @param corner (tl, tr, br, bl)
745
         * @return
746
         */
747
        public static double [] cornersToWorldFile(Point2D [] esq, Dimension size) {
748
                double a=0,b=0,c=0,d=0,e=0,f=0;
749
                double x1 = esq[0].getX(), y1 = esq[0].getY();
750
                double x2 = esq[1].getX(), y2 = esq[1].getY();
751
                double x3 = esq[2].getX(), y3 = esq[2].getY();
752
                double x4 = esq[3].getX(), y4 = esq[3].getY();
753
                // A: X-scale
754
                a = Math.abs( Math.sqrt( (x1-x2)*(x1-x2)+(y1-y2)*(y1-y2))
755
                      / size.getWidth());
756

    
757
                // E: negative Y-scale
758
                e =  - Math.abs(Math.sqrt((x1-x4)*(x1-x4)+
759
                      (y1-y4)*(y1-y4))/size.getHeight());
760

    
761
                // C, F: upper-left coordinates
762
                c = x1;
763
                f = y1;
764
                
765
                // B & D: rotation parameters
766
                b = (a * size.getWidth() + c - x3 ) / size.getHeight() * -1;
767
                d = (e * size.getHeight() + f - y3 ) / size.getWidth() * -1;
768

    
769
                double [] wf = {a,d,b,e,c,f}; 
770
                return wf;  
771
        }
772
    public static String printWF(String fName, Point2D [] esq, Dimension sz) {
773
            double [] wf = GeoRasterFile.cornersToWorldFile(esq, sz);
774
            System.out.println("wf para "+fName);
775
            System.out.println(esq+"\n"+sz);
776
            String wfData = "";
777
            for (int i=0; i<6; i++)
778
                    wfData += wf[i]+"\n";
779
                System.out.println(wfData);
780
                return wfData;
781
    }
782
    
783
    public static void saveWF(String fName, String data) throws IOException {
784
            FileWriter fw = new FileWriter(fName);
785
            fw.write(data);
786
            fw.flush();
787
            fw.close();
788
    }
789

    
790
        /**
791
         * Cosulta si hay que verificar la relaci?n de aspecto de la imagen, es decir comprueba que el ancho/alto
792
         * pasados a updateImage coinciden con el ancho/alto solicitado en setView a la imagen
793
         * @return true si est? verificando la relaci?n de aspecto. 
794
         */
795
        public boolean mustVerifySize() {
796
                return verifySize;
797
        }
798

    
799
        /**
800
         * Asigna el flag que dice si hay que verificar la relaci?n de aspecto de la imagen, es decir 
801
         * comprueba que el ancho/alto pasados a updateImage coinciden con el ancho/alto solicitado 
802
         * en setView a la imagen.
803
         * @return true si est? verificando la relaci?n de aspecto. 
804
         */
805
        public void setMustVerifySize(boolean verifySize) {
806
                this.verifySize = verifySize;
807
        }
808

    
809
        /**
810
         * Obtiene una ventana de datos de la imagen a partir de coordenadas reales. 
811
         * No aplica supersampleo ni subsampleo sino que devuelve una matriz de igual tama?o a los
812
         * pixeles de disco. 
813
         * @param x Posici?n X superior izquierda
814
         * @param y Posici?n Y superior izquierda
815
         * @param w Ancho en coordenadas reales
816
         * @param h Alto en coordenadas reales
817
         * @param rasterBuf        Buffer de datos
818
         * @param bandList
819
         * @return Buffer de datos
820
         */
821
        abstract public RasterBuf getWindowRaster(double x, double y, double w, double h, BandList bandList, RasterBuf rasterBuf);
822
        
823
        /**
824
         * Obtiene una ventana de datos de la imagen a partir de coordenadas pixel. 
825
         * No aplica supersampleo ni subsampleo sino que devuelve una matriz de igual tama?o a los
826
         * pixeles de disco. 
827
         * @param x Posici?n X superior izquierda
828
         * @param y Posici?n Y superior izquierda
829
         * @param w Ancho en coordenadas reales
830
         * @param h Alto en coordenadas reales
831
         * @param rasterBuf        Buffer de datos
832
         * @param bandList
833
         * @return Buffer de datos
834
         */
835
        abstract public RasterBuf getWindowRaster(int x, int y, int w, int h, BandList bandList, RasterBuf rasterBuf);
836

    
837
        /**
838
         * Obtiene una ventana de datos de la imagen a partir de coordenadas reales. 
839
         * Se aplica supersampleo o subsampleo dependiendo del tama?o del buffer especificado.
840
         * 
841
         * @param minX Posici?n m?nima X superior izquierda
842
         * @param minY Posici?n m?nima Y superior izquierda
843
         * @param maxX Posici?n m?xima X inferior derecha
844
         * @param maxY Posici?n m?xima Y inferior derecha
845
         * @param bufWidth Ancho del buffer de datos
846
         * @param bufHeight Alto del buffer de datos
847
         * @param rasterBuf        Buffer de datos
848
         * @param bandList
849
         * @return Buffer de datos
850
         */
851
        abstract public RasterBuf getWindowRaster(double minX, double minY, double maxX, double maxY, int bufWidth, int bufHeight, BandList bandList, RasterBuf rasterBuf);
852
        
853
        abstract public byte[] getWindow(int ulX, int ulY, int sizeX, int sizeY, int band);
854
        
855
        abstract public int getBlockSize();
856
        
857
        /**
858
         * Obtiene el objeto que contiene los metadatos. Este m?todo debe ser redefinido por los
859
         * drivers si necesitan devolver metadatos. 
860
         * @return
861
         */
862
        public Metadata getMetadata(){
863
                return null;
864
        }
865
        
866
        /**
867
         * Asigna un extent temporal que puede coincidir con el de la vista. Esto es 
868
         * util para cargar imagenes sin georreferenciar ya que podemos asignar el extent
869
         * que queramos para ajustarnos a una vista concreta
870
         * @param tempExtent The tempExtent to set.
871
         */
872
        public void setExtent(Extent ext) {
873
                this.extent = ext;
874
        }
875
        
876
        /**
877
         * Dice si el fichero tiene georreferenciaci?n o no.
878
         * @return true si tiene georreferenciaci?n y false si no la tiene
879
         */
880
        public boolean isGeoreferenced(){
881
                return true;
882
        }
883

    
884
        /**
885
         * Informa de si el driver ha supersampleado en el ?ltimo dibujado. Es el driver el que colocar?
886
         * el valor de esta variable cada vez que dibuja. Debe tenerse especial cuidado ya que est? consulta no es adecuada desde gvSIG ya que el
887
         * dibujado se realiza asincronamente por lo que el valor puede no coincidir con el ?ltimo
888
         * dibujado.
889
         * @return true si se ha supersampleado y false si no se ha hecho.
890
         */
891
        public boolean isSupersampling() {
892
                return this.isSupersampling;
893
        }
894
        
895
        /**
896
         * Asigna el valor del paso en X e Y aplicado en el ?ltimo dibujado. Es el driver el que colocar?
897
         * el valor de esta variable cada vez que dibuja. 
898
         * @param stepx Paso en X
899
         * @param stepy Paso en Y
900
         */
901
        public void setStep(int[] stepArrayx, int[] stepArrayy){
902
                this.stepArrayX = stepArrayx;
903
                this.stepArrayY = stepArrayy;
904
        }
905
        
906
        /**
907
         * Obtiene el valor del paso en X aplicado en el ?ltimo dibujado. Es el driver el que colocar?
908
         * el valor de esta variable cada vez que dibuja. 
909
         * @return
910
         */
911
        public int[] getStepX(){
912
                return stepArrayX;
913
        }
914
        
915
        /**
916
         * Obtiene el valor del paso en Y aplicado en el ?ltimo dibujado. Es el driver el que colocar?
917
         * el valor de esta variable cada vez que dibuja. 
918
         * @return
919
         */
920
        public int[] getStepY(){
921
                return stepArrayY;
922
        }
923

    
924
        /**
925
         * Obtiene el objeto paleta. Esta paleta es la que tiene adjunta el fichero de disco. Si es
926
         * null este objeto quiere decir que no tiene paleta para su visualizaci?n. 
927
         * @return Palette
928
         */
929
        public Palette getPalette() {
930
                return palette;
931
        }
932

    
933
        /**
934
         * Asigna el objeto paleta. Esta paleta es la que tiene adjunta el fichero de disco. Si es
935
         * null este objeto quiere decir que no tiene paleta para su visualizaci?n. 
936
         * @param Palette
937
         */
938
        public void setPalette(Palette palette) {
939
                this.palette = palette;
940
        }
941
        
942
        /**
943
         * M?todo que indica si existe un fichero .rmf asociado al GeoRasterFile.
944
         * @return
945
         */
946
        public boolean rmfExists(){
947
                return this.rmfExists;
948
        }
949
                
950
        /**
951
         * Obtiene los par?metros de la transformaci?n af?n que corresponde con los elementos de
952
         * un fichero tfw.
953
         * <UL> 
954
         * <LI>[1]tama?o de pixel en X</LI>
955
         * <LI>[2]rotaci?n en X</LI>
956
         * <LI>[4]rotaci?n en Y</LI>
957
         * <LI>[5]tama?o de pixel en Y</LI>
958
         * <LI>[0]origen en X</LI>
959
         * <LI>[3]origen en Y</LI>
960
         * </UL>
961
         * Este m?todo debe ser reimplementado por el driver si tiene esta informaci?n. En principio
962
         * Gdal es capaz de proporcionarla de esta forma.
963
         * @return vector de double con los elementos de la transformaci?n af?n.
964
         */
965
        public double[] getTransform(){return null;}
966
        
967
        /**
968
         * Convierte un punto desde coordenadas pixel a coordenadas del mundo.
969
         * @param pt Punto a transformar
970
         * @return punto transformado en coordenadas del mundo
971
         */
972
        abstract public Point2D rasterToWorld(Point2D pt);
973
        
974
        /**
975
         * Convierte un punto desde del mundo a coordenadas pixel.
976
         * @param pt Punto a transformar
977
         * @return punto transformado en coordenadas pixel
978
         */
979
        abstract public Point2D worldToRaster(Point2D pt);
980
}