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

History | View | Annotate | Download (13 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

    
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.BandList;
30
import org.gvsig.fmap.dal.coverage.datastruct.DatasetBand;
31
import org.gvsig.fmap.dal.coverage.datastruct.Extent;
32
import org.gvsig.fmap.dal.coverage.exception.BandNotFoundInListException;
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.RasterDriverException;
36
import org.gvsig.fmap.dal.coverage.store.parameter.RasterDataParameters;
37
import org.gvsig.fmap.dal.coverage.store.props.ColorInterpretation;
38
import org.gvsig.fmap.dal.coverage.util.RasterUtils;
39
import org.gvsig.raster.cache.tile.Tile;
40
import org.gvsig.raster.cache.tile.exception.TileGettingException;
41
import org.gvsig.raster.cache.tile.provider.CacheStruct;
42
import org.gvsig.raster.impl.DefaultRasterManager;
43
import org.gvsig.raster.impl.datastruct.BandListImpl;
44
import org.gvsig.raster.impl.datastruct.DatasetBandImpl;
45
import org.gvsig.raster.impl.datastruct.ExtentImpl;
46
import org.gvsig.raster.impl.provider.DefaultRasterProvider;
47
import org.gvsig.raster.impl.provider.RasterProvider;
48
import org.gvsig.raster.impl.provider.tile.BaseTileDownloader;
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 ArrayList<RasterProvider>        provList               = null;
60
        private int                              overlapMethod          = MosaicDataParameters.FIRST;
61
        private int                              colorCorrectionMethod  = MosaicDataParameters.NONE;
62
        private TileFusion                       tileFusion             = null;
63
        
64
        public TileDownloaderForMosaics(DefaultRasterProvider prov, 
65
                        ArrayList<RasterProvider> provList, 
66
                        CacheStruct struct,
67
                        int tilesize,
68
                        String extension,
69
                        int overlapMethod,
70
                        int colorCorrectionMethod) {
71
                super(prov, tilesize, tilesize);
72
                this.provList = provList;
73
                this.struct = struct;
74
                this.extension = extension;
75
                this.tileFusion = new TileFusion(overlapMethod, colorCorrectionMethod);
76
        }
77
        
78
        /*
79
         * (non-Javadoc)
80
         * @see org.gvsig.raster.cache.tile.provider.Downloader#getTile(org.gvsig.raster.cache.tile.Tile)
81
         */
82
        public synchronized Tile downloadTile(Tile tile) throws TileGettingException {
83
                
84
                try {
85
                        Extent tileExtent = new ExtentImpl(tile.getUl(), tile.getLr());
86
                        double pixelSize = struct.getPixelSizeByLevel(tile.getLevel());
87
                        Buffer bufResult = null;
88
                        boolean alphaBand = false;
89
                        ArrayList<Buffer> listBuffers = new ArrayList<Buffer>();
90
                        ColorInterpretation ci = null;
91
                        
92
                        //Iterates the list of providers clipping the selected extent
93
                        for (int i = 0; i < provList.size(); i++) {
94
                                RasterProvider p = provList.get(i);
95
                                if(!p.getDataParameters().isVisible())
96
                                        continue;
97
                                ci = p.getColorInterpretation();
98
                                Buffer bufPartialResult = clipTileFromProvider((DefaultRasterProvider)p, tile);
99
                                if(bufPartialResult != null) {
100
                                        if(p.getDataType()[0] == Buffer.TYPE_BYTE && bufPartialResult.getBandCount() > p.getBandCount()) {
101
                                                alphaBand = true; //If one result has alpha band then the alpha band flag is on
102
                                        }
103
                                        listBuffers.add(bufPartialResult);
104
                                } 
105
                        }
106
                        
107
                        if(listBuffers.size() == 0)
108
                                alphaBand = true;
109
                        
110
                        //The list of clips is joined in only one tile
111
                        bufResult = tileFusion.joinTiles(listBuffers, tile.getWidthPx(), tile.getHeightPx(), alphaBand ? 3 : -1);
112
                        
113
                        saveTile(bufResult, pixelSize, extension, 
114
                                        alphaBand, tile.getFile().getAbsolutePath(), tileExtent, ci);
115
                        
116
                        //Si borramos el rmf no se puede leer la etiqueta Alpha. En caso de que se modifique jgdal para
117
                        //poder guardar esta etiqueta deberiamos borrar el rmf para ahorrar ficheros
118
                        //File rmf = new File(tile.getFile().getAbsolutePath() + ".rmf");
119
                        //if(rmf.exists())
120
                                //rmf.delete();
121
                } catch (ProcessInterruptedException e) {
122
                } catch (RasterDriverException e) {
123
                        throw new TileGettingException(e);
124
                } catch (NotSupportedExtensionException e) {
125
                        throw new TileGettingException(e);
126
                } catch (IOException e) {
127
                        throw new TileGettingException(e);
128
                }
129
                readTileFromDisk(tile);
130
                return tile;
131
        }
132
        
133
        private Buffer clipTileFromProvider(DefaultRasterProvider p, Tile tile) throws RasterDriverException {
134
                Extent tileExtent = new ExtentImpl(tile.getUl(), tile.getLr());
135

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

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

    
243
        /**
244
         * Copies a piece of image into a tile taking into account the different size and proportion
245
         * @param bufResult
246
         * @param tileExtent
247
         * @param buf
248
         * @param ex
249
         * @param pixelSize
250
         */
251
        private void copyToBuffer(Buffer bufResult, Extent tileExtent,
252
                        Buffer buf, Extent ex, double pixelSize) {
253
                double distx = Math.abs(ex.getULX() - tileExtent.getULX());
254
                double disty = Math.abs(ex.getULY() - tileExtent.getULY());
255
                int distpxx = (int)Math.round(distx / pixelSize);
256
                int distpxy = (int)Math.round(disty / pixelSize);
257

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