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 @ 2300

History | View | Annotate | Download (13.5 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.Extent;
32
import org.gvsig.fmap.dal.coverage.datastruct.NoData;
33
import org.gvsig.fmap.dal.coverage.exception.NotSupportedExtensionException;
34
import org.gvsig.fmap.dal.coverage.exception.ProcessInterruptedException;
35
import org.gvsig.fmap.dal.coverage.exception.QueryException;
36
import org.gvsig.fmap.dal.coverage.exception.RasterDriverException;
37
import org.gvsig.fmap.dal.coverage.store.RasterQuery;
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.datastruct.BandListImpl;
45
import org.gvsig.raster.impl.datastruct.ExtentImpl;
46
import org.gvsig.raster.impl.provider.RasterProvider;
47
import org.gvsig.raster.impl.provider.tile.BaseTileDownloader;
48
import org.gvsig.raster.impl.store.DefaultRasterStore;
49
import org.gvsig.raster.mosaic.io.MosaicDataParameters;
50

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

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

    
199
        /**
200
         * If the provider doesn't support resampling then this method reamples the result manually
201
         * @param tileExtent
202
         * @param newBandList
203
         * @param bufWidth
204
         * @param bufHeight
205
         * @param nBands
206
         * @return
207
         * @throws ProcessInterruptedException
208
         * @throws RasterDriverException
209
         */
210
        private Buffer readSupersampledBuffer(Extent tileExtent, BandList newBandList, int bufWidth, int bufHeight, int nBands) throws ProcessInterruptedException, RasterDriverException {
211
                int widthImgPx = (int)Math.abs(tileExtent.width() / store.getPixelSizeX());
212
                int heightImgPx = (int)Math.abs(tileExtent.height() / store.getPixelSizeY());
213
                boolean supersampling = ((bufWidth > widthImgPx) || (bufHeight > heightImgPx)) ? true : false;
214
                
215
                if(supersampling /*&& !prov.isSupersamplingSupported()*/) {
216
                        //Ecw no supersamplea por lo que habr� que hacerlo a mano
217
                        Buffer buf = null;//buildTileBuffer(nBands, widthImgPx, heightImgPx);
218
                        
219
                        RasterQuery q = RasterLocator.getManager().createQuery();
220
                        q.setAreaOfInterest(tileExtent, widthImgPx, heightImgPx);
221
                        q.setDrawableBands(newBandList.getDrawableBands());
222
                        try {
223
                                buf = store.query(q);
224
                        } catch (QueryException e) {
225
                                throw new RasterDriverException("Error reading mosaic", e);
226
                        }
227
                        
228
                        //prov.getWindow(tileExtent, widthImgPx, heightImgPx, newBandList, buf, true, null);
229
                        return buf.getAdjustedWindow(bufWidth, bufHeight, Buffer.INTERPOLATION_NearestNeighbour);
230
                }
231
                return null;
232
        }
233
        
234
        /**
235
         * Builds a buffer using the specified number of bands and initialize it
236
         * @param nbands
237
         * @return
238
         */
239
        private Buffer buildTileBuffer(int nbands, int w, int h) {
240
                Buffer bufResult = DefaultRasterManager.getInstance().createMemoryBuffer(store.getDataType()[0], w, h, nbands, true);
241
                if(store.getDataType()[0] != Buffer.TYPE_BYTE) {
242
                        for (int i = 0; i < bufResult.getBandCount(); i++) {
243
                                clearMaskBuffer(bufResult, i);
244
                        }
245
                } else
246
                        clearMaskBuffer(bufResult, nbands - 1);
247
                return bufResult;
248
        }
249

    
250
        /**
251
         * Copies a piece of image into a tile taking into account the different size and proportion
252
         * @param bufResult
253
         * @param tileExtent
254
         * @param buf
255
         * @param ex
256
         * @param pixelSize
257
         */
258
        private void copyToBuffer(Buffer bufResult, Extent tileExtent,
259
                        Buffer buf, Extent ex, double pixelSize) {
260
                double distx = Math.abs(ex.getULX() - tileExtent.getULX());
261
                double disty = Math.abs(ex.getULY() - tileExtent.getULY());
262
                int distpxx = (int)Math.round(distx / pixelSize);
263
                int distpxy = (int)Math.round(disty / pixelSize);
264

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