Statistics
| Revision:

gvsig-raster / org.gvsig.raster / trunk / org.gvsig.raster / org.gvsig.raster.lib / org.gvsig.raster.lib.impl / src / main / java / org / gvsig / raster / impl / grid / render / ImageDrawerImpl.java @ 1419

History | View | Annotate | Download (15.1 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.FilterTypeException;
32
import org.gvsig.fmap.dal.coverage.exception.ProcessInterruptedException;
33
import org.gvsig.fmap.dal.coverage.exception.RasterDriverException;
34
import org.gvsig.fmap.dal.coverage.grid.RasterFilterList;
35
import org.gvsig.fmap.dal.coverage.grid.render.ImageDrawer;
36
import org.gvsig.fmap.dal.coverage.store.props.Statistics;
37
import org.gvsig.fmap.dal.coverage.store.props.Transparency;
38
import org.gvsig.raster.impl.DefaultRasterManager;
39
import org.gvsig.raster.impl.buffer.RasterBuffer;
40
import org.gvsig.raster.impl.grid.filter.enhancement.DefaultLinearStretchParams;
41
import org.gvsig.raster.impl.grid.filter.enhancement.EnhancementStretchListManager;
42
import org.gvsig.raster.impl.process.RasterTask;
43
import org.gvsig.raster.impl.process.RasterTaskQueue;
44
import org.slf4j.LoggerFactory;
45

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

    
75
        /*
76
         * (non-Javadoc)
77
         * @see org.gvsig.fmap.dal.coverage.grid.render.ImageDrawer#drawBufferOverImageObject()
78
         */
79
        public Image drawBufferOverImageObject() throws ProcessInterruptedException {
80
                if (rasterBuf == null)
81
                        return null;
82

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

    
100
                        if (rasterBuf.getDataType() != Buffer.TYPE_BYTE)
101
                                rasterBuf = convertToByte(rasterBuf);
102

    
103
                        byte[] data = new byte[rasterBuf.getBandCount()];
104

    
105
                        if (transparency != null && transparency.isTransparencyActive()) {
106
                                if (transparency.existAlphaBand() && 
107
                                        transparency.getAlphaBand() != null && 
108
                                        transparency.getAlphaBand().getDataType() != Buffer.TYPE_BYTE) {
109
                                        transparency.setAlphaBand(convertToByte(transparency.getAlphaBand()));
110
                                }
111
                                drawWithTransparency(image, data, supersamplingOn, transparency);
112
                        } else
113
                                drawByte(image, data, supersamplingOn);
114

    
115
                        step = null;
116
                        return image;
117
                } catch (OutOfMemoryError error) { // Temporal para la traza de un error
118
                                                                                        // aleatorio
119
                        LoggerFactory.getLogger(this.getClass()).debug(
120
                                        "Buffer: " + rasterBuf.getWidth() + " " + rasterBuf.getHeight() , error);
121
                }
122
                return null;
123
        }
124

    
125
        /**
126
         * Calcula los vectores de desplazamiento en pixels en X e Y cuando se supersamplea.
127
         * @param r Array de desplazamientos para las filas. Debe tener espacio reservado
128
         * @param c Array de desplazamientos para las columnas. Debe tener espacio reservado
129
         * cargados.
130
         */
131
        private void calcSupersamplingStepsArrays(int[] r, int[] c) {
132
                double pos = step[1];
133
                for(int row = 0; row < r.length; row ++) {
134
                        r[row] = (int)(pos / step[3]);
135
                        pos ++;
136
                }
137
                pos = step[0];
138
                for(int col = 0; col < c.length; col ++) {
139
                        c[col] = (int)(pos / step[2]);
140
                        pos ++;
141
                }
142
        }
143

    
144
        /**
145
         * Dibuja un raster sobre un BufferedImage
146
         * @param image BufferedImage sobre el que se dibuja
147
         * @param data buffer vacio. Se trata de un array de bytes donde cada elemento representa una banda.
148
         * @param supersampling true si se necesita supersamplear y false si no se necesita
149
         * @throws ProcessInterruptedException
150
         */
