Statistics
| Revision:

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

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
                setStep(stepArrayX, stepArrayY);
765

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

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

    
782
            int[] mascara = new int[3];
783
            int[] shl = new int[3];
784
            int[] shr = new int[3];
785
            boolean order = true;
786

    
787

    
788
            if (img == null) { //Caso en el que se crea un Image
789
                EcwFile.nUpdate = 1;
790
                isSupersampling = false;
791
                            this.stepArrayX = this.stepArrayY = null;
792

    
793
                Image ecwImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
794

    
795
                for (int nChunk = 0; nChunk < frames.length; nChunk++) {
796
                    ChunkFrame f = frames[nChunk];
797

    
798
                    try{
799
                            if (bandCount != 3) {
800
                                setFileView(file.numBands, bandlist, f);
801
                            } else {
802
                                setFileView(file.numBands, bandListTriband, f);
803
                            }
804
                    }catch(JNCSInvalidSetViewException exc){
805
                            trySupersampling = true;
806
                    }
807

    
808
                    order = calcMaskAndShift(bandlist, mascara, shl, shr);
809

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

    
816
                } //Chuncks
817

    
818
                applyAlpha(ecwImage);
819

    
820
                if (frames[0].mustResize && !this.multifile)
821
                    return resizeAndResampleImage(fullSize, ecwImage);
822

    
823
                lastRefreshPercent = file.getPercentComplete();
824

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

    
830
                for (int nChunk = 0; nChunk < frames.length; nChunk++) {
831
                    ChunkFrame f = frames[nChunk];
832

    
833
                    if (bandCount != 3) {
834
                        setFileView(file.numBands, bandlist, f);
835
                    } else {
836
                        setFileView(file.numBands, bandListTriband, f);
837
                    }
838

    
839
                    order = calcMaskAndShift(bandlist, mascara, shl, shr);
840

    
841
                    for (line = 0; line < f.height; line++) {
842
                        file.readLineRGBA(pRGBArray);
843
                        pRGBArray = changeBands(order, pRGBArray, mascara, shl, shr);
844
                        setRGBLine((BufferedImage) img, f.pos.x, f.pos.y + line, f.width, 1, pRGBArray, 0, f.width, origBand, destBandFlag);
845
                    }
846
                } //Chuncks
847

    
848
                applyAlpha(img);
849

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

    
857
                lastRefreshPercent = file.getPercentComplete();
858

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

    
879
        return img;
880
    }
881

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

    
898
        /**
899
         * Obtiene una ventana de datos de la imagen a partir de coordenadas reales.
900
         * No aplica supersampleo ni subsampleo sino que devuelve una matriz de igual tama?o a los
901
         * pixeles de disco.
902
         * @param x Posici?n X superior izquierda
903
         * @param y Posici?n Y superior izquierda
904
         * @param w Ancho en coordenadas reales
905
         * @param h Alto en coordenadas reales
906
         * @param rasterBuf        Buffer de datos
907
         * @param bandList
908
         * @return Buffer de datos
909
         */
910
        public RasterBuf getWindowRaster(double x, double y, double w, double h, BandList bandList, RasterBuf rasterBuf) {
911
                Extent selectedExtent = new Extent(x, y, x + w, y - h);
912
                setView(selectedExtent);
913
                int wPx = rasterBuf.getWidth();
914
                int hPx = rasterBuf.getHeight();
915
                try{
916
                        int[] bl = new int[3];
917
                        bl[0] = 0;bl[1] = 1;bl[2] = 2;
918
                        file.setView(file.numBands, bl, selectedExtent.minX(), selectedExtent.maxY(), selectedExtent.maxX(), selectedExtent.minY(), wPx, hPx);
919
                        int width = (int)((w * file.width) / extent.width());
920
                        int height = (int)((h * file.height) / extent.height());
921
//                        rasterBuf = new RasterBuf(RasterBuf.TYPE_BYTE, wPx, hPx, bandList.getDrawableBandsCount(), true);
922
                        // Este driver requiere escribir las 3 bandas, el proceso que las solicito ya utilizar? lo que
923
                        // necesite
924
                        rasterBuf = new RasterBuf(RasterBuf.TYPE_BYTE, wPx, hPx, 3, true);
925

    
926
                        int[] pRGBArray = new int[width];
927
                        for (int line = 0; line < rasterBuf.getHeight(); line++) {
928
                file.readLineRGBA(pRGBArray);
929
                for(int col = 0; col < pRGBArray.length; col ++){
930
                        rasterBuf.setElemByte(line, col, 0, (byte)(pRGBArray[col] & 0x000000ff));
931
                        rasterBuf.setElemByte(line, col, 1, (byte)((pRGBArray[col] & 0x0000ff00) >> 8));
932
                        rasterBuf.setElemByte(line, col, 2, (byte)((pRGBArray[col] & 0x00ff0000) >> 16));
933
                }
934
            }
935
                }catch(JNCSInvalidSetViewException exc){
936
                        exc.printStackTrace();
937
                }catch (JNCSFileNotOpenException e) {
938
                        e.printStackTrace();
939
                }catch (JNCSException ex) {
940
                        ex.printStackTrace();
941
                }
942

    
943
                return rasterBuf;
944
        }
