Statistics
| Revision:

gvsig-raster / org.gvsig.raster / branches / org.gvsig.raster.2.4 / org.gvsig.raster / org.gvsig.raster.gdal / org.gvsig.raster.gdal.provider / src / main / java / org / gvsig / raster / gdal / provider / AbstractFileRasterGdalStoreProvider.java @ 8697

History | View | Annotate | Download (18.5 KB)

1
/* gvSIG. Desktop Geographic Information System.
2
 *
3
 * Copyright ? 2007-2016 gvSIG Association
4
 *
5
 * This program is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU General Public License
7
 * as published by the Free Software Foundation; either version 2
8
 * of the License, or (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18
 * MA  02110-1301, USA.
19
 *
20
 * For any additional information, do not hesitate to contact us
21
 * at info AT gvsig.com, or visit our website www.gvsig.com.
22
 */
23
package org.gvsig.raster.gdal.provider;
24

    
25
import java.io.BufferedOutputStream;
26
import java.io.DataOutputStream;
27
import java.io.File;
28
import java.io.FileOutputStream;
29
import java.io.IOException;
30
import java.util.ArrayList;
31
import java.util.Arrays;
32
import java.util.List;
33
import java.util.Vector;
34

    
35
import org.apache.commons.io.FileUtils;
36
import org.apache.commons.io.FilenameUtils;
37
import org.apache.commons.lang3.StringUtils;
38
import org.cresques.cts.ICRSFactory;
39
import org.cresques.cts.IProjection;
40
import org.gdal.gdal.Driver;
41
import org.gdal.gdal.GCP;
42
import org.gdal.gdal.gdal;
43
import org.gdal.gdalconst.gdalconstConstants;
44
import org.slf4j.Logger;
45
import org.slf4j.LoggerFactory;
46

    
47
import org.gvsig.fmap.dal.DALLocator;
48
import org.gvsig.fmap.dal.DataManager;
49
import org.gvsig.fmap.dal.DataServerExplorer;
50
import org.gvsig.fmap.dal.DataStore;
51
import org.gvsig.fmap.dal.DataStoreParameters;
52
import org.gvsig.fmap.dal.exception.CreateException;
53
import org.gvsig.fmap.dal.exception.DataException;
54
import org.gvsig.fmap.dal.exception.InitializeException;
55
import org.gvsig.fmap.dal.exception.OpenException;
56
import org.gvsig.fmap.dal.exception.ReadException;
57
import org.gvsig.fmap.dal.exception.ValidateDataParametersException;
58
import org.gvsig.fmap.dal.resource.ResourceAction;
59
import org.gvsig.fmap.dal.resource.exception.AccessResourceException;
60
import org.gvsig.fmap.dal.resource.file.FileResource;
61
import org.gvsig.fmap.dal.resource.spi.ResourceConsumer;
62
import org.gvsig.fmap.dal.resource.spi.ResourceProvider;
63
import org.gvsig.fmap.dal.serverexplorer.filesystem.FilesystemServerExplorer;
64
import org.gvsig.fmap.dal.serverexplorer.filesystem.FilesystemServerExplorerParameters;
65
import org.gvsig.fmap.dal.spi.DataStoreProviderServices;
66
import org.gvsig.fmap.geom.DataTypes;
67
import org.gvsig.fmap.geom.Geometry;
68
import org.gvsig.fmap.geom.Geometry.DIMENSIONS;
69
import org.gvsig.fmap.geom.GeometryLocator;
70
import org.gvsig.fmap.geom.exception.CreateEnvelopeException;
71
import org.gvsig.fmap.geom.primitive.Envelope;
72
import org.gvsig.raster.lib.buffer.api.Buffer;
73
import org.gvsig.tools.dynobject.DynClass;
74
import org.gvsig.tools.dynobject.DynClass_v2;
75
import org.gvsig.tools.dynobject.DynField;
76
import org.gvsig.tools.dynobject.DynObject;
77
import org.gvsig.tools.dynobject.Tags;
78
import org.gvsig.tools.dynobject.exception.DynFieldNotFoundException;
79
import org.gvsig.tools.locator.LocatorException;
80

    
81
/**
82
 * Provider for Raster GDAL files
83
 * @author dmartinezizquierdo
84
 *
85
 */
