Statistics
| Revision:

svn-gvsig-desktop / trunk / libraries / libRaster / src / org / gvsig / raster / grid / render / Rendering.java @ 24170

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

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

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

    
105
        private IBuffer          lastRenderBuffer         = null;
106

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

    
113
        private Point2D          ulPxRequest, lrPxRequest;
114
        
115
        /**
116
         * Array de listeners que ser?n informados cuando cambia una propiedad en la visualizaci?n
117
         */
118
        private ArrayList        visualPropertyListener   = new ArrayList();
119

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

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

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

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

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

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

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

    
252
                if(RasterUtilities.isOutside(vp.getExtent(), dataset.getExtent()))
253
                        return null;
254

    
255
                Extent adjustedRotedRequest = request(vp, dataset);
256

    
257
                if ((widthImage <= 0) || (heightImage <= 0))
258
                        return null;
259

    
260
                double[] step = null;
261

    
262
                if (bufferFactory != null) {
263
                        if (lastTransparency == null) {
264
                                lastTransparency = new GridTransparency(bufferFactory.getDataSource().getTransparencyFilesStatus());
265
                                lastTransparency.addPropertyListener(this);
266
                        }
267
                        // Asignamos la banda de transparencia si existe esta
268
                        if (bufferFactory.getDataSource().getTransparencyFilesStatus().getAlphaBandNumber() != -1) {
269
                                bufferFactory.setSupersamplingLoadingBuffer(false); // Desactivamos el supersampleo en la carga del buffer.
270
                                bufferFactory.setDrawableBands(new int[] { lastTransparency.getAlphaBandNumber(), -1, -1 });
271
                                bufferFactory.setAreaOfInterest(adjustedRotedRequest.getULX(), adjustedRotedRequest.getULY(), adjustedRotedRequest.getLRX(), adjustedRotedRequest.getLRY(), (int)Math.round(widthImage), (int)Math.round(heightImage));
272
                                bufferFactory.setSupersamplingLoadingBuffer(true);
273
                                lastTransparency.setAlphaBand(bufferFactory.getRasterBuf());
274
                        }
275
                        bufferFactory.setSupersamplingLoadingBuffer(false); // Desactivamos el supersampleo en la carga del buffer.
276
                        // En el renderizado ser? ImageDrawer el que se encargue de esta funci?n
277
                        bufferFactory.setDrawableBands(getRenderBands());
278
                        step = bufferFactory.setAreaOfInterest(adjustedRotedRequest.getULX(), adjustedRotedRequest.getULY(), adjustedRotedRequest.getLRX(), adjustedRotedRequest.getLRY(), (int)Math.round(widthImage), (int)Math.round(heightImage));
279
                        bufferFactory.setSupersamplingLoadingBuffer(true);
280
                        
281
                        //Asignamos los datos al objeto transparencia antes de aplicar la pila de filtros para que el valor NoData sea efectivo
282
                        if (bufferFactory.getDataSource().getTransparencyFilesStatus().isNoDataActive())
283
                                lastTransparency.setDataBuffer(bufferFactory.getRasterBuf());
284
                        else
285
                                lastTransparency.setDataBuffer(null);
286
                        lastTransparency.activeTransparency();
287
                        
288
                } else
289
                        return null;
290

    
291
                //Aplicamos los filtros
292
                grid = new Grid(bufferFactory, true);
293
                filterList.addEnvParam("Transparency", lastTransparency);
294
                grid.setFilterList(filterList);
295
                grid.applyFilters();
296
                
297
                //Si la lista de filtros genera bandas de transparencia se mezclan con la actual 
298
                if(grid.getFilterList().getAlphaBand() != null) {
299
                        IBuffer t = grid.getFilterList().getAlphaBand();
300
                        if(lastTransparency.getAlphaBand() != null)
301
                                t = Transparency.merge(t, lastTransparency.getAlphaBand());
302
                        lastTransparency.setAlphaBand(t);
303
                        lastTransparency.activeTransparency();
304
                }
305

    
306
                //Buffer filtrado para renderizar
307
                lastRenderBuffer = grid.getRasterBuf();
308
                drawer.setBuffer(lastRenderBuffer); // Buffer de datos a renderizar
309
                drawer.setStep(step); // Desplazamiento para supersampleo
310
                drawer.setBufferSize((int)Math.round(widthImage), (int)Math.round(heightImage)); // Ancho y alto del buffer
311
                geoImage = drawer.drawBufferOverImageObject(replicateBand, getRenderBands()); // Acci?n de renderizado
312

    
313
                // Borramos el buffer de transparencia para que siempre se tenga que regenerar.