945

    
946
        /**
947
         * Obtiene una ventana de datos de la imagen a partir de coordenadas pixel.
948
         * No aplica supersampleo ni subsampleo sino que devuelve una matriz de igual tama?o a los
949
         * pixeles de disco.
950
         * @param x Posici?n X superior izquierda
951
         * @param y Posici?n Y superior izquierda
952
         * @param w Ancho en coordenadas reales
953
         * @param h Alto en coordenadas reales
954
         * @param rasterBuf        Buffer de datos
955
         * @param bandList
956
         * @return Buffer de datos
957
         */
958
        public RasterBuf getWindowRaster(int x, int y, int w, int h, BandList bandList, RasterBuf rasterBuf) {
959
                double initX = file.originX + ((x * extent.width()) / file.width);
960
                double initY = file.originY - ((y * extent.height()) / file.height);
961
                double width = ((w * extent.width()) / file.width);
962
                double height = ((h * extent.height()) / file.height);
963
                return getWindowRaster(initX, initY, width, height, bandList, rasterBuf);
964
        }
965

    
966
    /**
967
     *
968
     * @param sz
969
     * @param image
970
     * @return
971
     */
972
    private Image resizeAndResampleImage(Dimension sz, Image image) {
973
        int w = (int)sz.getWidth();
974
        int h = (int)sz.getHeight();
975
            Image buffImg = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
976

    
977
        //Desplazamiento para la X y la Y leidas. Estas tienen efecto cuando un pixel no empieza a visualizarse
978
        //justo en su esquina superior izquierda y tiene que ser cortado en la visualizaci?n.
979

    
980
        double currentViewX = (((double) file.width)/(Math.abs(extent.getMax().getX() - extent.getMin().getX())))*(v.minX()-file.originX);
981
                double currentViewY = (((double) file.height)/(Math.abs(extent.getMax().getY() - extent.getMin().getY())))*(file.originY - v.minY());
982
        double offsetX = Math.abs(currentViewX - ((int)currentViewX));
983
        double offsetY = Math.abs(currentViewY - ((int)currentViewY));
984

    
985
        int xSrc, ySrc;
986
        int decr = 2;
987

    
988
        if(v.minX() == extent.minX() || v.maxX() == extent.maxX() || v.minY() == extent.minY() || v.maxY() == extent.maxY()){
989
                decr = 0;
990
                offsetX = offsetY = 0;
991
        }
992

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

    
1007
        return buffImg;
1008
    }
1009

    
1010

    
1011
    private void applyAlpha(Image im) {
1012
        BufferedImage img = (BufferedImage) im;
1013
        int alpha = (getAlpha() & 0xff) << 24;
1014
        int w = img.getWidth();
1015
        int[] line = new int[w];
1016

    
1017
        for (int j = 0; j < img.getHeight(); j++) {
1018
            img.getRGB(0, j, w, 1, line, 0, w);
1019

    
1020
            for (int i = 0; i < w; i++)
1021
                line[i] = (alpha | (line[i] & 0x00ffffff));
1022

    
1023
            img.setRGB(0, j, w, 1, line, 0, w);
1024
        }
1025
    }
