Statistics
| Revision:

gvsig-raster / org.gvsig.raster.mosaic / trunk / org.gvsig.raster.mosaic / org.gvsig.raster.mosaic.io / src / main / java / org / gvsig / raster / mosaic / io / downloader / TileDownloaderForMosaics.java @ 2193

History | View | Annotate | Download (13.9 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.mosaic.io.downloader;
23

    
24
import java.io.IOException;
25
import java.util.ArrayList;
26
import java.util.List;
27

    
28
import org.gvsig.fmap.dal.coverage.RasterLocator;
29
import org.gvsig.fmap.dal.coverage.dataset.Buffer;
30
import org.gvsig.fmap.dal.coverage.datastruct.BandList;
31
import org.gvsig.fmap.dal.coverage.datastruct.DatasetBand;
32
import org.gvsig.fmap.dal.coverage.datastruct.Extent;
33
import org.gvsig.fmap.dal.coverage.datastruct.NoData;
34
import org.gvsig.fmap.dal.coverage.exception.BandNotFoundInListException;
35
import org.gvsig.fmap.dal.coverage.exception.NotSupportedExtensionException;
36
import org.gvsig.fmap.dal.coverage.exception.ProcessInterruptedException;
37
import org.gvsig.fmap.dal.coverage.exception.RasterDriverException;
38
import org.gvsig.fmap.dal.coverage.store.props.ColorInterpretation;
39
import org.gvsig.fmap.dal.coverage.util.RasterUtils;
40
import org.gvsig.raster.cache.tile.Tile;
41
import org.gvsig.raster.cache.tile.exception.TileGettingException;
42
import org.gvsig.raster.cache.tile.provider.CacheStruct;
43
import org.gvsig.raster.impl.DefaultRasterManager;
44
import org.gvsig.raster.impl.buffer.DefaultRasterQuery;
45
import org.gvsig.raster.impl.datastruct.BandListImpl;
46
import org.gvsig.raster.impl.datastruct.DatasetBandImpl;
47
import org.gvsig.raster.impl.datastruct.ExtentImpl;
48
import org.gvsig.raster.impl.provider.DefaultRasterProvider;
49
import org.gvsig.raster.impl.provider.RasterProvider;
50
import org.gvsig.raster.impl.provider.tile.BaseTileDownloader;
51
import org.gvsig.raster.mosaic.io.MosaicDataParameters;
52

    
53
/** 
54
 * Tile getter 
55
 * @author Nacho Brodin (nachobrodin@gmail.com)
56
 */
57
public class TileDownloaderForMosaics extends BaseTileDownloader {
58
        private CacheStruct                      struct                 = null;
59
        private RasterUtils                      util                   = RasterLocator.getManager().getRasterUtils();
60
        private String                           extension              = null;
61
        private List<RasterProvider>             provList               = null;
62
        private int                              overlapMethod          = MosaicDataParameters.FIRST;
63
        private int                              colorCorrectionMethod  = MosaicDataParameters.NONE;
64
        private TileFusion                       tileFusion             = null;
65
        
66
        public TileDownloaderForMosaics(DefaultRasterProvider prov, 
67
                        List<RasterProvider> provList, 
68
                        CacheStruct struct,
69
                        int tileWidth,
70
                        int tileHeight,
71
                        String extension,
72
                        int overlapMethod,
73
                        int colorCorrectionMethod,
74
                        NoData noData) {
75
                super(prov, tileWidth, tileHeight);
76
                this.provList = provList;
77
                this.struct = struct;
78
                this.extension = extension;
79
                this.tileFusion = new TileFusion(overlapMethod, colorCorrectionMethod, noData);
80
        }
81
        
82
        public synchronized Tile downloadTile(Tile tile) throws TileGettingException {
83
                try {
84
                        Extent tileExtent = new ExtentImpl(tile.getUl(), tile.getLr());
85
                        double pixelSize = struct.getPixelSizeByLevel(tile.getLevel());
86
                        Buffer bufResult = null;
87
                        boolean alphaBand = false;
88
                        List<Buffer> listBuffers = new ArrayList<Buffer>();
89
                        ColorInterpretation ci = null;
90
                        
91
                        //Iterates the list of providers clipping the selected extent
92
                        for (int i = 0; i < provList.size(); i++) {
93
                                RasterProvider p = provList.get(i);
94
                                if(!p.getDataParameters().isVisible())
95
                                        continue;
96
                                ci = p.getColorInterpretation();
97
                                Buffer bufPartialResult = clipTileFromProvider((DefaultRasterProvider)p, tile);
98
                                if(bufPartialResult != null) {
99
                                        if(p.getDataType()[0] == Buffer.TYPE_BYTE && bufPartialResult.getBandCount() > p.getBandCount()) {
100
                                                alphaBand = true; //If one result has alpha band then the alpha band flag is on
101
                                        }
102
                                        listBuffers.add(bufPartialResult);
103
                                } 
104
                        }
105
                        
106
                        if(listBuffers.size() == 0) 
107
                                alphaBand = true;
108
                                
109
                        //The list of clips is joined in only one tile
110
                        bufResult = tileFusion.joinTiles(listBuffers, tile.getWidthPx(), tile.getHeightPx(), alphaBand ? 3 : -1);
111
                        
112
                        if(bufResult == null)
113
                                bufResult = buildTileBuffer(provList.get(0).getDataType()[0] == Buffer.TYPE_BYTE ? provList.get(0).getBandCount() + 1 : provList.get(0).getBandCount(),
114
                                                tile.getWidthPx(), 
115
                                                tile.getHeightPx());
116
                        
117
                        //En el salvado de tiles alphaBand se usa para la interpretaci�n de color y si el tipo no es byte no debe haber banda alpha
118
                        if(provList.get(0).getDataType()[0] != Buffer.TYPE_BYTE) 
119
                                alphaBand = false;
120
                        
121
                        saveTile(bufResult, pixelSize, extension, 
122
                                        alphaBand, tile, tileExtent, ci);
123
                        
124
                        //Si borramos el rmf no se puede leer la etiqueta Alpha. En caso de que se modifique jgdal para
125
                        //poder guardar esta etiqueta deberiamos borrar el rmf para ahorrar ficheros
126
                        //File rmf = new File(tile.getFile().getAbsolutePath() + ".rmf");
127
                        //if(rmf.exists())
128
                                //rmf.delete();
129
                } catch (ProcessInterruptedException e) {
130
                } catch (RasterDriverException e) {
131
                        throw new TileGettingException(e);
132
                } catch (NotSupportedExtensionException e) {
133
                        throw new TileGettingException(e);
134
                } catch (IOException e) {
135
                        throw new TileGettingException(e);
136
                }
137
                readTileFromDisk(tile);
138
                return tile;
139
        }
140
        
141
        private Buffer clipTileFromProvider(DefaultRasterProvider p, Tile tile) throws RasterDriverException {
142
                Extent tileExtent = new ExtentImpl(tile.getUl(), tile.getLr());
143

    
144
                //Escribe todas las bandas a disco
145
                BandList newBandList = new BandListImpl(p.getURI(), p.getBandCount(), p.getDataType()[0]);
146
                
147
                Buffer bufResult = null;
148
                
149
                double pixelSize = struct.getPixelSizeByLevel(tile.getLevel());
150
                
151
                try {
152
                        Extent ex = util.intersection(p.getExtent(), tileExtent);
153
                        
154
                        if(ex == null)
155
                                return null;
156
                        
157
                        int newBufWidth = (int)Math.ceil((ex.width() * this.tilePxWidth) / tileExtent.width());
158
                        int newBufHeight = (int)Math.ceil((ex.height() * this.tilePxHeight) / tileExtent.height());
159
                        int nBandsBuffer = p.getBandCount();
160
                        
161
                        //Si no hay parte del tile que cae fuera de la imagen no se usa una nueva banda de transparencia ni valores nodata
162
                        /*if(newBufHeight == this.tilePxHeight && newBufWidth == this.tilePxWidth) {
163
                                bufResult = readSupersampledBuffer(tileExtent, newBandList, this.tilePxWidth, this.tilePxHeight, nBandsBuffer);
164
                                if(bufResult == null) {
165
                                        bufResult = buildTileBuffer(nBandsBuffer, this.tilePxWidth, this.tilePxHeight);
166
                                        bufResult = p.getWindow(tileExtent, this.tilePxWidth, this.tilePxHeight, newBandList, bufResult, true);
167
                                }
168
                        } else {*/
169
                                //Hay parte del tile que cae fuera de la imagen
170
                                if(p.getDataType()[0] == Buffer.TYPE_BYTE) {
171
                                        //Para imagenes byte se crea una banda de transparencia
172
                                        nBandsBuffer ++; 
173
                                } 
174
                                
175
                                bufResult = buildTileBuffer(nBandsBuffer, this.tilePxWidth, this.tilePxHeight);
176
                                Buffer smallBuf = readSupersampledBuffer(ex, newBandList, newBufWidth, newBufHeight, nBandsBuffer);
177
                                
178
                                if(smallBuf == null) { //No ha habido resampleo
179
                                        smallBuf = DefaultRasterManager.getInstance().createMemoryBuffer(p.getDataType()[0], newBufWidth, newBufHeight, nBandsBuffer, true);
180
                                        DefaultRasterQuery q = (DefaultRasterQuery)RasterLocator.getManager().createQuery();
181
                                        q.setAreaOfInterest(ex, newBufWidth, newBufHeight);
182
                                        q.setBandList(newBandList);
183
                                        q.setBuffer(smallBuf);
184
                                        q.setAdjustToExtent(true);
185
                                        smallBuf = p.getDataSet(q);
186
                                        //smallBuf = p.getWindow(ex, newBufWidth, newBufHeight, newBandList, smallBuf, true, null);
187
                                }
188
                                copyToBuffer(bufResult, tileExtent, smallBuf, ex, pixelSize);
189
                        //}
190
                        return bufResult;
191
                } catch (ProcessInterruptedException e) {
192
                } 
193
                return null;
194
        }
195

    
196
        /**
197
         * Builds a Bandlist object to load tiles
198
         * @return
199
         * @deprecated It is only for multifile providers
200
         */
201
        @SuppressWarnings("unused")
202
        private BandList getBandList() {
203
                BandListImpl bandList = new BandListImpl();
204
                for(int i = 0; i < prov.getBandCount(); i++) {
205
                        try {
206
                                int dataType = prov.getDataType()[i];
207
                                DatasetBand band = new DatasetBandImpl(prov.getURIByBand(i), i, dataType, prov.getBandCount());
208
                                bandList.addBand(band, i);
209
                        } catch(BandNotFoundInListException ex) {
210
                                //No a�adimos la banda
211
                        }
212
                }
213
                return bandList;
214
        }
215
        
216
        /**
217
         * If the provider doesn't support resampling then this method reamples the result manually
218
         * @param tileExtent
219
         * @param newBandList
220
         * @param bufWidth
221
         * @param bufHeight
222
         * @param nBands
223
         * @return
224
         * @throws ProcessInterruptedException
225
         * @throws RasterDriverException
226
         */
227
        private Buffer readSupersampledBuffer(Extent tileExtent, BandList newBandList, int bufWidth, int bufHeight, int nBands) throws ProcessInterruptedException, RasterDriverException {
228
                int widthImgPx = (int)Math.abs(tileExtent.width() / prov.getPixelSizeX());
229
                int heightImgPx = (int)Math.abs(tileExtent.height() / prov.getPixelSizeY());
230
                boolean supersampling = ((bufWidth > widthImgPx) || (bufHeight > heightImgPx)) ? true : false;
231
                
232
                if(supersampling && !prov.isSupersamplingSupported()) {
233
                        //Ecw no supersamplea por lo que habr� que hacerlo a mano
234
                        Buffer buf = buildTileBuffer(nBands, widthImgPx, heightImgPx);
235
                        
236
                        DefaultRasterQuery q = (DefaultRasterQuery)RasterLocator.getManager().createQuery();
237
                        q.setAreaOfInterest(tileExtent, widthImgPx, heightImgPx);
238
                        q.setBandList(newBandList);
239
                        q.setBuffer(buf);
240
                        q.setAdjustToExtent(true);
241
                        buf = prov.getDataSet(q);
242
                        
243
                        //prov.getWindow(tileExtent, widthImgPx, heightImgPx, newBandList, buf, true, null);
244
                        return buf.getAdjustedWindow(bufWidth, bufHeight, Buffer.INTERPOLATION_NearestNeighbour);
245
                }
246
                return null;
247
        }
248
        
249
        /**
250
         * Builds a buffer using the specified number of bands and initialize it
251
         * @param nbands
252
         * @return
253
         */
254
        private Buffer buildTileBuffer(int nbands, int w, int h) {
255
                Buffer bufResult = DefaultRasterManager.getInstance().createMemoryBuffer(prov.getDataType()[0], w, h, nbands, true);
256
                if(prov.getDataType()[0] != Buffer.TYPE_BYTE) {
257
                        for (int i = 0; i < bufResult.getBandCount(); i++) {
258
                                clearMaskBuffer(bufResult, i);
259
                        }
260
                } else
261
                        clearMaskBuffer(bufResult, nbands - 1);
262
                return bufResult;
263
        }
264

    
265
        /**
266
         * Copies a piece of image into a tile taking into account the different size and proportion
267
         * @param bufResult
268
         * @param tileExtent
269
         * @param buf
270
         * @param ex
271
         * @param pixelSize
272
         */
273
        private void copyToBuffer(Buffer bufResult, Extent tileExtent,
274
                        Buffer buf, Extent ex, double pixelSize) {
275
                double distx = Math.abs(ex.getULX() - tileExtent.getULX());
276
                double disty = Math.abs(ex.getULY() - tileExtent.getULY());
277
                int distpxx = (int)Math.round(distx / pixelSize);
278
                int distpxy = (int)Math.round(disty / pixelSize);
279

    
280
                //Para BYTE la �ltima banda es de transparencia por lo que en esa banda en las zonas donde hay imagen
281
                //hay que ponerle el valor 255 para que aparezcan visibles
282
                if(bufResult.getDataType() == Buffer.TYPE_BYTE) {
283
                        for (int iBand = 0; iBand < bufResult.getBandCount() - 1; iBand++) {
284
                                if(iBand == 0) {
285
                                        for (int i = distpxy; (i < bufResult.getHeight() && (i - distpxy) < buf.getHeight()); i++) {
286
                                                for (int j = distpxx; (j < bufResult.getWidth() && (j - distpxx) < buf.getWidth()); j++) {
287
                                                        bufResult.setElem(i, j, iBand, buf.getElemByte(i - distpxy, j - distpxx, iBand));
288
                                                        bufResult.setElem(i, j, bufResult.getBandCount() - 1, (byte)255);
289
                                                }
290
                                        }
291
                                } else {
292
                                        for (int i = distpxy; (i < bufResult.getHeight() && (i - distpxy) < buf.getHeight()); i++) {
293
                                                for (int j = distpxx; (j < bufResult.getWidth() && (j - distpxx) < buf.getWidth()); j++) {
294
                                                        bufResult.setElem(i, j, iBand, buf.getElemByte(i - distpxy, j - distpxx, iBand));
295
                                                }
296
                                        }
297
                                }
298
                        }
299
                }
300
                
301
                //En el resto de casos no se usa banda de transparencia sino que las zonas del tile fuera de la imagen
302
                //se inicializaron previamente a NoData
303
                
304
                if(bufResult.getDataType() == Buffer.TYPE_SHORT) {
305
                        for (int iBand = 0; iBand < buf.getBandCount(); iBand++) {
306
                                for (int i = distpxy; (i < bufResult.getHeight() && (i - distpxy) < buf.getHeight()); i++) {
307
                                        for (int j = distpxx; (j < bufResult.getWidth() && (j - distpxx) < buf.getWidth()); j++) {
308
                                                bufResult.setElem(i, j, iBand, buf.getElemShort(i - distpxy, j - distpxx, iBand));
309
                                        }
310
                                }
311
                        }
312
                }
313
                if(bufResult.getDataType() == Buffer.TYPE_INT) {
314
                        for (int iBand = 0; iBand < buf.getBandCount(); iBand++) {
315
                                for (int i = distpxy; (i < bufResult.getHeight() && (i - distpxy) < buf.getHeight()); i++) {
316
                                        for (int j = distpxx; (j < bufResult.getWidth() && (j - distpxx) < buf.getWidth()); j++) {
317
                                                bufResult.setElem(i, j, iBand, buf.getElemInt(i - distpxy, j - distpxx, iBand));
318
                                        }
319
                                }
320
                        }
321
                }
322
                if(bufResult.getDataType() == Buffer.TYPE_FLOAT) {
323
                        for (int iBand = 0; iBand < buf.getBandCount(); iBand++) {
324
                                for (int i = distpxy; (i < bufResult.getHeight() && (i - distpxy) < buf.getHeight()); i++) {
325
                                        for (int j = distpxx; (j < bufResult.getWidth() && (j - distpxx) < buf.getWidth()); j++) {
326
                                                bufResult.setElem(i, j, iBand, buf.getElemFloat(i - distpxy, j - distpxx, iBand));
327
                                        }
328
                                }
329
                        }
330
                }
331
                if(bufResult.getDataType() == Buffer.TYPE_DOUBLE) {
332
                        for (int iBand = 0; iBand < buf.getBandCount(); iBand++) {
333
                                for (int i = distpxy; (i < bufResult.getHeight() && (i - distpxy) < buf.getHeight()); i++) {
334
                                        for (int j = distpxx; (j < bufResult.getWidth() && (j - distpxx) < buf.getWidth()); j++) {
335
                                                bufResult.setElem(i, j, iBand, buf.getElemDouble(i - distpxy, j - distpxx, iBand));
336
                                        }
337
                                }
338
                        }
339
                }
340
        }
341
}