314
                lastTransparency.setAlphaBand(null);
315
                
316
                //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
317
                //transformaci?n. Esto no es necesario hacerlo, sin ello se visualiza igual. Unicamente se hace porque de esta
318
                //forma el raster resultante mejora un poco en calidad en ciertos niveles de zoom ya que al aplicar transformaciones
319
                //sobre el Graphics parece que pierde algo de calidad.
320
                if(transf.getScaleX() > 0 && transf.getScaleY() < 0 && transf.getShearX() == 0 && transf.getShearY() == 0) {
321
                        Point2D lastGraphicOffset = new Point2D.Double(adjustedRotedRequest.getULX(), adjustedRotedRequest.getULY());
322
                        vp.mat.transform(lastGraphicOffset, lastGraphicOffset);
323
                        g.drawImage(geoImage, (int) Math.round(lastGraphicOffset.getX()), (int) Math.round(lastGraphicOffset.getY()), null);
324
                        return geoImage;
325
                }
326

    
327
                /*
328
                 * Tenemos una matriz con la transformaci?n de la coordenadas de la vista a coordenadas reales vp.mat, adem?s tenemos
329
                 * la transformaci?n de coordenadas reales a coordenadas pixel (transf). Con ambas podemos obtener una matriz de trasformacion
330
                 * entre coordenadas de la vista a coordenadas pixel (transf X vp.mat). As? obtenemos la transformaci?n entre coordenadas
331
                 * de la vista y coordenadas pixel del raster. El problemas es que cada zoom la escala de la petici?n del raster varia
332
                 * por lo que habr? que calcular una matriz con la escala (escale). escale X transf X vp.mat
333
                 */
334
                double sX = Math.abs(ulPxRequest.getX() - lrPxRequest.getX()) / widthImage;
335
                double sY = Math.abs(ulPxRequest.getY() - lrPxRequest.getY()) / heightImage;
336
                AffineTransform escale = new AffineTransform(sX, 0, 0, sY, 0, 0);
337

    
338
                try {
339
                        AffineTransform at = (AffineTransform)escale.clone();
340
                        at.preConcatenate(transf);
341
                        at.preConcatenate(vp.getMat());
342
                        g.transform(at);
343
                        Point2D.Double pt = null;
344
                        //El punto sobre el que rota la imagen depende del signo de los tama?os del pixel
345
                        if(transf.getScaleX() < 0 && transf.getScaleY() < 0)
346
                                pt = new Point2D.Double(adjustedRotedRequest.maxX(), adjustedRotedRequest.maxY());
347
                        else if(transf.getScaleX() > 0 && transf.getScaleY() > 0)
348
                                pt = new Point2D.Double(adjustedRotedRequest.minX(), adjustedRotedRequest.minY());
349
                        else if(transf.getScaleX() < 0 && transf.getScaleY() > 0)
350
                                pt = new Point2D.Double(adjustedRotedRequest.maxX(), adjustedRotedRequest.minY());
351
                        else
352
                                pt = new Point2D.Double(adjustedRotedRequest.getULX(), adjustedRotedRequest.getULY());
353
                        vp.getMat().transform(pt, pt);
354
                        at.inverseTransform(pt, pt);
355
                        g.drawImage(geoImage, (int) Math.round(pt.getX()), (int) Math.round(pt.getY()), null);
356
                        g.transform(at.createInverse());
357
                } catch (NoninvertibleTransformException e) {
358
                        e.printStackTrace();
359
                }
360
                return geoImage;
361
                // long t2 = new Date().getTime();
362
                // System.out.println("Renderizando Raster: " + ((t2 - t1) / 1000D) + ", secs.");
363
        }
364

    
365
        /**
366
         * Calculamos la petici?n en coordenadas del mundo real con la transformaci?n del raster. Esto
367
         * permite obtener las coordenadas de la petici?n con la rotaci?n, si la tiene.
368
         * @param vp
369
         * @param dataset
370
         * @return
371
         */
