Statistics
| Revision:

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

History | View | Annotate | Download (29.8 KB)

1
/*
2
 * EcwFile.java
3
 */
4
package org.cresques.io;
5

    
6
import java.awt.Dimension;
7
import java.awt.Image;
8
import java.awt.Point;
9
import java.awt.image.BufferedImage;
10
import java.awt.image.PixelGrabber;
11

    
12
import com.ermapper.ecw.JNCSFile;
13
import com.ermapper.ecw.JNCSFileNotOpenException;
14
import com.ermapper.ecw.JNCSProgressiveUpdate;
15
import com.ermapper.util.JNCSDatasetPoint;
16
import com.ermapper.util.JNCSWorldPoint;
17
import com.ermapper.ecw.JNCSException;
18

    
19
import es.gva.cit.jmrsid.LTIMetadataRecord;
20
import es.gva.cit.jmrsid.MrSIDException;
21

    
22
import org.cresques.cts.ICoordTrans;
23
import org.cresques.cts.IProjection;
24
import org.cresques.px.*;
25

    
26

    
27
/**
28
 * Soporte para los ficheros .ecw de ErMapper.
29
 * <br>
30
 * NOTA: El SDK que ermapper ha puesto a disposici?n del p?blico en java
31
 * es una versi?n 2.45, de 19/11/2001. Est? implementada usando JNI que
32
 * se apoya en tres librer?as din?micas (dll), y presenta deficiencias
33
 * muy graves a la hora de acceder a la informaci?n. Hasta el momento
34
 * hemos detectado 3 de ellas:<BR>
35
 *     1?.- No soporta ampliaciones superiores a 1:1. si se intenta acceder
36
 * a un ecw con un zoom mayor da una excepci?n del tipo
37
 * com.ermapper.ecw.JNCSInvalidSetViewException, que de no ser tenida encuenta
38
 * acaba tirando abajo la m?quina virtual de java.<BR>
39
 *     2?.- La longitud m?xima de l?nea que adminte el m?todo readLineRGBA es
40
 * de unos 2500 pixeles, lo que hace el uso para la impresi?n en formatos
41
 * superiorea a A4 a 300 ppp o m?s inviable.<BR>
42
 *     3?.- La actualizaci?n progresiva usando el interface JNCSProgressiveUpdate
43
 * con el JNCSFile hace que el equipo genere un error severo y se apague. Este
44
 * error imposibilita esta t?cnica de acceso a ECW.<BR>
45
 * <br>
46
 * Para saltarnos la limitaci?n del bug#1 pedimos la ventana correspondiente al zoom 1:1 para
47
 * el view que nos han puesto, y la resizeamos al tama?o que nos pide el usuario.<br>
48
 * Como consecuencia del bug#2, para tama?os de ventana muy grandes (los necesarios
49
 * para imprimir a m?s de A4 a 300DPI), hay que hacer varias llamadas al fichero con
50
 * varios marcos contiguos, y los devolvemos 'pegados' en una sola imagen (esto se
51
 * realiza de manera transparente para el usuario dentro de la llamada a updateImage.<br>
52
 *
53
 * @author "Luis W. Sevilla" <sevilla_lui@gva.es>
54
 */
