Statistics
| Revision:

root / branches / v2_0_0_prep / libraries / libRaster / src / org / gvsig / raster / grid / render / Rendering.java @ 32880

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

    
76
        /**
77
         * Grid para la gesti?n del buffer
78
         */
79
        private Grid             grid                     = null;
80
        /**
81
         * Fuente de datos para el renderizado
82
         */
83
        private BufferFactory    bufferFactory            = null;
84

    
85
        /**
86
         * N?mero de bandas a renderizar y en el orden que se har?. Esto es asignado
87
         * por el usuario de la renderizaci?n.
88
         */
89
        private int[]            renderBands              = { 0, 1, 2 };
90
        /**
91
         * Tiene el comportamiento cuando se tiene un raster con una. Dice si en las
92
         * otras bandas a renderizar se replica la banda existente o se ponen a 0.
93
         */
94
        private boolean          replicateBand            = false;
95

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

    
107
        private IBuffer          lastRenderBuffer         = null;
108

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

    
115
        private Point2D          ulPxRequest, lrPxRequest;
116

    
117
        /**
118
         * Array de listeners que ser?n informados cuando cambia una propiedad en la visualizaci?n
119
         */
120
        private ArrayList        visualPropertyListener   = new ArrayList();
121

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

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

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

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

    
150
                if (bufferFactory == null) {
151
                        setRenderBands(new int[] { 0, 1, 2 });
152
                        return;
153
                }
154

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

    
168
                //---------------------------------------------------
169
                //INICIALIZACI?N DE LA INTERPRETACI?N DE COLOR
170

    
171
                //Inicializaci?n de la asignaci?n de bandas en el renderizado
172
                //Leemos el objeto metadata para obtener la interpretaci?n de color asociada al raster
173
                if (bufferFactory.getDataSource().getDatasetCount() == 1) {
174
                        DatasetColorInterpretation colorInterpr = bufferFactory.getDataSource().getColorInterpretation();
175
                        if (colorInterpr != null)
176
                                if (colorInterpr.getBand(DatasetColorInterpretation.PAL_BAND) == -1) {
177
                                        if (colorInterpr.isUndefined())
178
                                                return;
179
                                        int[] result = new int[] { -1, -1, -1 };
180
                                        int gray = colorInterpr.getBand(DatasetColorInterpretation.GRAY_BAND);
181
                                        if (gray != -1)
182
                                                result[0] = result[1] = result[2] = gray;
183
                                        else {
184
                                                int r = colorInterpr.getBand(DatasetColorInterpretation.RED_BAND);
185
                                                if (r != -1)
186
                                                        result[0] = r;
187
                                                int g = colorInterpr.getBand(DatasetColorInterpretation.GREEN_BAND);
188
                                                if (g != -1)
189
                                                        result[1] = g;
190
                                                int b = colorInterpr.getBand(DatasetColorInterpretation.BLUE_BAND);
191
                                                if (b != -1)
192
                                                        result[2] = b;
193
                                        }
194
                                        setRenderBands(result);
195
                                }
196
                }
197
        }
198

    
199
        /**
200
         * Asigna un listener a la lista que ser? informado cuando cambie una
201
         * propiedad visual en la renderizaci?n.
202
         * @param listener VisualPropertyListener
203
         */
204
        public void addVisualPropertyListener(VisualPropertyListener listener) {
205
                visualPropertyListener.add(listener);
206
        }
207

    
208
        /**
209
         * M?todo llamado cuando hay un cambio en una propiedad de visualizaci?n
210
         */
211
        private void callVisualPropertyChanged(Object obj) {
212
                for (int i = 0; i < visualPropertyListener.size(); i++) {
213
                        VisualPropertyEvent ev = new VisualPropertyEvent(obj);
214
                        ((VisualPropertyListener)visualPropertyListener.get(i)).visualPropertyValueChanged(ev);
215
                }
216
        }
217

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

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

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

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

    
261
                double[] step = null;
