Statistics
| Revision:

gvsig-raster / org.gvsig.raster / branches / org.gvsig.raster_dataaccess_refactoring / org.gvsig.raster.lib / org.gvsig.raster.lib.impl / src / main / java / org / gvsig / raster / impl / grid / render / ImageDrawerImpl.java @ 2308

History | View | Annotate | Download (13.7 KB)

1
/* gvSIG. Geographic Information System of the Valencian Government
2
 *
3
 * Copyright (C) 2007-2008 Infrastructures and Transports Department
4
 * of the Valencian Government (CIT)
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 2
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21
 */
22
package org.gvsig.raster.impl.grid.render;
23

    
24
import java.awt.Image;
25
import java.awt.image.BufferedImage;
26

    
27
import org.gvsig.fmap.dal.coverage.RasterLocator;
28
import org.gvsig.fmap.dal.coverage.dataset.Buffer;
29
import org.gvsig.fmap.dal.coverage.datastruct.Extent;
30
import org.gvsig.fmap.dal.coverage.exception.FileNotOpenException;
31
import org.gvsig.fmap.dal.coverage.exception.FilterAddException;
32
import org.gvsig.fmap.dal.coverage.exception.FilterTypeException;
33
import org.gvsig.fmap.dal.coverage.exception.ProcessInterruptedException;
34
import org.gvsig.fmap.dal.coverage.exception.RasterDriverException;
35
import org.gvsig.fmap.dal.coverage.grid.RasterFilterList;
36
import org.gvsig.fmap.dal.coverage.grid.render.ImageDrawer;
37
import org.gvsig.fmap.dal.coverage.store.props.Statistics;
38
import org.gvsig.fmap.dal.coverage.store.props.Transparency;
39
import org.gvsig.raster.impl.DefaultRasterManager;
40
import org.gvsig.raster.impl.buffer.RasterBuffer;
41
import org.gvsig.raster.impl.grid.filter.enhancement.DefaultLinearStretchParams;
42
import org.gvsig.raster.impl.grid.filter.enhancement.EnhancementStretchListManager;
43
import org.gvsig.raster.impl.process.RasterTask;
44
import org.gvsig.raster.impl.process.RasterTaskQueue;
45
import org.slf4j.Logger;
46
import org.slf4j.LoggerFactory;
47

    
48
/**
49
 * Objeto para la escritura de datos desde un buffer a un objeto Image. En este nivel de
50
 * renderizado no se gestiona extents, ni rotaciones ni coordenadas del mundo, solo la
51
 * escritura desde un buffer hasta otro de tama?o dado. Por medio de par?metros y de objetos
52
 * de estado varia el resultado de la escritura, selecci?n de bandas a escribir desde el buffer
53
 * a RGB, transparencias aplicadas o paletas.
54
 *
55
 * @author Nacho Brodin (nachobrodin@gmail.com)
56
 */