55

    
56
public class EcwFile extends GeoRasterFile  implements JNCSProgressiveUpdate {
57
        private JNCSFile file = null;
58
        private boolean bErrorOnOpen = false;
59
        private String errorMessage = null;
60

    
61
        private Extent v = null;
62
        
63
        // Ultimo porcentaje de refresco. Se carga en el update y se
64
        // actualiza en el refreshUpdate
65
        private int lastRefreshPercent = 0;
66
        
67
        public EcwFile(IProjection proj, String fName) {
68
                super(proj, null);
69
                fName = DataSource.normalize(fName);
70
                super.setName(fName);
71
                extent = new Extent();
72
                try {
73
                        System.err.println("Abriendo "+fName);
74
                        file = new JNCSFile(fName, false);
75
                        //file = new JNCSFile(fName, true);
76
                    //file.addProgressiveUpdateListener(this);
77
                        load();
78
                        bandCount = file.numBands;
79
                        /*if ( bandCount > 2) {
80
                                setBand(RED_BAND,   0);
81
                                setBand(GREEN_BAND, 1);
82
                                setBand(BLUE_BAND,  2);
83
                        } else
84
                                setBand(RED_BAND|GREEN_BAND|BLUE_BAND, 0);*/
85
                } catch(Exception e) {
86
                  bErrorOnOpen = true;
87
                  errorMessage = e.getMessage();
88
//                  g.drawString(errorMessage, 0, 50);
89
                  System.err.println(errorMessage);
90
                  e.printStackTrace();
91
                }
92
        }
93
                
94
        public void setView(Extent e) { v = new Extent(e); }
95
        public Extent getView() { return v; }
96
        
97
        /**
98
         * Carga un ECW.
99
         * 
100
         * @param fname
101
         */
102
        
103
        public GeoFile load() {
104
                double minX, minY, maxX, maxY;
105

    
106
                System.out.println("ECW size = ("+file.width+","+file.height+")\n"+
107
                        " inc=("+file.cellIncrementX+","+file.cellIncrementY+")\n"+
108
                        " datum='"+file.datum+"', proyeccion='"+file.projection+"'");
109
                minX = file.originX;
110
                maxY = file.originY;
111
                maxX = file.originX + (double)(file.width-1)*file.cellIncrementX;
112
                minY = file.originY + (double)(file.height-1)*file.cellIncrementY;
113
                extent = new Extent(minX, minY, maxX, maxY);
114
                        System.out.println(extent);
115
                
116
                return this;
117
        }
118
        
119
        public void close() {
120
                file.close(true);
121
                file = null;
122
        }
123
        
124
        public int getWidth() { return file.width; }
125
        public int getHeight() { return file.height; }
126
        
127
        /**
128
         * Trozo de imagen (Chunk) en que se divide la consulta a la librer?a,
129
         * para esquivar el bug#2.
130
         * 
131
         * @author luisw
132
         */
133
        static class ChunkFrame {
134
                // Ancho m?ximo (~2500 px)
135
                final static int MAX_WIDTH = 1536;
136
                // Alto m?ximo (no hay l?mite)
137
                final static int MAX_HEIGHT = 1536;
138
                Point pos;
139
                Extent v;
140
                int width, height;
141
                boolean mustResize = false;
142
                public ChunkFrame(Extent vista, int w, int h) {
143
                        v = vista;
144
                        width = w;
145
                        height = h;
146
                }
147
                /**
148
                 * Calcula el array de chunks (trozos).
149
                 * @param file        Fichero ecw que hay que trocear.
150
                 * @param v Extent total de la vista.
151
                 * @param sz        Tama?o total de la vista.
152
                 * @return array de ChunkFrames.
153
                 * @throws JNCSFileNotOpenException
154
                 */
155
                public static ChunkFrame [] computeFrames(JNCSFile file, Extent v, Dimension sz) throws JNCSFileNotOpenException {
156
                        ChunkFrame [] frames = null;
157
                        ChunkFrame f = null;
158
                        
159
                        // Calcula el n? de chunks (filas y columnas)
160
                        int numCol = (sz.width / MAX_WIDTH), numRow = (sz.height / MAX_HEIGHT);
161
                        if (sz.width -(numCol*MAX_WIDTH) > 0) numCol++;
162
                        if (sz.height - (numRow*MAX_HEIGHT) > 0) numRow++;
163
                        frames = new ChunkFrame[numCol*numRow];
164

    
165
                        // Coprobaci?n previa para resolver el bug#1
166
                        JNCSDatasetPoint ptMin = file.convertWorldToDataset(v.minX(), v.minY());
167
                        JNCSDatasetPoint ptMax = file.convertWorldToDataset(v.maxX(), v.maxY());
168
                        System.out.println("Dataset coords Width = "+(ptMax.x-ptMin.x)+", px width = "+sz.width+
169
                                        " px heigh = "+sz.height);
170
                        // BEGIN Cambiando para soportar e < 1:1
171
                        // TODO Mejorarlo para que los PAN con un zoom muy grande sean correctos
172
                        System.out.println("MAXX MINX-"+ptMax.x+","+ptMin.x);
173
                        if ((ptMax.x-ptMin.x)<sz.width) {
174
                                numCol = numRow = 1;
175
                                frames = new ChunkFrame[numCol*numRow];
176
                                f = frames[0] = new ChunkFrame(v, ptMax.x-ptMin.x, ptMin.y-ptMax.y);
177
                                System.out.println("Size=("+f.width+","+f.height+")");
178
                                f.pos = new Point(0,0);
179
                                f.mustResize = true;
180
                                f.v = new Extent(v);
181
                        } else {
182
                                // Calcula cada chunk
183
                                double stepx = ((double) ptMax.x-ptMin.x)/sz.getWidth();
184
                                double stepy = ((double) ptMax.y-ptMin.y)/sz.getHeight();
185
                                int h = sz.height;
186
                                for (int r=0; r<numRow; r++) {
187
                                        int w = sz.width;
188
                                        for (int c = 0; c<numCol; c++) {
189
                                                f = new ChunkFrame(null, -1, -1);
190
                                                // Posici?n del chunk
191
                                                f.pos = new Point(c*MAX_WIDTH, r*MAX_HEIGHT);
192
                                                // Tama?o del chunk
193
                                                f.width = Math.min(MAX_WIDTH, w);
194
                                                f.height = Math.min(MAX_HEIGHT, h);
195
                                                // Extent del chunk
196
                                                int x1 = ptMin.x+(int) (f.pos.x*stepx);
197
                                                int x2 = x1+(int)(f.width*stepx);
198
                                                int y1 = ptMax.y-(int) (f.pos.y*stepy); //ptMax.y;
199
                                                int y2 = y1-(int)(f.height*stepy);//ptMin.y;
200
                                                JNCSWorldPoint pt1 = file.convertDatasetToWorld(x1, y1);
201
                                                JNCSWorldPoint pt2 = file.convertDatasetToWorld(x2, y2);
202
                                                f.v = new Extent(pt1.x, pt1.y, pt2.x, pt2.y); // Hay que calcularlo
203
                                                System.out.println(" View DataSet = ("+x1+","+y1+","+x2+","+y2+")");
204
                                                System.out.println(" View Extent  = "+ v);
205
                                                System.out.println("Frame Extent  = "+ f.v);
206

    
207
                                                frames[r*numCol+c] = f;
208
                                                w -= MAX_WIDTH;
209
                                        }
210
                                        h -= MAX_HEIGHT;
211
                                }
212
                        }
213
                        System.out.println("Hay "+numRow+" filas y "+numCol+" columnas.");
214
                        return frames;
215
                }
216
        }
217

    
218
        /**
219
         * Obtiene un trozo de imagen (determinado por la vista y los par?metros.
220
         * 
221
         * @param width
222
         * @param height
223
         */
224
        
225
        public synchronized Image updateImage(int width, int height, ICoordTrans rp) {
226
                // TODO reproyectar para devolver el trozo de imagen pedida sobre ...
227
                // la proyecci?n de destino.
228
                int line = 0; 
229
                boolean mustResize = false;
230
                Dimension fullSize = null;
231
                Image ecwImage = null;
232
                if (file == null) return ecwImage;
233
                try {
234
                        double dFileAspect, dWindowAspect;
235
                        //double dWorldTLX, dWorldTLY, dWorldBRX, dWorldBRY;
236
                        int bandlist[];
237
                        int bandListTriband[];
238
                        int pRGBArray[] = null;
239

    
240
                        // Work out the correct aspect for the setView call.
241
                        dFileAspect = (double)v.width()/(double)v.height();
242
                        dWindowAspect = (double)width /(double)height;
243

    
244
                        if (dFileAspect > dWindowAspect) {
245
                          height =(int)((double)width/dFileAspect);
246
                        } else {
247
                          width = (int)((double)height*dFileAspect);
248
                        }
249

    
250
                        
251
                        fullSize = new Dimension(width, height);
252
                        System.out.println("fullSize = ("+width+","+height+")");
253
                        // Peta en los peque?os ... arreglar antes de meter del todo
254
                        ChunkFrame frames[] = ChunkFrame.computeFrames(file, v, fullSize);
255
                        for (int nChunk=0; nChunk<frames.length; nChunk++) {
256
                                System.out.println("chunck "+nChunk+"->"+frames[nChunk]);
257
                        }
258
                        if (frames.length == 1) {
259
                                width = frames[0].width; 
260
                                height = frames[0].height;
261
                                if(width<=0)width=1;
262
                                if(height<=0)height=1;
263
                                System.out.println("frameSize = ("+width+","+height+")");
264
                                //System.out.println("Cambio el ancho total a ("+width+","+height+")");
265
                        }
266
                        
267
/*                        JNCSDatasetPoint ptMin = file.convertWorldToDataset(v.minX(), v.minY());
268
                        JNCSDatasetPoint ptMax = file.convertWorldToDataset(v.maxX(), v.maxY());
269
                        System.out.println("Dataset coords Width = "+(ptMax.x-ptMin.x)+", px width ="+width);
270
                        // BEGIN Cambiando para soportar e < 1:1
271
                        // TODO Mejorarlo para que los PAN con un zoom muy grande sean correctos
272
                        if ((ptMax.x-ptMin.x)<width) {
273
                                width = ptMax.x-ptMin.x;
274
                                height = ptMin.y-ptMax.y;
275
                                System.out.println("Size=("+width+","+height+")");
276
                                mustResize = true;
277
                        }*/
278
                        // Create an image of the ecw file.
279
                        if (doTransparency)
280
                                ecwImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB) ;
281
                        else
282
                                ecwImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
283

    
284
                        pRGBArray = new int[width];
285

    
286
                        // Setup the view parameters for the ecw file.
287
                        bandlist = new int[bandCount];
288
                        bandListTriband = new int[bandCount];
289
                        if ( bandCount > 2) {
290
                                bandlist[0] = getBand(RED_BAND);
291
                                bandlist[1] = getBand(GREEN_BAND);
292
                                bandlist[2] = getBand(BLUE_BAND);
293
                                if (bandCount > 3)
294
                                        for (int i=3; i< bandCount; i++) {
295
                                                 bandlist[i] = 0;
296
                                        }
297
                        } else {
298
                                for (int i=0; i< bandCount; i++) {
299
                                  bandlist[i] = i;
300
                                }
301
                        }
302
                        
303
                        if(bandCount==3){
304
                                bandListTriband[0] = 0;
305
                                bandListTriband[1] = 1;
306
                                bandListTriband[2] = 2;
307
                        }
308
                        
309
                        for (int nChunk=0; nChunk<frames.length; nChunk++) {
310
                                ChunkFrame f = frames[nChunk];
311
                                
312
                                // Set the view                        
313
                                if(bandCount!=3)
314
                                        file.setView(file.numBands, bandlist, f.v.minX(), f.v.maxY(), f.v.maxX(), f.v.minY(), f.width, f.height);
315
                                else
316
                                        file.setView(file.numBands, bandListTriband, f.v.minX(), f.v.maxY(), f.v.maxX(), f.v.minY(), f.width, f.height);
317
                                
318
                                System.out.println("f.Size = ("+f.width+","+f.height+")+CHUNK="+nChunk);
319
                                
320
                                /* Esta peli es porque el Ecw no intercambia las bandas con lo que me toca hacerlo
321
                                 * a mano. Primero detectamos si se ha alterado el orden de las mismas. Si es as? 
322
                                 * calculamos mascaras y desplazamientos y hacemos una copia en pRGBArrayCopy 
323
                                 * con las bandas alteradas de orden
324
                                 */
325
                                
326
                                int pRGBArrayCopy[] = null;
327
                                int mascara[] = new int[3];
328
                                int shl[] = new int[3];
329
                                int shr[] = new int[3];
330
                                boolean order = true;
331
                                
332
                                if(bandCount==3){
333
                                        for(int i=0;i<bandCount;i++)
334
                                                if(bandlist[i]!=i)order=false;
335
                                        if(!order){
336
                                                for(int i=0;i<bandCount;i++){
337
                                                        switch(bandlist[i]){
338
                                                                case 0:mascara[i] = 0x00ff0000;break;
339
                                                                case 1:mascara[i] = 0x0000ff00;break;
340
                                                            case 2:mascara[i] = 0x000000ff;break;
341
                                                        }
342
                                                        if(i==1 && bandlist[i]==0)shr[i] = 8;
343
                                                        if(i==2 && bandlist[i]==0)shr[i] = 16;
344
                                                        if(i==0 && bandlist[i]==1)shl[i] = 8;
345
                                                        if(i==2 && bandlist[i]==1)shr[i] = 8;
346
                                                        if(i==0 && bandlist[i]==2)shl[i] = 16;
347
                                                        if(i==1 && bandlist[i]==2)shl[i] = 8;
348
                                                }
349
                                        }
350
                                }
351
                                
352
                                // Read the scan lines
353
                                for (line=0; line < f.height; line++) {
354
                                        file.readLineRGBA(pRGBArray);
355
                                        
356
                                        if(bandCount==3 && !order){
357
                                                        pRGBArrayCopy = new int[pRGBArray.length];
358
                                                        for(int i=0;i<pRGBArray.length;i++){ 
359
                                                                pRGBArrayCopy[i] =         (pRGBArray[i] & 0xff000000) + 
360
                                                                                                        (((pRGBArray[i] & mascara[2]) << shl[2] ) >> shr[2]) + 
361
                                                                                                        (((pRGBArray[i] & mascara[1]) << shl[1] ) >> shr[1]) +
362
                                                                                                        (((pRGBArray[i] & mascara[0]) << shl[0] ) >> shr[0]);
363
                                                        }
364
                                                        pRGBArray = pRGBArrayCopy;
365
                                        }
366
                                        
367
                                        // Prueba de sustituci?n de color transparente
368
                                        if (doTransparency) {
369
                                                if (line == 0) tFilter.debug = true;
370
                                                  tFilter.filterLine(pRGBArray);
371
                                                tFilter.debug = false; 
372
                                        }
373
                                        //System.out.println("setRGB("+f.pos.x+","+f.pos.y+line+","+f.width+","+1+","+pRGBArray+","+0+","+f.width+")");
374
                                        ((BufferedImage)ecwImage).setRGB(f.pos.x, f.pos.y+line, f.width, 1, pRGBArray, 0, f.width);
375
                                }
376
                        }
377
                        if (frames[0].mustResize) {
378
                                //System.out.println("resize "+fullSize);
379
                                return resizeImage(fullSize, ecwImage);
380
                        }
381
                /*
382
                 * La excepci?n atrapada es la de 'zoom > 1:1 no valido'
383
                } catch (com.ermapper.ecw.JNCSInvalidSetViewException e) {
384
                        System.err.println(errorMessage);
385
                        e.printStackTrace(); */
386
                } catch(com.ermapper.ecw.JNCSException e) { //java.lang.ArrayIndexOutOfBoundsException:
387
                        bErrorOnOpen = true;
388
                        System.err.println("EcwFile JNCS Error en la l?nea "+line+"/"+height);
389
                        System.err.println(e.getMessage());
390
                        e.printStackTrace();
391
                } catch(java.lang.ArrayIndexOutOfBoundsException e) { //:
392
                        bErrorOnOpen = true;
393
                        System.err.println("EcwFile ArrayIndex Error en la l?nea "+line+"/"+height);
394
                        System.err.println(e.getMessage());
395
                        e.printStackTrace();
396
                } catch(Exception e) {
397
                        bErrorOnOpen = true;
398
                        errorMessage = e.getMessage();
399
//                        g.drawString(errorMessage, 0, 50);
400
                        System.err.println(errorMessage);
401
                        e.printStackTrace();
402
                }
403
                lastRefreshPercent = file.getPercentComplete();
404
                System.out.println("Leido al "+lastRefreshPercent+" %.");
405
                return ecwImage;
406
        }
