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 / provider / tile / BaseTileDownloader.java @ 2236

History | View | Annotate | Download (14 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.provider.tile;
23

    
24
import java.awt.Graphics;
25
import java.awt.Rectangle;
26
import java.awt.color.ColorSpace;
27
import java.awt.geom.AffineTransform;
28
import java.awt.image.BufferedImage;
29
import java.io.IOException;
30

    
31
import javax.swing.ImageIcon;
32

    
33
import org.gvsig.fmap.dal.coverage.RasterLocator;
34
import org.gvsig.fmap.dal.coverage.RasterManager;
35
import org.gvsig.fmap.dal.coverage.dataset.Buffer;
36
import org.gvsig.fmap.dal.coverage.datastruct.BandList;
37
import org.gvsig.fmap.dal.coverage.datastruct.DatasetBand;
38
import org.gvsig.fmap.dal.coverage.datastruct.Extent;
39
import org.gvsig.fmap.dal.coverage.datastruct.NoData;
40
import org.gvsig.fmap.dal.coverage.datastruct.Params;
41
import org.gvsig.fmap.dal.coverage.exception.BandNotFoundInListException;
42
import org.gvsig.fmap.dal.coverage.exception.NotSupportedExtensionException;
43
import org.gvsig.fmap.dal.coverage.exception.ProcessInterruptedException;
44
import org.gvsig.fmap.dal.coverage.exception.QueryException;
45
import org.gvsig.fmap.dal.coverage.exception.RasterDriverException;
46
import org.gvsig.fmap.dal.coverage.store.DataServerWriter;
47
import org.gvsig.fmap.dal.coverage.store.RasterDataStore;
48
import org.gvsig.fmap.dal.coverage.store.RasterQuery;
49
import org.gvsig.fmap.dal.coverage.store.RasterWriter;
50
import org.gvsig.fmap.dal.coverage.store.props.ColorInterpretation;
51
import org.gvsig.fmap.dal.exception.InitializeException;
52
import org.gvsig.fmap.dal.exception.ProviderNotRegisteredException;
53
import org.gvsig.raster.cache.tile.Tile;
54
import org.gvsig.raster.cache.tile.exception.TileGettingException;
55
import org.gvsig.raster.cache.tile.provider.Downloader;
56
import org.gvsig.raster.impl.RasterDefaultImplLibrary;
57
import org.gvsig.raster.impl.buffer.DefaultRasterQuery;
58
import org.gvsig.raster.impl.datastruct.BandListImpl;
59
import org.gvsig.raster.impl.datastruct.DatasetBandImpl;
60
import org.gvsig.raster.impl.provider.AbstractRasterProvider;
61
import org.gvsig.raster.impl.provider.RasterProvider;
62
import org.gvsig.raster.impl.store.DefaultRasterStore;
63
import org.gvsig.raster.util.DefaultProviderServices;
64

    
65
/** 
66
 * Base class for downloaders  
67
 * @author Nacho Brodin (nachobrodin@gmail.com)
68
 */
69
public abstract class BaseTileDownloader implements Downloader {
70
        protected int                           tilePxWidth       = 0;
71
        protected int                           tilePxHeight      = 0;
72
        protected RasterDataStore               store              = null;
73
        protected byte                          byteNoData        = (byte)0x00;
74
        protected short                         shortNoData       = Short.MIN_VALUE;
75
        protected int                           intNoData         = Integer.MIN_VALUE;
76
        protected float                         floatNoData       = -99999;
77
        protected double                        doubleNoData      = -99999;
78
        
79
        public BaseTileDownloader(RasterDataStore store, int tilePxWidth, int tilePxHeight) {
80
                this.store = store;
81
                this.tilePxWidth = tilePxWidth;
82
                this.tilePxHeight = tilePxHeight;
83
                if(store.getNoDataValue() != null && store.getNoDataValue().isDefined())
84
                        setNoDataValue(store.getNoDataValue());
85
        }
86
        
87
        /**
88
         * Gets the image that represent a tile while is downloading. 
89
         * @return
90
         */
91
        public Object[] getDownloadingImage(int w, int h) {
92
                if(RasterDefaultImplLibrary.downloadingImg == null)
93
                        return null;
94
                String key = w + "X" + h + "_Downloading";
95
                return getBufferFromImageIcon(w, h, key, RasterDefaultImplLibrary.downloadingImg);
96
        }
97
        
98
        /**
99
         * Gets the image that represent a crash tile
100
         * @return
101
         */
102
        public Object[] getCrashImage(int w, int h) {
103
                if(RasterDefaultImplLibrary.crashImg == null)
104
                        return null;
105
                String key = w + "X" + h + "_Crash";
106
                return getBufferFromImageIcon(w, h, key, RasterDefaultImplLibrary.crashImg);
107
        }
108
        
109
        private Buffer[] getBufferFromImageIcon(int w, int h, String key, ImageIcon icon) {
110
                Buffer buf = RasterDefaultImplLibrary.defaultImages.get(key);
111
                Buffer alpha = RasterDefaultImplLibrary.defaultImages.get(key + "_Alpha");
112
                if(buf == null) {
113
                        buf = RasterLocator.getManager().createBuffer(Buffer.TYPE_BYTE, w, h, 3, true);
114
                        alpha = RasterLocator.getManager().createBuffer(Buffer.TYPE_BYTE, w, h, 1, true);
115
                        byte[] background = new byte[]{-1, -1, -1};
116
                        for (int i = 0; i < buf.getHeight(); i++)
117
                                for (int j = 0; j < buf.getWidth(); j++) {
118
                                        buf.setElemByte(j, i, background);
119
                                        alpha.setElem(j, i, 0, (byte)50);
120
                                }
121
                        
122
                        BufferedImage img = new BufferedImage(icon.getIconWidth(), icon.getIconHeight(), ColorSpace.TYPE_RGB);
123
                        Graphics g = img.createGraphics();
124
                    g.drawImage(icon.getImage(), 0, 0, null);
125
                        int initX = (w / 2) - (img.getWidth() / 2);
126
                        int initY = (h / 2) - (img.getHeight() / 2);
127
                        for (int i = initY; i < (img.getHeight() + initY); i++) {
128
                                for (int j = initX; j < (img.getWidth() + initX); j++) {
129
                                        int value = img.getRGB(j - initX, i - initY);
130
                                        buf.setElem(i, j, 0, (byte)((value & 0x00ff0000) >> 16));
131
                                        buf.setElem(i, j, 1, (byte)((value & 0x0000ff00) >> 8));
132
                                        buf.setElem(i, j, 2, (byte)(value & 0x000000ff));
133
                                }
134
                        }
135
                        RasterDefaultImplLibrary.defaultImages.put(key, buf);
136
                        RasterDefaultImplLibrary.defaultImages.put(key + "_Alpha", buf);
137
                }
138
                return new Buffer[]{buf, alpha};
139
        }
140
        
141
        /**
142
         * Gets the size of a tile in pixels 
143
         * @return Array of two integers. The first integer is the width and the second the height in pixels
144
         */
145
        public int[] getTileSize() {
146
                return new int[]{tilePxWidth, tilePxHeight};
147
        }
148
        
149
        /**
150
         * Sets the nodata value
151
         * @param noData
152
         */
153
        public void setNoDataValue(NoData noData) {
154
                switch (store.getDataType()[0]) {
155
                case Buffer.TYPE_BYTE:
156
                        byteNoData = noData.getValue().byteValue();
157
                        break;
158
                case Buffer.TYPE_SHORT:
159
                        shortNoData = noData.getValue().shortValue();
160
                        break;
161
                case Buffer.TYPE_INT:
162
                        intNoData = noData.getValue().intValue();
163
                        break;
164
                case Buffer.TYPE_FLOAT:
165
                        floatNoData = noData.getValue().floatValue();
166
                        break;
167
                case Buffer.TYPE_DOUBLE:
168
                        doubleNoData = ((NoData)noData).getValue().doubleValue();
169
                        break;
170
                }
171
        }
172

    
173
        public Tile readTileFromDisk(Tile tile) throws TileGettingException {
174
                if(!tile.getFile().exists()) {
175
                        tile.setCorrupt(true);
176
                        return null;
177
                }
178
                
179
                BandList bandList = (BandList)tile.getDownloaderParams("BandList");
180
                /*for (int j = 0; j < bandList.getBandCount(); j++) {
181
                        bandList.getBand(j).setFileName(tile.getFile().getAbsolutePath());
182
                }
183
                
184
                int mallocNBands = 0;
185
                if(bandList.getDrawableBands() != null)
186
                        mallocNBands = bandList.getDrawableBands().length;
187
                else
188
                        mallocNBands = bandList.getDrawableBandsCount();*/
189
                
190
                try {
191
                        DefaultRasterStore tileStore = new DefaultRasterStore();
192
                        AbstractRasterProvider tileProvider = DefaultProviderServices.loadProvider(tile.getFile());
193
                        tileStore.setProvider(tileProvider);
194
                        this.tilePxWidth = tile.getWidthPx();
195
                        this.tilePxHeight = tile.getHeightPx();
196
                        //int mallocNBands = prov.getDataType()[0] == Buffer.TYPE_BYTE ? provider.getBandCount() - 1 : provider.getBandCount();
197
                        //Buffer buf = DefaultRasterManager.getInstance().createMemoryBuffer(store.getDataType()[0], this.tilePxWidth, this.tilePxHeight, mallocNBands, true);
198
                        //Buffer transparency = DefaultRasterManager.getInstance().createMemoryBuffer(store.getDataType()[0], this.tilePxWidth, this.tilePxHeight, 1, true);
199
                        
200
                        //buf = provider.getWindow((int)0, (int)0, createBandListFromProvider(provider), buf);
201
                        
202
                        RasterQuery q = RasterLocator.getManager().createQuery();
203
                        
204
                        q.setAreaOfInterest(new Rectangle((int)0, (int)0, this.tilePxWidth, this.tilePxHeight));
205
                        q.setDrawableBands(bandList.getDrawableBands());//;.setBandList(bandList);
206
                        Buffer buf = tileStore.query(q);
207
                        
208
                        if(tileStore.getTransparency().getAlphaBandNumber() >= 0) {
209
                                //Lee la banda de transparencia para eliminar la zona del tile que est? fuera de la imagen
210
                                //BandList newBandList = new BandListImpl(tile.getFile().getAbsolutePath(), tileStore.getBandCount(), tileStore.getDataType()[0]);
211
                                //newBandList.clearDrawableBands();
212
                                //newBandList.addDrawableBand(0, tileStore.getBandCount() - 1);
213
                                
214
                                q = RasterLocator.getManager().createQuery();
215
                                q.setAreaOfInterest(new Rectangle((int)0, (int)0, this.tilePxWidth, this.tilePxHeight));
216
                                q.setDrawableBands(new int[]{tileStore.getBandCount() - 1});//.setBandList(newBandList);
217
                                Buffer transparency = tileStore.query(q);
218
                                
219
                                tile.setData(new Object[]{buf, transparency, null});
220
                        } else
221
                                tile.setData(new Object[]{buf, null, tileStore.getColorTable()});
222
                        
223
                        buf.setDataExtent(tileStore.getExtent().toRectangle2D());
224
                        tileStore.close();
225
                        return tile;
226
                } catch (ProcessInterruptedException e) {
227
                        throw new TileGettingException(e);
228
                } catch (ProviderNotRegisteredException e) {
229
                        throw new TileGettingException(e);
230
                } catch (InitializeException e) {
231
                        throw new TileGettingException(e);
232
                } catch (QueryException e) {
233
                        throw new TileGettingException(e);
234
                }
235
        }
236
        
237
        /**
238
         * Builds a BandList structure using all bands of a raster provider
239
         * @param prov
240
         * @return
241
         */
242
        @SuppressWarnings("unused")
243
        private BandList createBandListFromProvider(RasterProvider prov) {
244
                BandList bandList = new BandListImpl();
245
                bandList.clear();
246
                int nBands = prov.getDataType()[0] == Buffer.TYPE_BYTE ? prov.getBandCount() - 1 : prov.getBandCount();
247
                
248
                int[] drawableBands = new int[nBands];
249
                for(int i = 0; i < nBands; i++) {
250
                        try {
251
                                int dataType = prov.getDataType()[i];
252
                                DatasetBand band = new DatasetBandImpl(prov.getURIByBand(i), 
253
                                                                                                        prov.getBandPositionByProvider(i), 
254
                                                                                                        dataType, 
255
                                                                                                        nBands);
256
                                bandList.addBand(band);
257
                                drawableBands[i] = i;
258
                        } catch(BandNotFoundInListException ex) {
259
                                //No a?adimos la banda
260
                        }
261
                }
262
                bandList.setDrawableBands(drawableBands);
263
                return bandList;
264
        }
265
        
266
        /**
267
         * Sets a band to NODATA value 
268
         * @param bufResult
269
         * @param tileExtent
270
         * @param buf
271
         * @param ex
272
         * @param pixelSize
273
         */
274
        protected void clearMaskBuffer(Buffer buf, int nBand) {
275
                if(buf.getDataType() == Buffer.TYPE_BYTE) {
276
                        for (int i = 0; i < buf.getHeight(); i++) {
277
                                for (int j = 0; j < buf.getWidth(); j++) {
278
                                        buf.setElem(i, j, nBand, byteNoData);
279
                                }
280
                        }
281
                        return;
282
                }
283
                if(buf.getDataType() == Buffer.TYPE_SHORT) {
284
                        for (int i = 0; i < buf.getHeight(); i++) {
285
                                for (int j = 0; j < buf.getWidth(); j++) {
286
                                        buf.setElem(i, j, nBand, shortNoData);
287
                                }
288
                        }
289
                        return;
290
                }
291
                if(buf.getDataType() == Buffer.TYPE_INT) {
292
                        for (int i = 0; i < buf.getHeight(); i++) {
293
                                for (int j = 0; j < buf.getWidth(); j++) {
294
                                        buf.setElem(i, j, nBand, intNoData);
295
                                }
296
                        }
297
                        return;
298
                }
299
                if(buf.getDataType() == Buffer.TYPE_FLOAT) {
300
                        for (int i = 0; i < buf.getHeight(); i++) {
301
                                for (int j = 0; j < buf.getWidth(); j++) {
302
                                        buf.setElem(i, j, nBand, floatNoData);
303
                                }
304
                        }
305
                        return;
306
                }
307
                if(buf.getDataType() == Buffer.TYPE_DOUBLE) {
308
                        for (int i = 0; i < buf.getHeight(); i++) {
309
                                for (int j = 0; j < buf.getWidth(); j++) {
310
                                        buf.setElem(i, j, nBand, doubleNoData);
311
                                }
312
                        }
313
                        return;
314
                }
315
        }
316
        
317
        /**
318
         * Saves a buffer to disk
319
         * @param bufResult Buffer to save
320
         * @param pixelSize Pixel size
321
         * @param extension output file format
322
         * @param alphaBand true if it has alpha band
323
         * @param path Path to the new file
324
         * @param tileExtent Bounding box of the tile
325
         * @throws NotSupportedExtensionException
326
         * @throws RasterDriverException
327
         * @throws ProcessInterruptedException
328
         * @throws IOException
329
         */
330
        protected void saveTile(Buffer bufResult, 
331
                        double pixelSize, 
332
                        String extension, 
333
                        boolean alphaBand, 
334
                        Tile tile, 
335
                        Extent tileExtent,
336
                        ColorInterpretation colorInterpretation) throws NotSupportedExtensionException, RasterDriverException, ProcessInterruptedException, IOException {
337
                //Escritura en disco del tile
338
                RasterManager rManager = RasterLocator.getManager();
339
                DataServerWriter dataWriter = RasterLocator.getManager().createDataServerWriter();
340
                dataWriter.setBuffer(bufResult, -1);
341
                Params params = rManager.createWriter("_." + extension).getParams();
342
                AffineTransform affineTransform = new AffineTransform(pixelSize, 0, 0, -pixelSize,
343
                                tileExtent.getULX(),
344
                                tileExtent.getULY());
345
                RasterWriter rw = rManager.createWriter(dataWriter, tile.getFile().getAbsolutePath(),
346
                                bufResult.getBandCount(), affineTransform, bufResult.getWidth(),
347
                                bufResult.getHeight(), bufResult.getDataType(), params, null);
348
                
349
                if(colorInterpretation != null) {
350
                        String[] values = colorInterpretation.getValues();
351
                        if(alphaBand) {
352
                                String[] newValues = values;
353
                                boolean exists = false;
354
                                for (int i = 0; i < values.length; i++) {
355
                                        if(values[i] != null && values[i].compareTo("Alpha") == 0)
356
                                                exists = true;
357
                                }
358
                                if(!exists) {
359
                                        newValues = new String[values.length + 1];
360
                                        for (int i = 0; i < values.length; i++) {
361
                                                newValues[i] = values[i];
362
                                        }
363
                                        newValues[newValues.length - 1] = "Alpha";
364
                                }
365
                                rw.setColorBandsInterpretation(newValues);
366
                        }
367
                        
368
                } else {
369
                        if(alphaBand) {
370
                                String[] ci = new String[bufResult.getBandCount()];
371
                                if(bufResult.getBandCount() == 4) {
372
                                        ci[0] = "Red";
373
                                        ci[1] = "Green";
374
                                        ci[2] = "Blue";
375
                                        ci[3] = "Alpha";
376
                                } else {
377
                                        for (int i = 0; i < bufResult.getBandCount(); i++) {
378
                                                ci[i] = "Gray";
379
                                        }
380
                                }
381
                                rw.setColorBandsInterpretation(ci);
382
                        }
383
                }
384
                rw.dataWrite();
385
                rw.writeClose();
386
                tile.setCorrupt(false);
387
        }
388
}