57
public class ImageDrawerImpl implements ImageDrawer {
58
        private Logger        log                   = LoggerFactory.getLogger(ImageDrawerImpl.class);
59
        private Buffer        rasterBuf             = null;
60
        private double[]      step                  = null;
61
        private int           width                 = -1;
62
        private int           height                = -1;
63
        private double        scaleX                = 1; //rate between input and output buffer
64
        private double        scaleY                = 1; 
65
        private Transparency  transparency          = null;
66
        
67
        public ImageDrawerImpl() {
68
        }
69
        
70
        public void setLastTransparency(Transparency t) {
71
                this.transparency = t;
72
        }
73

    
74
        public Image drawBufferOverImageObject() throws ProcessInterruptedException {
75
                if (rasterBuf == null)
76
                        return null;
77

    
78
                try { // Temporal para la traza de un error aleatorio
79
                        boolean supersamplingOn = false;
80
                        BufferedImage image = null;
81
                        if(width <= 0 && height <= 0) {
82
                                width = rasterBuf.getWidth();
83
                                height = rasterBuf.getHeight();
84
                                scaleX = scaleY = 1;
85
                        } else {
86
                                scaleX = rasterBuf.getWidth() / width;
87
                                scaleY = rasterBuf.getHeight() / height;
88
                        }
89
                        image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
90
                        
91
                        if(step != null) {
92
                                supersamplingOn = true;
93
                        }
94

    
95
                        //En el caso de que llegue un buffer que no sea byte es que no se ha aplicado 
96
                        //filtro de realce por lo que habr? que hacer una conversi?n a byte de cualquier manera
97
                        //para que se muestre algo.
98
                        if (rasterBuf.getDataType() != Buffer.TYPE_BYTE)
99
                                rasterBuf = convertToByte(rasterBuf);
100

    
101
                        if (transparency != null && transparency.isTransparencyActive()) {
102
                                drawWithTransparency(image, supersamplingOn, transparency);
103
                        } else
104
                                drawByte(image, supersamplingOn);
105

    
106
                        step = null;
107
                        return image;
108
                } catch (OutOfMemoryError error) { // Temporal para la traza de un error
109
                                                                                        // aleatorio
110
                        log.debug("Buffer: " + rasterBuf.getWidth() + " " + rasterBuf.getHeight() , error);
111
                }
112
                return null;
113
        }
114

    
115
        /**
116
         * Calcula los vectores de desplazamiento en pixels en X e Y cuando se supersamplea.
117
         * @param r Array de desplazamientos para las filas. Debe tener espacio reservado
118
         * @param c Array de desplazamientos para las columnas. Debe tener espacio reservado
119
         * cargados.
120
         */
121
        private void calcSupersamplingStepsArrays(int[] r, int[] c) {
122
                double pos = step[1];
123
                for(int row = 0; row < r.length; row ++) {
124
                        r[row] = (int)(pos / step[3]);
125
                        pos ++;
126
                }
127
                pos = step[0];
128
                for(int col = 0; col < c.length; col ++) {
129
                        c[col] = (int)(pos / step[2]);
130
                        pos ++;
131
                }
132
        }
133

    
134
        /**
135
         * Dibuja un raster sobre un BufferedImage
136
         * @param image BufferedImage sobre el que se dibuja
137
         * @param data buffer vacio. Se trata de un array de bytes donde cada elemento representa una banda.
138
         * @param supersampling true si se necesita supersamplear y false si no se necesita
139
         * @throws ProcessInterruptedException
140
         */
141
        private void drawByte(BufferedImage image, boolean supersampling) throws ProcessInterruptedException {
142
                RasterTask task = RasterTaskQueue.get(Thread.currentThread().getId() + "");
143
                try {
144
                        byte[] data = new byte[rasterBuf.getBandCount()];
145
                        
146
                        if (supersampling) {
147
                                int[] r = new int[height];
148
                                int[] c = new int[width];
149
                                calcSupersamplingStepsArrays(r, c);
150
                                for (int row = 0; row < height; row++) {
151
                                        for (int col = 0; col < width; col++)
152
                                                try {
153
                                                        rasterBuf.getElemByte(r[row], c[col], data);
154
                                                        image.setRGB(col, row, (0xff000000 + ((data[0] & 0xff) << 16)
155
                                                                        + ((data[1] & 0xff) << 8) + (data[2] & 0xff)));
156
                                                } catch (ArrayIndexOutOfBoundsException e) {
157
                                                        log.info("== Size Image:" + image.getWidth() + " " + image.getHeight());
158
                                                        log.info("== Position required:" + col + " " + row);
159
                                                        break;
160
                                                }
161
                                                if (task.getEvent() != null)
162
                                                        task.manageEvent(task.getEvent());
163
                                }
164
                        } else {
165
                                for (int row = 0; row < height; row++) {
166
                                        for (int col = 0; col < width; col++) {
167
                                                try {
168
                                                        rasterBuf.getElemByte((int)(row * scaleY), (int)(col * scaleX), data);
169
                                                        image.setRGB(col, row, (0xff000000 + ((data[0] & 0xff) << 16)
170
                                                                        + ((data[1] & 0xff) << 8) + (data[2] & 0xff)));
171
                                                } catch (ArrayIndexOutOfBoundsException ex) {
172
                                                        log.info("== Size Image:" + image.getWidth() + " " + image.getHeight());
173
                                                        log.info("== Position required:" + (int)(col * scaleX) + " " + (int)(row * scaleY));
174
                                                        break;
175
                                                }
176
                                        }
177
                                        if (task.getEvent() != null)
178
                                                task.manageEvent(task.getEvent());
179
                                }
180
                        }
181
                } catch (Exception e) {
182
                        LoggerFactory.getLogger(this.getClass()).info(
183
                                        "Buffer: " + rasterBuf.getWidth() + " " + rasterBuf.getHeight() , e);
184
                }
185
        }
186

    
187
        /**
188
         * Dibuja un raster sobre un BufferedImage con las propiedades de paleta y transparencia
189
         * @param image BufferedImage sobre el que se dibuja
190
         * @param data buffer vacio. Se trata de un array de bytes donde cada elemento representa una banda.
191
         * @param supersampling true si se necesita supersamplear y false si no se necesita
192
         * @throws ProcessInterruptedException
193
         */
194
        private void drawWithTransparency(BufferedImage image, 
195
                        boolean supersampling,
196
                        Transparency t) throws ProcessInterruptedException {
197
                RasterTask task = RasterTaskQueue.get(Thread.currentThread().getId() + "");
198
                int value = 0;
199
                byte[] data = new byte[rasterBuf.getBandCount()];
200
                try {
201
                        if (supersampling) {
202
                                int[] r = new int[height];
203
                                int[] c = new int[width];
204
                                calcSupersamplingStepsArrays(r, c);
205
                                for (int row = 0; row < height; row++) {
206
                                        for (int col = 0; col < width; col++)
207
                                                try {
208
                                                        rasterBuf.getElemByte(r[row], c[col], data);
209
                                                        value = t.processRGB(data[0] & 0xff, data[1] & 0xff, data[2] & 0xff, r[row], c[col], rasterBuf);
210
                                                        image.setRGB(col, row, value);
211
                                                } catch (ArrayIndexOutOfBoundsException e) {
212
                                                        log.info("== Size Image:" + image.getWidth() + " " + image.getHeight());
213
                                                        log.info("== Position required:" + col + " " + row);
214
                                                        break;
215
                                                }
216
                                                if (task.getEvent() != null)
217
                                                        task.manageEvent(task.getEvent());
218
                                }
219
                        } else {
220
                                for (int row = 0; row < height; row++) {
221
                                        for (int col = 0; col < width; col++) {
222
                                                try {
223
                                                        int r = (int)(row * scaleY);
224
                                                        int c = (int)(col * scaleX);
225
                                                        rasterBuf.getElemByte(r, c, data);
226
                                                        value = t.processRGB(data[0] & 0xff, data[1] & 0xff, data[2] & 0xff, r, c, rasterBuf);
227
                                                        image.setRGB(col, row, value);
228
                                                } catch (ArrayIndexOutOfBoundsException e) {
229
                                                        log.info("== Size Image:" + image.getWidth() + " " + image.getHeight());
230
                                                        log.info("== Position required:" + col + " " + row);
231
                                                        break;
232
                                                }  //catch (Exception e) {
233
                                                //System.out.println("Row:" + (int)(row * scaleY) + " Col:" + (int)(col * scaleX) + " " + rasterBuf.getBandCount() + " " + data.length);
234
                                                //}
235
                                        }
236
                                        if (task.getEvent() != null)
237
                                                task.manageEvent(task.getEvent());
238
                                }
239

    
240
                        }
241
                } catch (Exception e) {
242
                        LoggerFactory.getLogger(this.getClass()).info(
243
                                        "Buffer: " + rasterBuf.getWidth() + " " + rasterBuf.getHeight() , e);
244
                }
245
        }        
246

    
247
        /**
248
         * Converts a Buffer object into a byte
249
         * @param buf
250
         * @return
251
         */
252
        private Buffer convertToByte(Buffer buf) {
253
                Buffer b = DefaultRasterManager.getInstance().createBuffer(Buffer.TYPE_BYTE, buf.getWidth(), buf.getHeight(), buf.getBandCount(), true);
254
                if(buf.getDataType() == Buffer.TYPE_SHORT)
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)(buf.getElemShort(row, col, nBand) & 0xffff));
259
                if(buf.getDataType() == Buffer.TYPE_INT)