407
        
408
        /**
409
         * Redimensionado de imagen
410
         * La funci?n getScaledInstance nos devuelve un tipo image que no sirve por lo que
411
         * habr? que crear  buffImg como BufferedImage y copiar los datos devueltos por esta 
412
         * funci?n a este que es el que ser? devuelto por la funci?n
413
         * @param sz
414
         * @param image        Image de entrada
415
         * @return        Imagen reescalada
416
         */
417
        private Image resizeImage(Dimension sz, Image image) {
418
                Image buffImg = null;
419
                Image img = image.getScaledInstance((int) sz.getWidth(),
420
                        (int) sz.getHeight(), Image.SCALE_SMOOTH);
421
                
422
                //Todo este pollo es para copiar el tipo image devuelto a BufferedImage
423
                
424
                buffImg = new BufferedImage(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_ARGB) ;
425
                
426
                int[] pixels = new int[img.getWidth(null) * img.getHeight(null)];
427
                PixelGrabber pg = new PixelGrabber(img, 0, 0, img.getWidth(null), img.getHeight(null), pixels, 0, img.getWidth(null));
428
                
429
                try {
430
                    pg.grabPixels();
431
                } catch (InterruptedException e) {
432
                    e.printStackTrace();
433
                }
434
                
435
                for (int j = 0; j < buffImg.getHeight(null); j++) {
436
                    for (int i = 0; i < buffImg.getWidth(null); i++) {
437
                                ((BufferedImage)buffImg).setRGB(i, j, pixels[j * buffImg.getWidth(null) + i]);
438
                    }
439
                }
440
                
441
                return buffImg;
442
        }
