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

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

    
24
import java.awt.Graphics;
25
import java.awt.geom.AffineTransform;
26
import java.awt.image.BufferedImage;
27
import java.io.IOException;
28

    
29
import javax.swing.ImageIcon;
30

    
31
import org.gvsig.fmap.dal.coverage.RasterLocator;
32
import org.gvsig.fmap.dal.coverage.RasterManager;
33
import org.gvsig.fmap.dal.coverage.dataset.Buffer;
34
import org.gvsig.fmap.dal.coverage.dataset.BufferParam;
35
import org.gvsig.fmap.dal.coverage.datastruct.BandList;
36
import org.gvsig.fmap.dal.coverage.datastruct.DatasetBand;
37
import org.gvsig.fmap.dal.coverage.datastruct.Extent;
38
import org.gvsig.fmap.dal.coverage.datastruct.NoData;
39
import org.gvsig.fmap.dal.coverage.datastruct.Params;
40
import org.gvsig.fmap.dal.coverage.exception.BandNotFoundInListException;
41
import org.gvsig.fmap.dal.coverage.exception.BufferCreationException;
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.datastruct.BandListImpl;
58
import org.gvsig.raster.impl.datastruct.DatasetBandImpl;
59
import org.gvsig.raster.impl.provider.AbstractRasterProvider;
60
import org.gvsig.raster.impl.provider.RasterProvider;
61
import org.gvsig.raster.impl.store.DefaultRasterStore;
62
import org.gvsig.raster.util.DefaultProviderServices;
63
import org.gvsig.tools.locator.LocatorException;
64
import org.slf4j.Logger;
65
import org.slf4j.LoggerFactory;
66

    
67
/**
68
 * Base class for downloaders
69
 * @author Nacho Brodin (nachobrodin@gmail.com)
70
 */