86
public abstract class AbstractFileRasterGdalStoreProvider extends AbstractRasterGdalStoreProvider implements
87
ResourceConsumer{
88

    
89
    private static final Logger logger =
90
        LoggerFactory.getLogger(AbstractFileRasterGdalStoreProvider.class);
91

    
92

    
93
    /**
94
     * Constructor
95
     * @param params
96
     * @param storeServices
97
     * @throws InitializeException
98
     */
99
    public AbstractFileRasterGdalStoreProvider(RasterGdalFileStoreParameters params,
100
        DataStoreProviderServices storeServices)
101
        throws InitializeException {
102
        super(
103
                params,
104
                storeServices);
105

    
106
    }
107

    
108
    protected AbstractFileRasterGdalStoreProvider(RasterGdalFileStoreParameters params,
109
            DataStoreProviderServices storeServices, DynObject metadata)
110
            throws InitializeException {
111
        super(params, storeServices, metadata);
112
    }
113

    
114
    protected AbstractFileRasterGdalStoreProvider(NewRasterGdalStoreParameters params, Driver gdalDriver) {
115
        //PARA Exportar
116
        super(params,gdalDriver);
117
    }
118

    
119
    @Override
120
    protected void init(DataStoreParameters params,
121
        DataStoreProviderServices storeServices) throws InitializeException {
122
        super.init(params, storeServices);
123
        File file = getRasterGdalParameters().getFile();
124
        if (file == null) {
125
            throw new InitializeException(
126
                new NullPointerException("Raster GDAL file is null"));
127
        }
128

    
129
        this.projection=getRasterGdalParameters().getCRS();
130

    
131
        resource = this.createResource(
132
            FileResource.NAME,
133
            new Object[] { file.getAbsolutePath() }
134
        );
135
        resource.addConsumer(this);
136

    
137
    }
138

    
139
    protected RasterGdalFileStoreParameters getRasterGdalParameters() {
140
        return (RasterGdalFileStoreParameters) this.getParameters();
141
    }
142

    
143
    @Override
144
    public Object getDynValue(String name) throws DynFieldNotFoundException {
145
        if( DataStore.METADATA_ENVELOPE.equalsIgnoreCase(name) ) {
146
            return this.envelope;
147
        } else if( DataStore.METADATA_CRS.equalsIgnoreCase(name) ) {
148
            IProjection pro = this.getRasterGdalParameters().getCRS();
149
            if (pro != null) {
150
                return pro;
151
            }
152
        }
153
        return super.getDynValue(name);
154
    }
155

    
156
    @Override
157
    public DataServerExplorer getExplorer()
158
        throws ReadException, ValidateDataParametersException {
159
        DataManager manager = DALLocator.getDataManager();
160
        FilesystemServerExplorerParameters params;
161
        try {
162
            params = (FilesystemServerExplorerParameters) manager
163
            .createServerExplorerParameters(FilesystemServerExplorer.NAME);
164
            params.setRoot(this.getRasterGdalParameters().getFile().getParent());
165
            return manager.openServerExplorer(FilesystemServerExplorer.NAME,params);
166
        } catch (DataException e) {
167
            throw new ReadException(this.getProviderName(), e);
168
        } catch (ValidateDataParametersException e) {
169
            throw new ReadException(this.getProviderName(), e);
170
        }
171

    
172
    }
173

    
174
    /**
175
     * Used to obtain the specific options for a specific driver
176
     * Not in use yet. Used as example.
177
     * @return options used to open a specific driver in format ("optionName=optionValue")
178
     */
179
    private String [] getParametersDriverOptions(){
180
        ArrayList<String> optionsList=new ArrayList<String>();
181
        DynClass dynClass = getRasterGdalParameters().getDynClass();
182
        DynField[] fields = dynClass.getDynFields();
183
        for (DynField field:fields){
184
            String fieldName = field.getName();
185
            String gdalOption = fieldName.toUpperCase();
186
            Object dynValue = getRasterGdalParameters().getDynValue(fieldName);
187

    
188
            if (dynValue!=null && field.getGroup().equalsIgnoreCase(RasterGdalFileStoreParameters.OPEN_OPTIONS_GROUP)){
189
                if(field.getType() == DataTypes.BOOLEAN) {
190
                    if((Boolean)dynValue){
191
                        optionsList.add(gdalOption+"=YES");
192
                    }else{
193
                        optionsList.add(gdalOption+"=NO");
194
                    }
195

    
196
                } else {
197
                    optionsList.add(gdalOption+"="+dynValue);
198
                }
199
            }
200
        }
201
        String[]options=new String[optionsList.size()];
202
        optionsList.toArray(options);
203
        return options;
204
    }
205

    
206
    private String getOpeningString(File file, String[] driverOptions){
207
        String openingString="PDF:"+"\""+file.getAbsolutePath()+"\"";
208
        for (String option:driverOptions){
209
            openingString+=" "+option;
210
        }
211
        return openingString;
212
    }
213

    
214
    @Override
215
    protected void openEver() throws OpenException {
216
        try {
217
            getResource().execute(new ResourceAction() {
218

    
219
                public Object run() throws Exception {
220

    
221
                    //Used in a future when we could use them
222
                    String[] driverOptions=getParametersDriverOptions();
223

    
224
                    if (driverOptions!=null && driverOptions.length>0){
225
                        //If we have driver specific opening options
226
                        //FIXME: Use "driverOptions" properly
227
                        String openingString=getOpeningString(getRasterGdalParameters().getFile(), driverOptions);
228
                        gdalDataSet = gdal.Open(
229
                            openingString,
230
                            gdalconstConstants.GA_ReadOnly);
231
                    }else{
232
                        //If we don't have driver specific opening options
233
                        gdalDataSet = gdal.Open(
234
                            getRasterGdalParameters().getFile().getAbsolutePath(),
235
                            gdalconstConstants.GA_ReadOnly);
236
                    }
237
                    if (gdalDataSet==null){
238
                        String errorMsg=gdal.GetLastErrorMsg();
239
                        logger.info(errorMsg);
240
                    }
241

    
242
                    resource.notifyOpen();
243

    
244
                    envelope = createEnvelope(getGeoTransform());
245

    
246
                    if (envelope == null) {
247
                        // If couldn't be possible to create an envelope,
248
                        // this is created at 0,0 coordinates.
249
                        envelope = GeometryLocator.getGeometryManager()
250
                            .createEnvelope(0, 0, gdalDataSet.getRasterXSize(),
251
                                gdalDataSet.getRasterYSize(),
252
                                Geometry.SUBTYPES.GEOM2D);
253
                    }
254

    
255
                    resource.notifyClose();
256

    
257
                    resource.setData(gdalDataSet);
258

    
259
                    return null;
260
                }
261

    
262
            });
263
        } catch (Exception e) {
264
            this.gdalDataSet = null;
265
            try {
266
                throw new OpenException(resource.getName(), e);
267
            } catch (AccessResourceException e1) {
268
                throw new OpenException(getProviderName(), e);
269
            }
270
        } finally {
271
            this.taskStatus.remove();
272
        }
273
    }
274

    
275
    private double[] getGeoTransform(){
276
        double[] geotransform = null;
277
        double[] defaultGeotransform =
278
            { 0.0, 1.0, 0.0, 0.0, 0.0, -1.0 };
279
        boolean geoTransformCreated=false;
280
        // Try to create an Envelope through geolocalization
281
        // methods
282
        if (getRasterGdalParameters().getWldParams() != null) {
283

    
284
            // Try to get a geotransform from wld file
285
            List<String> wldParams =
286
                getRasterGdalParameters().getWldParams();
287
            double pixelSizeX =
288
                Double.valueOf(wldParams.get(0));
289
            double rotationAxisY =
290
                Double.valueOf(wldParams.get(1));
291
            double rotationAxisX =
292
                Double.valueOf(wldParams.get(2));
293
            double pixelSizeY =
294
                Double.valueOf(wldParams.get(3));
295
            double upperLeftPixelCenterCoordX =
296
                Double.valueOf(wldParams.get(4));
297
            double upperLeftPixelCenterCoordY =
298
                Double.valueOf(wldParams.get(5));
299

    
300
            geotransform = new double[6];
301
            // Info found at:
302
            // http://www.gdal.org/gdal_8h.html#adae2ed5807e4ec288812b54c6fccda1e
303
            // and http://www.gdal.org/gdal_tutorial.html
304
            // GDALReadWorldFile
305

    
306
            geotransform[0] = upperLeftPixelCenterCoordX
307
                - (pixelSizeX * 0.5) - (rotationAxisX * 0.5);
308
            geotransform[1] = pixelSizeX;
309
            geotransform[2] = rotationAxisX;
310
            geotransform[3] = upperLeftPixelCenterCoordY
311
                - (pixelSizeY * 0.5) - (rotationAxisY * 0.5);
312
            geotransform[4] = rotationAxisY;
313
            geotransform[5] = pixelSizeY;
314

    
315
            geoTransformCreated=true;
316

    
317
        }
318

    
319
        if (!geoTransformCreated) {
320
            // Try to get a geotransform from the file
321
            geotransform = gdalDataSet.GetGeoTransform();
322
            if (Arrays.equals(defaultGeotransform, geotransform) ){
323
                geoTransformCreated=false;
324
            }
325
        }
326

    
327
        // Try to get a geotransform from GCPs in the file
328
        if (!geoTransformCreated) {
329
            Vector vectorGCPs = gdalDataSet.GetGCPs();
330
            GCP[] gcps = new GCP[gdalDataSet.GetGCPCount()];
331
            for (int i = 0; i < gdalDataSet
332
                .GetGCPCount(); i++) {
333
                gcps[i] = (GCP) vectorGCPs.get(i);
334
            }
335
            double[] gcpsGeotransform = new double[6];
336
            int isOK =
337
                gdal.GCPsToGeoTransform(gcps, gcpsGeotransform);
338
            if (isOK != 0) {
339
                geotransform = gcpsGeotransform;
340
            }
341
        }
342

    
343
        return geotransform;
344
    }
345

    
346
    protected void createWorldFile(File file, Buffer buffer) throws IOException {
347
        String fileName=file.getAbsolutePath();
348
        File tfw = null;
349

    
350
        String extWorldFile = ".wld";
351
        Tags paramsTags=((DynClass_v2)getParameters().getDynClass()).getTags();
352
        if (paramsTags!=null && paramsTags.has(RasterGdalFileStoreParameters.WLD_EXTENSION_TAG_NAME)){
353
            String tagWorldFile=(String)paramsTags.get(RasterGdalFileStoreParameters.WLD_EXTENSION_TAG_NAME);
354
            if (StringUtils.isNotEmpty(tagWorldFile)){
355
                extWorldFile=FilenameUtils.EXTENSION_SEPARATOR_STR+tagWorldFile;
356
            }
357
        }
358

    
359
        tfw = new File(FilenameUtils.removeExtension(fileName) + extWorldFile);
360
        Envelope envelope;
361
        try {
362
            envelope = buffer.getEnvelope();
363
        } catch (LocatorException | CreateEnvelopeException e) {
364
            logger.warn("Can't get the buffer envelope", e);
365
            return;
366
        }
367

    
368
        double pixelSizeX = buffer.getPixelSizeX();//(envelope.getMaximum(DIMENSIONS.X) - envelope.getMinimum(DIMENSIONS.X)) / (gdalDataSet.getRasterXSize());
369
        double pixelSizeY = -buffer.getPixelSizeY();//(envelope.getMinimum(DIMENSIONS.Y) - envelope.getMaximum(DIMENSIONS.Y)) / (gdalDataSet.getRasterYSize());
370
        double upperLeftPixelCenterCoordX = envelope.getMinimum(DIMENSIONS.X)+pixelSizeX/2;//+gdalDataSet.getRasterXSize()/2;
371
        double upperLeftPixelCenterCoordY = envelope.getMaximum(DIMENSIONS.Y)+pixelSizeY/2;//gdalDataSet.getRasterYSize()/2;
372

    
373
        // Generamos un world file para gdal
374
        DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(tfw)));