443
        
444
        /**
445
         * Reproyecta el raster.
446
         */
447
        public void reProject(ICoordTrans rp) {
448
                // TODO metodo reProject pendiente de implementar
449
        }
450

    
451

    
452
        /**
453
         * Soporte para actualizaci?n de la imagen
454
         * @see com.ermapper.ecw.JNCSProgressiveUpdate#refreshUpdate(int, int, double, double, double, double)
455
         */
456
        public void refreshUpdate(int nWidth, int nHeight, double dWorldTLX, double dWorldTLY, double dWorldBRX, double dWorldBRY) {
457
                int completado = file.getPercentComplete();
458
                System.out.println("EcwFile: se actualiza 1: "+completado+" % completado");
459
                if ((updatable != null) && (lastRefreshPercent < 100)) {
460
                        if ((completado-lastRefreshPercent > 25) || completado == 100) {
461
                                lastRefreshPercent = file.getPercentComplete();
462
                                updatable.repaint();
463
                        }
464
                }
465
        }
466

    
467
        public void refreshUpdate(int nWidth, int nHeight, int dDatasetTLX, int dDatasetTLY, int dDatasetBRX, int dDatasetBRY) {
468
                System.out.println("EcwFile: se actualiza 2");
469
        }
470

    
471
        /**
472
         *  Esta funci?n es porque el Ecw no intercambia las bandas con lo que me toca hacerlo
473
         * a mano. Primero detectamos si se ha alterado el orden de las mismas. Si es as? 
474
         * calculamos mascaras y desplazamientos y hacemos una copia en pRGBArrayCopy 
475
         * con las bandas alteradas de orden
476
         * @param bandList        lista de bandas
477
         * @param mask mascara
478
         * @param shl desplazamiento izquierda
479
         * @param shr desplazamiento derecha
480
         */