260
                        for (int nBand = 0; nBand < buf.getBandCount(); nBand++)
261
                                for (int row = 0; row < buf.getHeight(); row++)
262
                                        for (int col = 0; col < buf.getWidth(); col++)
263
                                                b.setElem(row, col, nBand, (byte)(buf.getElemInt(row, col, nBand) & 0xffffffff));
264
                if(buf.getDataType() == Buffer.TYPE_FLOAT)
265
                        for (int nBand = 0; nBand < buf.getBandCount(); nBand++)
266
                                for (int row = 0; row < buf.getHeight(); row++)
267
                                        for (int col = 0; col < buf.getWidth(); col++)
268
                                                b.setElem(row, col, nBand, (byte)(Math.round(buf.getElemFloat(row, col, nBand))));
269
                if(buf.getDataType() == Buffer.TYPE_DOUBLE)
270
                        for (int nBand = 0; nBand < buf.getBandCount(); nBand++)
271
                                for (int row = 0; row < buf.getHeight(); row++)
272
                                        for (int col = 0; col < buf.getWidth(); col++)
273
                                                b.setElem(row, col, nBand, (byte)(Math.round(buf.getElemDouble(row, col, nBand))));
274
                return b;
275
        }
276

    
277
        public void setBuffer(Buffer b) {
278
                this.rasterBuf = b;
279
        }
