Statistics
| Revision:

svn-gvsig-desktop / tags / v1_1_Build_1006 / libraries / libCq_CMS_praster / src / org / cresques / io / EcwFile.java @ 12458

History | View | Annotate | Download (48.1 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.Dimension;
27
import java.awt.Image;
28
import java.awt.Point;
29
import java.awt.geom.Point2D;
30
import java.awt.image.BufferedImage;
31
import java.awt.image.PixelGrabber;
32

    
33
import org.cresques.cts.ICoordTrans;
34
import org.cresques.cts.IProjection;
35
import org.cresques.io.data.BandList;
36
import org.cresques.io.data.RasterBuf;
37
import org.cresques.io.exceptions.SupersamplingNotSupportedException;
38
import org.cresques.px.Extent;
39

    
40
import com.ermapper.ecw.JNCSException;
41
import com.ermapper.ecw.JNCSFile;
42
import com.ermapper.ecw.JNCSFileNotOpenException;
43
import com.ermapper.ecw.JNCSInvalidSetViewException;
44
import com.ermapper.ecw.JNCSProgressiveUpdate;
45
import com.ermapper.util.JNCSDatasetPoint;
46
import com.ermapper.util.JNCSWorldPoint;
47

    
48

    
49
/**
50
 * Soporte para los ficheros .ecw de ErMapper.
51
 * <br>
52
 * NOTA: El SDK que ermapper ha puesto a disposici?n del p?blico en java
53
 * es una versi?n 2.45, de 19/11/2001. Est? implementada usando JNI que
54
 * se apoya en tres librer?as din?micas (dll), y presenta deficiencias
55
 * muy graves a la hora de acceder a la informaci?n. Hasta el momento
56
 * hemos detectado 3 de ellas:<BR>
57
 *     1?.- No soporta ampliaciones superiores a 1:1. si se intenta acceder
58
 * a un ecw con un zoom mayor da una excepci?n del tipo
59
 * com.ermapper.ecw.JNCSInvalidSetViewException, que de no ser tenida encuenta
60
 * acaba tirando abajo la m?quina virtual de java.<BR>
61
 *     2?.- La longitud m?xima de l?nea que adminte el m?todo readLineRGBA es
62
 * de unos 2500 pixeles, lo que hace el uso para la impresi?n en formatos
63
 * superiorea a A4 a 300 ppp o m?s inviable.<BR>
64
 *     3?.- La actualizaci?n progresiva usando el interface JNCSProgressiveUpdate
65
 * con el JNCSFile hace que el equipo genere un error severo y se apague. Este
66
 * error imposibilita esta t?cnica de acceso a ECW.<BR>
67
 * <br>
68
 * Para saltarnos la limitaci?n del bug#1 pedimos la ventana correspondiente al zoom 1:1 para
69
 * el view que nos han puesto, y la resizeamos al tama?o que nos pide el usuario.<br>
70
 * Como consecuencia del bug#2, para tama?os de ventana muy grandes (los necesarios
71
 * para imprimir a m?s de A4 a 300DPI), hay que hacer varias llamadas al fichero con
72
 * varios marcos contiguos, y los devolvemos 'pegados' en una sola imagen (esto se
73
 * realiza de manera transparente para el usuario dentro de la llamada a updateImage.<br>
74
 *
75
 * @author "Luis W. Sevilla" <sevilla_lui@gva.es>
76
 */
77
public class EcwFile extends GeoRasterFile implements JNCSProgressiveUpdate {
78
    //Lleva la cuenta del n?mero de actualizaciones que se hace de una imagen que corresponde con el 
79
    //n?mero de bandas que tiene. Esto es necesario ya que si una imagen tiene el mustResize a
80
    //true solo debe llamar a la funci?n resizeImage al actualizar la ?ltima banda, sino al hacer
81
    //un zoom menor que 1:1 se veria mal
82
    private static int nUpdate = 0;
83
    private JNCSFile file = null;
84
    private boolean bErrorOnOpen = false;
85
    private String errorMessage = null;
86
    private boolean multifile = false;
87
    private Extent v = null;
88

    
89
    // Ultimo porcentaje de refresco. Se carga en el update y se
90
    // actualiza en el refreshUpdate
91
    private int lastRefreshPercent = 0;
92

    
93
    public EcwFile(IProjection proj, String fName) {
94
        super(proj, null);
95
        fName = DataSource.normalize(fName);
96
        super.setName(fName);
97
        extent = new Extent();
98

    
99
        try {
100
            System.err.println("Abriendo "+fName);
101
            file = new JNCSFile(fName, false);
102
            load();
103
            //readGeoInfo(fName);
104
            bandCount = file.numBands;
105

    
106
            if ( bandCount > 2) {
107
                    setBand(RED_BAND,   0);
108
                    setBand(GREEN_BAND, 1);
109
                    setBand(BLUE_BAND,  2);
110
            } else
111
                    setBand(RED_BAND|GREEN_BAND|BLUE_BAND, 0);
112
        } catch (Exception e) {
113
            bErrorOnOpen = true;
114
            errorMessage = e.getMessage();
115
            System.err.println(errorMessage);
116
            e.printStackTrace();
117
        }
118
    }
119

    
120
    /**
121
     * Carga un ECW.
122
     *
123
     * @param fname
124
     */
125
    public GeoFile load() {
126
        double minX;
127
        double minY;
128
        double maxX;
129
        double maxY;
130

    
131
        if(file.cellIncrementY > 0)
132
                file.cellIncrementY = -file.cellIncrementY;
133
        
134
        minX = file.originX;
135
        maxY = file.originY;
136
        maxX = file.originX +
137
               ((double) (file.width - 1) * file.cellIncrementX);
138
        minY = file.originY +
139
               ((double) (file.height - 1) * file.cellIncrementY);
140
        
141
        extent = new Extent(minX, minY, maxX, maxY);
142
        requestExtent = extent;
143
        return this;
144
    }
145

    
146
    public void close() {
147
            if(file != null){
148
                    file.close(true);
149
                    file = null;
150
            }
151
    }
152

    
153
    /**
154
     * Devuelve el ancho de la imagen
155
     */
156
    public int getWidth() {
157
        return file.width;
158
    }
159

    
160
    /**
161
     * Devuelve el alto de la imagen
162
     */
163
    public int getHeight() {
164
        return file.height;
165
    }
166

    
167
    /**
168
     *
169
     */
170
    public void setMultifile(boolean mult) {
171
        this.multifile = mult;
172
    }
173

    
174
    public void setView(Extent e) {
175
            //Aplicamos la transformaci?n a la vista en caso de que haya un fichero .rmf 
176
            /*                     
177
            if(file.cellIncrementY > 0)
178
                file.cellIncrementY = -file.cellIncrementY;
179
            if(minX < file.originX)
180
                    minX = file.originX;
181
            if(maxY > file.originY)
182
                    maxY = file.originY;
183
            if(maxX > (file.originX + ((double) (file.width - 1) * file.cellIncrementX)))
184
                    maxX = file.originX + ((double) (file.width - 1) * file.cellIncrementX);
185
            if(minY < file.originY + ((double) (file.height - 1) * file.cellIncrementY))
186
                    minY = file.originY + ((double) (file.height - 1) * file.cellIncrementY);
187
            
188
                Extent transformView = new Extent(        minX, minY, maxX, maxY );*/
189
        v = new Extent(e);
190
    }
191

    
192
    public Extent getView() {
193
        return v;
194
    }
195
    
196
    private void setFileView(int numBands, int [] bandList, ChunkFrame f)
197
            throws JNCSFileNotOpenException, JNCSInvalidSetViewException {
198
        file.setView(file.numBands, bandList, f.v.minX(), f.v.maxY(), f.v.maxX(), f.v.minY(), f.width, f.height);
199
    }
200

    
201
    /**
202
     * Obtiene un trozo de imagen (determinado por la vista y los par?metros.
203
     *
204
     * @param width
205
     * @param height
206
     */
207
    public synchronized Image updateImage(int width, int height, ICoordTrans rp) {
208
        // TODO reproyectar para devolver el trozo de imagen pedida sobre ...
209
        // la proyecci?n de destino.
210
        int line = 0;
211
        boolean mustResize = false;
212
        Dimension fullSize = null;
213
        Image ecwImage = null;
214

    
215
        if (file == null) {
216
            return ecwImage;
217
        }
218

    
219
        try {
220
            int[] bandlist;
221
            int[] bandListTriband;
222
            int[] pRGBArray = null;
223

    
224
            if(mustVerifySize()){
225
            // Work out the correct aspect for the setView call.
226
                    double dFileAspect = (double) v.width() / (double) v.height();
227
                    double dWindowAspect = (double) width / (double) height;
228
        
229
                    if (dFileAspect > dWindowAspect) {
230
                        height = (int) ((double) width / dFileAspect);
231
                    } else {
232
                        width = (int) ((double) height * dFileAspect);
233
                    }
234
            }
235
            fullSize = new Dimension(width, height);
236

    
237
            //System.out.println("fullSize = ("+width+","+height+")");
238
            // Peta en los peque?os ... arreglar antes de meter del todo
239
            ChunkFrame[] frames = ChunkFrame.computeFrames(file, v, fullSize, extent);
240

    
241
            if (frames.length == 1) {
242
                width = frames[0].width;
243
                height = frames[0].height;
244

    
245
                if (width <= 0) {
246
                    width = 1;
247
                }
248

    
249
                if (height <= 0) {
250
                    height = 1;
251
                }
252
            }
253

    
254
            /*                        JNCSDatasetPoint ptMin = file.convertWorldToDataset(v.minX(), v.minY());
255
                                    JNCSDatasetPoint ptMax = file.convertWorldToDataset(v.maxX(), v.maxY());
256
                                    System.out.println("Dataset coords Width = "+(ptMax.x-ptMin.x)+", px width ="+width);
257
                                    // BEGIN Cambiando para soportar e < 1:1
258
                                    // TODO Mejorarlo para que los PAN con un zoom muy grande sean correctos
259
                                    if ((ptMax.x-ptMin.x)<width) {
260
                                            width = ptMax.x-ptMin.x;
261
                                            height = ptMin.y-ptMax.y;
262
                                            System.out.println("Size=("+width+","+height+")");
263
                                            mustResize = true;
264
                                    }*/
265

    
266
            // Create an image of the ecw file.
267
            if (doTransparency) {
268
                ecwImage = new BufferedImage(width, height,
269
                                             BufferedImage.TYPE_INT_ARGB);
270
            } else {
271
                ecwImage = new BufferedImage(width, height,
272
                                             BufferedImage.TYPE_INT_RGB);
273
            }
274

    
275
            pRGBArray = new int[width];
276

    
277
            // Setup the view parameters for the ecw file.
278
            bandlist = new int[bandCount];
279
            bandListTriband = new int[bandCount];
280

    
281
            if (bandCount > 2) {
282
                bandlist[0] = getBand(RED_BAND);
283
                bandlist[1] = getBand(GREEN_BAND);
284
                bandlist[2] = getBand(BLUE_BAND);
285

    
286
                if (bandCount > 3) {
287
                    for (int i = 3; i < bandCount; i++) {
288
                        bandlist[i] = 0;
289
                    }
290
                }
291
            } else {
292
                for (int i = 0; i < bandCount; i++) {
293
                    bandlist[i] = i;
294
                }
295
            }
296

    
297
            if (bandCount == 3) {
298
                bandListTriband[0] = 0;
299
                bandListTriband[1] = 1;
300
                bandListTriband[2] = 2;
301
            }
302

    
303
            for (int nChunk = 0; nChunk < frames.length; nChunk++) {
304
                ChunkFrame f = frames[nChunk];
305

    
306
                // Set the view                        
307
                if (bandCount != 3) {
308
                    setFileView(file.numBands, bandlist, f);
309
                } else {
310
                    setFileView(file.numBands, bandListTriband, f);
311
                }
312

    
313
                /* 
314
                 * Esta peli es porque el Ecw no intercambia las bandas con lo que me toca hacerlo
315
                 * a mano. Primero detectamos si se ha alterado el orden de las mismas. Si es as?
316
                 * calculamos mascaras y desplazamientos y hacemos una copia en pRGBArrayCopy
317
                 * con las bandas alteradas de orden
318
                 */
319
                int[] pRGBArrayCopy = null;
320
                int[] mascara = new int[3];
321
                int[] shl = new int[3];
322
                int[] shr = new int[3];
323
                boolean order = true;
324

    
325
                if (bandCount == 3) {
326
                    for (int i = 0; i < bandCount; i++)
327
                        if (bandlist[i] != i) {
328
                            order = false;
329
                        }
330

    
331
                    if (!order) {
332
                        for (int i = 0; i < bandCount; i++) {
333
                            switch (bandlist[i]) {
334
                            case 0:
335
                                mascara[i] = 0x00ff0000;
336
                                break;
337
                            case 1:
338
                                mascara[i] = 0x0000ff00;
339
                                break;
340
                            case 2:
341
                                mascara[i] = 0x000000ff;
342
                                break;
343
                            }
344
                            if ((i == 1) && (bandlist[i] == 0)) 
345
                                shr[i] = 8;
346
                            if ((i == 2) && (bandlist[i] == 0)) 
347
                                shr[i] = 16;
348
                            if ((i == 0) && (bandlist[i] == 1)) 
349
                                shl[i] = 8;
350
                            if ((i == 2) && (bandlist[i] == 1))
351
                                shr[i] = 8;
352
                            if ((i == 0) && (bandlist[i] == 2)) 
353
                                shl[i] = 16;
354
                            if ((i == 1) && (bandlist[i] == 2))
355
                                shl[i] = 8;
356
                        }
357
                    }
358
                }
359

    
360
                // Read the scan lines
361
                for (line = 0; line < f.height; line++) {
362
                    file.readLineRGBA(pRGBArray);
363

    
364
                    if ((bandCount == 3) && !order) {
365
                        pRGBArrayCopy = new int[pRGBArray.length];
366

    
367
                        for (int i = 0; i < pRGBArray.length; i++) {
368
                            pRGBArrayCopy[i] = (pRGBArray[i] & 0xff000000) +
369
                                               (((pRGBArray[i] & mascara[2]) << shl[2]) >> shr[2]) +
370
                                               (((pRGBArray[i] & mascara[1]) << shl[1]) >> shr[1]) +
371
                                               (((pRGBArray[i] & mascara[0]) << shl[0]) >> shr[0]);
372
                        }
373

    
374
                        pRGBArray = pRGBArrayCopy;
375
                    }
376

    
377
                    // Prueba de sustituci?n de color transparente
378
                    if (doTransparency) {
379
                        if (line == 0) {
380
                            tFilter.debug = true;
381
                        }
382

    
383
                        tFilter.filterLine(pRGBArray);
384
                        tFilter.debug = false;
385
                    }
386

    
387
                    ((BufferedImage) ecwImage).setRGB(f.pos.x, f.pos.y + line,
388
                                                      f.width, 1, pRGBArray, 0,
389
                                                      f.width);
390
                }
391
            }
392

    
393
            if (frames[0].mustResize) {
394
                //System.out.println("resize "+fullSize);
395
                return resizeImage(fullSize, ecwImage);
396
            }
397

    
398
            /*
399
             * La excepci?n atrapada es la de 'zoom > 1:1 no valido'
400
            } catch (com.ermapper.ecw.JNCSInvalidSetViewException e) {
401
                    System.err.println(errorMessage);
402
                    e.printStackTrace(); */
403
        } catch (com.ermapper.ecw.JNCSException e) { //java.lang.ArrayIndexOutOfBoundsException:
404
            bErrorOnOpen = true;
405
            System.err.println("EcwFile JNCS Error en la l?nea " + line + "/" +
406
                               height);
407
            System.err.println(e.getMessage());
408
            e.printStackTrace();
409
        } catch (java.lang.ArrayIndexOutOfBoundsException e) { //:
410
            bErrorOnOpen = true;
411
            System.err.println("EcwFile ArrayIndex Error en la l?nea " + line +
412
                               "/" + height);
413
            System.err.println(e.getMessage());
414
            e.printStackTrace();
415
        } catch (Exception e) {
416
            bErrorOnOpen = true;
417
            errorMessage = e.getMessage();
418

    
419
            //                        g.drawString(errorMessage, 0, 50);
420
            System.err.println(errorMessage);
421
            e.printStackTrace();
422
        }
423

    
424
        lastRefreshPercent = file.getPercentComplete();
425
        System.out.println("Leido al " + lastRefreshPercent + " %.");
426

    
427
        return ecwImage;
428
    }
429

    
430
    /**
431
     * Redimensionado de imagen
432
     * La funci?n getScaledInstance nos devuelve un tipo image que no sirve por lo que
433
     * habr? que crear  buffImg como BufferedImage y copiar los datos devueltos por esta
434
     * funci?n a este que es el que ser? devuelto por la funci?n
435
     * @param sz
436
     * @param image        Image de entrada
437
     * @return        Imagen reescalada
438
     */
439
    private Image resizeImage(Dimension sz, Image image) {
440
        Image buffImg = null;
441
        Image img = image.getScaledInstance((int) sz.getWidth(),
442
                                            (int) sz.getHeight(),
443
                                            Image.SCALE_SMOOTH);
444

    
445
        //Todo este pollo es para copiar el tipo image devuelto a BufferedImage
446
        buffImg = new BufferedImage(img.getWidth(null), img.getHeight(null),
447
                                    BufferedImage.TYPE_INT_ARGB);
448

    
449
        int[] pixels = new int[img.getWidth(null) * img.getHeight(null)];
450
        PixelGrabber pg = new PixelGrabber(img, 0, 0, img.getWidth(null),
451
                                           img.getHeight(null), pixels, 0,
452
                                           img.getWidth(null));
453

    
454
        try {
455
            pg.grabPixels();
456
        } catch (InterruptedException e) {
457
            e.printStackTrace();
458
        }
459

    
460
        for (int j = 0; j < buffImg.getHeight(null); j++) {
461
            for (int i = 0; i < buffImg.getWidth(null); i++) {
462
                ((BufferedImage) buffImg).setRGB(i, j,
463
                                                 pixels[(j * buffImg.getWidth(null)) +
464
                                                 i]);
465
            }
466
        }
467

    
468
        return buffImg;
469
    }
470

    
471
    /**
472
     * Reproyecta el raster.
473
     */
474
    public void reProject(ICoordTrans rp) {
475
        // TODO metodo reProject pendiente de implementar
476
    }
477

    
478
    /**
479
     * Soporte para actualizaci?n de la imagen
480
     * @see com.ermapper.ecw.JNCSProgressiveUpdate#refreshUpdate(int, int, double, double, double, double)
481
     */
482
    public void refreshUpdate(int nWidth, int nHeight, double dWorldTLX,
483
                              double dWorldTLY, double dWorldBRX,
484
                              double dWorldBRY) {
485
        int completado = file.getPercentComplete();
486
        System.out.println("EcwFile: se actualiza 1: " + completado +
487
                           " % completado");
488

    
489
        if ((updatable != null) && (lastRefreshPercent < 100)) {
490
            if (((completado - lastRefreshPercent) > 25) ||
491
                    (completado == 100)) {
492
                lastRefreshPercent = file.getPercentComplete();
493
                updatable.repaint();
494
            }
495
        }
496
    }
497

    
498
    public void refreshUpdate(int nWidth, int nHeight, int dDatasetTLX,
499
                              int dDatasetTLY, int dDatasetBRX, int dDatasetBRY) {
500
        System.out.println("EcwFile: se actualiza 2");
501
    }
502

    
503
    /**
504
     *  Esta funci?n es porque el Ecw no intercambia las bandas con lo que me toca hacerlo
505
     * a mano. Primero detectamos si se ha alterado el orden de las mismas. Si es as?
506
     * calculamos mascaras y desplazamientos y hacemos una copia en pRGBArrayCopy
507
     * con las bandas alteradas de orden
508
     * @param bandList        lista de bandas
509
     * @param mask mascara
510
     * @param shl desplazamiento izquierda
511
     * @param shr desplazamiento derecha
512
     */
513
    private boolean calcMaskAndShift(int[] bandList, int[] mask, int[] shl,
514
                                     int[] shr) {
515
        boolean order = true;
516

    
517
        if (bandCount == 3) {
518
            for (int i = 0; i < bandCount; i++)
519
                if (bandList[i] != i) {
520
                    order = false;
521
                }
522

    
523
            if (!order) {
524
                for (int i = 0; i < bandCount; i++) {
525
                    switch (bandList[i]) {
526
                    case 0:
527
                        mask[i] = 0x00ff0000;
528
                        break;
529
                    case 1:
530
                        mask[i] = 0x0000ff00;
531
                        break;
532
                    case 2:
533
                        mask[i] = 0x000000ff;
534
                        break;
535
                    }
536
                    
537
                    if ((i == 1) && (bandList[i] == 0))
538
                        shr[i] = 8;
539
                    if ((i == 2) && (bandList[i] == 0)) 
540
                        shr[i] = 16;
541
                    if ((i == 0) && (bandList[i] == 1))
542
                        shl[i] = 8;
543
                    if ((i == 2) && (bandList[i] == 1))
544
                        shr[i] = 8;
545
                    if ((i == 0) && (bandList[i] == 2))
546
                        shl[i] = 16;
547
                    if ((i == 1) && (bandList[i] == 2))
548
                        shl[i] = 8;
549
                }
550
            }
551
        }
552

    
553
        return order;
554
    }
555

    
556
    /**
557
     * Intercambio de bandas para ecw manual. Se le pasa el array de bytes que se desea intercambiar
558
     * la mascara y desplazamientos previamente calculados con calcMaskAndShift
559
     * @param order        true si el orden de las bandas no est? alterado y false si lo est?
560
     * @param pRGBArray array de
561
     * @param mascara
562
     * @param shl desplazamiento a izquierda
563
     * @param shr desplazamiento a derecha
564
     * @return array con las bandas cambiadas
565
     */
566
    private int[] changeBands(boolean order, int[] pRGBArray, int[] mascara,
567
                              int[] shl, int[] shr) {
568
        if ((bandCount == 3) && !order) {
569
            int[] pRGBArrayCopy = new int[pRGBArray.length];
570

    
571
            for (int i = 0; i < pRGBArray.length; i++) {
572
                pRGBArrayCopy[i] = (pRGBArray[i] & 0xff000000) +
573
                                   (((pRGBArray[i] & mascara[2]) << shl[2]) >> shr[2]) +
574
                                   (((pRGBArray[i] & mascara[1]) << shl[1]) >> shr[1]) +
575
                                   (((pRGBArray[i] & mascara[0]) << shl[0]) >> shr[0]);
576
            }
577

    
578
            return pRGBArrayCopy;
579
        }
580

    
581
        return pRGBArray;
582
    }
583

    
584
    /**
585
     * Asigna al objeto Image los valores con los dato de la imagen contenidos en el
586
     * vector de enteros.
587
     * @param image        imagen con los datos actuales
588
     * @param startX        inicio de la posici?n en X dentro de la imagen
589
     * @param startY        inicio de la posici?n en X dentro de la imagen
590
     * @param w        Ancho de la imagen
591
     * @param h        Alto de la imagen
592
     * @param rgbArray        vector que contiene la banda que se va a sustituir
593
     * @param offset        desplazamiento
594
     * @param scansize        tama?o de imagen recorrida por cada p
595
     */
596
    protected void setRGBLine(BufferedImage image, int startX, int startY,
597
                              int w, int h, int[] rgbArray, int offset,
598
                              int scansize) {
599
        image.setRGB(startX, startY, w, h, rgbArray, offset, scansize);
600
    }
601

    
602
    /**
603
     * Asigna al objeto Image la mezcla entre los valores que ya tiene y los valores
604
     * con los dato de la imagen contenidos en el vector de enteros. De los valores RGB
605
     * que ya contiene se mantienen las bandas que no coinciden con el valor de flags. La
606
     * banda correspondiente a flags es sustituida por los datos del vector.
607
     * @param image        imagen con los datos actuales
608
     * @param startX        inicio de la posici?n en X dentro de la imagen
609
     * @param startY        inicio de la posici?n en X dentro de la imagen
610
     * @param w        Ancho de la imagen
611
     * @param h        Alto de la imagen
612
     * @param rgbArray        vector que contiene la banda que se va a sustituir
613
     * @param offset        desplazamiento
614
     * @param scansize        tama?o de imagen recorrida por cada paso
615
     * @param flags        banda que se va a sustituir (Ctes de GeoRasterFile)
616
     */
617
    protected void setRGBLine(BufferedImage image, int startX, int startY,
618
                              int w, int h, int[] rgbArray, int offset,
619
                              int scansize, int flags) {
620
        int[] line = new int[rgbArray.length];
621
        image.getRGB(startX, startY, w, h, line, offset, scansize);
622

    
623
        if (flags == GeoRasterFile.RED_BAND) {
624
            for (int i = 0; i < line.length; i++)
625
                line[i] = (line[i] & 0x0000ffff) | (rgbArray[i] & 0xffff0000);
626
        } else if (flags == GeoRasterFile.GREEN_BAND) {
627
            for (int i = 0; i < line.length; i++)
628
                line[i] = (line[i] & 0x00ff00ff) | (rgbArray[i] & 0xff00ff00);
629
        } else if (flags == GeoRasterFile.BLUE_BAND) {
630
            for (int i = 0; i < line.length; i++)
631
                line[i] = (line[i] & 0x00ffff00) | (rgbArray[i] & 0xff0000ff);
632
        }
633

    
634
        image.setRGB(startX, startY, w, h, line, offset, scansize);
635
    }
636

    
637
    /**
638
     * Asigna al objeto Image la mezcla entre los valores que ya tiene y los valores
639
     * con los dato de la imagen contenidos en el vector de enteros. De los valores RGB
640
     * que ya contiene se mantienen las bandas que no coinciden con el valor de flags. La
641
     * banda correspondiente a flags es sustituida por los datos del vector.
642
     * @param image        imagen con los datos actuales
643
     * @param startX        inicio de la posici?n en X dentro de la imagen
644
     * @param startY        inicio de la posici?n en X dentro de la imagen
645
     * @param w        Ancho de la imagen
646
     * @param h        Alto de la imagen
647
     * @param rgbArray        vector que contiene la banda que se va a sustituir
648
     * @param offset        desplazamiento
649
     * @param scansize        tama?o de imagen recorrida por cada paso
650
     * @param origBand        Banda origen del GeoRasterFile
651
     * @param destBandFlag        banda que se va a sustituir (Ctes de GeoRasterFile)
652
     */
653
    protected void setRGBLine(BufferedImage image, int startX, int startY,
654
                              int w, int h, int[] rgbArray, int offset,
655
                              int scansize, int origBand, int destBandFlag) {
656
        int[] line = new int[rgbArray.length];
657
        image.getRGB(startX, startY, w, h, line, offset, scansize);
658

    
659
        if ((origBand == 0) && (destBandFlag == GeoRasterFile.RED_BAND)) {
660
            for (int i = 0; i < line.length; i++)
661
                line[i] = (line[i] & 0xff00ffff) | (rgbArray[i] & 0x00ff0000);
662
        } else if ((origBand == 1) &&
663
                       (destBandFlag == GeoRasterFile.GREEN_BAND)) {
664
            for (int i = 0; i < line.length; i++)
665
                line[i] = (line[i] & 0xffff00ff) | (rgbArray[i] & 0x0000ff00);
666
        } else if ((origBand == 2) &&
667
                       (destBandFlag == GeoRasterFile.BLUE_BAND)) {
668
            for (int i = 0; i < line.length; i++)
669
                line[i] = (line[i] & 0xffffff00) | (rgbArray[i] & 0x000000ff);
670
        }
671
        else if ((origBand == 0) && (destBandFlag == GeoRasterFile.GREEN_BAND)) {
672
            for (int i = 0; i < line.length; i++)
673
                line[i] = (line[i] & 0xffff00ff) |
674
                          ((rgbArray[i] & 0x00ff0000) >> 8);
675
        } else if ((origBand == 0) &&
676
                       (destBandFlag == GeoRasterFile.BLUE_BAND)) {
677
            for (int i = 0; i < line.length; i++)
678
                line[i] = (line[i] & 0xffffff00) |
679
                          ((rgbArray[i] & 0x00ff0000) >> 16);
680
        }
681
        else if ((origBand == 1) && (destBandFlag == GeoRasterFile.RED_BAND)) {
682
            for (int i = 0; i < line.length; i++)
683
                line[i] = (line[i] & 0xff00ffff) |
684
                          ((rgbArray[i] & 0x0000ff00) << 8);
685
        } else if ((origBand == 1) &&
686
                       (destBandFlag == GeoRasterFile.BLUE_BAND)) {
687
            for (int i = 0; i < line.length; i++)
688
                line[i] = (line[i] & 0xffffff00) |
689
                          ((rgbArray[i] & 0x0000ff00) >> 8);
690
        }
691
        else if ((origBand == 2) && (destBandFlag == GeoRasterFile.RED_BAND)) {
692
            for (int i = 0; i < line.length; i++)
693
                line[i] = (line[i] & 0xff00ffff) |
694
                          ((rgbArray[i] & 0x000000ff) << 16);
695
        } else if ((origBand == 2) &&
696
                       (destBandFlag == GeoRasterFile.GREEN_BAND)) {
697
            for (int i = 0; i < line.length; i++)
698
                line[i] = (line[i] & 0xffff00ff) |
699
                          ((rgbArray[i] & 0x000000ff) << 8);
700
        }
701

    
702
        image.setRGB(startX, startY, w, h, line, offset, scansize);
703
    }
704
            
705
    /* (non-Javadoc)
706
     * @see org.cresques.io.GeoRasterFile#updateImage(int, int, org.cresques.cts.ICoordTrans, java.awt.Image, int origBand, int destBand)
707
     */
708
    public Image updateImage(int width, int height, ICoordTrans rp, Image img,
709
                             int origBand, int destBandFlag) throws SupersamplingNotSupportedException{
710
        //TODO reproyectar para devolver el trozo de imagen pedida sobre ...
711
        // la proyecci?n de destino.
712
        int line = 0;
713
        boolean mustResize = false;
714
        Dimension fullSize = null;
715
        boolean trySupersampling = false;
716

    
717
        if (file == null) {
718
            return null;
719
        }
720

    
721
        try {
722
            int[] bandlist;
723
            int[] bandListTriband;
724
            int[] pRGBArray = null;
725

    
726
            if(mustVerifySize()){
727
                    // Work out the correct aspect for the setView call.
728
                    double dFileAspect = (double) v.width() / (double) v.height();
729
                    double dWindowAspect = (double) width / (double) height;
730
        
731
                    if (dFileAspect > dWindowAspect) {
732
                        height = (int) ((double) width / dFileAspect);
733
                    } else {
734
                        width = (int) ((double) height * dFileAspect);
735
                    }
736
            }
737

    
738
            fullSize = new Dimension(width, height);
739
                        
740
            ChunkFrame[] frames = ChunkFrame.computeFrames(file, v, fullSize, extent);
741
                    
742
            if (frames.length == 1) {
743
                width = frames[0].width;
744
                height = frames[0].height;
745

    
746
                if (width <= 0)
747
                    width = 1;
748
             
749
                if (height <= 0)
750
                    height = 1;
751
            }
752
                        
753
            // Create an image of the ecw file.
754
            pRGBArray = new int[width];
755

    
756
            // Setup the view parameters for the ecw file.
757
            bandlist = new int[bandCount];
758
            bandListTriband = new int[bandCount];
759

    
760
            if (bandCount > 2) {
761
                bandlist[0] = getBand(RED_BAND);
762
                bandlist[1] = getBand(GREEN_BAND);
763
                bandlist[2] = getBand(BLUE_BAND);
764

    
765
                if (bandCount > 3) {
766
                    for (int i = 3; i < bandCount; i++) {
767
                        bandlist[i] = 0;
768
                    }
769
                }
770
            } else {
771
                for (int i = 0; i < bandCount; i++)
772
                    bandlist[i] = i;
773
            }
774

    
775
            if (bandCount == 3) {
776
                bandListTriband[0] = 0;
777
                bandListTriband[1] = 1;
778
                bandListTriband[2] = 2;
779
            }
780

    
781
            int[] mascara = new int[3];
782
            int[] shl = new int[3];
783
            int[] shr = new int[3];
784
            boolean order = true;
785
            
786
                        
787
            if (img == null) { //Caso en el que se crea un Image
788
                EcwFile.nUpdate = 1;
789

    
790
                Image ecwImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
791

    
792
                for (int nChunk = 0; nChunk < frames.length; nChunk++) {
793
                    ChunkFrame f = frames[nChunk];
794
                    
795
                    try{
796
                            if (bandCount != 3) {
797
                                setFileView(file.numBands, bandlist, f);
798
                            } else {
799
                                setFileView(file.numBands, bandListTriband, f);
800
                            }
801
                    }catch(JNCSInvalidSetViewException exc){
802
                            trySupersampling = true;
803
                    }
804

    
805
                    order = calcMaskAndShift(bandlist, mascara, shl, shr);
806

    
807
                    for (line = 0; line < f.height; line++) {
808
                        file.readLineRGBA(pRGBArray);
809
                        pRGBArray = changeBands(order, pRGBArray, mascara, shl, shr);
810
                        setRGBLine((BufferedImage) ecwImage, f.pos.x, f.pos.y + line, f.width, 1, pRGBArray, 0, f.width);
811
                    }
812
                                        
813
                } //Chuncks
814

    
815
                applyAlpha(ecwImage);
816

    
817
                if (frames[0].mustResize && !this.multifile)
818
                    return resizeAndResampleImage(fullSize, ecwImage);
819
                
820
                lastRefreshPercent = file.getPercentComplete();
821

    
822
                //System.out.println("Leido al "+lastRefreshPercent+" %.");
823
                return ecwImage;
824
            } else { //Caso en el que se actualiza una banda del Image
825
                EcwFile.nUpdate++;
826

    
827
                for (int nChunk = 0; nChunk < frames.length; nChunk++) {
828
                    ChunkFrame f = frames[nChunk];
829

    
830
                    if (bandCount != 3) {
831
                        setFileView(file.numBands, bandlist, f);
832
                    } else {
833
                        setFileView(file.numBands, bandListTriband, f);
834
                    }
835

    
836
                    order = calcMaskAndShift(bandlist, mascara, shl, shr);
837
                    
838
                    for (line = 0; line < f.height; line++) {
839
                        file.readLineRGBA(pRGBArray);
840
                        pRGBArray = changeBands(order, pRGBArray, mascara, shl, shr);
841
                        setRGBLine((BufferedImage) img, f.pos.x, f.pos.y + line, f.width, 1, pRGBArray, 0, f.width, origBand, destBandFlag);
842
                    }
843
                } //Chuncks
844

    
845
                applyAlpha(img);
846

    
847
                if (frames[0].mustResize && (nUpdate == 3) && this.multifile) {
848
                    return resizeAndResampleImage(fullSize, img);
849
                }else{
850
                        isSupersampling = false;
851
                                this.stepArrayX = this.stepArrayY = null;
852
                }
853

    
854
                lastRefreshPercent = file.getPercentComplete();
855

    
856
                //System.out.println("Leido al "+lastRefreshPercent+" %.");
857
                return img;
858
            }
859
        } catch (com.ermapper.ecw.JNCSException e) { //java.lang.ArrayIndexOutOfBoundsException:
860
            bErrorOnOpen = true;
861
            System.err.println("EcwFile JNCS Error en la l?nea " + line + "/" +
862
                               height);
863
            System.err.println(e.getMessage());
864
        } catch (java.lang.ArrayIndexOutOfBoundsException e) { //:
865
            bErrorOnOpen = true;
866
            System.err.println("EcwFile ArrayIndex Error en la l?nea " + line +"/" + height);
867
            System.err.println(e.getMessage());
868
        } catch (Exception e) {
869
            bErrorOnOpen = true;
870
            errorMessage = e.getMessage();
871
            System.err.println(errorMessage);
872
            if(trySupersampling)
873
                    throw new SupersamplingNotSupportedException();
874
        }
875

    
876
        return img;
877
    }
878

    
879
        /**
880
         * Esta funci?n calcula los arrays de steps en X e Y para que cuando hay supersampleo 
881
         * se aplique el filtro solo a la esquina superior izquierda de cada pixel. 
882
         */
883
    private void calcArraySteps(int width, int height, double stepX, double stepY, double offsetX, double offsetY){
884
            isSupersampling = true;
885
            int w = (int) (Math.ceil(((double)width) * stepX) + 1);
886
            this.stepArrayX = new int[w];
887
            for (double j =  Math.abs(offsetX); j < w; j += stepX) 
888
                    stepArrayX[(int)(j)] ++;
889
            int h = (int) (Math.ceil(((double)height) * stepY) + 1);
890
            this.stepArrayY = new int[h];
891
            for (double j =  Math.abs(offsetY); j < h; j += stepY) 
892
                    stepArrayY[(int)(j)] ++;
893
        }
894

    
895
        /**
896
         * Obtiene una ventana de datos de la imagen a partir de coordenadas reales. 
897
         * No aplica supersampleo ni subsampleo sino que devuelve una matriz de igual tama?o a los
898
         * pixeles de disco. 
899
         * @param x Posici?n X superior izquierda
900
         * @param y Posici?n Y superior izquierda
901
         * @param w Ancho en coordenadas reales
902
         * @param h Alto en coordenadas reales
903
         * @param rasterBuf        Buffer de datos
904
         * @param bandList
905
         * @return Buffer de datos
906
         */
907
        public RasterBuf getWindowRaster(double x, double y, double w, double h, BandList bandList, RasterBuf rasterBuf) {                
908
                Extent selectedExtent = new Extent(x, y, x + w, y - h);
909
                setView(selectedExtent);
910
                int wPx = rasterBuf.getWidth();
911
                int hPx = rasterBuf.getHeight();
912
                try{
913
                        int[] bl = new int[3];
914
                        bl[0] = 0;bl[1] = 1;bl[2] = 2;
915
                        file.setView(file.numBands, bl, selectedExtent.minX(), selectedExtent.maxY(), selectedExtent.maxX(), selectedExtent.minY(), wPx, hPx);                        
916
                        int width = (int)((w * file.width) / extent.width());
917
                        int height = (int)((h * file.height) / extent.height());
918
                        rasterBuf = new RasterBuf(RasterBuf.TYPE_BYTE, wPx, hPx, bandList.getDrawableBandsCount(), true);
919
                        
920
                        int[] pRGBArray = new int[width];
921
                        for (int line = 0; line < rasterBuf.getHeight(); line++) {
922
                file.readLineRGBA(pRGBArray);
923
                for(int col = 0; col < pRGBArray.length; col ++){
924
                        rasterBuf.setElemByte(line, col, 0, (byte)(pRGBArray[col] & 0x000000ff));
925
                        rasterBuf.setElemByte(line, col, 1, (byte)((pRGBArray[col] & 0x0000ff00) >> 8));
926
                        rasterBuf.setElemByte(line, col, 2, (byte)((pRGBArray[col] & 0x00ff0000) >> 16));
927
                }
928
            }
929
                }catch(JNCSInvalidSetViewException exc){
930
                        exc.printStackTrace();
931
                }catch (JNCSFileNotOpenException e) {
932
                        e.printStackTrace();
933
                }catch (JNCSException ex) {
934
                        ex.printStackTrace();
935
                }
936
                
937
                return rasterBuf;
938
        }
939
        
940
        /**
941
         * Obtiene una ventana de datos de la imagen a partir de coordenadas pixel. 
942
         * No aplica supersampleo ni subsampleo sino que devuelve una matriz de igual tama?o a los
943
         * pixeles de disco. 
944
         * @param x Posici?n X superior izquierda
945
         * @param y Posici?n Y superior izquierda
946
         * @param w Ancho en coordenadas reales
947
         * @param h Alto en coordenadas reales
948
         * @param rasterBuf        Buffer de datos
949
         * @param bandList
950
         * @return Buffer de datos
951
         */
952
        public RasterBuf getWindowRaster(int x, int y, int w, int h, BandList bandList, RasterBuf rasterBuf) {
953
                double initX = file.originX + ((x * extent.width()) / file.width);
954
                double initY = file.originY - ((y * extent.height()) / file.height);
955
                double width = ((w * extent.width()) / file.width);
956
                double height = ((h * extent.height()) / file.height);
957
                return getWindowRaster(initX, initY, width, height, bandList, rasterBuf);
958
        }
959
    
960
    /**
961
     * 
962
     * @param sz
963
     * @param image
964
     * @return
965
     */
966
    private Image resizeAndResampleImage(Dimension sz, Image image) {
967
        int w = (int)sz.getWidth();
968
        int h = (int)sz.getHeight();
969
            Image buffImg = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
970
            
971
        //Desplazamiento para la X y la Y leidas. Estas tienen efecto cuando un pixel no empieza a visualizarse
972
        //justo en su esquina superior izquierda y tiene que ser cortado en la visualizaci?n.
973
       
974
        double currentViewX = (((double) file.width)/(Math.abs(extent.getMax().getX() - extent.getMin().getX())))*(v.minX()-file.originX);
975
                double currentViewY = (((double) file.height)/(Math.abs(extent.getMax().getY() - extent.getMin().getY())))*(file.originY - v.minY());
976
        double offsetX = Math.abs(currentViewX - ((int)currentViewX));
977
        double offsetY = Math.abs(currentViewY - ((int)currentViewY));
978
        
979
        int xSrc, ySrc;
980
        int decr = 2;
981

    
982
        if(v.minX() == extent.minX() || v.maxX() == extent.maxX() || v.minY() == extent.minY() || v.maxY() == extent.maxY()){
983
                decr = 0;
984
                offsetX = offsetY = 0;
985
        }
986

    
987
        double scaleW = (double)((double)(image.getWidth(null) - decr) / (double)w);
988
        double scaleH = (double)((double)(image.getHeight(null) - decr) / (double)h);
989
        this.calcArraySteps(w, h, scaleW, scaleH, offsetX, offsetY);
990
        for (int y1 = 0; y1 < h; y1++){
991
        ySrc = (int) ((y1 * scaleH) + offsetY);
992
                for (int x1 = 0; x1 < w; x1++){
993
                        xSrc = (int) ((x1 * scaleW) + offsetX);
994
                        try {
995
                                ((BufferedImage) buffImg).setRGB(x1, y1, ((BufferedImage)image).getRGB(xSrc, ySrc));
996
                        } catch (java.lang.ArrayIndexOutOfBoundsException e) {
997
                        }
998
                }
999
        }
1000
        
1001
        return buffImg;
1002
    }
1003

    
1004
    
1005
    private void applyAlpha(Image im) {
1006
        BufferedImage img = (BufferedImage) im;
1007
        int alpha = (getAlpha() & 0xff) << 24;
1008
        int w = img.getWidth();
1009
        int[] line = new int[w];
1010

    
1011
        for (int j = 0; j < img.getHeight(); j++) {
1012
            img.getRGB(0, j, w, 1, line, 0, w);
1013

    
1014
            for (int i = 0; i < w; i++)
1015
                line[i] = (alpha | (line[i] & 0x00ffffff));
1016

    
1017
            img.setRGB(0, j, w, 1, line, 0, w);
1018
        }
1019
    }
1020

    
1021
    /* (non-Javadoc)
1022
     * @see org.cresques.io.GeoRasterFile#getData(int, int)
1023
     */
1024
    public Object getData(int x, int y, int band) {
1025
        //file.readLineRGBA();
1026
        return null;
1027
    }
1028

    
1029
    /**
1030
     * Devuelve los datos de una ventana solicitada
1031
     * @param ulX        coordenada X superior izda.
1032
     * @param ulY        coordenada Y superior derecha.
1033
     * @param sizeX        tama?o en X de la ventana.
1034
     * @param sizeY tama?o en Y de la ventana.
1035
     * @param band        Banda solicitada.
1036
     */
1037
    public byte[] getWindow(int ulX, int ulY, int sizeX, int sizeY, int band) {
1038
        //TODO Nacho: Implementar getWindow de EcwFile
1039
        return null;
1040
    }
1041

    
1042
    /**
1043
     * Obtiene la zona (Norte / Sur)
1044
     * @return true si la zona es norte y false si es sur
1045
     */
1046
    public boolean getZone() {
1047
        //TODO Nacho: Implementar getZone de EcwFile
1048
        return false;
1049
    }
1050

    
1051
    /**
1052
     *Devuelve el n?mero de zona UTM
1053
     *@return N?mero de zona
1054
     */
1055
    public int getUTM() {
1056
        //                TODO Nacho: Implementar getUTM de EcwFile
1057
        return 0;
1058
    }
1059

    
1060
    /**
1061
     * Obtiene el sistema de coordenadas geograficas
1062
     * @return Sistema de coordenadas geogr?ficas
1063
     */
1064
    public String getGeogCS() {
1065
        //TODO Nacho: Implementar getGeogCS de EcwFile
1066
        return new String("");
1067
    }
1068

    
1069
    /**
1070
     * Devuelve el tama?o de bloque
1071
     * @return Tama?o de bloque
1072
     */
1073
    public int getBlockSize() {
1074
        //TODO Nacho: Implementar getBlockSize de EcwFile        
1075
        return 1;
1076
    }
1077
        
1078
    /**
1079
         * Calcula la transformaci?n que se produce sobre la vista cuando la imagen tiene un fichero .rmf
1080
         * asociado. En Ecw el origen de coordenadas en Y es el valor m?ximo y decrece hasta el m?nimo.
1081
         * @param originX Origen de la imagen en la coordenada X
1082
         * @param originY Origen de la imagen en la coordenada Y
1083
         */
1084
    public void setExtentTransform(double originX, double originY, double psX, double psY) {
1085
                
1086
        }
1087

    
1088
    /**
1089
     * Trozo de imagen (Chunk) en que se divide la consulta a la librer?a,
1090
     * para esquivar el bug#2.
1091
     *
1092
     * @author luisw
1093
     */
1094
    static class ChunkFrame {
1095
        // Ancho m?ximo (~2500 px)
1096
        final static int MAX_WIDTH = 1536;
1097

    
1098
        // Alto m?ximo (no hay l?mite)
1099
        final static int MAX_HEIGHT = 1536;
1100
        Point pos;
1101
        Extent v;
1102
        int width;
1103
        int height;
1104
        boolean mustResize = false;
1105

    
1106
        public ChunkFrame(Extent vista, int w, int h) {
1107
            v = vista;
1108
            width = w;
1109
            height = h;
1110
        }
1111

    
1112
        /**
1113
         * Calcula el array de chunks (trozos).
1114
         * @param file        Fichero ecw que hay que trocear.
1115
         * @param v Extent total de la vista.
1116
         * @param sz        Tama?o total de la vista.
1117
         * @return array de ChunkFrames.
1118
         * @throws JNCSFileNotOpenException
1119
         */
1120
        public static ChunkFrame[] computeFrames(JNCSFile file, Extent v,
1121
                                                 Dimension sz, Extent extent)
1122
                                          throws JNCSFileNotOpenException {
1123
            ChunkFrame[] frames = null;
1124
            ChunkFrame f = null;
1125

    
1126
            // Calcula el n? de chunks (filas y columnas)
1127
            int numCol = (sz.width / MAX_WIDTH);
1128

    
1129
            // Calcula el n? de chunks (filas y columnas)
1130
            int numRow = (sz.height / MAX_HEIGHT);
1131

    
1132
            if ((sz.width - (numCol * MAX_WIDTH)) > 0) {
1133
                numCol++;
1134
            }
1135

    
1136
            if ((sz.height - (numRow * MAX_HEIGHT)) > 0) {
1137
                numRow++;
1138
            }
1139

    
1140
            frames = new ChunkFrame[numCol * numRow];
1141

    
1142
            JNCSDatasetPoint ptMin = file.convertWorldToDataset(v.minX(), v.minY());
1143
            JNCSDatasetPoint ptMax = file.convertWorldToDataset(v.maxX(), v.maxY());
1144

    
1145
            //No utilizamos JNCSDatasetPoint porque siempre hace un redondeo por abajo con lo que perdemos precisi?n. En su lugar
1146
            //utilizamos currentViewM... calculado manualmente y que nos proporciona todos los decimales 
1147
            double currentViewMinX = (((double) file.width)/(Math.abs(extent.getMax().getX() - extent.getMin().getX())))*(v.minX()-file.originX);
1148
            double currentViewMaxX = (((double) file.width)/(Math.abs(extent.getMax().getX() - extent.getMin().getX())))*(v.maxX()-file.originX);
1149
                    double currentViewMinY = (((double) file.height)/(Math.abs(extent.getMax().getY() - extent.getMin().getY())))*(file.originY - v.minY());
1150
                    double currentViewMaxY = (((double) file.height)/(Math.abs(extent.getMax().getY() - extent.getMin().getY())))*(file.originY - v.maxY());
1151
                      
1152
            if ((ptMax.x - ptMin.x) < sz.width) {
1153
                numCol = numRow = 1;
1154
                frames = new ChunkFrame[numCol * numRow];
1155
                int nPixelsX = (int)Math.ceil(Math.abs(currentViewMaxX - currentViewMinX));
1156
                int nPixelsY = (int)Math.ceil(Math.abs(currentViewMaxY - currentViewMinY));
1157
                
1158
                if(v.minX() == extent.minX() || v.maxX() == extent.maxX() || v.minY() == extent.minY() || v.maxY() == extent.maxY()){
1159
                        f = frames[0] = new ChunkFrame(v, nPixelsX, nPixelsY);
1160
                        f.v = new Extent(v);
1161
                }else{
1162
                        f = frames[0] = new ChunkFrame(v, nPixelsX + 1, nPixelsY + 1);
1163
                        double pointEndWcX = v.minX() + (((nPixelsX + 1) * Math.abs(v.maxX() - v.minX())) / nPixelsX);
1164
                        double pointEndWcY = v.maxY() - (((nPixelsY + 1) * Math.abs(v.maxY() - v.minY())) / nPixelsY);
1165
                        f.v = new Extent(v.minX(), v.maxY(), pointEndWcX, pointEndWcY);
1166
                }
1167
                
1168
                f.pos = new Point(0, 0);
1169
                f.mustResize = true;
1170
            } else {
1171
                // Calcula cada chunk
1172
                double stepx = ((double) ptMax.x - ptMin.x) / sz.getWidth();
1173
                double stepy = ((double) ptMax.y - ptMin.y) / sz.getHeight();
1174
                int h = sz.height;
1175

    
1176
                for (int r = 0; r < numRow; r++) {
1177
                    int w = sz.width;
1178

    
1179
                    for (int c = 0; c < numCol; c++) {
1180
                        f = new ChunkFrame(null, -1, -1);
1181

    
1182
                        // Posici?n del chunk
1183
                        f.pos = new Point(c * MAX_WIDTH, r * MAX_HEIGHT);
1184

    
1185
                        // Tama?o del chunk
1186
                        f.width = Math.min(MAX_WIDTH, w);
1187
                        f.height = Math.min(MAX_HEIGHT, h);
1188

    
1189
                        // Extent del chunk
1190
                        int x1 = ptMin.x + (int) (f.pos.x * stepx);
1191
                        int x2 = x1 + (int) (f.width * stepx);
1192
                        int y1 = ptMax.y - (int) (f.pos.y * stepy); 
1193
                        int y2 = y1 - (int) (f.height * stepy); //ptMin.y;
1194
                        JNCSWorldPoint pt1 = file.convertDatasetToWorld(x1, y1);
1195
                        JNCSWorldPoint pt2 = file.convertDatasetToWorld(x2, y2);
1196
                        
1197
                        f.v = new Extent(pt1.x, pt1.y, pt2.x, pt2.y); // Hay que calcularlo
1198
                        frames[(r * numCol) + c] = f;
1199
                        w -= MAX_WIDTH;
1200
                    }
1201

    
1202
                    h -= MAX_HEIGHT;
1203
                }
1204
            }
1205

    
1206
            //System.out.println("Hay "+numRow+" filas y "+numCol+" columnas.");
1207
            return frames;
1208
        }
1209
    }
1210

    
1211
        public RasterBuf getWindowRaster(double minX, double minY, double maxX, double maxY, int bufWidth, int bufHeight, BandList bandList, RasterBuf rasterBuf) {
1212
                // TODO Auto-generated method stub
1213
                return null;
1214
        }
1215

    
1216
        public Point2D rasterToWorld(Point2D pt) {
1217
                // TODO Auto-generated method stub
1218
                return null;
1219
        }
1220

    
1221
        public Point2D worldToRaster(Point2D pt) {
1222
                // TODO Auto-generated method stub
1223
                return null;
1224
        }
1225

    
1226
        public RasterBuf getWindowRasterWithNoData(double x, double y, double w, double h, BandList bandList, RasterBuf rasterBuf) {
1227
                // TODO Auto-generated method stub
1228
                return null;
1229
        }
1230
}