481
        private boolean calcMaskAndShift(int[] bandList, int[] mask, int[] shl, int[] shr){
482
                boolean order = true;
483
                if(bandCount==3){
484
                        for(int i=0;i<bandCount;i++)
485
                                if(bandList[i]!=i)order=false;
486
                        if(!order){
487
                                for(int i=0;i<bandCount;i++){
488
                                        switch(bandList[i]){
489
                                                case 0:mask[i] = 0x00ff0000;break;
490
                                                case 1:mask[i] = 0x0000ff00;break;
491
                                            case 2:mask[i] = 0x000000ff;break;
492
                                        }
493
                                        if(i==1 && bandList[i]==0)shr[i] = 8;
494
                                        if(i==2 && bandList[i]==0)shr[i] = 16;
495
                                        if(i==0 && bandList[i]==1)shl[i] = 8;
496
                                        if(i==2 && bandList[i]==1)shr[i] = 8;
497
                                        if(i==0 && bandList[i]==2)shl[i] = 16;
498
                                        if(i==1 && bandList[i]==2)shl[i] = 8;
499
                                }
500
                        }
501
                }
502
                return order;
503
        }
504
        
505
        /**
506
         * Intercambio de bandas para ecw manual. Se le pasa el array de bytes que se desea intercambiar
507
         * la mascara y desplazamientos previamente calculados con calcMaskAndShift
508
         * @param order        true si el orden de las bandas no est? alterado y false si lo est? 
509
         * @param pRGBArray array de
510
         * @param mascara
511
         * @param shl desplazamiento a izquierda 
512
         * @param shr desplazamiento a derecha
513
         * @return array con las bandas cambiadas
514
         */
515
        private int[] changeBands(boolean order, int[] pRGBArray, int[] mascara, int[] shl, int[] shr){
516
                if(bandCount==3 && !order){
517
                        int[] pRGBArrayCopy = new int[pRGBArray.length];
518
                        for(int i=0;i<pRGBArray.length;i++){ 
519
                                pRGBArrayCopy[i] =         (pRGBArray[i] & 0xff000000) + 
520
                                                                        (((pRGBArray[i] & mascara[2]) << shl[2] ) >> shr[2]) + 
521
                                                                        (((pRGBArray[i] & mascara[1]) << shl[1] ) >> shr[1]) +
522
                                                                        (((pRGBArray[i] & mascara[0]) << shl[0] ) >> shr[0]);
523
                        }
524
                        return pRGBArrayCopy;
525
                }
526
                return pRGBArray;
527
        }
528
        
529
        /**
530
         * Asigna al objeto Image los valores con los dato de la imagen contenidos en el 
531
         * vector de enteros.
532
         * @param image        imagen con los datos actuales
533
         * @param startX        inicio de la posici?n en X dentro de la imagen
534
         * @param startY        inicio de la posici?n en X dentro de la imagen
535
         * @param w        Ancho de la imagen
536
         * @param h        Alto de la imagen
537
         * @param rgbArray        vector que contiene la banda que se va a sustituir
538
         * @param offset        desplazamiento
539
         * @param scansize        tama?o de imagen recorrida por cada p
540
         */