280

    
281
        public void setSupersamplingOn(double[] step) {
282
                this.step = step;
283
        }
284

    
285
        public void setOutputSize(int w, int h) {
286
                this.width = w;
287
                this.height = h;
288
        }
289
        
290
        public void dispose() {
291
                if(rasterBuf != null)
292
                        rasterBuf.dispose();
293
                if(transparency != null)
294
                        transparency.dispose();
295
                try {
296
                        finalize();
297
                } catch (Throwable e) {
298
                }
299
        }
300
        
301
        /*
302
         * (non-Javadoc)
303
         * @see org.gvsig.fmap.dal.coverage.grid.render.ImageDrawer#addEnhanced(org.gvsig.fmap.dal.coverage.store.props.Statistics)
304
         */
305
        public Buffer addEnhanced(Statistics stats) {
306
                return addEnhanced(stats, true, 0.0);
307
        }
308

    
309
        public Buffer addEnhanced(Statistics stats, boolean tailTrim, double tailTrimValue) {
310
                RasterFilterList filterList = RasterLocator.getManager().createEmptyFilterList(rasterBuf.getDataType());
311

    
312
                try {
313
                        /*RasterFilterListManager enhancementManager = filterList.getManagerByID("EnhancementStretch");
314
                        Params params = filterList.createEmptyFilterParams();
315
                        params.setParam("stats", stats);
316
                        params.setParam("remove", new Boolean(false));
317
                        int[] renderBands = new int[rasterBuf.getBandCount()];
318
                        for (int i = 0; i < renderBands.length; i++) {
319
                                renderBands[i] = i;
320
                        }
321
                        params.setParam("renderBands", renderBands);
322
                        params.setParam("stretchs", null);//coge el LinearStretchParams por defecto
323
                        params.setParam("rgb", new Boolean(true));
324

325
                        enhancementManager.addFilter(params);
326
                         */
327
                        EnhancementStretchListManager enhancementManager = (EnhancementStretchListManager) filterList.getManagerByClass(EnhancementStretchListManager.class);
328
                        int[] renderBands = new int[rasterBuf.getBandCount()];
329
                        for (int i = 0; i < renderBands.length; i++) {
330
                                renderBands[i] = i;
331
                        }
332
                        enhancementManager.addEnhancedStretchFilter(
333
                                        DefaultLinearStretchParams.createStandardParam(new int[] { 0, 1, 2 }, tailTrimValue, stats, true), 
334
                                        stats, 
335
                                        renderBands, 
336
                                        tailTrim);
337
                } catch (FilterTypeException e1) {
338
                } catch (FileNotOpenException e) {
339
                } catch (RasterDriverException e) {
340
                }
341

    
342
                if(filterList != null) {
343
                        Extent ext = RasterLocator.getManager().getDataStructFactory().
344
                                createExtent(rasterBuf.getDataExtent());
345
                        filterList.addEnvParam("SrcStatistics", stats);
346
                        filterList.addEnvParam("Transparency", transparency);
347
                        filterList.addEnvParam("GridExtent", ext);
348
                        filterList.addEnvParam("WindowExtent", ext);
349
                        filterList.setInitRasterBuf(rasterBuf);
350
                        try {
351
                                filterList.execute();
352
                        } catch (ProcessInterruptedException e) {
353
                                return rasterBuf;
354
                        } catch (FilterAddException e) {
355
                                log.debug("Filters cannot be added", e);
356
                                return rasterBuf;
357
                        }
358
                        rasterBuf = (RasterBuffer) filterList.getResult();
359
                }
360
                return rasterBuf;
361
        }
362
        
363
        protected void finalize() throws Throwable {
364
                step        = null;
365
                rasterBuf   = null;
366
                transparency = null;
367
                super.finalize();
368
        }
369

    
370
}