71
public abstract class BaseTileDownloader implements Downloader {
72
        private Logger                          log               = LoggerFactory.getLogger(BaseTileDownloader.class);
73
        protected int                           tilePxWidth       = 0;
74
        protected int                           tilePxHeight      = 0;
75
        protected RasterDataStore               store             = null;
76
        protected byte                          byteNoData        = (byte)0x00;
77
        protected short                         shortNoData       = Short.MIN_VALUE;
78
        protected int                           intNoData         = Integer.MIN_VALUE;
79
        protected float                         floatNoData       = -99999;
80
        protected double                        doubleNoData      = -99999;
81

    
82
        public BaseTileDownloader(RasterDataStore store, int tilePxWidth, int tilePxHeight) {
83
                this.store = store;
84
                this.tilePxWidth = tilePxWidth;
85
                this.tilePxHeight = tilePxHeight;
86
                if(store.getNoDataValue() != null && store.getNoDataValue().isDefined())
87
                        setNoDataValue(store.getNoDataValue());
88
        }
89

    
90
        /**
91
         * Gets the image that represent a tile while is downloading.
92
         * @return
93
         */
94
        public Object[] getDownloadingImage(int w, int h) {
95
                if(RasterDefaultImplLibrary.downloadingImg == null)
96
                        return null;
97
                String key = w + "X" + h + "_Downloading";
98
                return new Object[]{getBufferFromImageIcon(w, h, key, RasterDefaultImplLibrary.downloadingImg)};
99
        }
100

    
101
        /**
102
         * Gets the image that represent a crash tile
103
         * @return
104
         */
105
        public Object[] getCrashImage(int w, int h) {
106
                if(RasterDefaultImplLibrary.crashImg == null)
107
                        return null;
108
                String key = w + "X" + h + "_Crash";
109
                return new Object[]{getBufferFromImageIcon(w, h, key, RasterDefaultImplLibrary.crashImg)};
110
        }
111

    
112
        private Buffer getBufferFromImageIcon(int w, int h, String key, ImageIcon icon) {
113
                Buffer buf = RasterDefaultImplLibrary.defaultImages.get(key);
114
                if(buf == null) {
115
                        try {
116
                                BufferParam par = RasterLocator.getManager().getBufferFactory().createBufferParams(w, h, 4, Buffer.TYPE_BYTE, true);
117
                                buf = RasterLocator.getManager().getBufferFactory().createBuffer(par);
118
                        } catch (LocatorException e) {
119
                                log.debug("Error creating buffers ", e);
120
                        } catch (BufferCreationException e) {
121
                                log.debug("Error creating buffers ", e);
122
                        }
123

    
124
                        byte[] background = new byte[]{-1, -1, -1, (byte)50};
125
                        for (int i = 0; i < buf.getHeight(); i++)
126
                                for (int j = 0; j < buf.getWidth(); j++)
127
                                        buf.setElemByte(j, i, background);
128

    
129
                        BufferedImage img = new BufferedImage(icon.getIconWidth(), icon.getIconHeight(), BufferedImage.TYPE_INT_ARGB);
130
                        Graphics g = img.createGraphics();
131
                    g.drawImage(icon.getImage(), 0, 0, null);
132
                        int initX = (w / 2) - (img.getWidth() / 2);
133
                        int initY = (h / 2) - (img.getHeight() / 2);
134
                        for (int i = initY; i < (img.getHeight() + initY); i++) {
135
                                for (int j = initX; j < (img.getWidth() + initX); j++) {
136
                                        int value = img.getRGB(j - initX, i - initY);
137
                                        buf.setElem(i, j, 0, (byte)((value & 0x00ff0000) >> 16));
138
                                        buf.setElem(i, j, 1, (byte)((value & 0x0000ff00) >> 8));
139
                                        buf.setElem(i, j, 2, (byte)(value & 0x000000ff));
140
                                        buf.setElem(i, j, 3, (byte)((value & 0xff000000) >> 24));
141
                                }
142
                        }
143
                        RasterDefaultImplLibrary.defaultImages.put(key, buf);
144
                }
145
                return buf;
146
        }
147

    
148
        /**
149
         * Gets the size of a tile in pixels
150
         * @return Array of two integers. The first integer is the width and the second the height in pixels
151
         */
152
        public int[] getTileSize() {
153
                return new int[]{tilePxWidth, tilePxHeight};
154
        }
155

    
156
        /**
157
         * Sets the nodata value
158
         * @param noData
159
         */
160
        public void setNoDataValue(NoData noData) {
161
                switch (store.getDataType()[0]) {
162
                case Buffer.TYPE_BYTE:
163
                        byteNoData = noData.getValue().byteValue();
164
                        break;
165
                case Buffer.TYPE_SHORT:
166
                        shortNoData = noData.getValue().shortValue();
167
                        break;
168
                case Buffer.TYPE_INT:
169
                        intNoData = noData.getValue().intValue();
170
                        break;
171
                case Buffer.TYPE_FLOAT:
172
                        floatNoData = noData.getValue().floatValue();
173
                        break;
174
                case Buffer.TYPE_DOUBLE:
175
                        doubleNoData = ((NoData)noData).getValue().doubleValue();
176
                        break;
177
                }
178
        }
179

    
180
        public Tile readTileFromDisk(Tile tile) throws TileGettingException {
181
                if(!tile.getFile().exists()) {
182
                        tile.setCorrupt(true);
183
                        return null;
184
                }
185

    
186
                BandList bandList = (BandList)tile.getDownloaderParams("BandList");
187

    
188
                try {
189
                        DefaultRasterStore tileStore = new DefaultRasterStore();
190
                        AbstractRasterProvider tileProvider = DefaultProviderServices.loadProvider(tile.getFile());
191
                        tileStore.setProvider(tileProvider);
192
                        this.tilePxWidth = tile.getWidthPx();
193
                        this.tilePxHeight = tile.getHeightPx();
194

    
195
                        RasterQuery q = RasterLocator.getManager().createQuery();
196
                        int[] renderBands = bandList.getDrawableBands();
197
                        if(renderBands.length == 4 && renderBands[3] < tileProvider.getBandCount())
198
                                q.forceARGBRequest();
199
                        else
200
                                q.forceRGBRequest();
201
                        q.setDrawableBands(bandList.getDrawableBands());
202
                        Buffer buf = tileStore.query(q);
203

    
204
                        tile.setData(new Object[]{buf, null, tileStore.getColorTable()});
205

    
206
                        buf.setDataExtent(tileStore.getExtent().toRectangle2D());
207
                        tileStore.close();
208
                        return tile;
209
                } catch (ProcessInterruptedException e) {
210
                        throw new TileGettingException(e);
211
                } catch (ProviderNotRegisteredException e) {
212
                        throw new TileGettingException(e);
213
                } catch (InitializeException e) {
214
                        throw new TileGettingException(e);
215
                } catch (QueryException e) {
216
                        throw new TileGettingException(e);
217
                }
218
        }
219

    
220
        /**
221
         * Builds a BandList structure using all bands of a raster provider
222
         * @param prov
223
         * @return
224
         */
225
        @SuppressWarnings("unused")
226
        private BandList createBandListFromProvider(RasterProvider prov) {
227
                BandList bandList = new BandListImpl();
228
                bandList.clear();
229
                int nBands = prov.getDataType()[0] == Buffer.TYPE_BYTE ? prov.getBandCount() - 1 : prov.getBandCount();
230

    
231
                int[] drawableBands = new int[nBands];
232
                for(int i = 0; i < nBands; i++) {
233
                        try {
234
                                int dataType = prov.getDataType()[i];
235
                                DatasetBand band = new DatasetBandImpl(prov.getURIByBand(i).getPath(),
236
                                                                                                        prov.getBandPositionByProvider(i),
237
                                                                                                        dataType,
238
                                                                                                        nBands);
239
                                bandList.addBand(band);
240
                                drawableBands[i] = i;
241
                        } catch(BandNotFoundInListException ex) {
242
                                //No a?adimos la banda
243
                        }
244
                }
245
                bandList.setDrawableBands(drawableBands);
246
                return bandList;
247
        }
248

    
249
        /**
250
         * Sets a band to NODATA value
251
         * @param bufResult
252
         * @param tileExtent
253
         * @param buf
254
         * @param ex
255
         * @param pixelSize
256
         */
257
        protected void clearMaskBuffer(Buffer buf, int nBand) {
258
                if(buf.getDataType() == Buffer.TYPE_BYTE) {
259
                        for (int i = 0; i < buf.getHeight(); i++) {
260
                                for (int j = 0; j < buf.getWidth(); j++) {
261
                                        buf.setElem(i, j, nBand, byteNoData);
262
                                }
263
                        }
264
                        return;
265
                }
266
                if(buf.getDataType() == Buffer.TYPE_SHORT) {
267
                        for (int i = 0; i < buf.getHeight(); i++) {
268
                                for (int j = 0; j < buf.getWidth(); j++) {
269
                                        buf.setElem(i, j, nBand, shortNoData);
270
                                }
271
                        }
272
                        return;
273
                }
274
                if(buf.getDataType() == Buffer.TYPE_INT) {
275
                        for (int i = 0; i < buf.getHeight(); i++) {
276
                                for (int j = 0; j < buf.getWidth(); j++) {
277
                                        buf.setElem(i, j, nBand, intNoData);
278
                                }
279
                        }
280
                        return;
281
                }
282
                if(buf.getDataType() == Buffer.TYPE_FLOAT) {
283
                        for (int i = 0; i < buf.getHeight(); i++) {
284
                                for (int j = 0; j < buf.getWidth(); j++) {
285
                                        buf.setElem(i, j, nBand, floatNoData);
286
                                }
287
                        }
288
                        return;
289
                }
290
                if(buf.getDataType() == Buffer.TYPE_DOUBLE) {
291
                        for (int i = 0; i < buf.getHeight(); i++) {
292
                                for (int j = 0; j < buf.getWidth(); j++) {
293
                                        buf.setElem(i, j, nBand, doubleNoData);
294
                                }
295
                        }
296
                        return;
297
                }
298
        }
299

    
300
        /**
301
         * Saves a buffer to disk
302
         * @param bufResult Buffer to save
303
         * @param pixelSize Pixel size
304
         * @param extension output file format
305
         * @param alphaBand true if it has alpha band
306
         * @param path Path to the new file
307
         * @param tileExtent Bounding box of the tile
308
         * @throws NotSupportedExtensionException
309
         * @throws RasterDriverException
310
         * @throws ProcessInterruptedException
311
         * @throws IOException
312
         */
313
        protected void saveTile(Buffer bufResult,
314
                        double pixelSize,
315
                        String extension,
316
                        boolean alphaBand,
317
                        Tile tile,
318
                        Extent tileExtent,
319
                        ColorInterpretation colorInterpretation) throws NotSupportedExtensionException, RasterDriverException, ProcessInterruptedException, IOException {
320
                //Escritura en disco del tile
321
                RasterManager rManager = RasterLocator.getManager();
322
                DataServerWriter dataWriter = RasterLocator.getManager().createDataServerWriter();
323
                dataWriter.setBuffer(bufResult, -1);
324
                Params params = rManager.createWriter("_." + extension).getParams();
325
                AffineTransform affineTransform = new AffineTransform(pixelSize, 0, 0, -pixelSize,
326
                                tileExtent.getULX(),
327
                                tileExtent.getULY());
328
                RasterWriter rw = rManager.createWriter(dataWriter, tile.getFile().getAbsolutePath(),
329
                                bufResult.getBandCount(), affineTransform, bufResult.getWidth(),
330
                                bufResult.getHeight(), bufResult.getDataType(), params, null);
331

    
332
                if(colorInterpretation != null) {
333
                        String[] values = colorInterpretation.getValues();
334
                        if(alphaBand) {
335
                                String[] newValues = values;
336
                                boolean exists = false;
337
                                for (int i = 0; i < values.length; i++) {
338
                                        if(values[i] != null && values[i].compareTo("Alpha") == 0)
339
                                                exists = true;
340
                                }
341
                                if(!exists) {
342
                                        newValues = new String[values.length + 1];
343
                                        for (int i = 0; i < values.length; i++) {
344
                                                newValues[i] = values[i];
345
                                        }
346
                                        newValues[newValues.length - 1] = "Alpha";
347
                                }
348
                                rw.setColorBandsInterpretation(newValues);
349
                        }
350

    
351
                } else {
352
                        if(alphaBand) {
353
                                String[] ci = new String[bufResult.getBandCount()];
354
                                if(bufResult.getBandCount() == 4) {
355
                                        ci[0] = "Red";
356
                                        ci[1] = "Green";
357
                                        ci[2] = "Blue";
358
                                        ci[3] = "Alpha";
359
                                } else {
360
                                        for (int i = 0; i < bufResult.getBandCount(); i++) {
361
                                                ci[i] = "Gray";
362
                                        }
363
                                }
364
                                rw.setColorBandsInterpretation(ci);
365
                        }
366
                }
367
                rw.dataWrite();
368
                rw.writeClose();
369
                tile.setCorrupt(false);
370
        }
371
}