375
        dos.writeBytes(pixelSizeX + "\n");
376
        dos.writeBytes("0.0\n");//rotationAxisY:Not implemented yet
377
        dos.writeBytes("0.0\n");//rotationAxisX:Not implemented yet
378
        dos.writeBytes(pixelSizeY + "\n");//Negative value
379
        dos.writeBytes("" + upperLeftPixelCenterCoordX + "\n");
380
        dos.writeBytes("" + upperLeftPixelCenterCoordY + "\n");
381
        dos.close();
382
    }
383

    
384
    @Override
385
    public Object getSourceId() {
386
        return this.getRasterGdalParameters().getFile();
387
    }
388

    
389
    @Override
390
    public String getName() {
391
        String name = this.getRasterGdalParameters().getFile().getName();
392
        return FilenameUtils.getBaseName(name);
393
    }
394

    
395
    @Override
396
    public String getFullName() {
397
        return this.getRasterGdalParameters().getFile().getAbsolutePath();
398
    }
399

    
400
    @Override
401
    public boolean closeResourceRequested(ResourceProvider resource) {
402
        gdalDataSet.delete();
403
        gdalDataSet=null;
404
        return true;
405
    }
406

    
407

    
408
    /**
409
     * Stores a buffer into a new file
410
     * @param newRasterParams
411
     * @param overwrite
412
     * @throws CreateException
413
     */