151
        private void drawByte(BufferedImage image, byte[] data, boolean supersampling) throws ProcessInterruptedException {
152
                RasterTask task = RasterTaskQueue.get(Thread.currentThread().getId() + "");
153

    
154
                if (supersampling) {
155
                        int[] r = new int[height];
156
                        int[] c = new int[width];
157
                        calcSupersamplingStepsArrays(r, c);
158
                        for (int row = 0; row < height; row++) {
159
                                for (int col = 0; col < width; col++)
160
                                        try {
161
                                                rasterBuf.getElemByte(r[row], c[col], data);
162
                                                image.setRGB(col, row, (0xff000000 + ((data[0] & 0xff) << 16)
163
                                                                + ((data[1] & 0xff) << 8) + (data[2] & 0xff)));
164
                                        } catch (ArrayIndexOutOfBoundsException e) {
165
                                                System.err.println("== Size Image:" + image.getWidth() + " " + image.getHeight());
166
                                                System.err.println("== Position required:" + col + " " + row);
167
                                                break;
168
                                        }
169
                                if (task.getEvent() != null)
170
                                        task.manageEvent(task.getEvent());
171
                        }
172
                } else {
173
                        /*Old code
174
                          for (int row = 0; row < rasterBuf.getHeight(); row++) {
175
                                for (int col = 0; col < rasterBuf.getWidth(); col++)
176
                                        try {
177
                                                rasterBuf.getElemByte(row, col, data);
178
                                                image.setRGB(col, row, (0xff000000 + ((data[0] & 0xff) << 16)
179
                                                                + ((data[1] & 0xff) << 8) + (data[2] & 0xff)));
180
                                        } catch (ArrayIndexOutOfBoundsException ex) {
181
                                                System.err.println("== Size Image:" + image.getWidth() + " " + image.getHeight());
182
                                                System.err.println("== Position required:" + col + " " + row);
183
                                                break;
184
                                        }
185
                                if (task.getEvent() != null)
186
                                        task.manageEvent(task.getEvent());
187
                        }*/
188
                        for (int row = 0; row < height; row++) {
189
                                for (int col = 0; col < width; col++) {
190
                                        try {
191
                                                rasterBuf.getElemByte((int)(row * scaleY), (int)(col * scaleX), data);
192
                                                image.setRGB(col, row, (0xff000000 + ((data[0] & 0xff) << 16)
193
                                                                + ((data[1] & 0xff) << 8) + (data[2] & 0xff)));
194
                                        } catch (ArrayIndexOutOfBoundsException ex) {
195
                                                System.err.println("== Size Image:" + image.getWidth() + " " + image.getHeight());
196
                                                System.err.println("== Position required:" + (int)(col * scaleX) + " " + (int)(row * scaleY));
197
                                                break;
198
                                        }
199
                                }
200
                                if (task.getEvent() != null)
201
                                        task.manageEvent(task.getEvent());
202
                        }
203
                }
204
        }
205

    
206
        /**
207
         * Dibuja un raster sobre un BufferedImage con las propiedades de paleta y transparencia
208
         * @param image BufferedImage sobre el que se dibuja
209
         * @param data buffer vacio. Se trata de un array de bytes donde cada elemento representa una banda.
210
         * @param supersampling true si se necesita supersamplear y false si no se necesita
211
         * @throws ProcessInterruptedException
212
         */