372
        private Extent request(ViewPortData vp, IRasterDataSource dataset) {
373
                if (dataset.isRotated()) {
374
                        //Obtenemos las cuatro esquinas de la selecci?n que hemos hecho en la vista
375
                        Point2D ul = new Point2D.Double(vp.getExtent().minX(), vp.getExtent().maxY());
376
                        Point2D ur = new Point2D.Double(vp.getExtent().maxX(), vp.getExtent().maxY());
377
                        Point2D ll = new Point2D.Double(vp.getExtent().minX(), vp.getExtent().minY());
378
                        Point2D lr = new Point2D.Double(vp.getExtent().maxX(), vp.getExtent().minY());
379

    
380
                        //Las pasamos a coordenadas pixel del raster
381
                        ul = dataset.worldToRaster(ul);
382
                        ur = dataset.worldToRaster(ur);
383
                        ll = dataset.worldToRaster(ll);
384
                        lr = dataset.worldToRaster(lr);
385

    
386
                        //Obtenemos los valores pixel m?ximos y m?nimos para X e Y
387
                        double pxMaxX = Math.max(Math.max(ul.getX(), ur.getX()), Math.max(ll.getX(), lr.getX()));
388
                        double pxMaxY = Math.max(Math.max(ul.getY(), ur.getY()), Math.max(ll.getY(), lr.getY()));
389
                        double pxMinX = Math.min(Math.min(ul.getX(), ur.getX()), Math.min(ll.getX(), lr.getX()));
390
                        double pxMinY = Math.min(Math.min(ul.getY(), ur.getY()), Math.min(ll.getY(), lr.getY()));
391

    
392
                        //Ajustamos las coordenadas pixel al ?rea m?xima del raster
393
                        pxMinX = Math.max(pxMinX, 0);
394
                        pxMinY = Math.max(pxMinY, 0);
395
                        pxMaxX = Math.min(pxMaxX, dataset.getWidth());
396
                        pxMaxY = Math.min(pxMaxY, dataset.getHeight());
397

    
398
                        //Petici?n en coordenadas pixel
399
                        ulPxRequest = new Point2D.Double(pxMinX, pxMinY);
400
                        lrPxRequest = new Point2D.Double(pxMaxX, pxMaxY);
401

    
402
                        //Calculamos el ancho y alto del buffer sobre el que se escribe la petici?n
403
                        widthImage = ((Math.abs(lrPxRequest.getX() - ulPxRequest.getX()) * vp.getWidth()) / Math.abs(ul.getX() - ur.getX()));
404
                        heightImage = ((Math.abs(lrPxRequest.getY() - ulPxRequest.getY()) * vp.getHeight()) / Math.abs(ur.getY() - lr.getY()));
405

    
406
                        //Convertimos la petici?n en coordenadas pixel a petici?n en coordenadas reales.
407
                        Point2D ulWC = dataset.rasterToWorld(ulPxRequest);
408
                        Point2D lrWC = dataset.rasterToWorld(lrPxRequest);
409

    
410
                        //Ajustamos la petici?n a los limites del raster, teniendo en cuenta la rotaci?n de este.
411
                        return new Extent(ulWC, lrWC);
412
                }
413
                Extent adjustedRotedExtent = RasterUtilities.calculateAdjustedView(vp.getExtent(), dataset.getAffineTransform(), new Dimension((int)dataset.getWidth(), (int)dataset.getHeight()));
414
                widthImage = (int)Math.round(Math.abs(adjustedRotedExtent.width() * vp.getMat().getScaleX()));
415
                heightImage = (int)Math.round(Math.abs(adjustedRotedExtent.height() * vp.getMat().getScaleY()));
416
                Point2D ul = new Point2D.Double(adjustedRotedExtent.getULX(), adjustedRotedExtent.getULY());
417
                Point2D lr = new Point2D.Double(adjustedRotedExtent.getLRX(), adjustedRotedExtent.getLRY());
418
                ul = dataset.worldToRaster(ul);
419
                lr = dataset.worldToRaster(lr);
420
                ulPxRequest = new Point2D.Double(ul.getX(), ul.getY());
421
                lrPxRequest = new Point2D.Double(lr.getX(), lr.getY());
422
                return adjustedRotedExtent;
423
        }
424

    
425
        /**
426
         * Obtiene el n?mero de bandas y el orden de renderizado. Cada posici?n del
427
         * vector es una banda del buffer y el contenido de esa posici?n es la banda
428
         * de la imagen que se dibujar? sobre ese buffer. A la hora de renderizar hay
429
         * que tener en cuenta que solo se renderizan las tres primeras bandas del
430
         * buffer por lo que solo se tienen en cuenta los tres primeros elementos. Por
431
         * ejemplo, el array {1, 0, 3} dibujar? sobre el Graphics las bandas 1,0 y 3
432
         * de un raster de al menos 4 bandas. La notaci?n con -1 en alguna posici?n
433
         * del vector solo tiene sentido en la visualizaci?n pero no se puede as?gnar
434
         * una banda del buffer a null. Algunos ejemplos:
435
         * <P>
436
         * <UL>
437
         * <LI> {-1, 0, -1} Dibuja la banda 0 del raster en la G de la visualizaci?n. Si
438
         * replicateBand es true R = G = B sino R = B = 0 </LI>
439
         * <LI> {1, 0, 3} La R = banda 1 del raster, G = 0 y B = 3 </LI>
440
         * <LI> {0} La R = banda 0 del raster. Si replicateBand es true R = G = B 
441
         * sino G = B = 0</LI>
442
         * </UL>
443
         * </P>
444
         *
445
         * @return bandas y su posici?n
446
         */
