Statistics
| Revision:

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

History | View | Annotate | Download (24.9 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.Dimension;
22
import java.awt.Graphics2D;
23
import java.awt.Image;
24
import java.awt.geom.AffineTransform;
25
import java.awt.geom.NoninvertibleTransformException;
26
import java.awt.geom.Point2D;
27
import java.util.ArrayList;
28

    
29
import org.gvsig.raster.buffer.BufferFactory;
30
import org.gvsig.raster.dataset.IBuffer;
31
import org.gvsig.raster.dataset.IRasterDataSource;
32
import org.gvsig.raster.dataset.InvalidSetViewException;
33
import org.gvsig.raster.dataset.io.RasterDriverException;
34
import org.gvsig.raster.dataset.properties.DatasetColorInterpretation;
35
import org.gvsig.raster.datastruct.Extent;
36
import org.gvsig.raster.datastruct.Transparency;
37
import org.gvsig.raster.datastruct.ViewPortData;
38
import org.gvsig.raster.grid.Grid;
39
import org.gvsig.raster.grid.GridTransparency;
40
import org.gvsig.raster.grid.filter.FilterListChangeEvent;
41
import org.gvsig.raster.grid.filter.FilterListChangeListener;
42
import org.gvsig.raster.grid.filter.RasterFilter;
43
import org.gvsig.raster.grid.filter.RasterFilterList;
44
import org.gvsig.raster.grid.filter.bands.ColorTableFilter;
45
import org.gvsig.raster.util.Cancellable;
46
import org.gvsig.raster.util.PropertyEvent;
47
import org.gvsig.raster.util.PropertyListener;
48
import org.gvsig.raster.util.RasterUtilities;
49

    
50
/**
51
 * Esta clase se encarga de la gesti?n del dibujado de datos le?dos desde la capa
52
 * "dataaccess" sobre objetos java. Para ello necesita una fuente de datos que tipicamente
53
 * es un buffer (RasterBuffer) y un objeto que realice la funci?n de escritura de datos a
54
 * partir de un estado inicial.
55
 * Esta capa del renderizado gestiona Extents, rotaciones, tama?os de vista pero la escritura
56
 * de datos desde el buffer al objeto image es llevada a cabo por ImageDrawer.
57
 *
58
 * Par?metros de control de la visualizaci?n:
59
 * <UL>
60
 * <LI>renderBands: Orden de visualizado de las bands.</LI>
61
 * <LI>replicateBands: Para visualizaci?n de raster de una banda. Dice si se replica sobre las otras dos bandas
62
 * de visualizaci?n o se ponen a 0.</LI>
63
 * <LI>enhanced: aplicaci?n de filtro de realce</LI>
64
 * <LI>removeEnds: Eliminar extremos en el filtro de realce. Uso del segundo m?ximo y m?nimo</LI>
65
 * <LI>tailTrim: Aplicacion de recorte de colas en el realce. Es un valor decimal que representa el porcentaje del recorte entre 100.
66
 * Es decir, 0.1 significa que el recorte es de un 10%</LI>
67
 * </UL>
68
 *
69
 * @author Nacho Brodin (nachobrodin@gmail.com)
70
 */
71
public class Rendering implements PropertyListener, FilterListChangeListener {
72

    
73
        /**
74
         * Grid para la gesti?n del buffer
75
         */
76
        private Grid             grid                     = null;
77
        /**
78
         * Fuente de datos para el renderizado
79
         */
80
        private BufferFactory    bufferFactory            = null;
81
        /**
82
         * N?mero de bandas a renderizar y en el orden que se har?. Esto es asignado
83
         * por el usuario de la renderizaci?n.
84
         */
85
        private int[]            renderBands              = { 0, 1, 2 };
86
        /**
87
         * Tiene el comportamiento cuando se tiene un raster con una. Dice si en las
88
         * otras bandas a renderizar se replica la banda existente o se ponen a 0.
89
         */
90
        private boolean          replicateBand            = false;
91

    
92
        private ImageDrawer      drawer                   = null;
93
        /**
94
         * Ultima transparencia aplicada en la visualizaci?n que es obtenida desde el
95
         * grid
96
         */
97
        private GridTransparency lastTransparency         = null;
98
        /**
99
         * Lista de filtros aplicada en la renderizaci?n
100
         */
101
        private RasterFilterList filterList               = null;
102

    
103
        private IBuffer          lastRenderBuffer         = null;
104

    
105
        /**
106
         * Ancho y alto del objeto Image en una petici?n de dibujado a un raster
107
         * raster
108
         */
109
        private double           widthImage, heightImage;
110

    
111
        private Point2D          ulPxRequest, lrPxRequest;
112
        
113
        /**
114
         * Array de listeners que ser?n informados cuando cambia una propiedad en la visualizaci?n
115
         */
116
        private ArrayList        visualPropertyListener   = new ArrayList();
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
                init();
132
        }
133

    
134
        /**
135
         * Constructor
136
         * @param grid
137
         */
138
        public Rendering(BufferFactory ds) {
139
                this.bufferFactory = ds;
140
                init();
141
        }
142

    
143
        private void init() {
144
                drawer = new ImageDrawer(this);
145
                
146
                if (bufferFactory == null) {
147
                        setRenderBands(new int[] { 0, 1, 2 });
148
                        return;
149
                }
150

    
151
                //Bandas que se dibujan por defecto si la interpretaci?n de color no tiene valores
152
                switch (bufferFactory.getDataSource().getBandCount()) {
153
                        case 1:
154
                                setRenderBands(new int[] { 0, 0, 0 });
155
                                break;
156
                        case 2:
157
                                setRenderBands(new int[] { 0, 1, 1 });
158
                                break;
159
                        default:
160
                                setRenderBands(new int[] { 0, 1, 2 });
161
                                break;
162
                }
163
                        
164
                //---------------------------------------------------
165
                //INICIALIZACI?N DE LA INTERPRETACI?N DE COLOR
166

    
167
                //Inicializaci?n de la asignaci?n de bandas en el renderizado
168
                //Leemos el objeto metadata para obtener la interpretaci?n de color asociada al raster
169
                if (bufferFactory.getDataSource().getDatasetCount() == 1) {
170
                        DatasetColorInterpretation colorInterpr = bufferFactory.getDataSource().getColorInterpretation();
171
                        if (colorInterpr != null) {
172
                                if (colorInterpr.getBand(DatasetColorInterpretation.PAL_BAND) == -1) {
173
                                        if (colorInterpr.isUndefined())
174
                                                return;
175
                                        int[] result = new int[] { -1, -1, -1 };
176
                                        int gray = colorInterpr.getBand(DatasetColorInterpretation.GRAY_BAND);
177
                                        if (gray != -1) {
178
                                                result[0] = result[1] = result[2] = gray;
179
                                        } else {
180
                                                int r = colorInterpr.getBand(DatasetColorInterpretation.RED_BAND);
181
                                                if (r != -1)
182
                                                        result[0] = r;
183
                                                int g = colorInterpr.getBand(DatasetColorInterpretation.GREEN_BAND);
184
                                                if (g != -1)
185
                                                        result[1] = g;
186
                                                int b = colorInterpr.getBand(DatasetColorInterpretation.BLUE_BAND);
187
                                                if (b != -1)
188
                                                        result[2] = b;
189
                                        }
190
                                        setRenderBands(result);
191
                                }
192
                        }
193
                }
194
        }
195
        
196
        /**
197
         * Asigna un listener a la lista que ser? informado cuando cambie una
198
         * propiedad visual en la renderizaci?n. 
199
         * @param listener VisualPropertyListener
200
         */
201
        public void addVisualPropertyListener(VisualPropertyListener listener) {
202
                visualPropertyListener.add(listener);
203
        }
204
        
205
        /**
206
         * M?todo llamado cuando hay un cambio en una propiedad de visualizaci?n
207
         */
208
        private void callVisualPropertyChanged(Object obj) {
209
                for (int i = 0; i < visualPropertyListener.size(); i++) {
210
                        VisualPropertyEvent ev = new VisualPropertyEvent(obj);
211
                        ((VisualPropertyListener)visualPropertyListener.get(i)).visualPropertyValueChanged(ev);
212
                }
213
        }
214

    
215
        /**
216
         * Dibuja el raster sobre el Graphics. Para ello debemos de pasar el viewPort que corresponde a la
217
         * vista. Este viewPort es ajustado a los tama?os m?ximos y m?nimos de la imagen por la funci?n
218
         * calculateNewView. Esta funci?n tambi?n asignar? la vista a los drivers. Posteriormente se calcula
219
         * el alto y ancho de la imagen a dibujar (wImg, hImg), as? como el punto donde se va a pintar dentro
220
         * del graphics (pt). Finalmente se llama a updateImage del driver para que pinte y una vez dibujado
221
         * se pasa a trav?s de la funci?n renderizeRaster que es la encargada de aplicar la pila de filtros
222
         * sobre el Image que ha devuelto el driver.
223
         *
224
         * Para calcular en que coordenada pixel (pt) se empezar? a pintar el BufferedImage con el raster le?do
225
         * se aplica sobre la esquina superior izquierda de esta la matriz de transformaci?n del ViewPortData
226
         * pasado vp.mat.transform(pt, pt). Si el raster no est? rotado este punto es el resultante de la
227
         * funci?n calculateNewView que devuelve la petici?n ajustada al extent de la imagen (sin rotar). Si
228
         * el raster est? rotado necesitaremos para la transformaci?n el resultado de la funci?n coordULRotateRaster.
229
         * Lo que hace esta ?ltima es colocar la petici?n que ha sido puesta en coordenadas de la imagen sin rotar
230
         * (para pedir al driver de forma correcta) otra vez en coordenadas de la imagen rotada (para calcular su
231
         * posici?n de dibujado).
232
         *
233
         * Para dibujar sobre el Graphics2D el raster rotado aplicaremos la matriz de transformaci?n con los
234
         * par?metros de Shear sobre este Graphics de forma inversa. Como hemos movido el fondo tendremos que
235
         * recalcular ahora el punto donde se comienza a dibujar aplicandole la transformaci?n sobre este
236
         * at.inverseTransform(pt, pt);. Finalmente volcamos el BufferedImage sobre el Graphics volviendo a dejar
237
         * el Graphics en su posici?n original al acabar.
238
         *
239
         * @param g Graphics sobre el que se pinta
240
         * @param vp ViewPort de la extensi?n a dibujar
241
         * @param cancel 
242
         * @throws InvalidSetViewException
243
         * @throws ArrayIndexOutOfBoundsException
244
         */
245
        public synchronized Image draw(Graphics2D g, ViewPortData vp, Object cancel)
246
                throws RasterDriverException, InvalidSetViewException, InterruptedException {
247
                Image geoImage = null;
248
                if (bufferFactory == null) {
249
                        System.err.println("Rendering.java: bufferFactory = null");
250
                        return null;
251
                }
252
                Cancellable cancelWrapper = new Cancellable(cancel);
253
                IRasterDataSource dataset = bufferFactory.getDataSource();
254
                AffineTransform transf = dataset.getAffineTransform(0);
255

    
256
                if(RasterUtilities.isOutside(vp.getExtent(), dataset.getExtent()))
257
                        return null;
258

    
259
                Extent adjustedRotedRequest = request(vp, dataset);
260

    
261
                if ((widthImage <= 0) || (heightImage <= 0))
262
                        return null;
263

    
264
                double[] step = null;
265
                
266
                if (bufferFactory != null) {
267
                        if (lastTransparency == null) {
268
                                lastTransparency = new GridTransparency(bufferFactory.getDataSource().getTransparencyFilesStatus());
269
                                lastTransparency.addPropertyListener(this);
270
                        }
271
                        // Asignamos la banda de transparencia si existe esta
272
                        if (bufferFactory.getDataSource().getTransparencyFilesStatus().getAlphaBandNumber() != -1) {
273
                                bufferFactory.setSupersamplingLoadingBuffer(false); // Desactivamos el supersampleo en la carga del buffer.
274
                                bufferFactory.setDrawableBands(new int[] { lastTransparency.getAlphaBandNumber(), -1, -1 });
275
                                bufferFactory.setAreaOfInterest(adjustedRotedRequest.getULX(), adjustedRotedRequest.getULY(), adjustedRotedRequest.getLRX(), adjustedRotedRequest.getLRY(), (int)Math.round(widthImage), (int)Math.round(heightImage));
276
                                bufferFactory.setSupersamplingLoadingBuffer(true);
277
                                lastTransparency.setAlphaBand(bufferFactory.getRasterBuf());
278
                        }
279
                        bufferFactory.setSupersamplingLoadingBuffer(false); // Desactivamos el supersampleo en la carga del buffer.
280
                        // En el renderizado ser? ImageDrawer el que se encargue de esta funci?n
281
                        Thread.sleep(50); // damos tiempo a un posible interrupci?n
282
                        if (cancel != null)
283
                                if (cancelWrapper.isCanceled())
284
                                        return null;
285
                
286
                        bufferFactory.setDrawableBands(getRenderBands());
287
                        step = bufferFactory.setAreaOfInterest(adjustedRotedRequest.getULX(), adjustedRotedRequest.getULY(),
288
                                        adjustedRotedRequest.getLRX(), adjustedRotedRequest.getLRY(),
289
                                        (int)Math.round(widthImage), (int)Math.round(heightImage));
290
                        if (cancel != null)
291
                                if (cancelWrapper.isCanceled())
292
                                        return null;
293
                        
294
                        bufferFactory.setSupersamplingLoadingBuffer(true);
295
                                                
296
                        
297
                        //Asignamos los datos al objeto transparencia antes de aplicar la pila de filtros para que el valor NoData sea efectivo
298
                        if (bufferFactory.getDataSource().getTransparencyFilesStatus().isNoDataActive())
299
                                lastTransparency.setDataBuffer(bufferFactory.getRasterBuf());
300
                        else
301
                                lastTransparency.setDataBuffer(null);
302
                        lastTransparency.activeTransparency();
303
                        
304
                } else
305
                        return null;
306
                
307
                //Aplicamos los filtros
308
                grid = new Grid(bufferFactory, true);
309
                filterList.addEnvParam("Transparency", lastTransparency);
310
                grid.setFilterList(filterList);
311
                grid.applyFilters(); // Esto tambi?n consume tiempo. TODO: Revisar
312
                
313
                //Si la lista de filtros genera bandas de transparencia se mezclan con la actual 
314
                if(grid.getFilterList().getAlphaBand() != null) {
315
                        IBuffer t = grid.getFilterList().getAlphaBand();
316
                        if(lastTransparency.getAlphaBand() != null)
317
                                t = Transparency.merge(t, lastTransparency.getAlphaBand());
318
                        lastTransparency.setAlphaBand(t);
319
                        lastTransparency.activeTransparency();
320
                }
321

    
322
                //Buffer filtrado para renderizar
323
                lastRenderBuffer = grid.getRasterBuf();
324
                drawer.setBuffer(lastRenderBuffer); // Buffer de datos a renderizar
325
                drawer.setStep(step); // Desplazamiento para supersampleo
326
                drawer.setBufferSize((int)Math.round(widthImage), (int)Math.round(heightImage)); // Ancho y alto del buffer
327
                geoImage = drawer.drawBufferOverImageObject(replicateBand, getRenderBands(), cancelWrapper); // Acci?n de renderizado
328

    
329
                // Borramos el buffer de transparencia para que siempre se tenga que regenerar.
330
                lastTransparency.setAlphaBand(null);
331
                
332
                //En el caso de no tenga rotaci?n y el tama?o de pixel sea positivo en X y negativo en Y no aplicamos ninguna
333
                //transformaci?n. Esto no es necesario hacerlo, sin ello se visualiza igual. Unicamente se hace porque de esta
334
                //forma el raster resultante mejora un poco en calidad en ciertos niveles de zoom ya que al aplicar transformaciones
335
                //sobre el Graphics parece que pierde algo de calidad.
336
                if(transf.getScaleX() > 0 && transf.getScaleY() < 0 && transf.getShearX() == 0 && transf.getShearY() == 0) {
337
                        Point2D lastGraphicOffset = new Point2D.Double(adjustedRotedRequest.getULX(), adjustedRotedRequest.getULY());
338
                        vp.mat.transform(lastGraphicOffset, lastGraphicOffset);
339
                        g.drawImage(geoImage, (int) Math.round(lastGraphicOffset.getX()), (int) Math.round(lastGraphicOffset.getY()), null);
340
                        return geoImage;
341
                }
342

    
343
                /*
344
                 * Tenemos una matriz con la transformaci?n de la coordenadas de la vista a coordenadas reales vp.mat, adem?s tenemos
345
                 * la transformaci?n de coordenadas reales a coordenadas pixel (transf). Con ambas podemos obtener una matriz de trasformacion
346
                 * entre coordenadas de la vista a coordenadas pixel (transf X vp.mat). As? obtenemos la transformaci?n entre coordenadas
347
                 * de la vista y coordenadas pixel del raster. El problemas es que cada zoom la escala de la petici?n del raster varia
348
                 * por lo que habr? que calcular una matriz con la escala (escale). escale X transf X vp.mat
349
                 */
350
                double sX = Math.abs(ulPxRequest.getX() - lrPxRequest.getX()) / widthImage;
351
                double sY = Math.abs(ulPxRequest.getY() - lrPxRequest.getY()) / heightImage;
352
                AffineTransform escale = new AffineTransform(sX, 0, 0, sY, 0, 0);
353

    
354
                try {
355
                        AffineTransform at = (AffineTransform)escale.clone();
356
                        at.preConcatenate(transf);
357
                        at.preConcatenate(vp.getMat());
358
                        g.transform(at);
359
                        Point2D.Double pt = null;
360
                        //El punto sobre el que rota la imagen depende del signo de los tama?os del pixel
361
                        if(transf.getScaleX() < 0 && transf.getScaleY() < 0)
362
                                pt = new Point2D.Double(adjustedRotedRequest.maxX(), adjustedRotedRequest.maxY());
363
                        else if(transf.getScaleX() > 0 && transf.getScaleY() > 0)
364
                                pt = new Point2D.Double(adjustedRotedRequest.minX(), adjustedRotedRequest.minY());
365
                        else if(transf.getScaleX() < 0 && transf.getScaleY() > 0)
366
                                pt = new Point2D.Double(adjustedRotedRequest.maxX(), adjustedRotedRequest.minY());
367
                        else
368
                                pt = new Point2D.Double(adjustedRotedRequest.getULX(), adjustedRotedRequest.getULY());
369
                        vp.getMat().transform(pt, pt);
370
                        at.inverseTransform(pt, pt);
371
                        g.drawImage(geoImage, (int) Math.round(pt.getX()), (int) Math.round(pt.getY()), null);
372
                        g.transform(at.createInverse());
373
                } catch (NoninvertibleTransformException e) {
374
                        e.printStackTrace();
375
                }
376
                return geoImage;
377
                // long t2 = new Date().getTime();
378
                // System.out.println("Renderizando Raster: " + ((t2 - t1) / 1000D) + ", secs.");
379
        }
380

    
381
        /**
382
         * Calculamos la petici?n en coordenadas del mundo real con la transformaci?n del raster. Esto
383
         * permite obtener las coordenadas de la petici?n con la rotaci?n, si la tiene.
384
         * @param vp
385
         * @param dataset
386
         * @return
387
         */
388
        private Extent request(ViewPortData vp, IRasterDataSource dataset) {
389
                if (dataset.isRotated()) {
390
                        //Obtenemos las cuatro esquinas de la selecci?n que hemos hecho en la vista
391
                        Point2D ul = new Point2D.Double(vp.getExtent().minX(), vp.getExtent().maxY());
392
                        Point2D ur = new Point2D.Double(vp.getExtent().maxX(), vp.getExtent().maxY());
393
                        Point2D ll = new Point2D.Double(vp.getExtent().minX(), vp.getExtent().minY());
394
                        Point2D lr = new Point2D.Double(vp.getExtent().maxX(), vp.getExtent().minY());
395

    
396
                        //Las pasamos a coordenadas pixel del raster
397
                        ul = dataset.worldToRaster(ul);
398
                        ur = dataset.worldToRaster(ur);
399
                        ll = dataset.worldToRaster(ll);
400
                        lr = dataset.worldToRaster(lr);
401

    
402
                        //Obtenemos los valores pixel m?ximos y m?nimos para X e Y
403
                        double pxMaxX = Math.max(Math.max(ul.getX(), ur.getX()), Math.max(ll.getX(), lr.getX()));
404
                        double pxMaxY = Math.max(Math.max(ul.getY(), ur.getY()), Math.max(ll.getY(), lr.getY()));
405
                        double pxMinX = Math.min(Math.min(ul.getX(), ur.getX()), Math.min(ll.getX(), lr.getX()));
406
                        double pxMinY = Math.min(Math.min(ul.getY(), ur.getY()), Math.min(ll.getY(), lr.getY()));
407

    
408
                        //Ajustamos las coordenadas pixel al ?rea m?xima del raster
409
                        pxMinX = Math.max(pxMinX, 0);
410
                        pxMinY = Math.max(pxMinY, 0);
411
                        pxMaxX = Math.min(pxMaxX, dataset.getWidth());
412
                        pxMaxY = Math.min(pxMaxY, dataset.getHeight());
413

    
414
                        //Petici?n en coordenadas pixel
415
                        ulPxRequest = new Point2D.Double(pxMinX, pxMinY);
416
                        lrPxRequest = new Point2D.Double(pxMaxX, pxMaxY);
417

    
418
                        //Calculamos el ancho y alto del buffer sobre el que se escribe la petici?n
419
                        widthImage = ((Math.abs(lrPxRequest.getX() - ulPxRequest.getX()) * vp.getWidth()) / Math.abs(pxMaxX - pxMinX));
420
                        heightImage = ((Math.abs(lrPxRequest.getY() - ulPxRequest.getY()) * vp.getHeight()) / Math.abs(pxMaxY - pxMinY));
421
                        
422
                        //Convertimos la petici?n en coordenadas pixel a petici?n en coordenadas reales.
423
                        Point2D ulWC = dataset.rasterToWorld(ulPxRequest);
424
                        Point2D lrWC = dataset.rasterToWorld(lrPxRequest);
425

    
426
                        //Ajustamos la petici?n a los limites del raster, teniendo en cuenta la rotaci?n de este.
427
                        return new Extent(ulWC, lrWC);
428
                }
429
                Extent adjustedRotedExtent = RasterUtilities.calculateAdjustedView(vp.getExtent(), dataset.getAffineTransform(0), new Dimension((int)dataset.getWidth(), (int)dataset.getHeight()));
430
                widthImage = (int)Math.round(Math.abs(adjustedRotedExtent.width() * vp.getMat().getScaleX()));
431
                heightImage = (int)Math.round(Math.abs(adjustedRotedExtent.height() * vp.getMat().getScaleY()));
432
                Point2D ul = new Point2D.Double(adjustedRotedExtent.getULX(), adjustedRotedExtent.getULY());
433
                Point2D lr = new Point2D.Double(adjustedRotedExtent.getLRX(), adjustedRotedExtent.getLRY());
434
                ul = dataset.worldToRaster(ul);
435
                lr = dataset.worldToRaster(lr);
436
                ulPxRequest = new Point2D.Double(ul.getX(), ul.getY());
437
                lrPxRequest = new Point2D.Double(lr.getX(), lr.getY());
438
                return adjustedRotedExtent;
439
        }
440

    
441
        /**
442
         * Obtiene el n?mero de bandas y el orden de renderizado. Cada posici?n del
443
         * vector es una banda del buffer y el contenido de esa posici?n es la banda
444
         * de la imagen que se dibujar? sobre ese buffer. A la hora de renderizar hay
445
         * que tener en cuenta que solo se renderizan las tres primeras bandas del
446
         * buffer por lo que solo se tienen en cuenta los tres primeros elementos. Por
447
         * ejemplo, el array {1, 0, 3} dibujar? sobre el Graphics las bandas 1,0 y 3
448
         * de un raster de al menos 4 bandas. La notaci?n con -1 en alguna posici?n
449
         * del vector solo tiene sentido en la visualizaci?n pero no se puede as?gnar
450
         * una banda del buffer a null. Algunos ejemplos:
451
         * <P>
452
         * <UL>
453
         * <LI> {-1, 0, -1} Dibuja la banda 0 del raster en la G de la visualizaci?n. Si
454
         * replicateBand es true R = G = B sino R = B = 0 </LI>
455
         * <LI> {1, 0, 3} La R = banda 1 del raster, G = 0 y B = 3 </LI>
456
         * <LI> {0} La R = banda 0 del raster. Si replicateBand es true R = G = B 
457
         * sino G = B = 0</LI>
458
         * </UL>
459
         * </P>
460
         *
461
         * @return bandas y su posici?n
462
         */
463
        public int[] getRenderBands() {
464
                return renderBands;
465
        }
466

    
467
        /**
468
                 * Asigna el n?mero de bandas y el orden de renderizado. Cada posici?n del vector es una banda
469
         * del buffer y el contenido de esa posici?n es la banda de la imagen que se dibujar?
470
         * sobre ese buffer. A la hora de renderizar hay que tener en cuenta que solo se renderizan las
471
         * tres primeras bandas del buffer por lo que solo se tienen en cuenta los tres primeros
472
         * elementos. Por ejemplo, el array {1, 0, 3} dibujar? sobre el Graphics las bandas 1,0 y 3 de un
473
         * raster que tiene al menos 4 bandas. La notaci?n con -1 en alguna posici?n del vector solo tiene sentido
474
         * en la visualizaci?n pero no se puede as?gnar una banda del buffer a null.
475
         * Algunos ejemplos:
476
         * <P>
477
         * {-1, 0, -1} Dibuja la banda 0 del raster en la G de la visualizaci?n.
478
         * Si replicateBand es true R = G = B sino R = B = 0
479
         * {1, 0, 3} La R = banda 1 del raster, G = 0 y B = 3
480
         * {0} La R = banda 0 del raster. Si replicateBand es true R = G = B sino G = B = 0
481
         * </P>
482
         *
483
         *
484
                 * @param renderBands: bandas y su posici?n
485
                 */
486
        public void setRenderBands(int[] renderBands) {
487
                if(        renderBands[0] != this.renderBands[0] || 
488
                        renderBands[1] != this.renderBands[1] || 
489
                        renderBands[2] != this.renderBands[2])
490
                        callVisualPropertyChanged(renderBands);
491
                this.renderBands = renderBands;
492
                if (filterList != null) {
493
                        for (int i = 0; i < filterList.lenght(); i++)
494
                                ((RasterFilter) filterList.get(i)).addParam("renderBands", renderBands);
495
                }
496
        }
497

    
498
        /**
499
         * Dado que la notaci?n de bandas para renderizado admite posiciones con -1 y la notaci?n del
500
         * buffer no ya que no tendria sentido. Esta funci?n adapta la primera notaci?n a la segunda
501
         * para realizar la petici?n setAreaOfInterest y cargar el buffer.
502
         * @param b Array que indica la posici?n de bandas para el renderizado
503
         * @return Array que indica la posici?n de bandas para la petici?n
504
         */
505
        public int[] formatArrayRenderBand(int[] b) {
506
                int cont = 0;
507
                for(int i = 0; i < b.length; i++)
508
                        if(b[i] >= 0)
509
                                cont ++;
510
                if(cont <= 0)
511
                        return null;
512
                int[] out = new int[cont];
513
                int pos = 0;
514
                for(int i = 0; i < cont; i++) {
515
                        while(b[pos] == -1)
516
                                pos ++;
517
                        out[i] = b[pos];
518
                        pos ++;
519
                }
520
                return out;
521
        }
522

    
523
        /**
524
         * Obtiene el ?ltimo objeto transparencia aplicado en la renderizaci?n
525
         * @return GridTransparency
526
         */
527
        public GridTransparency getLastTransparency() {
528
                return lastTransparency;
529
        }
530

    
531
        /**
532
         * Asigna el ?ltimo estado de transparencia de la renderizaci?n.  
533
         * @param lastTransparency
534
         */
535
        public void setLastTransparency(GridTransparency lastTransparency) {
536
                this.lastTransparency = lastTransparency;
537
                this.lastTransparency.addPropertyListener(this);
538
                if (getFilterList() != null)
539
                        getFilterList().addEnvParam("Transparency", lastTransparency);
540
        }
541

    
542
        /**
543
         * Obtiene las lista de filtros aplicados en la renderizaci?n
544
         * @return RasterFilterList
545
         */
546
        public RasterFilterList getFilterList() {
547
                return filterList;
548
        }
549

    
550
        /**
551
         * Obtiene el ?ltimo buffer renderizado.
552
         * @return IBuffer
553
         */
554
        public IBuffer getLastRenderBuffer() {
555
                return this.lastRenderBuffer;
556
        }
557

    
558
        /**
559
         * Asigna el ?ltimo renderizado.
560
         * @param buf
561
         */
562
        public void setLastRenderBuffer(IBuffer buf) {
563
                this.lastRenderBuffer = buf;
564
        }
565

    
566
        /**
567
         * Asigna la lista de filtros que se usar? en el renderizado
568
         * @param RasterFilterList
569
         */
570
        public void setFilterList(RasterFilterList filterList) {
571
                this.filterList = filterList;
572
                this.filterList.addFilterListListener(this);
573
        }
574

    
575
        /**
576
         * Informa de si el raster tiene tabla de color asociada o no.
577
         * @return true si tiene tabla de color y false si no la tiene.
578
         */
579
        public boolean existColorTable() {
580
                        return (filterList.getFilterByBaseClass(ColorTableFilter.class) != null);
581
        }
582

    
583
        /**
584
         * Obtiene el grid asociado al render
585
         * @return
586
         */
587
        public Grid getGrid() {
588
                return grid;
589
        }
590

    
591
        /**
592
         * Asigna la factoria de buffer del renderizador
593
         * @param bf
594
         */
595
        public void setBufferFactory(BufferFactory bf) {
596
                this.bufferFactory = bf;
597
        }
598

    
599
        /**
600
         * Evento activado cuando cambia una propiedad de transparencia.
601
         */
602
        public void actionValueChanged(PropertyEvent e) {
603
                callVisualPropertyChanged(new VisualPropertyEvent(e.getSource()));
604
        }
605

    
606
        /**
607
         * Evento activado cuando cambia la lista de filtros.
608
         */
609
        public void filterListChanged(FilterListChangeEvent e) {
610
                callVisualPropertyChanged(new VisualPropertyEvent(e.getSource()));
611
        }
612
        
613
        public void free() {
614
                if(lastTransparency != null)
615
                        lastTransparency.free();
616
                if(grid != null)
617
                        grid.free();
618
                if(getFilterList() != null)
619
                        getFilterList().free();
620
                grid = null;
621
                bufferFactory = null;
622
                if(lastRenderBuffer != null)
623
                        lastRenderBuffer.free();
624
                lastRenderBuffer = null;
625
        }
626

    
627
        public Image draw(Graphics2D g, ViewPortData vp) throws RasterDriverException, InvalidSetViewException, InterruptedException {
628
                System.err.println("TODO: REVISAR EL DIBUJADO!!!. Hay una llamada a Rendering.draw sin cancel");
629
                return draw(g, vp, null);
630
        }
631
}