213
        private void drawWithTransparency(BufferedImage image, 
214
                        byte[] data, 
215
                        boolean supersampling,
216
                        Transparency t) throws ProcessInterruptedException {
217
                RasterTask task = RasterTaskQueue.get(Thread.currentThread().getId() + "");
218
                int value = 0;
219
//                try {
220
                if (supersampling) {
221
                        int[] r = new int[height];
222
                        int[] c = new int[width];
223
                        calcSupersamplingStepsArrays(r, c);
224
                        for (int row = 0; row < height; row++) {
225
                                for (int col = 0; col < width; col++)
226
                                        try {
227
                                                rasterBuf.getElemByte(r[row], c[col], data);
228
                                                value = t.processRGB(data[0] & 0xff, data[1] & 0xff, data[2] & 0xff, r[row], c[col]);
229
                                                image.setRGB(col, row, value);
230
                                        } catch (ArrayIndexOutOfBoundsException e) {
231
                                                System.err.println("== Size Image:" + image.getWidth() + " " + image.getHeight());
232
                                                System.err.println("== Position required:" + col + " " + row);
233
                                                break;
234
                                        }
235
                                if (task.getEvent() != null)
236
                                        task.manageEvent(task.getEvent());
237
                        }
238
                } else {
239
                        /*Old code
240
                        for (int row = 0; row < rasterBuf.getHeight(); row++) {
241
                                for (int col = 0; col < rasterBuf.getWidth(); col++)
242
                                        try {
243
                                                rasterBuf.getElemByte(row, col, data);
244
                                                value = t.processRGB(data[0] & 0xff, data[1] & 0xff, data[2] & 0xff, row, col);
245
                                                image.setRGB(col, row, value);
246
                                        } catch (ArrayIndexOutOfBoundsException e) {
247
                                                System.err.println("== Size Image:" + image.getWidth() + " " + image.getHeight());
248
                                                System.err.println("== Position required:" + col + " " + row);
249
                                                break;
250
                                        }
251
                                if (task.getEvent() != null)
252
                                        task.manageEvent(task.getEvent());
253
                        }
254
                        */
255
                        for (int row = 0; row < height; row++) {
256
                                for (int col = 0; col < width; col++) {
257
                                        try {
258
                                                int r = (int)(row * scaleY);
259
                                                int c = (int)(col * scaleX);
260
                                                rasterBuf.getElemByte(r, c, data);
261
                                                value = t.processRGB(data[0] & 0xff, data[1] & 0xff, data[2] & 0xff, r, c);
262
                                                image.setRGB(col, row, value);
263
                                        } catch (ArrayIndexOutOfBoundsException e) {
264
                                                System.err.println("== Size Image:" + image.getWidth() + " " + image.getHeight());
265
                                                System.err.println("== Position required:" + col + " " + row);
266
                                                break;
267
                                        }
268
                                }
269
                                if (task.getEvent() != null)
270
                                        task.manageEvent(task.getEvent());
271
                        }
272
                }
273
        }        
274

    
275
        /**
276
         * Converts a Buffer object into a byte
277
         * @param buf
278
         * @return
279
         */
280
        private Buffer convertToByte(Buffer buf) {
281
                Buffer b = DefaultRasterManager.getInstance().createBuffer(Buffer.TYPE_BYTE, buf.getWidth(), buf.getHeight(), buf.getBandCount(), true);
282
                if(buf.getDataType() == Buffer.TYPE_SHORT)
283
                        for (int nBand = 0; nBand < buf.getBandCount(); nBand++)
284
                                for (int row = 0; row < buf.getHeight(); row++)
285
                                        for (int col = 0; col < buf.getWidth(); col++)
286
                                                b.setElem(row, col, nBand, (byte)(buf.getElemShort(row, col, nBand) & 0xffff));
287
                if(buf.getDataType() == Buffer.TYPE_INT)
288
                        for (int nBand = 0; nBand < buf.getBandCount(); nBand++)
289
                                for (int row = 0; row < buf.getHeight(); row++)
290
                                        for (int col = 0; col < buf.getWidth(); col++)
291
                                                b.setElem(row, col, nBand, (byte)(buf.getElemInt(row, col, nBand) & 0xffffffff));
292
                if(buf.getDataType() == Buffer.TYPE_FLOAT)
293
                        for (int nBand = 0; nBand < buf.getBandCount(); nBand++)
294
                                for (int row = 0; row < buf.getHeight(); row++)
295
                                        for (int col = 0; col < buf.getWidth(); col++)
296
                                                b.setElem(row, col, nBand, (byte)(Math.round(buf.getElemFloat(row, col, nBand))));
297
                if(buf.getDataType() == Buffer.TYPE_DOUBLE)
298
                        for (int nBand = 0; nBand < buf.getBandCount(); nBand++)
299
                                for (int row = 0; row < buf.getHeight(); row++)
300
                                        for (int col = 0; col < buf.getWidth(); col++)
301
                                                b.setElem(row, col, nBand, (byte)(Math.round(buf.getElemDouble(row, col, nBand))));
302
                return b;
303
        }
304

    
305
        /*
306
         * (non-Javadoc)
307
         * @see org.gvsig.fmap.dal.coverage.grid.render.ImageDrawer#setBuffer(org.gvsig.fmap.dal.coverage.dataset.Buffer)
308
         */
309
        public void setBuffer(Buffer b) {
310
                this.rasterBuf = b;
311
        }
312

    
313
        /*
314
         * (non-Javadoc)
315
         * @see org.gvsig.fmap.dal.coverage.grid.render.ImageDrawer#setSupersamplingOn(double[], int, int)
316
         */