541
        protected void setRGBLine(BufferedImage image, int startX, int startY, int w, int h, int[] rgbArray, 
542
                         int offset, int scansize) {
543
                image.setRGB(startX, startY, w, h, rgbArray, offset, scansize);
544
        }
545
        
546
        /**
547
         * Asigna al objeto Image la mezcla entre los valores que ya tiene y los valores 
548
         * con los dato de la imagen contenidos en el vector de enteros. De los valores RGB
549
         * que ya contiene se mantienen las bandas que no coinciden con el valor de flags. La
550
         * banda correspondiente a flags es sustituida por los datos del vector.
551
         * @param image        imagen con los datos actuales
552
         * @param startX        inicio de la posici?n en X dentro de la imagen
553
         * @param startY        inicio de la posici?n en X dentro de la imagen
554
         * @param w        Ancho de la imagen
555
         * @param h        Alto de la imagen
556
         * @param rgbArray        vector que contiene la banda que se va a sustituir
557
         * @param offset        desplazamiento
558
         * @param scansize        tama?o de imagen recorrida por cada paso
559
         * @param flags        banda que se va a sustituir (Ctes de GeoRasterFile)
560
         */
561
        protected void setRGBLine(BufferedImage image, int startX, int startY, int w, int h, int[] rgbArray, 
562
                         int offset, int scansize, int flags) {
563
                int [] line = new int[rgbArray.length]; 
564
                image.getRGB(startX, startY, w, h, line, offset, scansize);
565
                if (flags == GeoRasterFile.RED_BAND)
566
                        for (int i=0; i<line.length; i++)
567
                                line[i] = (line[i] & 0x0000ffff) | (rgbArray[i] & 0xffff0000);
568
                else if (flags == GeoRasterFile.GREEN_BAND)
569
                        for (int i=0; i<line.length; i++)
570
                                line[i] = (line[i] & 0x00ff00ff) | (rgbArray[i] & 0xff00ff00);
571
                else if (flags == GeoRasterFile.BLUE_BAND)
572
                        for (int i=0; i<line.length; i++)
573
                                line[i] = (line[i] & 0x00ffff00) | (rgbArray[i] & 0xff0000ff);
574
                image.setRGB(startX, startY, w, h, line, offset, scansize);
575
        }
576
        
577
        /**
578
         * Asigna al objeto Image la mezcla entre los valores que ya tiene y los valores 
579
         * con los dato de la imagen contenidos en el vector de enteros. De los valores RGB
580
         * que ya contiene se mantienen las bandas que no coinciden con el valor de flags. La
581
         * banda correspondiente a flags es sustituida por los datos del vector.
582
         * @param image        imagen con los datos actuales
583
         * @param startX        inicio de la posici?n en X dentro de la imagen
584
         * @param startY        inicio de la posici?n en X dentro de la imagen
585
         * @param w        Ancho de la imagen
586
         * @param h        Alto de la imagen
587
         * @param rgbArray        vector que contiene la banda que se va a sustituir
588
         * @param offset        desplazamiento
589
         * @param scansize        tama?o de imagen recorrida por cada paso
590
         * @param origBand        Banda origen del GeoRasterFile
591
         * @param destBandFlag        banda que se va a sustituir (Ctes de GeoRasterFile)
592
         */
593
        protected void setRGBLine(BufferedImage image, int startX, int startY, int w, int h, int[] rgbArray, 
594
                         int offset, int scansize, int origBand, int destBandFlag) {
595
                int [] line = new int[rgbArray.length]; 
596
                image.getRGB(startX, startY, w, h, line, offset, scansize);
597
                
598
                if (origBand == 0 && destBandFlag == GeoRasterFile.RED_BAND)
599
                        for (int i=0; i<line.length; i++)
600
                                line[i] = (line[i] & 0xff00ffff) | (rgbArray[i] & 0x00ff0000);
601
                else if (origBand == 1 && destBandFlag == GeoRasterFile.GREEN_BAND)
602
                        for (int i=0; i<line.length; i++)
603
                                line[i] = (line[i] & 0xffff00ff) | (rgbArray[i] & 0x0000ff00);
604
                else if (origBand == 2 && destBandFlag == GeoRasterFile.BLUE_BAND)
605
                        for (int i=0; i<line.length; i++)
606
                                line[i] = (line[i] & 0xffffff00) | (rgbArray[i] & 0x000000ff);
607
                
608
                else if (origBand == 0 && destBandFlag == GeoRasterFile.GREEN_BAND)
609
                        for (int i=0; i<line.length; i++)
610
                                line[i] = (line[i] & 0xffff00ff) | ((rgbArray[i] & 0x00ff0000) >> 8) ;
611
                else if (origBand == 0 && destBandFlag == GeoRasterFile.BLUE_BAND)
612
                        for (int i=0; i<line.length; i++)
613
                                line[i] = (line[i] & 0xffffff00) | ((rgbArray[i] & 0x00ff0000) >> 16);
614
                
615
                else if (origBand == 1 && destBandFlag == GeoRasterFile.RED_BAND)
616
                        for (int i=0; i<line.length; i++)
617
                                line[i] = (line[i] & 0xff00ffff) | ((rgbArray[i] & 0x0000ff00) << 8);
618
                else if (origBand == 1 && destBandFlag == GeoRasterFile.BLUE_BAND)
619
                        for (int i=0; i<line.length; i++)
620
                                line[i] = (line[i] & 0xffffff00) | ((rgbArray[i] & 0x0000ff00) >> 8);
621
                
622
                else if (origBand == 2 && destBandFlag == GeoRasterFile.RED_BAND)
623
                        for (int i=0; i<line.length; i++)
624
                                line[i] = (line[i] & 0xff00ffff) | ((rgbArray[i] & 0x000000ff) << 16);
625
                else if (origBand == 2 && destBandFlag == GeoRasterFile.GREEN_BAND)
626
                        for (int i=0; i<line.length; i++)
627
                                line[i] = (line[i] & 0xffff00ff) | ((rgbArray[i] & 0x000000ff) << 8);
628
                
629
                image.setRGB(startX, startY, w, h, line, offset, scansize);
630
        }