414
    public void store(boolean overwrite)
415
        throws CreateException {
416
        //This method must be overwritten by subclasses than can be stored
417
        throw new UnsupportedOperationException("This provider can't store the raster");
418
    }
419

    
420

    
421
    /**
422
     * Creates a Geotransform (Geolocalization data in Gdal formal) from  buffer envelope
423
     * @param buffer
424
     * @return
425
     */
426
    protected double[] createGeoTransform(Buffer buffer){
427
        double[] result=new double[6];
428
        try {
429
            result[0]=buffer.getEnvelope().getMinimum(DIMENSIONS.X);
430
        } catch (LocatorException | CreateEnvelopeException e) {
431
            result[0]=0;
432
        }
433
        result[1]=buffer.getPixelSizeX();
434
        //TODO: Rotation not implemented yet
435
        result[2]=0;
436
        try {
437
            result[3]=buffer.getEnvelope().getMaximum(DIMENSIONS.Y);
438
        } catch (LocatorException | CreateEnvelopeException e) {
439
            result[3]=0;
440
        }
441
        //TODO: Rotation not implemented yet
442
        result[4]=0;
443
        result[5]=-buffer.getPixelSizeY();
444
        return result;
445
    }
446

    
447
    /**
448
     * Extracts the options to create a new raster, if any of them exist
449
     * @param newRasterParams
450
     * @return
451
     */