317
        public void setSupersamplingOn(double[] step) {
318
                this.step = step;
319
        }
320

    
321
        /*
322
         * (non-Javadoc)
323
         * @see org.gvsig.fmap.dal.coverage.grid.render.ImageDrawer#setOutPutSize(int, int)
324
         */
325
        public void setOutputSize(int w, int h) {
326
                this.width = w;
327
                this.height = h;
328
        }
329
        
330
        /*
331
         * (non-Javadoc)
332
         * @see org.gvsig.fmap.dal.coverage.grid.render.ImageDrawer#dispose()
333
         */
334
        public void dispose() {
335
                if(rasterBuf != null)
336
                        rasterBuf.dispose();
337
                try {
338
                        finalize();
339
                } catch (Throwable e) {
340
                }
341
        }
342
        
343
        /*
344
         * (non-Javadoc)
345
         * @see org.gvsig.fmap.dal.coverage.grid.render.ImageDrawer#addEnhanced(org.gvsig.fmap.dal.coverage.store.props.Statistics)
346
         */
347
        public Buffer addEnhanced(Statistics stats) {
348
                return addEnhanced(stats, true, 0.0);
349
        }
350

    
351
        /*
352
         * (non-Javadoc)
353
         * @see org.gvsig.fmap.dal.coverage.grid.render.ImageDrawer#addEnhanced(org.gvsig.fmap.dal.coverage.store.props.Statistics)
354
         */
355
        public Buffer addEnhanced(Statistics stats, boolean tailTrim, double tailTrimValue) {
356
                RasterFilterList filterList = RasterLocator.getManager().createEmptyFilterList(rasterBuf.getDataType());
357

    
358
                try {
359
                        /*RasterFilterListManager enhancementManager = filterList.getManagerByID("EnhancementStretch");
360
                        Params params = filterList.createEmptyFilterParams();
361
                        params.setParam("stats", stats);
362
                        params.setParam("remove", new Boolean(false));
363
                        int[] renderBands = new int[rasterBuf.getBandCount()];
364
                        for (int i = 0; i < renderBands.length; i++) {
365
                                renderBands[i] = i;
366
                        }
367
                        params.setParam("renderBands", renderBands);
368
                        params.setParam("stretchs", null);//coge el LinearStretchParams por defecto
369
                        params.setParam("rgb", new Boolean(true));
370

371
                        enhancementManager.addFilter(params);
372
                         */
373
                        EnhancementStretchListManager enhancementManager = (EnhancementStretchListManager) filterList.getManagerByClass(EnhancementStretchListManager.class);
374
                        int[] renderBands = new int[rasterBuf.getBandCount()];
375
                        for (int i = 0; i < renderBands.length; i++) {
376
                                renderBands[i] = i;
377
                        }
378
                        enhancementManager.addEnhancedStretchFilter(
379
                                        DefaultLinearStretchParams.createStandardParam(new int[] { 0, 1, 2 }, tailTrimValue, stats, true), 
380
                                        stats, 
381
                                        renderBands, 
382
                                        tailTrim);
383
                } catch (FilterTypeException e1) {
384
                } catch (FileNotOpenException e) {
385
                } catch (RasterDriverException e) {
386
                }
387

    
388
                if(filterList != null) {
389
                        Extent ext = RasterLocator.getManager().getDataStructFactory().
390
                                createExtent(rasterBuf.getDataExtent());
391
                        filterList.addEnvParam("IStatistics", stats);
392
                        filterList.addEnvParam("Transparency", transparency);
393
                        filterList.addEnvParam("GridExtent", ext);
394
                        filterList.addEnvParam("WindowExtent", ext);
395
                        filterList.setInitRasterBuf(rasterBuf);
396
                        try {
397
                                filterList.execute();
398
                        } catch (ProcessInterruptedException e) {
399
                                return rasterBuf;
400
                        }
401
                        rasterBuf = (RasterBuffer) filterList.getResult();
402
                }
403
                return rasterBuf;
404
        }
405
        
406
        /*
407
         * (non-Javadoc)
408
         * @see java.lang.Object#finalize()
409
         */
410
        protected void finalize() throws Throwable {
411
                step        = null;
412
                rasterBuf   = null;
413
                super.finalize();
414
        }
415

    
416
}