262

    
263
                if (bufferFactory != null) {
264
                        if (lastTransparency == null) {
265
                                lastTransparency = new GridTransparency(bufferFactory.getDataSource().getTransparencyFilesStatus());
266
                                lastTransparency.addPropertyListener(this);
267
                        }
268
                        // Asignamos la banda de transparencia si existe esta
269
                        if (bufferFactory.getDataSource().getTransparencyFilesStatus().getAlphaBandNumber() != -1) {
270
                                bufferFactory.setSupersamplingLoadingBuffer(false); // Desactivamos el supersampleo en la carga del buffer.
271
                                bufferFactory.setDrawableBands(new int[] { lastTransparency.getAlphaBandNumber(), -1, -1 });
272
                                bufferFactory.setAreaOfInterest(adjustedRotedRequest.getULX(), adjustedRotedRequest.getULY(), adjustedRotedRequest.getLRX(), adjustedRotedRequest.getLRY(), (int)Math.round(widthImage), (int)Math.round(heightImage));
273
                                bufferFactory.setSupersamplingLoadingBuffer(true);
274
                                lastTransparency.setAlphaBand(bufferFactory.getRasterBuf());
275
                        }
276
                        bufferFactory.setSupersamplingLoadingBuffer(false); // Desactivamos el supersampleo en la carga del buffer.
277
                        // En el renderizado ser? ImageDrawer el que se encargue de esta funci?n
278
                        bufferFactory.setDrawableBands(getRenderBands());
279
                        step = bufferFactory.setAreaOfInterest(adjustedRotedRequest.getULX(), adjustedRotedRequest.getULY(), adjustedRotedRequest.getLRX(), adjustedRotedRequest.getLRY(), (int)Math.round(widthImage), (int)Math.round(heightImage));
280
                        bufferFactory.setSupersamplingLoadingBuffer(true);
281

    
282
                        //Asignamos los datos al objeto transparencia antes de aplicar la pila de filtros para que el valor NoData sea efectivo
283
                        if (bufferFactory.getDataSource().getTransparencyFilesStatus().isNoDataActive())
284
                                lastTransparency.setDataBuffer(bufferFactory.getRasterBuf());
285
                        else
286
                                lastTransparency.setDataBuffer(null);
287
                        lastTransparency.activeTransparency();
288

    
289
                } else
290
                        return null;
291

    
292
                //Aplicamos los filtros
293
                grid = new Grid(bufferFactory, true);
294
                filterList.addEnvParam("Transparency", lastTransparency);
295
                grid.setFilterList(filterList);
296
                grid.applyFilters();
297

    
298
                //Si la lista de filtros genera bandas de transparencia se mezclan con la actual
299
                if(grid.getFilterList().getAlphaBand() != null) {
300
                        IBuffer t = grid.getFilterList().getAlphaBand();
301
                        if(lastTransparency.getAlphaBand() != null)
302
                                t = Transparency.merge(t, lastTransparency.getAlphaBand());
303
                        lastTransparency.setAlphaBand(t);
304
                        lastTransparency.activeTransparency();
305
                }
306

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

    
314
                // Borramos el buffer de transparencia para que siempre se tenga que regenerar.
315
                lastTransparency.setAlphaBand(null);
316

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

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

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

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

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

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

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

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

    
403
                        //Calculamos el ancho y alto del buffer sobre el que se escribe la petici?n
404
                        widthImage = ((Math.abs(lrPxRequest.getX() - ulPxRequest.getX()) * vp
405
                                        .getWidth()) / Math.abs(pxMaxX - pxMinX));
406
                        heightImage = ((Math.abs(lrPxRequest.getY() - ulPxRequest.getY()) * vp
407
                                        .getHeight()) / Math.abs(pxMaxY - pxMinY));
408

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
599
        /**
600
         * Sets buffers to null
601
         */
602
        public void free() {
603
                if (lastTransparency != null)
604
                        lastTransparency.free();
605
                if (grid != null)
606
                        grid.free();
607
                if (getFilterList() != null)
608
                        getFilterList().free();
609
                grid = null;
610
                bufferFactory = null;
611
                if (lastRenderBuffer != null)
612
                        lastRenderBuffer.free();
613
                lastRenderBuffer = null;
614
        }
615

    
616
        public void loadFromState(PersistentState state)
617
                        throws PersistenceException {
618
                lastTransparency = (GridTransparency)state.get("lastTransparency");                
619
        }
620

    
621
        public void saveToState(PersistentState state) throws PersistenceException {
622
                state.set("lastTransparency", lastTransparency);        
623
        }
624
        
625
        public static void registerPersistent() {
626
                PersistenceManager manager = ToolsLocator.getPersistenceManager();
627
                DynStruct definition = manager.addDefinition(
628
                                Rendering.class,
629
                                "RasterRendering",
630
                                "RasterRendering Persistent definition",
631
                                null, 
632
                                null
633
                );
634
                definition.addDynField("lastTransparency");
635
        }
636

    
637
}