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 / AbstractRasterGdalStoreProvider.java @ 6337

History | View | Annotate | Download (17.3 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.util.ArrayList;
26
import java.util.List;
27

    
28
import org.cresques.cts.IProjection;
29
import org.gdal.gdal.Dataset;
30
import org.gdal.gdal.Driver;
31
import org.gvsig.fmap.dal.DataStoreNotification;
32
import org.gvsig.fmap.dal.DataStoreParameters;
33
import org.gvsig.fmap.dal.FileHelper;
34
import org.gvsig.fmap.dal.exception.CloseException;
35
import org.gvsig.fmap.dal.exception.CreateException;
36
import org.gvsig.fmap.dal.exception.InitializeException;
37
import org.gvsig.fmap.dal.exception.OpenException;
38
import org.gvsig.fmap.dal.raster.api.BandAttributeDescriptor;
39
import org.gvsig.fmap.dal.raster.api.BandDescriptor;
40
import org.gvsig.fmap.dal.raster.api.RasterQuery;
41
import org.gvsig.fmap.dal.raster.spi.AbstractRasterStoreProvider;
42
import org.gvsig.fmap.dal.resource.spi.ResourceConsumer;
43
import org.gvsig.fmap.dal.resource.spi.ResourceProvider;
44
import org.gvsig.fmap.dal.spi.DataStoreProviderServices;
45
import org.gvsig.fmap.geom.DataTypes;
46
import org.gvsig.fmap.geom.Geometry;
47
import org.gvsig.fmap.geom.GeometryLocator;
48
import org.gvsig.fmap.geom.exception.CreateEnvelopeException;
49
import org.gvsig.fmap.geom.primitive.Envelope;
50
import org.gvsig.metadata.MetadataLocator;
51
import org.gvsig.metadata.MetadataManager;
52
import org.gvsig.metadata.exceptions.MetadataException;
53
import org.gvsig.raster.lib.buffer.api.Band;
54
import org.gvsig.raster.lib.buffer.api.BandInfo;
55
import org.gvsig.raster.lib.buffer.api.Buffer;
56
import org.gvsig.raster.lib.buffer.api.BufferLocator;
57
import org.gvsig.raster.lib.buffer.api.BufferManager;
58
import org.gvsig.raster.lib.buffer.api.NoData;
59
import org.gvsig.raster.lib.buffer.api.PageManager;
60
import org.gvsig.raster.lib.buffer.api.exceptions.BufferException;
61
import org.gvsig.tools.ToolsLocator;
62
import org.gvsig.tools.dynobject.DynClass;
63
import org.gvsig.tools.dynobject.DynField;
64
import org.gvsig.tools.dynobject.DynObject;
65
import org.gvsig.tools.exception.BaseException;
66
import org.gvsig.tools.locator.LocatorException;
67
import org.gvsig.tools.task.SimpleTaskStatus;
68
import org.gvsig.tools.task.TaskStatusManager;
69
import org.slf4j.Logger;
70
import org.slf4j.LoggerFactory;
71

    
72
/**
73
 * Provider for Raster GDAL files
74
 * @author dmartinezizquierdo
75
 *
76
 */
77
public abstract class AbstractRasterGdalStoreProvider extends AbstractRasterStoreProvider implements
78
ResourceConsumer{
79

    
80
    private static final Logger logger =
81
        LoggerFactory.getLogger(AbstractRasterGdalStoreProvider.class);
82

    
83
    /**
84
     * Provider name
85
     */
86
    public static String NAME = "RasterGdal";
87
    /**
88
     * Provider description
89
     */
90
    public static String DESCRIPTION = "Raster GDAL raster";
91
    /**
92
     * Parameters definition name for metadata
93
     */
94
    public static final String METADATA_DEFINITION_NAME = NAME;
95

    
96
    protected ResourceProvider resource;
97
    protected final SimpleTaskStatus taskStatus;
98

    
99
    protected Envelope envelope = null;
100
    protected IProjection projection= null;
101
    protected Dataset gdalDataSet;
102
    protected Driver gdalDriver;
103

    
104
    /**
105
     * Dataset from gdal containing the raster data
106
     * @return Dataset
107
     */
108
    public Dataset getGdalDataSet() {
109
        return gdalDataSet;
110
    }
111

    
112
    protected static void registerMetadataDefinition()
113
        throws MetadataException {
114
        MetadataManager manager = MetadataLocator.getMetadataManager();
115
        if (manager.getDefinition(METADATA_DEFINITION_NAME) == null) {
116
            manager.addDefinition(METADATA_DEFINITION_NAME,
117
                DataStoreParameters.class
118
                    .getResourceAsStream("RasterGdalMetadata.xml"),
119
                    DataStoreParameters.class.getClassLoader());
120
        }
121
    }
122

    
123
    /**
124
     * Constructor
125
     * @param params
126
     * @param storeServices
127
     * @throws InitializeException
128
     */
129
    public AbstractRasterGdalStoreProvider(DataStoreParameters params,
130
        DataStoreProviderServices storeServices)
131
        throws InitializeException {
132
        super(
133
                params,
134
                storeServices,
135
                FileHelper.newMetadataContainer(METADATA_DEFINITION_NAME)
136
        );
137
        TaskStatusManager manager = ToolsLocator.getTaskStatusManager();
138
        this.taskStatus = manager.createDefaultSimpleTaskStatus("RasterGdal");
139
        this.init(params, storeServices);
140
    }
141

    
142
    protected AbstractRasterGdalStoreProvider(DataStoreParameters params,
143
            DataStoreProviderServices storeServices, DynObject metadata)
144
            throws InitializeException {
145
        super(params, storeServices, metadata);
146
        TaskStatusManager manager = ToolsLocator.getTaskStatusManager();
147
        this.taskStatus = manager.createDefaultSimpleTaskStatus("RasterGdal");
148
        this.init((DataStoreParameters)params, storeServices);
149
    }
150

    
151
    protected AbstractRasterGdalStoreProvider(NewRasterGdalStoreParameters params, Driver gdalDriver) {
152
        //PARA Exportar
153
        super(params,null,null);
154
        this.gdalDriver=gdalDriver;
155
        TaskStatusManager manager = ToolsLocator.getTaskStatusManager();
156
        this.taskStatus = manager.createDefaultSimpleTaskStatus("RasterGdal");
157
    }
158

    
159
    protected void init(DataStoreParameters params,
160
        DataStoreProviderServices storeServices) throws InitializeException {
161
        if (params == null) {
162
            throw new InitializeException(
163
                new NullPointerException("params is null"));
164
        }
165

    
166
    }
167

    
168
    protected DataStoreParameters getRasterGdalParameters() {
169
        return (DataStoreParameters) this.getParameters();
170
    }
171

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

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

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

    
204
    @Override
205
    public Buffer createBuffer(RasterQuery rasterQuery) throws BufferException {
206
        int bandCount=gdalDataSet.getRasterCount();
207
        BufferManager bufferManager=BufferLocator.getBufferManager();
208
        int[] bandDataTypes=new int[bandCount];
209
        NoData[] bandNoData=new NoData[bandCount];
210
        List<PageManager> pageManagers=new ArrayList<PageManager>();
211

    
212
        for (int i=0;i<bandCount;i++){
213
            //Gdal bands begin count in 1
214
            int gdalBandNumber=i+1;
215
            org.gdal.gdal.Band gdalBand=gdalDataSet.GetRasterBand(gdalBandNumber);
216

    
217
            bandDataTypes[i]=getRasterBufTypeFromGdalType(gdalBand.getDataType());
218
            Double noData=getNoData(gdalBand);
219
            if (noData!=null){
220
                bandNoData[i]=bufferManager.createNoData(noData, noData);
221
            }else{
222
                bandNoData[i]=null;
223
            }
224
            //Paginated
225
            //pageManagers.add(new RasterGdalBandPageManager(gdalDataSet, gdalBandNumber));
226
            //Tiled
227
            pageManagers.add(new RasterGdalBandTileManager(gdalDataSet, gdalBandNumber, 256, 256));
228
        }
229

    
230
        Buffer buffer =
231
            bufferManager.createBuffer(gdalDataSet.getRasterYSize(), gdalDataSet.getRasterXSize(),
232
                bandDataTypes, bandNoData, projection, envelope, pageManagers);
233

    
234
        return buffer;
235
    }
236

    
237
    @Override
238
    public BandInfo getBandInfo(int band) {
239
        RasterGdalBandPageManager gdalBandPageManager =
240
            new RasterGdalBandPageManager(gdalDataSet, band + 1); // Gdal bands start at 1
241
        return gdalBandPageManager.getBandInfo();
242
    }
243

    
244
    @Override
245
    public BandDescriptor getBandDescriptor(int band) {
246
        // Returns an empty band descriptor
247
        return getStoreServices().createBandDescriptor(band,
248
            new ArrayList<BandAttributeDescriptor>(0));
249
    }
250

    
251
    @Override
252
    public int getBands() {
253
        return gdalDataSet.getRasterCount();
254
    }
255

    
256
    private Double getNoData(org.gdal.gdal.Band gdalBand){
257
        Double[] noDataValueResult=new Double[1];
258
        gdalBand.GetNoDataValue(noDataValueResult);
259
        Double noData=noDataValueResult[0];
260
        return noData;
261
    }
262

    
263

    
264

    
265
    public void open() throws OpenException {
266
        if (this.gdalDataSet != null) {
267
            return;
268
        }
269
        openEver();
270
    }
271

    
272
    protected void openEver() throws OpenException {
273
        //This method must be overwritten by subclasses than can open a raster
274
        throw new UnsupportedOperationException("This provider can't open the raster");
275
    }
276

    
277
    protected Envelope createEnvelope(double[] geotransform){
278

    
279
        double leftMostX        = geotransform[0];/* top left x */
280
        double pixelSizeX       = geotransform[1];/* w-e pixel resolution */
281
        double rotationAxisX    = geotransform[2];/* 0 */
282
        double upperMostY       = geotransform[3];/* top left y */
283
        double rotationAxisY    = geotransform[4];/* 0 */
284
        double pixelSizeY       = geotransform[5];/* n-s pixel resolution (negative value) */
285

    
286
        if (0.0 != rotationAxisX || 0.0 != rotationAxisY) {
287
            logger.warn(
288
                "Rotation in wld file not implemented yet. It will be ignored");
289
        }
290

    
291
        double width =gdalDataSet.getRasterXSize()*pixelSizeX;
292
        double height=gdalDataSet.getRasterYSize()*pixelSizeY;
293

    
294
        // double minX, double minY, double maxX, double maxY, int subType
295
        try {
296
            envelope = GeometryLocator.getGeometryManager().createEnvelope(
297
                Math.min(leftMostX,leftMostX + width),
298
                Math.min(upperMostY,upperMostY + height),
299
                Math.max(leftMostX,leftMostX + width),
300
                Math.max(upperMostY,upperMostY + height),
301
                Geometry.SUBTYPES.GEOM2D);
302
        } catch (LocatorException | CreateEnvelopeException e) {
303
            logger.warn(
304
                "Failed to create envelope from wld file with coords: minx:"+leftMostX+
305
                ", miny:"+upperMostY+", maxX: "+leftMostX + width+", maxY: "+upperMostY + height);
306
            e.printStackTrace();
307
        }
308

    
309
        return envelope;
310
    }
311

    
312
    @Override
313
    public void close() throws CloseException {
314
        this.gdalDataSet = null;
315
    }
316

    
317
    @Override
318
    public ResourceProvider getResource() {
319
        return this.resource;
320
    }
321

    
322
    @Override
323
    public String getProviderName() {
324
        return getRasterGdalParameters().getDataStoreName();
325
    }
326

    
327
    @Override
328
    public boolean closeResourceRequested(ResourceProvider resource) {
329
        return true;
330
    }
331

    
332
    @Override
333
    /*
334
     * (non-Javadoc)
335
     *
336
     * @see
337
     * org.gvsig.fmap.dal.resource.spi.ResourceConsumer#resourceChanged(org.
338
     * gvsig.fmap.dal.resource.spi.ResourceProvider)
339
     */
340
    public void resourceChanged(ResourceProvider resource) {
341
        this.getStoreServices().notifyChange(
342
            DataStoreNotification.RESOURCE_CHANGED,
343
            resource);
344
    }
345

    
346
    @Override
347
    /* (non-Javadoc)
348
     * @see org.gvsig.fmap.dal.feature.spi.memory.AbstractMemoryStoreProvider#doDispose()
349
     */
350
    protected void doDispose() throws BaseException {
351
        super.doDispose();
352
        resource.removeConsumer(this);
353
    }
354

    
355
    /**
356
     * Conversi?n de los tipos de datos de gdal a los tipos de datos de RasterBuf
357
     * @param gdalType Tipo de dato de gdal
358
     * @return Tipo de dato de RasterBuf
359
     */
360
    protected static int getRasterBufTypeFromGdalType(int gdalType) {
361
        switch (gdalType) {
362
            case 1:// Eight bit unsigned integer GDT_Byte = 1
363
                return BufferManager.TYPE_BYTE;
364

    
365
            case 3:// Sixteen bit signed integer GDT_Int16 = 3,
366
                return BufferManager.TYPE_SHORT;
367

    
368
            case 2:// Sixteen bit unsigned integer GDT_UInt16 = 2
369
                //return RasterBuffer.TYPE_USHORT;
370
                return BufferManager.TYPE_SHORT; //Apa?o para usar los tipos de datos que soportamos
371

    
372
            case 5:// Thirty two bit signed integer GDT_Int32 = 5
373
                return BufferManager.TYPE_INT;
374

    
375
            case 6:// Thirty two bit floating point GDT_Float32 = 6
376
                return BufferManager.TYPE_FLOAT;
377

    
378
            case 7:// Sixty four bit floating point GDT_Float64 = 7
379
                return BufferManager.TYPE_DOUBLE;
380

    
381
                // TODO:Estos tipos de datos no podemos gestionarlos. Habria que definir
382
                // el tipo complejo y usar el tipo long que de momento no se gasta.
383
            case 4:// Thirty two bit unsigned integer GDT_UInt32 = 4,
384
                return BufferManager.TYPE_INT;
385
                //return RasterBuffer.TYPE_UNDEFINED; // Deberia devolver un Long
386

    
387
            case 8:// Complex Int16 GDT_CInt16 = 8
388
            case 9:// Complex Int32 GDT_CInt32 = 9
389
            case 10:// Complex Float32 GDT_CFloat32 = 10
390
            case 11:// Complex Float64 GDT_CFloat64 = 11
391
                return BufferManager.TYPE_UNDEFINED;
392
        }
393
        return BufferManager.TYPE_UNDEFINED;
394
    }
395

    
396
    /**
397
     * Stores a buffer into a new entity
398
     * @param newRasterParams
399
     * @param overwrite
400
     * @throws CreateException
401
     */
402
    public void store(boolean overwrite)
403
        throws CreateException {
404
        //This method must be overwritten by subclasses than can be stored
405
        throw new UnsupportedOperationException("This provider can't store the raster");
406
    }
407

    
408

    
409
    /**
410
     * Fills a given dataset with data from a buffer
411
     * @param buffer
412
     * @param gdalDataset
413
     */
414
    protected void fillDataset(Buffer buffer, Dataset gdalDataset) {
415
        for (int i=0;i<buffer.getBandCount();i++){
416
            Band band = buffer.getBand(i);
417

    
418
            switch (band.getDataType()) {
419
            case BufferManager.TYPE_BYTE:
420
                byte[] byteRowBuffer = (byte[])band.createRowBuffer(); //new byte[band.getColumns()];
421
                for (int row=0;row<band.getRows();row++){
422
                    band.fetchRow(row, byteRowBuffer);
423
                    gdalDataset.GetRasterBand(i+1).WriteRaster(0, row, band.getColumns(), 1,
424
                        byteRowBuffer);
425
                }
426
                break;
427

    
428
            case BufferManager.TYPE_DOUBLE:
429
                double[] doubleRowBuffer=(double[])band.createRowBuffer();
430
                for (int row=0;row<band.getRows();row++){
431
                    band.fetchRow(row, doubleRowBuffer);
432
                    gdalDataset.GetRasterBand(i+1).WriteRaster(0, row, band.getColumns(), 1,
433
                        doubleRowBuffer);
434
                }
435
                break;
436

    
437
            case BufferManager.TYPE_FLOAT:
438
                float[] floatRowBuffer=(float[])band.createRowBuffer();
439
                for (int row=0;row<band.getRows();row++){
440
                    band.fetchRow(row, floatRowBuffer);
441
                    gdalDataset.GetRasterBand(i+1).WriteRaster(0, row, band.getColumns(), 1,
442
                        floatRowBuffer);
443
                }
444
                break;
445

    
446
            case BufferManager.TYPE_INT:
447
                int[] intRowBuffer=(int[])band.createRowBuffer();
448
                for (int row=0;row<band.getRows();row++){
449
                    band.fetchRow(row, intRowBuffer);
450
                    gdalDataset.GetRasterBand(i+1).WriteRaster(0, row, band.getColumns(), 1,
451
                        intRowBuffer);
452
                }
453
                break;
454

    
455
            case BufferManager.TYPE_SHORT:
456
            case BufferManager.TYPE_USHORT:
457
                short[] shortRowBuffer=(short[])band.createRowBuffer();
458
                for (int row=0;row<band.getRows();row++){
459
                    band.fetchRow(row, shortRowBuffer);
460
                    gdalDataset.GetRasterBand(i+1).WriteRaster(0, row, band.getColumns(), 1,
461
                        shortRowBuffer);
462
                }
463
                break;
464

    
465
            default:
466
                break;
467
            }
468

    
469
        }
470
    }
471

    
472
}