Statistics
| Revision:

svn-gvsig-desktop / branches / CqCMSDvp / libraries / libCq CMS for java.old / src / org / cresques / io / EcwFile.java @ 1809

History | View | Annotate | Download (14.6 KB)

1 2 luisw
/*
2
 * EcwFile.java
3
 */
4
package org.cresques.io;
5
6 158 luisw
import java.awt.Dimension;
7 2 luisw
import java.awt.Image;
8 181 luisw
import java.awt.Point;
9 2 luisw
import java.awt.image.BufferedImage;
10
11
import com.ermapper.ecw.JNCSFile;
12 181 luisw
import com.ermapper.ecw.JNCSFileNotOpenException;
13 130 luisw
import com.ermapper.ecw.JNCSProgressiveUpdate;
14 23 luisw
import com.ermapper.util.JNCSDatasetPoint;
15 184 luisw
import com.ermapper.util.JNCSWorldPoint;
16 1735 igbrotru
import com.ermapper.ecw.JNCSException;
17 2 luisw
18 1735 igbrotru
import es.gva.cit.jmrsid.LTIMetadataRecord;
19
import es.gva.cit.jmrsid.MrSIDException;
20 2 luisw
21 1735 igbrotru
import org.cresques.cts.ICoordTrans;
22
import org.cresques.cts.IProjection;
23
import org.cresques.px.*;
24
25
26 2 luisw
/**
27 141 luisw
 * Soporte para los ficheros .ecw de ErMapper.
28
 * <br>
29 130 luisw
 * NOTA: El SDK que ermapper ha puesto a disposici?n del p?blico en java
30
 * es una versi?n 2.45, de 19/11/2001. Est? implementada usando JNI que
31
 * se apoya en tres librer?as din?micas (dll), y presenta deficiencias
32
 * muy graves a la hora de acceder a la informaci?n. Hasta el momento
33 141 luisw
 * hemos detectado 3 de ellas:<BR>
34 130 luisw
 *     1?.- No soporta ampliaciones superiores a 1:1. si se intenta acceder
35
 * a un ecw con un zoom mayor da una excepci?n del tipo
36
 * com.ermapper.ecw.JNCSInvalidSetViewException, que de no ser tenida encuenta
37 141 luisw
 * acaba tirando abajo la m?quina virtual de java.<BR>
38 130 luisw
 *     2?.- La longitud m?xima de l?nea que adminte el m?todo readLineRGBA es
39
 * de unos 2500 pixeles, lo que hace el uso para la impresi?n en formatos
40 160 luisw
 * superiorea a A4 a 300 ppp o m?s inviable.<BR>
41 130 luisw
 *     3?.- La actualizaci?n progresiva usando el interface JNCSProgressiveUpdate
42
 * con el JNCSFile hace que el equipo genere un error severo y se apague. Este
43 141 luisw
 * error imposibilita esta t?cnica de acceso a ECW.<BR>
44 181 luisw
 * <br>
45
 * Para saltarnos la limitaci?n del bug#1 pedimos la ventana correspondiente al zoom 1:1 para
46
 * el view que nos han puesto, y la resizeamos al tama?o que nos pide el usuario.<br>
47
 * Como consecuencia del bug#2, para tama?os de ventana muy grandes (los necesarios
48
 * para imprimir a m?s de A4 a 300DPI), hay que hacer varias llamadas al fichero con
49
 * varios marcos contiguos, y los devolvemos 'pegados' en una sola imagen (esto se
50
 * realiza de manera transparente para el usuario dentro de la llamada a updateImage.<br>
51
 *
52 2 luisw
 * @author "Luis W. Sevilla" <sevilla_lui@gva.es>
53
 */