631
                
632
        /* (non-Javadoc)
633
         * @see org.cresques.io.GeoRasterFile#updateImage(int, int, org.cresques.cts.ICoordTrans, java.awt.Image, int origBand, int destBand)
634
         */
635
        public Image updateImage(int width, int height, ICoordTrans rp, Image img, int origBand, int destBandFlag) {
636
                //TODO reproyectar para devolver el trozo de imagen pedida sobre ...
637
                // la proyecci?n de destino.
638
                int line = 0; 
639
                boolean mustResize = false;
640
                Dimension fullSize = null;
641
                
642
                if (file == null) return null;
643
                try {
644
                        double dFileAspect, dWindowAspect;
645
                        //double dWorldTLX, dWorldTLY, dWorldBRX, dWorldBRY;
646
                        int bandlist[];
647
                        int bandListTriband[];
648
                        int pRGBArray[] = null;
649

    
650
                        // Work out the correct aspect for the setView call.
651
                        dFileAspect = (double)v.width()/(double)v.height();
652
                        dWindowAspect = (double)width /(double)height;
653

    
654
                        if (dFileAspect > dWindowAspect) {
655
                          height =(int)((double)width/dFileAspect);
656
                        } else {
657
                          width = (int)((double)height*dFileAspect);
658
                        }
659

    
660
                        fullSize = new Dimension(width, height);
661
                        System.out.println("fullSize = ("+width+","+height+")");
662
                        // Peta en los peque?os ... arreglar antes de meter del todo
663
                        ChunkFrame frames[] = ChunkFrame.computeFrames(file, v, fullSize);
664
                        for (int nChunk=0; nChunk<frames.length; nChunk++) {
665
                                System.out.println("chunck "+nChunk+"->"+frames[nChunk]);
666
                        }
667
                        if (frames.length == 1) {
668
                                width = frames[0].width; 
669
                                height = frames[0].height;
670
                                if(width<=0)width=1;
671
                                if(height<=0)height=1;
672
                                System.out.println("frameSize = ("+width+","+height+")");
673
                                //System.out.println("Cambio el ancho total a ("+width+","+height+")");
674
                        }
675
                                        
676
                        // Create an image of the ecw file.
677
                                                
678
                        pRGBArray = new int[width];
679

    
680
                        // Setup the view parameters for the ecw file.
681
                        bandlist = new int[bandCount];
682
                        bandListTriband = new int[bandCount];
683
                        if ( bandCount > 2) {
684
                                bandlist[0] = getBand(RED_BAND);
685
                                bandlist[1] = getBand(GREEN_BAND);
686
                                bandlist[2] = getBand(BLUE_BAND);
687
                                if (bandCount > 3)
688
                                        for (int i=3; i< bandCount; i++) {
689
                                                 bandlist[i] = 0;
690
                                        }
691
                        } else {
692
                                for (int i=0; i< bandCount; i++) {
693
                                  bandlist[i] = i;
694
                                }
695
                        }
696
                        
697
                        if(bandCount==3){
698
                                bandListTriband[0] = 0;
699
                                bandListTriband[1] = 1;
700
                                bandListTriband[2] = 2;
701
                        }
702
                        
703
                        int mascara[] = new int[3];
704
                        int shl[] = new int[3];
705
                        int shr[] = new int[3];
706
                        boolean order = true;
707
                        
708
                        if(img==null){ //Caso en el que se crea un Image
709
                                Image ecwImage = null;
710
                                for (int nChunk=0; nChunk<frames.length; nChunk++) {
711
                                        ChunkFrame f = frames[nChunk];
712
                                        if(bandCount!=3)
713
                                                file.setView(file.numBands, bandlist, f.v.minX(), f.v.maxY(), f.v.maxX(), f.v.minY(), f.width, f.height);
714
                                        else
715
                                                file.setView(file.numBands, bandListTriband, f.v.minX(), f.v.maxY(), f.v.maxX(), f.v.minY(), f.width, f.height);                                        
716
                                        
717
                                        order = calcMaskAndShift(bandlist, mascara, shl, shr);
718

    
719
                                        ecwImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
720
                                        
721
                                        for (line=0; line < f.height; line++) {
722
                                                file.readLineRGBA(pRGBArray);
723
                                                pRGBArray = changeBands(order, pRGBArray, mascara, shl, shr);
724
                                                setRGBLine((BufferedImage) ecwImage, f.pos.x, f.pos.y+line, f.width, 1, pRGBArray, 0, f.width);
725
                                        }
726
                                                                                
727
                                }//Chuncks
728
                                applyAlpha(ecwImage);
729
                                if (frames[0].mustResize) {
730
                                        return resizeImage(fullSize, ecwImage);
731
                                }
732
                                lastRefreshPercent = file.getPercentComplete();
733
                                System.out.println("Leido al "+lastRefreshPercent+" %.");
734
                                return ecwImage;
735
                        }else{        //Caso en el que se actualiza una banda del Image
736
                                for (int nChunk=0; nChunk<frames.length; nChunk++) {
737
                                        ChunkFrame f = frames[nChunk];
738
                                        if(bandCount!=3)
739
                                                file.setView(file.numBands, bandlist, f.v.minX(), f.v.maxY(), f.v.maxX(), f.v.minY(), f.width, f.height);
740
                                        else
741
                                                file.setView(file.numBands, bandListTriband, f.v.minX(), f.v.maxY(), f.v.maxX(), f.v.minY(), f.width, f.height);                                        
742
                                        order = calcMaskAndShift(bandlist, mascara, shl, shr);
743
                                        
744
                                        //System.out.println("ORIGEN="+origBand+" DESTINO="+destBandFlag);
745
                                        for (line=0; line < f.height; line++) {
746
                                                file.readLineRGBA(pRGBArray);
747
                                                pRGBArray = changeBands(order, pRGBArray, mascara, shl, shr);
748
                                                setRGBLine((BufferedImage) img, f.pos.x, f.pos.y+line, f.width, 1, pRGBArray, 0, f.width, origBand, destBandFlag);
749
                                        }
750
                                                                                
751
                                }//Chuncks
752
                                
753
                                applyAlpha(img);
754
                                
755
                                if (frames[0].mustResize) {
756
                                        return resizeImage(fullSize, img);
757
                                }
758
                                lastRefreshPercent = file.getPercentComplete();
759
                                System.out.println("Leido al "+lastRefreshPercent+" %.");
760
                                return img;
761
                        }
762
                        
763

    
764
                } catch(com.ermapper.ecw.JNCSException e) { //java.lang.ArrayIndexOutOfBoundsException:
765
                        bErrorOnOpen = true;
766
                        System.err.println("EcwFile JNCS Error en la l?nea "+line+"/"+height);
767
                        System.err.println(e.getMessage());
768
                        e.printStackTrace();
769
                } catch(java.lang.ArrayIndexOutOfBoundsException e) { //:
770
                        bErrorOnOpen = true;
771
                        System.err.println("EcwFile ArrayIndex Error en la l?nea "+line+"/"+height);
772
                        System.err.println(e.getMessage());
773
                        e.printStackTrace();
774
                } catch(Exception e) {
775
                        bErrorOnOpen = true;
776
                        errorMessage = e.getMessage();
777
                        System.err.println(errorMessage);
778
                        e.printStackTrace();
779
                }
780
                return img;
781
        }
