Statistics
| Revision:

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

History | View | Annotate | Download (12.9 KB)

1
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
2
 *
3
 * Copyright (C) 2006 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.Image;
22
import java.awt.image.BufferedImage;
23

    
24
import org.gvsig.raster.buffer.RasterBuffer;
25
import org.gvsig.raster.dataset.IBuffer;
26
import org.gvsig.raster.grid.GridTransparency;
27
/**
28
 * Objeto para la escritura de datos desde un buffer a un objeto Image. En este nivel de 
29
 * renderizado no se gestiona extents, ni rotaciones ni coordenadas del mundo, solo la
30
 * escritura desde un buffer hasta otro de tama?o dado. Por medio de par?metros y de objetos
31
 * de estado varia el resultado de la escritura, selecci?n de bandas a escribir desde el buffer
32
 * a RGB, transparencias aplicadas o paletas.
33
 * 
34
 * @author Nacho Brodin (nachobrodin@gmail.com)
35
 */
36
public class ImageDrawer {
37
        /**
38
         * Fuente de datos para el renderizado
39
         */
40
        private IBuffer                                rasterBuf = null;
41
        private GridTransparency        transparency = null;
42
        private int[]                                step = null;
43
        /**
44
         * Ancho y alto del objeto image
45
         */
46
        private int                                 width = 0;
47
        private int                                 height = 0;
48
        /**
49
         * Ancho y alto en pixeles del ?ltimo buffer asignado
50
         */
51
        private double                                         nWidth = 0;
52
        private double                                         nHeight = 0;
53

    
54
        /**
55
         * Dibuja el buffer sobre un objeto Image de java.awt y devuelve el resultado.
56
         * 
57
         * @param replicateBand Flag de comportamiento del renderizado. Al renderizar el buffer
58
         * este obtiene la primera banda del buffer y la asigna al R, la segunda al G y la tercera
59
         * al B. Este flag no es tomado en cuenta en caso de que existan 3 bandas en el buffer.
60
         * Si no hay tres bandas, por ejemplo una y el flag es true esta ser? replicada 
61
         * en R, G y B, en caso de ser false la banda ser? dibujada en su posici?n (R, G o B)
62
         * y en las otras bandas se rellenar? con 0.
63
         *  
64
         * @param transparentBand. Si es true la banda 4 es alpha y si es false no lo es. 
65
         *  
66
         * @return java.awt.Image con el buffer dibujado.
67
         */
68
        public Image drawBufferOverImageObject(boolean replicateBand, int[] renderBands){
69
                if(rasterBuf == null)
70
                        return null;
71

    
72
                BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
73

    
74
                //Dibujado de raster de 1 o 2 bandas.
75
                //adaptBufferToRender(replicateBand, renderBands);
76

    
77
                if(rasterBuf.getDataType() != IBuffer.TYPE_BYTE)
78
                        rasterBuf = convertToByte(rasterBuf);
79

    
80
                //Asigna la banda de transparencia si existe esta.
81
                //assignTransparencyBand(renderBands);
82

    
83
                byte[] data = new byte[rasterBuf.getBandCount()];
84
                if(transparency != null && transparency.isTransparencyActive())
85
                        drawWithTransparency(image, data, (step != null));
86
                else
87
                        drawByte(image, data, (step != null));
88

    
89
                step = null;
90
                return image;
91
        }
92

    
93
        /**
94
         * Calcula los vectores de desplazamiento en pixels en X e Y cuando se supersamplea. 
95
         * @param r Array de desplazamientos para las filas. Debe tener espacio reservado
96
         * @param c Array de desplazamientos para las columnas. Debe tener espacio reservado 
97
         * @param rel relaci?n entre el ancho o alto del objeto Image y el ancho o alto del buffer con los pixels
98
         * cargados.
99
         */
100
        private void calcSupersamplingStepsArrays(int[] r, int[] c, double relRow, double relCol) {
101
                for(int row = 0; row < r.length; row ++)
102
                        r[row] = (int)((row + step[1]) / relRow);
103

    
104
                for(int col = 0; col < c.length; col ++)
105
                        c[col] = (int)((col + step[0]) / relCol);
106
        }
107

    
108
        /**
109
         * Dibuja un raster sobre un BufferedImage
110
         * @param image BufferedImage sobre el que se dibuja
111
         * @param data buffer vacio. Se trata de un array de bytes donde cada elemento representa una banda.
112
         * @param supersampling true si se necesita supersamplear y false si no se necesita
113
         */
114
        private void drawByte(BufferedImage image, byte[] data, boolean supersampling) {
115
                if(supersampling) {
116
                        int[] r = new int[height];
117
                        int[] c = new int[width];
118
                        calcSupersamplingStepsArrays(r, c, (double)((double)height / (rasterBuf.getHeight() - 1)), (double)((double)width / (rasterBuf.getWidth() - 1)));
119
                        for(int row = 0; row < height; row ++) {
120
                                for(int col = 0; col < width; col ++) {
121
                                        try {
122
                                                rasterBuf.getElemByte(r[row], c[col], data);
123
                                                image.setRGB(col, row, (0xff000000 + ((data[0] & 0xff) << 16) + ((data[1] & 0xff) << 8) + (data[2] & 0xff)));
124
                                        } catch(ArrayIndexOutOfBoundsException e){
125
                                                System.err.println("== Size Image:" + image.getWidth() + " " + image.getHeight());
126
                                                System.err.println("== Position required:" + col + " " + row);
127
                                        }
128
                                }
129
                        }
130
                } else {
131
                        for(int row = 0; row < rasterBuf.getHeight(); row ++) {
132
                                for(int col = 0; col < rasterBuf.getWidth(); col ++) {
133
                                        try {
134
                                                rasterBuf.getElemByte(row, col, data);
135
                                                image.setRGB(col, row, (0xff000000 + ((data[0] & 0xff) << 16) + ((data[1] & 0xff) << 8) + (data[2] & 0xff)));
136
                                        } catch (ArrayIndexOutOfBoundsException ex) {
137
                                                System.err.println("== Size Image:" + image.getWidth() + " " + image.getHeight());
138
                                                System.err.println("== Position required:" + col + " " + row);
139
                                        }
140
                                }
141
                        }
142
                }
143
        }
144

    
145
        /**
146
         * Dibuja un raster sobre un BufferedImage con las propiedades de paleta y transparencia
147
         * @param image BufferedImage sobre el que se dibuja
148
         * @param data buffer vacio. Se trata de un array de bytes donde cada elemento representa una banda.
149
         * @param supersampling true si se necesita supersamplear y false si no se necesita
150
         */
151
        private void drawWithTransparency(BufferedImage image, byte[] data, boolean supersampling) {
152
                int value = 0;
153
                if(supersampling) {
154
                        int[] r = new int[height];
155
                        int[] c = new int[width];
156
                        calcSupersamplingStepsArrays(r, c, (double)((double)height/ nHeight), (double)((double)width / nWidth));
157
                        for(int row = 0; row < height; row ++) {
158
                                for(int col = 0; col < width; col ++) {
159
                                        try{
160
                                                rasterBuf.getElemByte(r[row], c[col], data);
161
                                                value = transparency.processRGB(0xff000000 + ((data[0] & 0xff) << 16) + ((data[1] & 0xff) << 8) + (data[2] & 0xff), r[row], c[col]);
162
                                                image.setRGB(col, row, value);
163
                                        } catch(ArrayIndexOutOfBoundsException e){}
164
                                }
165
                        }
166
                } else {
167
                        for(int row = 0; row < rasterBuf.getHeight(); row ++) {
168
                                for(int col = 0; col < rasterBuf.getWidth(); col ++) {
169
                                        try{
170
                                                rasterBuf.getElemByte(row, col, data);
171
                                                value = transparency.processRGB(0xff000000 + ((data[0] & 0xff) << 16) + ((data[1] & 0xff) << 8) + (data[2] & 0xff), row, col);
172
                                                image.setRGB(col, row, value);
173
                                        } catch(ArrayIndexOutOfBoundsException e){
174
                                                continue;
175
                                        }
176
                                }
177
                        }
178
                }
179
        }
180
        /**
181
         * Intercala bandas en el buffer dependiendo de si hay que replicar o meter
182
         * bandas en negro. Esto tiene es valido para buffers con solo una banda ya que
183
         * el dibujado sobre Graphics debe ser R, G, B.
184
         * 
185
         * @param replicateBand false si no se replican bandas y las que no existen 
186
         * se ponen en negro y false si hay que dibujar la misma en R,G y B. Esto 
187
         * tiene sentido si el raster tiene solo 1 o 2 bandas.
188
         * @param renderBands array con las posiciones de renderizado. 
189
         *  A la hora de renderizar hay que tener en cuenta que solo se renderizan las 
190
         * tres primeras bandas del buffer por lo que solo se tienen en cuenta los tres primeros
191
         * elementos. Por ejemplo, el array {1, 0, 3} dibujar? sobre el Graphics las bandas 1,0 y 3 de un
192
         * raster de al menos 4 bandas.La notaci?n con -1 en alguna posici?n del vector solo tiene sentido
193
         * en la visualizaci?n pero no se puede as?gnar una banda del buffer a null.
194
         * Algunos ejemplos:
195
         * <P> 
196
         * {-1, 0, -1} Dibuja la banda 0 del raster en la G de la visualizaci?n.
197
         * Si replicateBand es true R = G = B sino R = B = 0
198
         * {1, 0, 3} La R = banda 1 del raster, G = 0 y B = 3
199
         * {0} La R = banda 0 del raster. Si replicateBand es true R = G = B sino G = B = 0
200
         * </P>
201
         */
202
        /*private void adaptBufferToRender(boolean replicateBand, int[] renderBands){
203
                byte[][] aux = null;
204
                if(rasterBuf.getBandCount() < 3){
205
                        for(int i = 0; i < renderBands.length; i++){
206
                                if( replicateBand && renderBands[i] == -1)
207
                                        rasterBuf.replicateBand(0, i);
208
                                if( !replicateBand && renderBands[i] == -1){
209
                                        if(aux == null)
210
                                                aux = rasterBuf.createByteBand(rasterBuf.getWidth(), rasterBuf.getHeight(), (byte)0);
211
                                        rasterBuf.addBandByte(i, aux);
212
                                }
213
                        }
214
                }
215
        }*/
216

    
217
        /**
218
         * Asigna al objeto GridTransparency la banda de transparencia si la tiene para
219
         * tenerla en cuenta en el renderizado.
220
         * @param renderBands Lista de bandas a renderizar
221
         * @param ts Objeto con las propiedades de transparencia del Grid.
222
         */
223
        /*private void assignTransparencyBand(int[] renderBands) {
224
                if(transparency != null){
225
                        for(int i = 0; i < transparency.getTransparencyBandNumberList().size(); i ++) {
226
                                for(int j = 0; j < renderBands.length; j ++) {
227
                                        if(renderBands[j] == ((Integer)transparency.getTransparencyBandNumberList().get(i)).intValue()){
228
                                                if(transparency.getBand() == null)
229
                                                        transparency.setBand(rasterBuf.getBandBuffer(renderBands[j]));
230
                                                else {
231
                                                        IBuffer outBuf = transparency.getBand().cloneBuffer();
232
                                                        transparency.mergeTransparencyBands(new IBuffer[]{transparency.getBand(), rasterBuf.getBandBuffer(renderBands[j])}, outBuf);
233
                                                }
234
                                        }
235
                                }
236
                        }
237
                }
238
        }*/
239

    
240
        private IBuffer convertToByte(IBuffer buf) {
241
                IBuffer b = RasterBuffer.getBuffer(IBuffer.TYPE_BYTE, buf.getWidth(), buf.getHeight(), buf.getBandCount(), true);
242
                if(buf.getDataType() == IBuffer.TYPE_SHORT) {
243
                        for (int nBand = 0; nBand < buf.getBandCount(); nBand++)
244
                                for (int row = 0; row < buf.getHeight(); row++)
245
                                        for (int col = 0; col < buf.getWidth(); col++)
246
                                                b.setElem(row, col, nBand, (byte)(buf.getElemShort(row, col, nBand) & 0xffff));
247
                }
248
                if(buf.getDataType() == IBuffer.TYPE_INT) {
249
                        for (int nBand = 0; nBand < buf.getBandCount(); nBand++)
250
                                for (int row = 0; row < buf.getHeight(); row++)
251
                                        for (int col = 0; col < buf.getWidth(); col++)
252
                                                b.setElem(row, col, nBand, (byte)(buf.getElemInt(row, col, nBand) & 0xffffffff));
253
                }
254
                if(buf.getDataType() == IBuffer.TYPE_FLOAT) {
255
                        for (int nBand = 0; nBand < buf.getBandCount(); nBand++)
256
                                for (int row = 0; row < buf.getHeight(); row++)
257
                                        for (int col = 0; col < buf.getWidth(); col++)
258
                                                b.setElem(row, col, nBand, (byte)(Math.round(buf.getElemFloat(row, col, nBand))));
259
                }
260
                if(buf.getDataType() == IBuffer.TYPE_DOUBLE) {
261
                        for (int nBand = 0; nBand < buf.getBandCount(); nBand++)
262
                                for (int row = 0; row < buf.getHeight(); row++)
263
                                        for (int col = 0; col < buf.getWidth(); col++)
264
                                                b.setElem(row, col, nBand, (byte)(Math.round(buf.getElemDouble(row, col, nBand))));
265
                }
266
                return b;
267
        }
268

    
269
        /**
270
         * Asigna el buffer a renderizar
271
         * @param b Buffer a renderizar
272
         */
273
        public void setBuffer(IBuffer b) {
274
                this.rasterBuf = b;
275
        }
276

    
277
        /**
278
         * Asigna la paleta asociada al grid
279
         * @param palette 
280
         */
281
        /*public void setPalette(GridPalette palette) {
282
                this.palette = palette;
283
        }*/
284

    
285
        /**
286
         * Asigna el objeto que contiene el estado de transparencia del grid
287
         * @param transparency
288
         */
289
        public void setTransparency(GridTransparency transparency) {
290
                this.transparency = transparency;
291
        }
292

    
293
        /**
294
         * Asigna el desplazamiento en pixeles desde la esquina superior izquierda. Si es null se considera que esta
295
         * funci?n la ha hecho el driver quedando desactivada en el renderizador. Si es as? no debe variar el resultado
296
         * en la visualizacion. 
297
         * Si Supersamplea el renderizador se cargar? una matriz de datos 1:1 por lo que se podr? aplicar un filtro 
298
         * a este buffer de datos leidos independientemente del zoom que tengamos.
299
         * @param step Desplazamiento
300
         */
301
        public void setStep(int[] step) {
302
                this.step = step;
303
        }
304

    
305
        /**
306
         * Asigna el ancho y el alto del BufferedImage. Esto es util para cuando hay supersampling
307
         * que el tama?o del objeto Image no coincide con el buffer con los datos raster.  
308
         * @param w Ancho
309
         * @param h Alto
310
         */
311
        public void setBufferSize(int w, int h) {
312
                this.width = w;
313
                this.height = h;
314
        }
315

    
316
        /**
317
         * Asigna el ancho y el alto en pixeles a dibujar. Esto es util para cuando hay supersampling
318
         * ya que necesitamos saber la relaci?n entre el ancho o alto del objeto image y en ancho o alto en pixels
319
         * del buffer. No vale la informaci?n contenida en rasterBuf (ni rasterBuf.getWidth ni rasterBuf.getHeight) 
320
         * ya que esta es entera y necesitamos el valor en double para mantener la precisi?n del calculo.  
321
         * @param w Ancho
322
         * @param h Alto
323
         */
324
        public void setPixelsToDrawSize(double w, double h) {
325
                this.nWidth = w;
326
                this.nHeight = h;
327
        }
328

    
329
}