Statistics
| Revision:

root / trunk / libraries / libRaster / src / org / gvsig / raster / grid / render / Rendering.java @ 12383

History | View | Annotate | Download (23.2 KB)

1
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
2
 *
3
 * Copyright (C) 2007 IVER T.I. and Generalitat Valenciana.
4
 *
5
 * This program is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU General Public License
7
 * as published by the Free Software Foundation; either version 2
8
 * of the License, or (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
18
 */
19
package org.gvsig.raster.grid.render;
20

    
21
import java.awt.Graphics2D;
22
import java.awt.Image;
23
import java.awt.geom.AffineTransform;
24
import java.awt.geom.NoninvertibleTransformException;
25
import java.awt.geom.Point2D;
26

    
27
import org.gvsig.raster.buffer.BufferFactory;
28
import org.gvsig.raster.dataset.IBuffer;
29
import org.gvsig.raster.dataset.properties.DatasetColorInterpretation;
30
import org.gvsig.raster.datastruct.Extent;
31
import org.gvsig.raster.datastruct.ViewPortData;
32
import org.gvsig.raster.grid.Grid;
33
import org.gvsig.raster.grid.GridTransparency;
34
import org.gvsig.raster.grid.filter.RasterFilterList;
35
/**
36
 * Esta clase se encarga de la gesti?n del dibujado de datos le?dos desde la capa
37
 * "dataaccess" sobre objetos java. Para ello necesita una fuente de datos que tipicamente
38
 * es un buffer (RasterBuffer) y un objeto que realice la funci?n de escritura de datos a
39
 * partir de un estado inicial.
40
 * Esta capa del renderizado gestiona Extents, rotaciones, tama?os de vista pero la escritura
41
 * de datos desde el buffer al objeto image es llevada a cabo por ImageDrawer.
42
 *
43
 * Par?metros de control de la visualizaci?n:
44
 * <UL>
45
 * <LI>renderBands: Orden de visualizado de las bands.</LI>
46
 * <LI>replicateBands: Para visualizaci?n de raster de una banda. Dice si se replica sobre las otras dos bandas
47
 * de visualizaci?n o se ponen a 0.</LI>
48
 * <LI>enhanced: aplicaci?n de filtro de realce</LI>
49
 * <LI>removeEnds: Eliminar extremos en el filtro de realce. Uso del segundo m?ximo y m?nimo</LI>
50
 * <LI>tailTrim: Aplicacion de recorte de colas en el realce. Es un valor decimal que representa el porcentaje del recorte entre 100.
51
 * Es decir, 0.1 significa que el recorte es de un 10%</LI>
52
 * </UL>
53
 *
54
 * @author Nacho Brodin (nachobrodin@gmail.com)
55
 */
56
public class Rendering {
57

    
58
        /**
59
         * Grid para la gesti?n del buffer
60
         */
61
        private Grid                                         grid = null;
62
        /**
63
         * Fuente de datos para el renderizado
64
         */
65
        private BufferFactory                        bufferFactory = null;
66
        /**
67
         * Contiene el ?ltimo viewPort que se asigno en una petici?n de dibujado
68
         */
69
//        private ViewPortData                         lastViewPort = null;
70
        /**
71
         * Extent completo del raster. Este contiene las coordenadas reales tanto
72
         * para un raster rotado como sin rotar. Este extent coincide con requestExtent
73
         * cuando el raster no tiene rotaci?n.
74
         */
75
        private Extent                                         extent = null;
76
        /**
77
         * Este es el extent sobre el que se ajusta una petici?n para que esta no exceda el
78
         * extent m?ximo del raster. Para un raster sin rotar ser? igual al extent
79
         * pero para un raster rotado ser? igual al extent del raster como si no
80
         * tuviera rotaci?n. Esto ha de ser as? ya que la rotaci?n solo se hace sobre la
81
         * vista y las peticiones han de hacerse en coordenadas de la imagen sin shearing
82
         * aplicado.
83
         */
84
        private Extent                                         requestExtent = null;
85
        /**
86
         * Variable usada por el draw para calcular el n?mero de pixeles a leer de un
87
         * raster rotado.
88
         */
89
        private double[]                                 adjustedRotedExtent = null;
90
        /**
91
         * Objeto sobre el cual se hace el renderizado
92
         */
93
        private Image                                         geoImage = null;
94
        /**
95
         * N?mero de bandas a renderizar y en el orden que se har?. Esto es asignado por el
96
         * usuario de la renderizaci?n.
97
         */
98
        private int[]                                        renderBands = {0, 1, 2};
99
        /**
100
         * Tiene el comportamiento cuando se tiene un raster con una. Dice si en las otras
101
         * bandas a renderizar se replica la banda existente o se ponen a 0.
102
         */
103
        private boolean                                 replicateBand = false;
104

    
105
        private ImageDrawer                                drawer = null;
106
        /**
107
         * Ultima transparencia aplicada en la visualizaci?n que es obtenida desde el grid
108
         */
109
        private GridTransparency                lastTransparency = null;
110
        /**
111
         * Lista de filtros aplicada en la renderizaci?n
112
         */
113
        private RasterFilterList                filterList = null;
114

    
115

    
116
        private IBuffer                                        lastRenderBuffer = null;
117

    
118
        /**
119
         * Constructor
120
         */
121
        public Rendering() {
122
                init();
123
        }
124

    
125
        /**
126
         * Constructor
127
         * @param grid
128
         */
129
        public Rendering(Grid grid) {
130
                this.grid = grid;
131
                extent = (Extent)grid.getGridExtent();
132
                init();
133
        }
134

    
135
        /**
136
         * Constructor
137
         * @param grid
138
         */
139
        public Rendering(BufferFactory ds) {
140
                this.bufferFactory = ds;
141
                extent = ds.getExtent();
142
                //extent = (Extent)grid.getGridExtent();
143
                init();
144
        }
145

    
146
        private void init(){
147
                drawer = new ImageDrawer();
148

    
149
                //---------------------------------------------------
150
                //INICIALIZACI?N DE LA INTERPRETACI?N DE COLOR
151

    
152
                //Inicializaci?n de la asignaci?n de bandas en el renderizado
153
                //Leemos el objeto metadata para obtener la interpretaci?n de color asociada al raster
154
                if (bufferFactory != null && bufferFactory.getMultiRasterDataset().getDatasetCount() == 1) {
155
                        DatasetColorInterpretation colorInterpr = bufferFactory.getMultiRasterDataset().getDataset(0).getColorInterpretation();
156
                        if (colorInterpr != null) {
157
                                int red = 0, green = 0, blue = 0;
158
                                if (colorInterpr.getBand(DatasetColorInterpretation.PAL_BAND) == -1) {
159
                                        if (bufferFactory.getBandCount() >= 3) {
160
                                                green = 1;
161
                                                blue = 2;
162
                                        }
163

    
164
                                        if (bufferFactory.getBandCount() == 2)
165
                                                green = blue = 1;
166

    
167
                                        if (colorInterpr.getBand(DatasetColorInterpretation.RED_BAND) != -1)
168
                                                red = colorInterpr.getBand(DatasetColorInterpretation.RED_BAND);
169
                                        if (colorInterpr.getBand(DatasetColorInterpretation.GREEN_BAND) != -1)
170
                                                green = colorInterpr.getBand(DatasetColorInterpretation.GREEN_BAND);
171
                                        if (colorInterpr.getBand(DatasetColorInterpretation.BLUE_BAND) != -1)
172
                                                blue = colorInterpr.getBand(DatasetColorInterpretation.BLUE_BAND);
173

    
174
                                        renderBands = new int[] { red, green, blue };
175
                                }
176
                        }
177
                }
178
        }
179

    
180
        /*
181
        private void pruebaFiltrado() {
182
                RasterFilterListManager filterManager = new RasterFilterListManager(grid.getFilterList());
183
                BrightnessContrastListManager bManager = (BrightnessContrastListManager) filterManager.getManagerByClass(BrightnessContrastListManager.class);
184
                bManager.addBrightnessFilter(80);
185
                grid.applyFilters();
186
        }
187
        */
188

    
189
        /**
190
         * Dibuja el raster sobre el Graphics. Para ello debemos de pasar el viewPort que corresponde a la
191
         * vista. Este viewPort es ajustado a los tama?os m?ximos y m?nimos de la imagen por la funci?n
192
         * calculateNewView. Esta funci?n tambi?n asignar? la vista a los drivers. Posteriormente se calcula
193
         * el alto y ancho de la imagen a dibujar (wImg, hImg), as? como el punto donde se va a pintar dentro
194
         * del graphics (pt). Finalmente se llama a updateImage del driver para que pinte y una vez dibujado
195
         * se pasa a trav?s de la funci?n renderizeRaster que es la encargada de aplicar la pila de filtros
196
         * sobre el Image que ha devuelto el driver.
197
         *
198
         * Para calcular en que coordenada pixel (pt) se empezar? a pintar el BufferedImage con el raster le?do
199
         * se aplica sobre la esquina superior izquierda de esta la matriz de transformaci?n del ViewPortData
200
         * pasado vp.mat.transform(pt, pt). Si el raster no est? rotado este punto es el resultante de la
201
         * funci?n calculateNewView que devuelve la petici?n ajustada al extent de la imagen (sin rotar). Si
202
         * el raster est? rotado necesitaremos para la transformaci?n el resultado de la funci?n coordULRotateRaster.
203
         * Lo que hace esta ?ltima es colocar la petici?n que ha sido puesta en coordenadas de la imagen sin rotar
204
         * (para pedir al driver de forma correcta) otra vez en coordenadas de la imagen rotada (para calcular su
205
         * posici?n de dibujado).
206
         *
207
         * Para dibujar sobre el Graphics2D el raster rotado aplicaremos la matriz de transformaci?n con los
208
         * par?metros de Shear sobre este Graphics de forma inversa. Como hemos movido el fondo tendremos que
209
         * recalcular ahora el punto donde se comienza a dibujar aplicandole la transformaci?n sobre este
210
         * at.inverseTransform(pt, pt);. Finalmente volcamos el BufferedImage sobre el Graphics volviendo a dejar
211
         * el Graphics en su posici?n original al acabar.
212
         *
213
         * @param g Graphics sobre el que se pinta
214
         * @param vp ViewPort de la extensi?n a dibujar
215
         */
216
        public synchronized void draw(Graphics2D g, ViewPortData vp) {
217
                geoImage = null;
218
                double shearX = 0;
219
                double shearY = 0;
220
                requestExtent = bufferFactory.getMultiRasterDataset().getExtentForRequest();
221

    
222
                // long t1 = new Date().getTime();
223
                // lastViewPort = vp;
224

    
225
                if ((vp.getExtent().minX() > extent.maxX()) || (vp.getExtent().minY() > extent.maxY()) || (vp.getExtent().maxX() < extent.minX()) || (vp.getExtent().maxY() < extent.minY())) {
226
                        return;
227
                }
228

    
229
                double[] adjustedExtent = calculateNewView(vp);
230
                Point2D p2d = coordULRotateRaster(adjustedExtent);
231

    
232
                double scalex = vp.mat.getScaleX();
233
                double scaley = vp.mat.getScaleY();
234

    
235
                int wImg = (int) Math.round(Math.abs((adjustedExtent[2] - adjustedExtent[0]) * scalex));
236
                int hImg = (int) Math.round(Math.abs((adjustedExtent[3] - adjustedExtent[1]) * scaley));
237
                int[] step = null;
238

    
239
                if (bufferFactory != null) {
240
                        if (lastTransparency == null)
241
                                lastTransparency = new GridTransparency(bufferFactory.getMultiRasterDataset().getTransparencyFilesStatus());
242
                        // Asignamos la banda de transparencia si existe esta
243
                        if (bufferFactory.getMultiRasterDataset().getTransparencyFilesStatus().existAlphaBand()) {
244
                                // BufferFactory bufferFactoryAlphaBand = new BufferFactory(bufferFactory.getMultiRasterDataset());
245
                                bufferFactory.setSupersamplingLoadingBuffer(false); // Desactivamos el supersampleo en la carga del buffer.
246
                                bufferFactory.setDrawableBands(new int[] { lastTransparency.getAlphaBandNumber(), -1, -1 });
247
                                bufferFactory.setAreaOfInterest(adjustedExtent[0], adjustedExtent[1], adjustedExtent[2], adjustedExtent[3], wImg, hImg);
248
                                bufferFactory.setSupersamplingLoadingBuffer(true);
249
                                lastTransparency.setAlphaBand(bufferFactory.getRasterBuf());
250
                                lastTransparency.activeTransparency();
251
                        }
252
                        bufferFactory.setSupersamplingLoadingBuffer(false); // Desactivamos el supersampleo en la carga del buffer.
253
                        // En el renderizado ser? ImageDrawer el que se encargue de esta funci?n
254
                        bufferFactory.setDrawableBands(getRenderBands());
255
                        step = bufferFactory.setAreaOfInterest(adjustedExtent[0], adjustedExtent[1], adjustedExtent[2], adjustedExtent[3], wImg, hImg);
256
                        bufferFactory.setSupersamplingLoadingBuffer(true);
257

    
258
                } else
259
                        return;
260

    
261
                grid = new Grid(bufferFactory, true);
262
                grid.setTransparency(lastTransparency);
263
                if (filterList == null)
264
                        filterList = grid.getFilterList();
265
                else
266
                        grid.setFilterList(filterList);
267

    
268
                try {
269
                        grid.applyFilters();
270
                } catch (InterruptedException e1) {
271
                }
272

    
273
                if ((wImg <= 0) || (hImg <= 0))
274
                        return;
275

    
276
                // Para la transformaci?n usamos el extent que ha ajustado la funci?n calculateNewView y no usamos
277
                // el getView porque el getView puede haber sufrido una transformaci?n en caso de que exista
278
                // fichero .rmf. En caso de no existir este fichero ser?a lo mismo aplicar la funci?n:
279
                // Point2D.Double pt = new Point2D.Double(x, y + h);
280
                int wI = wImg, hI = hImg;
281
                double[] transf = bufferFactory.getCoordsGeoTransformFile();
282
                Point2D.Double pt = null;
283
                if (transf != null && (transf[2] != 0 || transf[4] != 0)) { // Esta rotada
284
                        pt = new Point2D.Double(p2d.getX(), p2d.getY());
285
                        wImg = (int) Math.round(Math.abs((adjustedRotedExtent[2] - adjustedRotedExtent[0]) * scalex));
286
                        hImg = (int) Math.round(Math.abs((adjustedRotedExtent[3] - adjustedRotedExtent[1]) * scaley));
287
                } else { // No est? rotada
288
                        pt = new Point2D.Double(adjustedExtent[0], adjustedExtent[3]);
289
                }
290

    
291
                vp.mat.transform(pt, pt);
292

    
293
                try {
294
                        /*
295
                         * if(grid.getColorTables() != null)
296
                         * drawer.setColorTable(grid.getColorTables()[0]);
297
                         */
298
                        // Objeto con la info de paleta
299
                        lastRenderBuffer = grid.getRasterBuf();
300
                        drawer.setBuffer(lastRenderBuffer); // Buffer de datos a renderizar
301
                        lastTransparency = grid.getTransparency();
302
                        drawer.setTransparency(lastTransparency); // Objeto con la info de transparencia
303
                        drawer.setStep(step); // Desplazamiento para supersampleo
304
                        drawer.setBufferSize(wImg, hImg); // Ancho y alto del buffer
305
                        drawer.setPixelsToDrawSize(bufferFactory.getNWidth(), bufferFactory.getNHeight()); // Ancho y alto del buffer
306
                        geoImage = drawer.drawBufferOverImageObject(replicateBand, getRenderBands()); // Acci?n de renderizado
307

    
308
                        AffineTransform at = new AffineTransform();
309

    
310
                        if (transf != null && (transf[2] != 0 || transf[4] != 0)) {
311

    
312
                                // Obtenemos los par?metros de shearing
313
                                if (transf[5] != 0)
314
                                        shearX = transf[2] / transf[5];
315
                                else
316
                                        shearX = transf[2];
317
                                if (transf[1] != 0)
318
                                        shearY = transf[4] / transf[1];
319
                                else
320
                                        shearY = transf[4];
321

    
322
                                // Aplicamos el shear a la vista
323
                                at.setToShear(-shearX, -shearY);
324

    
325
                                // Escalamos en pixeles la misma cantidad que hemos le?do de m?s.
326
                                at.scale(((double) wI / (double) wImg), ((double) hI / (double) hImg));
327

    
328
                                g.transform(at);
329

    
330
                                // Aplicamos el shear inverso al punto donde se comienza a dibujar
331
                                at.inverseTransform(pt, pt);
332

    
333
                                g.drawImage(geoImage, (int) (pt.getX()), (int) (pt.getY()), null);
334
                                g.transform(at.createInverse());
335
                        } else
336
                                g.drawImage(geoImage, (int) (pt.getX()), (int) (pt.getY()), null);
337

    
338
                        // long t2 = new Date().getTime();
339
                        // System.out.println("Renderizando Raster: " + ((t2 - t1) / 1000D) + ", secs.");
340
                } catch (NoninvertibleTransformException e) {
341
                        e.printStackTrace();
342
                }
343
        }
344

    
345
        /**
346
         * Ajusta la extensi?n pasada por par?metro y que corresponde al extent de la
347
         * vista donde se va a dibujar a los valores m?ximos y m?nimos de la imagen.
348
         * Esto sirve para que la petici?n al driver nunca sobrepase los l?mites de la
349
         * imagen tratada aunque la vista donde se dibuje sea de mayor tama?o. Antes
350
         * de realizar este ajuste hay que transformar la petici?n que puede
351
         * corresponder a una imagen rotada a las coordenadas de la imagen sin rotar
352
         * ya que las peticiones al driver hay que hacerlas con estas coordenadas.
353
         * Para esto trasladamos la petici?n al origen de la imagen (esquina superior
354
         * izquierda), aplicamos la transformaci?n inversa a las cuatro esquinas
355
         * obtenidas y volvemos a trasladar a su posici?n original. Se usa la
356
         * transformaci?n inversa para trasladar un punto del raster rotado al mismo
357
         * sin rotar y la transformaci?n af?n normal para trasladar un punto sin rotar
358
         * a uno rotado.
359
         *
360
         * @param sz Extent completo de la vista donde se va a dibujar.
361
         * @param w Ancho del buffer
362
         * @param h Alto del buffer
363
         */
364
        protected double[] calculateNewView(ViewPortData vp) {
365
                Extent sz = vp.getExtent();
366
                double vx = sz.minX();
367
                double vy = sz.minY();
368
                double vx2 = sz.maxX();
369
                double vy2 = sz.maxY();
370

    
371
                // Trasladamos la petici?n si est? rotada a su posici?n sin rotar
372

    
373
                double[] transf = bufferFactory.getCoordsGeoTransformFile();
374

    
375
                if (transf != null && (transf[2] != 0 || transf[4] != 0)) {
376

    
377
                        // La transformaci?n se hace en base a una esquina que varia con el signo del pixel size.
378
                        double ptoDesplX = (transf[1] > 0) ? requestExtent.minX() : requestExtent.maxX();
379
                        double ptoDesplY = (transf[5] < 0) ? requestExtent.maxY() : requestExtent.minY();
380

    
381
                        Point2D ul = new Point2D.Double(vx - ptoDesplX, vy2 - ptoDesplY);
382
                        Point2D ur = new Point2D.Double(vx2 - ptoDesplX, vy2 - ptoDesplY);
383
                        Point2D ll = new Point2D.Double(vx - ptoDesplX, vy - ptoDesplY);
384
                        Point2D lr = new Point2D.Double(vx2 - ptoDesplX, vy - ptoDesplY);
385

    
386
                        double shearX = 0;
387
                        double shearY = 0;
388
                        if (transf[5] != 0)
389
                                shearX = transf[2] / transf[5];
390
                        else
391
                                shearX = transf[2];
392
                        if (transf[1] != 0)
393
                                shearY = transf[4] / transf[1];
394
                        else
395
                                shearY = transf[4];
396

    
397
                        AffineTransform at = new AffineTransform();
398
                        at.setToShear(shearX, shearY);
399

    
400
                        try {
401
                                at.inverseTransform(ul, ul);
402
                                at.inverseTransform(ur, ur);
403
                                at.inverseTransform(ll, ll);
404
                                at.inverseTransform(lr, lr);
405
                        } catch (NoninvertibleTransformException e) {
406
                                e.printStackTrace();
407
                        }
408

    
409
                        ul = new Point2D.Double(ul.getX() + ptoDesplX, ul.getY() + ptoDesplY);
410
                        ur = new Point2D.Double(ur.getX() + ptoDesplX, ur.getY() + ptoDesplY);
411
                        ll = new Point2D.Double(ll.getX() + ptoDesplX, ll.getY() + ptoDesplY);
412
                        lr = new Point2D.Double(lr.getX() + ptoDesplX, lr.getY() + ptoDesplY);
413

    
414
                        vx2 = Math.max(Math.max(ul.getX(), ur.getX()), Math.max(ll.getX(), lr.getX()));
415
                        vy2 = Math.max(Math.max(ul.getY(), ur.getY()), Math.max(ll.getY(), lr.getY()));
416
                        vx = Math.min(Math.min(ul.getX(), ur.getX()), Math.min(ll.getX(), lr.getX()));
417
                        vy = Math.min(Math.min(ul.getY(), ur.getY()), Math.min(ll.getY(), lr.getY()));
418
                }
419

    
420
                if (vx < requestExtent.minX())
421
                        vx = requestExtent.minX();
422

    
423
                if (vy < requestExtent.minY())
424
                        vy = requestExtent.minY();
425

    
426
                if (vx2 > requestExtent.maxX())
427
                        vx2 = requestExtent.maxX();
428

    
429
                if (vy2 > requestExtent.maxY())
430
                        vy2 = requestExtent.maxY();
431

    
432
                double[] adjustedExtent = { vx, vy, vx2, vy2 };
433
                return adjustedExtent;
434
        }
435

    
436
        /**
437
         * Transforma la petici?n que est? en coordenadas de la imagen sin rotar a
438
         * coordenadas de la imagen rotada para que sea posible el calculo de la caja
439
         * m?nima de inclusi?n. La coordenada superior izquierda de esta ser? la que
440
         * se use para posicionar la imagen sobre el graphics aplicandole la
441
         * transformaci?n de la la vista.
442
         *
443
         * @param v
444
         * @return
445
         */
446
        private Point2D coordULRotateRaster(double[] v) {
447
                double vx = v[0];
448
                double vy = v[1];
449
                double vx2 = v[2];
450
                double vy2 = v[3];
451

    
452
                double[] transf = bufferFactory.getCoordsGeoTransformFile();
453

    
454
                if (transf != null && (transf[2] != 0 || transf[4] != 0)) {
455
                        // La transformaci?n se hace en base a una esquina que varia con el signo
456
                        // del
457
                        // pixel size.
458
                        double ptoDesplX = (transf[1] > 0) ? requestExtent.minX() : requestExtent.maxX();
459
                        double ptoDesplY = (transf[5] < 0) ? requestExtent.maxY() : requestExtent.minY();
460

    
461
                        Point2D ul = new Point2D.Double(vx - ptoDesplX, vy2 - ptoDesplY);
462
                        Point2D ur = new Point2D.Double(vx2 - ptoDesplX, vy2 - ptoDesplY);
463
                        Point2D ll = new Point2D.Double(vx - ptoDesplX, vy - ptoDesplY);
464
                        Point2D lr = new Point2D.Double(vx2 - ptoDesplX, vy - ptoDesplY);
465

    
466
                        double shearX = 0;
467
                        double shearY = 0;
468

    
469
                        if (transf[5] != 0)
470
                                shearX = transf[2] / transf[5];
471
                        else
472
                                shearX = transf[2];
473
                        if (transf[1] != 0)
474
                                shearY = transf[4] / transf[1];
475
                        else
476
                                shearY = transf[4];
477

    
478
                        AffineTransform at = new AffineTransform();
479
                        at.setToShear(shearX, shearY);
480

    
481
                        at.transform(ul, ul);
482
                        at.transform(ur, ur);
483
                        at.transform(ll, ll);
484
                        at.transform(lr, lr);
485

    
486
                        ul = new Point2D.Double(ul.getX() + ptoDesplX, ul.getY() + ptoDesplY);
487
                        ur = new Point2D.Double(ur.getX() + ptoDesplX, ur.getY() + ptoDesplY);
488
                        ll = new Point2D.Double(ll.getX() + ptoDesplX, ll.getY() + ptoDesplY);
489
                        lr = new Point2D.Double(lr.getX() + ptoDesplX, lr.getY() + ptoDesplY);
490

    
491
                        vx2 = Math.max(Math.max(ul.getX(), ur.getX()), Math.max(ll.getX(), lr.getX()));
492
                        vy2 = Math.max(Math.max(ul.getY(), ur.getY()), Math.max(ll.getY(), lr.getY()));
493
                        vx = Math.min(Math.min(ul.getX(), ur.getX()), Math.min(ll.getX(), lr.getX()));
494
                        vy = Math.min(Math.min(ul.getY(), ur.getY()), Math.min(ll.getY(), lr.getY()));
495
                        adjustedRotedExtent = new double[4];
496
                        adjustedRotedExtent[0] = vx;
497
                        adjustedRotedExtent[1] = vy;
498
                        adjustedRotedExtent[2] = vx2;
499
                        adjustedRotedExtent[3] = vy2;
500
                        return ul;
501
                }
502
                return null;
503
        }
504

    
505
        /**
506
         * Obtiene el n?mero de bandas y el orden de renderizado. Cada posici?n del
507
         * vector es una banda del buffer y el contenido de esa posici?n es la banda
508
         * de la imagen que se dibujar? sobre ese buffer. A la hora de renderizar hay
509
         * que tener en cuenta que solo se renderizan las tres primeras bandas del
510
         * buffer por lo que solo se tienen en cuenta los tres primeros elementos. Por
511
         * ejemplo, el array {1, 0, 3} dibujar? sobre el Graphics las bandas 1,0 y 3
512
         * de un raster de al menos 4 bandas. La notaci?n con -1 en alguna posici?n
513
         * del vector solo tiene sentido en la visualizaci?n pero no se puede as?gnar
514
         * una banda del buffer a null. Algunos ejemplos:
515
         * <P>
516
         * {-1, 0, -1} Dibuja la banda 0 del raster en la G de la visualizaci?n. Si
517
         * replicateBand es true R = G = B sino R = B = 0 {1, 0, 3} La R = banda 1 del
518
         * raster, G = 0 y B = 3 {0} La R = banda 0 del raster. Si replicateBand es
519
         * true R = G = B sino G = B = 0
520
         * </P>
521
         *
522
         * @return bandas y su posici?n
523
         */
524
        public int[] getRenderBands() {
525
                return renderBands;
526
        }
527

    
528
        /**
529
                 * Asigna el n?mero de bandas y el orden de renderizado. Cada posici?n del vector es una banda
530
         * del buffer y el contenido de esa posici?n es la banda de la imagen que se dibujar?
531
         * sobre ese buffer. A la hora de renderizar hay que tener en cuenta que solo se renderizan las
532
         * tres primeras bandas del buffer por lo que solo se tienen en cuenta los tres primeros
533
         * elementos. Por ejemplo, el array {1, 0, 3} dibujar? sobre el Graphics las bandas 1,0 y 3 de un
534
         * raster que tiene al menos 4 bandas. La notaci?n con -1 en alguna posici?n del vector solo tiene sentido
535
         * en la visualizaci?n pero no se puede as?gnar una banda del buffer a null.
536
         * Algunos ejemplos:
537
         * <P>
538
         * {-1, 0, -1} Dibuja la banda 0 del raster en la G de la visualizaci?n.
539
         * Si replicateBand es true R = G = B sino R = B = 0
540
         * {1, 0, 3} La R = banda 1 del raster, G = 0 y B = 3
541
         * {0} La R = banda 0 del raster. Si replicateBand es true R = G = B sino G = B = 0
542
         * </P>
543
         *
544
         *
545
                 * @param renderBands: bandas y su posici?n
546
                 */
547
        public void setRenderBands(int[] renderBands) {
548
                this.renderBands = renderBands;
549
        }
550

    
551
        /**
552
         * Dado que la notaci?n de bandas para renderizado admite posiciones con -1 y la notaci?n del
553
         * buffer no ya que no tendria sentido. Esta funci?n adapta la primera notaci?n a la segunda
554
         * para realizar la petici?n setAreaOfInterest y cargar el buffer.
555
         * @param b Array que indica la posici?n de bandas para el renderizado
556
         * @return Array que indica la posici?n de bandas para la petici?n
557
         */
558
        public int[] formatArrayRenderBand(int[] b) {
559
                int cont = 0;
560
                for(int i = 0; i < b.length; i++)
561
                        if(b[i] >= 0)
562
                                cont ++;
563
                if(cont <= 0)
564
                        return null;
565
                int[] out = new int[cont];
566
                int pos = 0;
567
                for(int i = 0; i < cont; i++) {
568
                        while(b[pos] == -1)
569
                                pos ++;
570
                        out[i] = b[pos];
571
                        pos ++;
572
                }
573
                return out;
574
        }
575

    
576
        /**
577
         * Obtiene el ?ltimo objeto transparencia aplicado en la renderizaci?n
578
         * @return GridTransparency
579
         */
580
        public GridTransparency getLastTransparency() {
581
                return lastTransparency;
582
        }
583

    
584
        /**
585
         * Obtiene las lista de filtros aplicados en la renderizaci?n
586
         * @return RasterFilterList
587
         */
588
        public RasterFilterList getFilterList() {
589
                return filterList;
590
        }
591

    
592
        /**
593
         * Obtiene el ?ltimo buffer renderizado.
594
         * @return IBuffer
595
         */
596
        public IBuffer getLastRenderBuffer() {
597
                return this.lastRenderBuffer;
598
        }
599

    
600
        /**
601
         * Asigna la lista de filtros que se usar? en el renderizado
602
         * @param RasterFilterList
603
         */
604
        public void setFilterList(RasterFilterList filterList) {
605
                this.filterList = filterList;
606
        }
607

    
608
        /**
609
         * Informa de si el raster tiene tabla de color asociada o no.
610
         * @return true si tiene tabla de color y false si no la tiene.
611
         */
612
        public boolean existColorTable() {
613
                        return (grid.getPalettes() != null && grid.getPalettes()[0] != null);
614
        }
615
}