782
        
783
        private void applyAlpha(Image im) {
784
                BufferedImage img = (BufferedImage) im;
785
                int alpha = (getAlpha() & 0xff) << 24;
786
                int w = img.getWidth();
787
                int [] line = new int[w];
788
                for (int j=0; j<img.getHeight(); j++) {
789
                        img.getRGB(0, j, w, 1, line, 0, w);
790
                        for (int i=0; i<w; i++)
791
                                line[i] = (alpha | line[i] & 0x00ffffff);
792
                        img.setRGB(0, j, w, 1, line, 0, w);
793
                }
794
        }
795

    
796
        /* (non-Javadoc)
797
         * @see org.cresques.io.GeoRasterFile#getData(int, int)
798
         */
799
        public Object getData(int x, int y, int band) {
800
                //file.readLineRGBA();
801
                return null;
802
        }
803
        
804
        /**
805
         * Devuelve los datos de una ventana solicitada
806
         * @param ulX        coordenada X superior izda.
807
         * @param ulY        coordenada Y superior derecha.
808
         * @param sizeX        tama?o en X de la ventana.
809
         * @param sizeY tama?o en Y de la ventana.
810
         * @param band        Banda solicitada.
811
         */
812
        
813
        public byte[] getWindow(int ulX, int ulY, int sizeX, int sizeY, int band){
814
                //TODO Nacho: Implementar getWindow de EcwFile
815
                        return null;
816
                
817
        }
818
        
819
        /**
820
         * Obtiene la zona (Norte / Sur)
821
         * @return true si la zona es norte y false si es sur
822
         */
823
        
824
        public boolean getZone(){
825
                //TODO Nacho: Implementar getZone de EcwFile
826
                return false;
827
        }
828
        
829
        /**
830
         *Devuelve el n?mero de zona UTM
831
         *@return N?mero de zona 
832
         */
833
        
834
        public int getUTM(){
835
//                TODO Nacho: Implementar getUTM de EcwFile
836
                return 0;        
837
        }
838
        
839
        /**
840
         * Obtiene el sistema de coordenadas geograficas
841
         * @return Sistema de coordenadas geogr?ficas
842
         */
843
        public String getGeogCS(){
844
                //TODO Nacho: Implementar getGeogCS de EcwFile
845
                return new String("");        
846
        }
847
        
848
        /**
849
         * Devuelve el tama?o de bloque
850
         * @return Tama?o de bloque
851
         */
852
        public int getBlockSize(){
853
     //TODO Nacho: Implementar getBlockSize de EcwFile        
854
          return 1;
855
        }
856

    
857
}