452
    protected String[] getStoringOptions(
453
        NewRasterGdalStoreParameters newRasterParams) {
454
        //Specific params from the driver are readed
455
        //IMPORTANT:Param names defined in the XML must be the same that the properties used for the driver
456
        ArrayList<String> optionsList=new ArrayList<String>();
457
        DynClass dynClass = newRasterParams.getDynClass();
458
        DynField[] fields = dynClass.getDynFields();
459
        for (DynField field:fields){
460
            String fieldName = field.getName();
461
            String gdalOption = fieldName.toUpperCase();
462
            Object dynValue = newRasterParams.getDynValue(fieldName);
463

    
464
            if (dynValue!=null && field.getGroup().equalsIgnoreCase(NewRasterGdalStoreParameters.CREATE_OPTIONS_GROUP)){
465
                if(field.getType() == DataTypes.BOOLEAN) {
466
                    if((Boolean)dynValue){
467
                        optionsList.add(gdalOption+"=YES");
468
                    }else{
469
                        optionsList.add(gdalOption+"=NO");
470
                    }
471

    
472
                } else {
473
                    optionsList.add(gdalOption+"="+dynValue);
474
                }
475
            }
476
        }
477
        String[]options=new String[optionsList.size()];
478
        optionsList.toArray(options);
479
        return options;
480
    }
481

    
482
    protected void savePrjFile(File dataFile, IProjection proj) throws IOException {
483
        if (proj == null) {
484
            return;
485
        }
486
        File file = new File(FilenameUtils.removeExtension(dataFile.getAbsolutePath()) + ".prj");
487
        String export = proj.export(ICRSFactory.FORMAT_WKT_ESRI);
488
        if (export != null) {
489
            FileUtils.writeStringToFile(file, export);
490
        }
491
    }
492

    
493
}