1026

    
1027
    /* (non-Javadoc)
1028
     * @see org.cresques.io.GeoRasterFile#getData(int, int)
1029
     */
1030
    public Object getData(int x, int y, int band) {
1031
        //file.readLineRGBA();
1032
        return null;
1033
    }
1034

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

    
1048
    /**
1049
     * Obtiene la zona (Norte / Sur)
1050
     * @return true si la zona es norte y false si es sur
1051
     */
1052
    public boolean getZone() {
1053
        //TODO Nacho: Implementar getZone de EcwFile
1054
        return false;
1055
    }
1056

    
1057
    /**
1058
     *Devuelve el n?mero de zona UTM
1059
     *@return N?mero de zona
1060
     */
1061
    public int getUTM() {
1062
        //                TODO Nacho: Implementar getUTM de EcwFile
1063
        return 0;
1064
    }
1065

    
1066
    /**
1067
     * Obtiene el sistema de coordenadas geograficas
1068
     * @return Sistema de coordenadas geogr?ficas
1069
     */
1070
    public String getGeogCS() {
1071
        //TODO Nacho: Implementar getGeogCS de EcwFile
1072
        return new String("");
1073
    }
1074

    
1075
    /**
1076
     * Devuelve el tama?o de bloque
1077
     * @return Tama?o de bloque
1078
     */
1079
    public int getBlockSize() {
1080
        //TODO Nacho: Implementar getBlockSize de EcwFile
1081
        return 1;
1082
    }
1083

    
1084
    /**
1085
         * Calcula la transformaci?n que se produce sobre la vista cuando la imagen tiene un fichero .rmf
1086
         * asociado. En Ecw el origen de coordenadas en Y es el valor m?ximo y decrece hasta el m?nimo.
1087
         * @param originX Origen de la imagen en la coordenada X
1088
         * @param originY Origen de la imagen en la coordenada Y
1089
         */
1090
    public void setExtentTransform(double originX, double originY, double psX, double psY) {
1091

    
1092
        }
1093

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

    
1104
        // Alto m?ximo (no hay l?mite)
1105
        final static int MAX_HEIGHT = 1536;
1106
        Point pos;
1107
        Extent v;
1108
        int width;
1109
        int height;
1110
        boolean mustResize = false;
1111

    
1112
        public ChunkFrame(Extent vista, int w, int h) {
1113
            v = vista;
1114
            width = w;
1115
            height = h;
1116
        }
1117

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

    
1132
            // Calcula el n? de chunks (filas y columnas)
1133
            int numCol = (sz.width / MAX_WIDTH);
1134

    
1135
            // Calcula el n? de chunks (filas y columnas)
1136
            int numRow = (sz.height / MAX_HEIGHT);
1137

    
1138
            if ((sz.width - (numCol * MAX_WIDTH)) > 0) {
1139
                numCol++;
1140
            }
1141

    
1142
            if ((sz.height - (numRow * MAX_HEIGHT)) > 0) {
1143
                numRow++;
1144
            }
1145

    
1146
            frames = new ChunkFrame[numCol * numRow];
1147

    
1148
            JNCSDatasetPoint ptMin = file.convertWorldToDataset(v.minX(), v.minY());
1149
            JNCSDatasetPoint ptMax = file.convertWorldToDataset(v.maxX(), v.maxY());
1150

    
1151
            //No utilizamos JNCSDatasetPoint porque siempre hace un redondeo por abajo con lo que perdemos precisi?n. En su lugar
1152
            //utilizamos currentViewM... calculado manualmente y que nos proporciona todos los decimales
1153
            double currentViewMinX = (((double) file.width)/(Math.abs(extent.getMax().getX() - extent.getMin().getX())))*(v.minX()-file.originX);
1154
            double currentViewMaxX = (((double) file.width)/(Math.abs(extent.getMax().getX() - extent.getMin().getX())))*(v.maxX()-file.originX);
1155
                    double currentViewMinY = (((double) file.height)/(Math.abs(extent.getMax().getY() - extent.getMin().getY())))*(file.originY - v.minY());