54
55 130 luisw
public class EcwFile extends GeoRasterFile  implements JNCSProgressiveUpdate {
56
        private JNCSFile file = null;
57
        private boolean bErrorOnOpen = false;
58
        private String errorMessage = null;
59 2 luisw
60 130 luisw
        private Extent v = null;
61 2 luisw
62 130 luisw
        // Ultimo porcentaje de refresco. Se carga en el update y se
63
        // actualiza en el refreshUpdate
64
        private int lastRefreshPercent = 0;
65
66 94 luisw
        public EcwFile(IProjection proj, String fName) {
67 50 luisw
                super(proj, null);
68
                fName = DataSource.normalize(fName);
69
                super.setName(fName);
70 2 luisw
                extent = new Extent();
71
                try {
72 50 luisw
                        System.err.println("Abriendo "+fName);
73 134 luisw
                        file = new JNCSFile(fName, false);
74
                        //file = new JNCSFile(fName, true);
75
                    //file.addProgressiveUpdateListener(this);
76 2 luisw
                        load();
77 1533 luisw
                        bandCount = file.numBands;
78
                        if ( bandCount > 2) {
79
                                setBand(RED_BAND,   0);
80
                                setBand(GREEN_BAND, 1);
81
                                setBand(BLUE_BAND,  2);
82
                        } else
83
                                setBand(RED_BAND|GREEN_BAND|BLUE_BAND, 0);
84 2 luisw
                } catch(Exception e) {
85
                  bErrorOnOpen = true;
86
                  errorMessage = e.getMessage();
87
//                  g.drawString(errorMessage, 0, 50);
88
                  System.err.println(errorMessage);
89
                  e.printStackTrace();
90
                }
91
        }
92
93
        public void setView(Extent e) { v = new Extent(e); }
94
        public Extent getView() { return v; }
95
96
        /**
97
         * Carga un ECW.
98
         *
99
         * @param fname
100
         */
101
102
        public GeoFile load() {
103
                double minX, minY, maxX, maxY;
104
105
                System.out.println("ECW size = ("+file.width+","+file.height+")\n"+
106
                        " inc=("+file.cellIncrementX+","+file.cellIncrementY+")\n"+
107
                        " datum='"+file.datum+"', proyeccion='"+file.projection+"'");
108
                minX = file.originX;
109
                maxY = file.originY;
110
                maxX = file.originX + (double)(file.width-1)*file.cellIncrementX;
111
                minY = file.originY + (double)(file.height-1)*file.cellIncrementY;
112
                extent = new Extent(minX, minY, maxX, maxY);
113
                        System.out.println(extent);
114
115
                return this;
116
        }
117
118
        public void close() {
119
                file.close(true);
120
                file = null;
121
        }
122 130 luisw
123
        public int getWidth() { return file.width; }
124
        public int getHeight() { return file.height; }
125 181 luisw
126
        /**
127 184 luisw
         * Trozo de imagen (Chunk) en que se divide la consulta a la librer?a,
128 181 luisw
         * para esquivar el bug#2.
129
         *
130
         * @author luisw
131
         */
132
        static class ChunkFrame {
133
                // Ancho m?ximo (~2500 px)
134 184 luisw
                final static int MAX_WIDTH = 1536;
135 181 luisw
                // Alto m?ximo (no hay l?mite)
136 210 luisw
                final static int MAX_HEIGHT = 1536;
137 181 luisw
                Point pos;
138
                Extent v;
139
                int width, height;
140 210 luisw
                boolean mustResize = false;
141 181 luisw
                public ChunkFrame(Extent vista, int w, int h) {
142
                        v = vista;
143
                        width = w;
144
                        height = h;
145
                }
146
                /**
147
                 * Calcula el array de chunks (trozos).
148
                 * @param file        Fichero ecw que hay que trocear.
149
                 * @param v Extent total de la vista.
150
                 * @param sz        Tama?o total de la vista.
151
                 * @return array de ChunkFrames.
152
                 * @throws JNCSFileNotOpenException
153
                 */
154
                public static ChunkFrame [] computeFrames(JNCSFile file, Extent v, Dimension sz) throws JNCSFileNotOpenException {
155
                        ChunkFrame [] frames = null;
156
                        ChunkFrame f = null;
157
158
                        // Calcula el n? de chunks (filas y columnas)
159
                        int numCol = (sz.width / MAX_WIDTH), numRow = (sz.height / MAX_HEIGHT);
160
                        if (sz.width -(numCol*MAX_WIDTH) > 0) numCol++;
161 210 luisw
                        if (sz.height - (numRow*MAX_HEIGHT) > 0) numRow++;
162 181 luisw
                        frames = new ChunkFrame[numCol*numRow];
163 2 luisw
164 181 luisw
                        // Coprobaci?n previa para resolver el bug#1
165
                        JNCSDatasetPoint ptMin = file.convertWorldToDataset(v.minX(), v.minY());
166
                        JNCSDatasetPoint ptMax = file.convertWorldToDataset(v.maxX(), v.maxY());
167 210 luisw
                        System.out.println("Dataset coords Width = "+(ptMax.x-ptMin.x)+", px width = "+sz.width+
168
                                        " px heigh = "+sz.height);
169 181 luisw
                        // BEGIN Cambiando para soportar e < 1:1
170
                        // TODO Mejorarlo para que los PAN con un zoom muy grande sean correctos
171 1735 igbrotru
                        System.out.println("MAXX MINX-"+ptMax.x+","+ptMin.x);
172 181 luisw
                        if ((ptMax.x-ptMin.x)<sz.width) {
173
                                numCol = numRow = 1;
174 1735 igbrotru
                                frames = new ChunkFrame[numCol*numRow];
175 184 luisw
                                f = frames[0] = new ChunkFrame(v, ptMax.x-ptMin.x, ptMin.y-ptMax.y);
176 181 luisw
                                System.out.println("Size=("+f.width+","+f.height+")");
177 184 luisw
                                f.pos = new Point(0,0);
178
                                f.mustResize = true;
179
                                f.v = new Extent(v);
180 181 luisw
                        } else {
181
                                // Calcula cada chunk
182 210 luisw
                                double stepx = ((double) ptMax.x-ptMin.x)/sz.getWidth();
183
                                double stepy = ((double) ptMax.y-ptMin.y)/sz.getHeight();
184 184 luisw
                                int h = sz.height;
185 181 luisw
                                for (int r=0; r<numRow; r++) {
186 184 luisw
                                        int w = sz.width;
187 181 luisw
                                        for (int c = 0; c<numCol; c++) {
188
                                                f = new ChunkFrame(null, -1, -1);
189
                                                // Posici?n del chunk
190
                                                f.pos = new Point(c*MAX_WIDTH, r*MAX_HEIGHT);
191
                                                // Tama?o del chunk
192 184 luisw
                                                f.width = Math.min(MAX_WIDTH, w);
193 210 luisw
                                                f.height = Math.min(MAX_HEIGHT, h);
194 181 luisw
                                                // Extent del chunk
195 210 luisw
                                                int x1 = ptMin.x+(int) (f.pos.x*stepx);
196
                                                int x2 = x1+(int)(f.width*stepx);
197
                                                int y1 = ptMax.y-(int) (f.pos.y*stepy); //ptMax.y;
198
                                                int y2 = y1-(int)(f.height*stepy);//ptMin.y;
199 184 luisw
                                                JNCSWorldPoint pt1 = file.convertDatasetToWorld(x1, y1);
200
                                                JNCSWorldPoint pt2 = file.convertDatasetToWorld(x2, y2);
201
                                                f.v = new Extent(pt1.x, pt1.y, pt2.x, pt2.y); // Hay que calcularlo
202
                                                System.out.println(" View DataSet = ("+x1+","+y1+","+x2+","+y2+")");
203
                                                System.out.println(" View Extent  = "+ v);
204
                                                System.out.println("Frame Extent  = "+ f.v);
205
206 181 luisw
                                                frames[r*numCol+c] = f;
207 184 luisw
                                                w -= MAX_WIDTH;
208 181 luisw
                                        }
209 184 luisw
                                        h -= MAX_HEIGHT;
210 181 luisw
                                }
211
                        }
212 184 luisw
                        System.out.println("Hay "+numRow+" filas y "+numCol+" columnas.");
213 181 luisw
                        return frames;
214
                }
215
        }
216
217 2 luisw
        /**
218
         * Obtiene un trozo de imagen (determinado por la vista y los par?metros.
219
         *
220
         * @param width
221
         * @param height
222
         */
223
224 130 luisw
        public synchronized Image updateImage(int width, int height, ICoordTrans rp) {
225
                // TODO reproyectar para devolver el trozo de imagen pedida sobre ...
226
                // la proyecci?n de destino.
227 210 luisw
                int line = 0;
228 158 luisw
                boolean mustResize = false;
229
                Dimension fullSize = null;
230
                Image ecwImage = null;
231 130 luisw
                if (file == null) return ecwImage;
232
                try {
233 2 luisw
                        double dFileAspect, dWindowAspect;
234
                        //double dWorldTLX, dWorldTLY, dWorldBRX, dWorldBRY;
235
                        int bandlist[];
236 210 luisw
                        int pRGBArray[] = null;
237 158 luisw
238 2 luisw
                        // Work out the correct aspect for the setView call.
239
                        dFileAspect = (double)v.width()/(double)v.height();
240
                        dWindowAspect = (double)width /(double)height;
241
242
                        if (dFileAspect > dWindowAspect) {
243
                          height =(int)((double)width/dFileAspect);
244
                        } else {
245
                          width = (int)((double)height*dFileAspect);
246
                        }
247
248 1735 igbrotru
249 181 luisw
                        fullSize = new Dimension(width, height);
250 210 luisw
                        System.out.println("fullSize = ("+width+","+height+")");
251 184 luisw
                        // Peta en los peque?os ... arreglar antes de meter del todo
252 181 luisw
                        ChunkFrame frames[] = ChunkFrame.computeFrames(file, v, fullSize);
253 1735 igbrotru
                        for (int nChunk=0; nChunk<frames.length; nChunk++) {
254
                                System.out.println("chunck "+nChunk+"->"+frames[nChunk]);
255
                        }
256 184 luisw
                        if (frames.length == 1) {
257 1735 igbrotru
                                width = frames[0].width;
258
                                height = frames[0].height;
259
                                if(width<=0)width=1;
260
                                if(height<=0)height=1;
261 210 luisw
                                System.out.println("frameSize = ("+width+","+height+")");
262 184 luisw
                                //System.out.println("Cambio el ancho total a ("+width+","+height+")");
263
                        }
264 181 luisw
265 184 luisw
/*                        JNCSDatasetPoint ptMin = file.convertWorldToDataset(v.minX(), v.minY());
266 158 luisw
                        JNCSDatasetPoint ptMax = file.convertWorldToDataset(v.maxX(), v.maxY());
267
                        System.out.println("Dataset coords Width = "+(ptMax.x-ptMin.x)+", px width ="+width);
268 160 luisw
                        // BEGIN Cambiando para soportar e < 1:1
269
                        // TODO Mejorarlo para que los PAN con un zoom muy grande sean correctos
270 158 luisw
                        if ((ptMax.x-ptMin.x)<width) {
271
                                width = ptMax.x-ptMin.x;
272
                                height = ptMin.y-ptMax.y;
273
                                System.out.println("Size=("+width+","+height+")");
274
                                mustResize = true;
275 184 luisw
                        }*/
276
                        // Create an image of the ecw file.
277
                        if (doTransparency)
278
                                ecwImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
279
                        else
280
                                ecwImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
281 158 luisw
282 2 luisw
                        pRGBArray = new int[width];
283
284
                        // Setup the view parameters for the ecw file.
285 1533 luisw
286
                        if ( bandCount > 2) {
287
                                bandlist = new int[bandCount];
288
                                bandlist[0] = getBand(RED_BAND);
289
                                bandlist[1] = getBand(GREEN_BAND);
290
                                bandlist[2] = getBand(BLUE_BAND);
291
                                if (bandCount > 3)
292
                                        for (int i=3; i< bandCount; i++) {
293
                                                 bandlist[i] = 0;
294
                                        }
295
                        } else {
296
                                bandlist = new int[bandCount];
297
                                for (int i=0; i< bandCount; i++) {
298
                                  bandlist[i] = i;
299
                                }
300 2 luisw
                        }
301 158 luisw
302 184 luisw
                        for (int nChunk=0; nChunk<frames.length; nChunk++) {
303
                                ChunkFrame f = frames[nChunk];
304
                                // Set the view
305 1735 igbrotru
                                file.setView(file.numBands, bandlist, f.v.minX(), f.v.maxY(), f.v.maxX(), f.v.minY(), f.width, f.height);
306
                                System.out.println("f.Size = ("+f.width+","+f.height+")+CHUNK="+nChunk);
307 210 luisw
308 184 luisw
309
                                // Read the scan lines
310 210 luisw
                                for (line=0; line < f.height; line++) {
311 184 luisw
                                        file.readLineRGBA(pRGBArray);
312
                                        // Prueba de sustituci?n de color transparente
313
                                        if (doTransparency) {
314
                                                if (line == 0) tFilter.debug = true;
315
                                                  tFilter.filterLine(pRGBArray);
316
                                                tFilter.debug = false;
317
                                        }
318
                                        //System.out.println("setRGB("+f.pos.x+","+f.pos.y+line+","+f.width+","+1+","+pRGBArray+","+0+","+f.width+")");
319
                                        ((BufferedImage)ecwImage).setRGB(f.pos.x, f.pos.y+line, f.width, 1, pRGBArray, 0, f.width);
320 130 luisw
                                }
321 2 luisw
                        }
322 184 luisw
                        if (frames[0].mustResize) {
323
                                //System.out.println("resize "+fullSize);
324
                                return resizeImage(fullSize, ecwImage);
325
                        }
326 130 luisw
                /*
327
                 * La excepci?n atrapada es la de 'zoom > 1:1 no valido'
328
                } catch (com.ermapper.ecw.JNCSInvalidSetViewException e) {
329
                        System.err.println(errorMessage);
330
                        e.printStackTrace(); */
331 210 luisw
                } catch(com.ermapper.ecw.JNCSException e) { //java.lang.ArrayIndexOutOfBoundsException:
332
                        bErrorOnOpen = true;
333
                        System.err.println("EcwFile JNCS Error en la l?nea "+line+"/"+height);
334
                        System.err.println(e.getMessage());
335
                        e.printStackTrace();
336
                } catch(java.lang.ArrayIndexOutOfBoundsException e) { //:
337
                        bErrorOnOpen = true;
338
                        System.err.println("EcwFile ArrayIndex Error en la l?nea "+line+"/"+height);
339
                        System.err.println(e.getMessage());
340
                        e.printStackTrace();
341 130 luisw
                } catch(Exception e) {
342 2 luisw
                        bErrorOnOpen = true;
343
                        errorMessage = e.getMessage();
344
//                        g.drawString(errorMessage, 0, 50);
345
                        System.err.println(errorMessage);
346
                        e.printStackTrace();
347
                }
348 130 luisw
                lastRefreshPercent = file.getPercentComplete();
349 210 luisw
                System.out.println("Leido al "+lastRefreshPercent+" %.");
350 2 luisw
                return ecwImage;
351
        }
352 125 luisw
353 158 luisw
        private Image resizeImage(Dimension sz, Image image) {
354
                return image.getScaledInstance((int) sz.getWidth(),
355
                        (int) sz.getHeight(), Image.SCALE_SMOOTH);
356 125 luisw
        }
357 2 luisw
358
        /**
359 130 luisw
         * Reproyecta el raster.
360 2 luisw
         */
361 94 luisw
        public void reProject(ICoordTrans rp) {
362 2 luisw
                // TODO metodo reProject pendiente de implementar
363
        }
364
365 130 luisw
366
        /**
367
         * Soporte para actualizaci?n de la imagen
368
         * @see com.ermapper.ecw.JNCSProgressiveUpdate#refreshUpdate(int, int, double, double, double, double)
369
         */
370
        public void refreshUpdate(int nWidth, int nHeight, double dWorldTLX, double dWorldTLY, double dWorldBRX, double dWorldBRY) {
371
                int completado = file.getPercentComplete();
372
                System.out.println("EcwFile: se actualiza 1: "+completado+" % completado");
373
                if ((updatable != null) && (lastRefreshPercent < 100)) {
374
                        if ((completado-lastRefreshPercent > 25) || completado == 100) {
375
                                lastRefreshPercent = file.getPercentComplete();
376
                                updatable.repaint();
377
                        }
378
                }
379
        }
380
381
        public void refreshUpdate(int nWidth, int nHeight, int dDatasetTLX, int dDatasetTLY, int dDatasetBRX, int dDatasetBRY) {
382
                System.out.println("EcwFile: se actualiza 2");
383
        }
384 210 luisw
385
        /* (non-Javadoc)
386
         * @see org.cresques.io.GeoRasterFile#updateImage(int, int, org.cresques.cts.ICoordTrans, java.awt.Image, int)
387
         */
388
        public Image updateImage(int width, int height, ICoordTrans rp, Image img, int flags) {
389
                // TODO Auto-generated method stub
390
                return null;
391
        }
392 553 luisw
393
        /* (non-Javadoc)
394
         * @see org.cresques.io.GeoRasterFile#getData(int, int)
395
         */
396
        public Object getData(int x, int y, int band) {
397
                //file.readLineRGBA();
398
                return null;
399
        }
400 1735 igbrotru
401
        /**
402
         * Devuelve los datos de una ventana solicitada
403
         * @param ulX        coordenada X superior izda.
404
         * @param ulY        coordenada Y superior derecha.
405
         * @param sizeX        tama?o en X de la ventana.
406
         * @param sizeY tama?o en Y de la ventana.
407
         * @param band        Banda solicitada.
408
         */
409
410
        public byte[] getWindow(int ulX, int ulY, int sizeX, int sizeY, int band){
411
                //TODO Nacho: Implementar getWindow de EcwFile
412
                        return null;
413
414
        }
415
416
        /**
417
         * Obtiene la zona (Norte / Sur)
418
         * @return true si la zona es norte y false si es sur
419
         */
420
421
        public boolean getZone(){
422
                //TODO Nacho: Implementar getZone de EcwFile
423
                return false;
424
        }
425
426
        /**
427
         *Devuelve el n?mero de zona UTM
428
         *@return N?mero de zona
429
         */
430
431
        public int getUTM(){
432
//                TODO Nacho: Implementar getUTM de EcwFile
433
                return 0;
434
        }
435
436
        /**
437
         * Obtiene el sistema de coordenadas geograficas
438
         * @return Sistema de coordenadas geogr?ficas
439
         */
440
        public String getGeogCS(){
441
                //TODO Nacho: Implementar getGeogCS de EcwFile
442
                return new String("");
443
        }
444
445
        /**
446
         * Devuelve el tama?o de bloque
447
         * @return Tama?o de bloque
448
         */
449
        public int getBlockSize(){
450
     //TODO Nacho: Implementar getBlockSize de EcwFile
451
          return 1;
452
        }
453 2 luisw
}