447
        public int[] getRenderBands() {
448
                return renderBands;
449
        }
450

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

    
482
        /**
483
         * Dado que la notaci?n de bandas para renderizado admite posiciones con -1 y la notaci?n del
484
         * buffer no ya que no tendria sentido. Esta funci?n adapta la primera notaci?n a la segunda
485
         * para realizar la petici?n setAreaOfInterest y cargar el buffer.
486
         * @param b Array que indica la posici?n de bandas para el renderizado
487
         * @return Array que indica la posici?n de bandas para la petici?n
488
         */
489
        public int[] formatArrayRenderBand(int[] b) {
490
                int cont = 0;
491
                for(int i = 0; i < b.length; i++)
492
                        if(b[i] >= 0)
493
                                cont ++;
494
                if(cont <= 0)
495
                        return null;
496
                int[] out = new int[cont];
497
                int pos = 0;
498
                for(int i = 0; i < cont; i++) {
499
                        while(b[pos] == -1)
500
                                pos ++;
501
                        out[i] = b[pos];
502
                        pos ++;
503
                }
504
                return out;
505
        }
506

    
507
        /**
508
         * Obtiene el ?ltimo objeto transparencia aplicado en la renderizaci?n
509
         * @return GridTransparency
510
         */
511
        public GridTransparency getLastTransparency() {
512
                return lastTransparency;
513
        }
514

    
515
        /**
516
         * Asigna el ?ltimo estado de transparencia de la renderizaci?n.  
517
         * @param lastTransparency
518
         */
519
        public void setLastTransparency(GridTransparency lastTransparency) {
520
                this.lastTransparency = lastTransparency;
521
                this.lastTransparency.addPropertyListener(this);
522
                if (getFilterList() != null)
523
                        getFilterList().addEnvParam("Transparency", lastTransparency);
524
        }
525

    
526
        /**
527
         * Obtiene las lista de filtros aplicados en la renderizaci?n
528
         * @return RasterFilterList
529
         */
530
        public RasterFilterList getFilterList() {
531
                return filterList;
532
        }
533

    
534
        /**
535
         * Obtiene el ?ltimo buffer renderizado.
536
         * @return IBuffer
537
         */
538
        public IBuffer getLastRenderBuffer() {
539
                return this.lastRenderBuffer;
540
        }
541

    
542
        /**
543
         * Asigna el ?ltimo renderizado.
544
         * @param buf
545
         */
546
        public void setLastRenderBuffer(IBuffer buf) {
547
                this.lastRenderBuffer = buf;
548
        }
549

    
550
        /**
551
         * Asigna la lista de filtros que se usar? en el renderizado
552
         * @param RasterFilterList
553
         */
554
        public void setFilterList(RasterFilterList filterList) {
555
                this.filterList = filterList;
556
                this.filterList.addFilterListListener(this);
557
        }
558

    
559
        /**
560
         * Informa de si el raster tiene tabla de color asociada o no.
561
         * @return true si tiene tabla de color y false si no la tiene.
562
         */
563
        public boolean existColorTable() {
564
                        return (filterList.getFilterByBaseClass(ColorTableFilter.class) != null);
565
        }
566

    
567
        /**
568
         * Obtiene el grid asociado al render
569
         * @return
570
         */
571
        public Grid getGrid() {
572
                return grid;
573
        }
574

    
575
        /**
576
         * Asigna la factoria de buffer del renderizador
577
         * @param bf
578
         */
579
        public void setBufferFactory(BufferFactory bf) {
580
                this.bufferFactory = bf;
581
        }
582

    
583
        /**
584
         * Evento activado cuando cambia una propiedad de transparencia.
585
         */
586
        public void actionValueChanged(PropertyEvent e) {
587
                callVisualPropertyChanged(new VisualPropertyEvent(e.getSource()));
588
        }
589

    
590
        /**
591
         * Evento activado cuando cambia la lista de filtros.
592
         */
593
        public void filterListChanged(FilterListChangeEvent e) {
594
                callVisualPropertyChanged(new VisualPropertyEvent(e.getSource()));
595
        }
596
}