1156
                    double currentViewMaxY = (((double) file.height)/(Math.abs(extent.getMax().getY() - extent.getMin().getY())))*(file.originY - v.maxY());
1157

    
1158
            if ((ptMax.x - ptMin.x) < sz.width) {
1159
                numCol = numRow = 1;
1160
                frames = new ChunkFrame[numCol * numRow];
1161
                int nPixelsX = (int)Math.ceil(Math.abs(currentViewMaxX - currentViewMinX));
1162
                int nPixelsY = (int)Math.ceil(Math.abs(currentViewMaxY - currentViewMinY));
1163

    
1164
                if(v.minX() == extent.minX() || v.maxX() == extent.maxX() || v.minY() == extent.minY() || v.maxY() == extent.maxY()){
1165
                        f = frames[0] = new ChunkFrame(v, nPixelsX, nPixelsY);
1166
                        f.v = new Extent(v);
1167
                }else{
1168
                        f = frames[0] = new ChunkFrame(v, nPixelsX + 1, nPixelsY + 1);
1169
                        double pointEndWcX = v.minX() + (((nPixelsX + 1) * Math.abs(v.maxX() - v.minX())) / nPixelsX);
1170
                        double pointEndWcY = v.maxY() - (((nPixelsY + 1) * Math.abs(v.maxY() - v.minY())) / nPixelsY);
1171
                        f.v = new Extent(v.minX(), v.maxY(), pointEndWcX, pointEndWcY);
1172
                }
1173

    
1174
                f.pos = new Point(0, 0);
1175
                f.mustResize = true;
1176
            } else {
1177
                // Calcula cada chunk
1178
                double stepx = ((double) ptMax.x - ptMin.x) / sz.getWidth();
1179
                double stepy = ((double) ptMax.y - ptMin.y) / sz.getHeight();
1180
                int h = sz.height;
1181

    
1182
                for (int r = 0; r < numRow; r++) {
1183
                    int w = sz.width;
1184

    
1185
                    for (int c = 0; c < numCol; c++) {
1186
                        f = new ChunkFrame(null, -1, -1);
1187

    
1188
                        // Posici?n del chunk
1189
                        f.pos = new Point(c * MAX_WIDTH, r * MAX_HEIGHT);
1190

    
1191
                        // Tama?o del chunk
1192
                        f.width = Math.min(MAX_WIDTH, w);
1193
                        f.height = Math.min(MAX_HEIGHT, h);
1194

    
1195
                        // Extent del chunk
1196
                        int x1 = ptMin.x + (int) (f.pos.x * stepx);
1197
                        int x2 = x1 + (int) (f.width * stepx);
1198
                        int y1 = ptMax.y - (int) (f.pos.y * stepy);
1199
                        int y2 = y1 - (int) (f.height * stepy); //ptMin.y;
1200
                        JNCSWorldPoint pt1 = file.convertDatasetToWorld(x1, y1);
1201
                        JNCSWorldPoint pt2 = file.convertDatasetToWorld(x2, y2);
1202

    
1203
                        f.v = new Extent(pt1.x, pt1.y, pt2.x, pt2.y); // Hay que calcularlo
1204
                        frames[(r * numCol) + c] = f;
1205
                        w -= MAX_WIDTH;
1206
                    }
1207

    
1208
                    h -= MAX_HEIGHT;
1209
                }
1210
            }
1211

    
1212
            //System.out.println("Hay "+numRow+" filas y "+numCol+" columnas.");
1213
            return frames;
1214
        }
1215
    }
1216

    
1217
        public RasterBuf getWindowRaster(double minX, double minY, double maxX, double maxY, int bufWidth, int bufHeight, BandList bandList, RasterBuf rasterBuf) {
1218
                // TODO Auto-generated method stub
1219
                return null;
1220
        }
1221

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

    
1227
        public Point2D worldToRaster(Point2D pt) {
1228
                // TODO Auto-generated method stub
1229
                return null;
1230
        }
1231

    
1232
        public RasterBuf getWindowRasterWithNoData(double x, double y, double w, double h, BandList bandList, RasterBuf rasterBuf) {
1233
                // TODO Auto-generated method stub
1234
                return null;
1235
        }
1236
}