1 : /******************************************************************************
2 : * $Id: bagdataset.cpp 22145 2011-04-12 15:42:18Z warmerdam $
3 : *
4 : * Project: Hierarchical Data Format Release 5 (HDF5)
5 : * Purpose: Read BAG datasets.
6 : * Author: Frank Warmerdam <warmerdam@pobox.com>
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2009, Frank Warmerdam <warmerdam@pobox.com>
10 : *
11 : * Permission is hereby granted, free of charge, to any person obtaining a
12 : * copy of this software and associated documentation files (the "Software"),
13 : * to deal in the Software without restriction, including without limitation
14 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 : * and/or sell copies of the Software, and to permit persons to whom the
16 : * Software is furnished to do so, subject to the following conditions:
17 : *
18 : * The above copyright notice and this permission notice shall be included
19 : * in all copies or substantial portions of the Software.
20 : *
21 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 : * DEALINGS IN THE SOFTWARE.
28 : ****************************************************************************/
29 :
30 : #include "gh5_convenience.h"
31 :
32 : #include "gdal_pam.h"
33 : #include "gdal_priv.h"
34 : #include "ogr_spatialref.h"
35 : #include "cpl_string.h"
36 :
37 : CPL_CVSID("$Id: bagdataset.cpp 22145 2011-04-12 15:42:18Z warmerdam $");
38 :
39 : CPL_C_START
40 : void GDALRegister_BAG(void);
41 : CPL_C_END
42 :
43 : OGRErr OGR_SRS_ImportFromISO19115( OGRSpatialReference *poThis,
44 : const char *pszISOXML );
45 :
46 : /************************************************************************/
47 : /* ==================================================================== */
48 : /* BAGDataset */
49 : /* ==================================================================== */
50 : /************************************************************************/
51 : class BAGDataset : public GDALPamDataset
52 : {
53 :
54 : friend class BAGRasterBand;
55 :
56 : hid_t hHDF5;
57 :
58 : char *pszProjection;
59 : double adfGeoTransform[6];
60 :
61 : void LoadMetadata();
62 :
63 : char *pszXMLMetadata;
64 : char *apszMDList[2];
65 :
66 : public:
67 : BAGDataset();
68 : ~BAGDataset();
69 :
70 : virtual CPLErr GetGeoTransform( double * );
71 : virtual const char *GetProjectionRef(void);
72 : virtual char **GetMetadata( const char * pszDomain = "" );
73 :
74 : static GDALDataset *Open( GDALOpenInfo * );
75 : static int Identify( GDALOpenInfo * );
76 : };
77 :
78 : /************************************************************************/
79 : /* ==================================================================== */
80 : /* BAGRasterBand */
81 : /* ==================================================================== */
82 : /************************************************************************/
83 : class BAGRasterBand : public GDALPamRasterBand
84 : {
85 : friend class BAGDataset;
86 :
87 : hid_t hDatasetID;
88 : hid_t native;
89 : hid_t dataspace;
90 :
91 : bool bMinMaxSet;
92 : double dfMinimum;
93 : double dfMaximum;
94 :
95 : public:
96 :
97 : BAGRasterBand( BAGDataset *, int );
98 : ~BAGRasterBand();
99 :
100 : bool Initialize( hid_t hDataset, const char *pszName );
101 :
102 : virtual CPLErr IReadBlock( int, int, void * );
103 : virtual double GetNoDataValue( int * );
104 :
105 : virtual double GetMinimum( int *pbSuccess = NULL );
106 : virtual double GetMaximum(int *pbSuccess = NULL );
107 : };
108 :
109 : /************************************************************************/
110 : /* BAGRasterBand() */
111 : /************************************************************************/
112 3 : BAGRasterBand::BAGRasterBand( BAGDataset *poDS, int nBand )
113 :
114 : {
115 3 : this->poDS = poDS;
116 3 : this->nBand = nBand;
117 :
118 3 : hDatasetID = -1;
119 3 : dataspace = -1;
120 3 : native = -1;
121 3 : bMinMaxSet = false;
122 3 : }
123 :
124 : /************************************************************************/
125 : /* ~BAGRasterBand() */
126 : /************************************************************************/
127 :
128 3 : BAGRasterBand::~BAGRasterBand()
129 : {
130 3 : if( dataspace > 0 )
131 3 : H5Sclose(dataspace);
132 :
133 3 : if( native > 0 )
134 3 : H5Tclose( native );
135 :
136 3 : if( hDatasetID > 0 )
137 3 : H5Dclose( hDatasetID );
138 3 : }
139 :
140 : /************************************************************************/
141 : /* Initialize() */
142 : /************************************************************************/
143 :
144 3 : bool BAGRasterBand::Initialize( hid_t hDatasetID, const char *pszName )
145 :
146 : {
147 3 : SetDescription( pszName );
148 :
149 3 : this->hDatasetID = hDatasetID;
150 :
151 3 : hid_t datatype = H5Dget_type( hDatasetID );
152 3 : dataspace = H5Dget_space( hDatasetID );
153 3 : hid_t n_dims = H5Sget_simple_extent_ndims( dataspace );
154 3 : native = H5Tget_native_type( datatype, H5T_DIR_ASCEND );
155 : hsize_t dims[3], maxdims[3];
156 :
157 3 : eDataType = GH5_GetDataType( native );
158 :
159 3 : if( n_dims == 2 )
160 : {
161 3 : H5Sget_simple_extent_dims( dataspace, dims, maxdims );
162 :
163 3 : nRasterXSize = (int) dims[1];
164 3 : nRasterYSize = (int) dims[0];
165 : }
166 : else
167 : {
168 : CPLError( CE_Failure, CPLE_AppDefined,
169 0 : "Dataset not of rank 2." );
170 0 : return false;
171 : }
172 :
173 3 : nBlockXSize = nRasterXSize;
174 3 : nBlockYSize = 1;
175 :
176 : /* -------------------------------------------------------------------- */
177 : /* Check for chunksize, and use it as blocksize for optimized */
178 : /* reading. */
179 : /* -------------------------------------------------------------------- */
180 3 : hid_t listid = H5Dget_create_plist( hDatasetID );
181 3 : if (listid>0)
182 : {
183 3 : if(H5Pget_layout(listid) == H5D_CHUNKED)
184 : {
185 : hsize_t panChunkDims[3];
186 0 : int nDimSize = H5Pget_chunk(listid, 3, panChunkDims);
187 0 : nBlockXSize = (int) panChunkDims[nDimSize-1];
188 0 : nBlockYSize = (int) panChunkDims[nDimSize-2];
189 : }
190 3 : H5Pclose(listid);
191 : }
192 :
193 : /* -------------------------------------------------------------------- */
194 : /* Load min/max information. */
195 : /* -------------------------------------------------------------------- */
196 3 : if( EQUAL(pszName,"elevation")
197 : && GH5_FetchAttribute( hDatasetID, "Maximum Elevation Value",
198 : dfMaximum )
199 : && GH5_FetchAttribute( hDatasetID, "Minimum Elevation Value",
200 : dfMinimum ) )
201 1 : bMinMaxSet = true;
202 2 : else if( EQUAL(pszName,"uncertainty")
203 : && GH5_FetchAttribute( hDatasetID, "Maximum Uncertainty Value",
204 : dfMaximum )
205 : && GH5_FetchAttribute( hDatasetID, "Minimum Uncertainty Value",
206 : dfMinimum ) )
207 1 : bMinMaxSet = true;
208 1 : else if( EQUAL(pszName,"nominal_elevation")
209 : && GH5_FetchAttribute( hDatasetID, "max_value",
210 : dfMaximum )
211 : && GH5_FetchAttribute( hDatasetID, "min_value",
212 : dfMinimum ) )
213 1 : bMinMaxSet = true;
214 :
215 3 : return true;
216 : }
217 :
218 : /************************************************************************/
219 : /* GetMinimum() */
220 : /************************************************************************/
221 :
222 1 : double BAGRasterBand::GetMinimum( int * pbSuccess )
223 :
224 : {
225 1 : if( bMinMaxSet )
226 : {
227 1 : if( pbSuccess )
228 1 : *pbSuccess = TRUE;
229 1 : return dfMinimum;
230 : }
231 : else
232 0 : return GDALRasterBand::GetMinimum( pbSuccess );
233 : }
234 :
235 : /************************************************************************/
236 : /* GetMaximum() */
237 : /************************************************************************/
238 :
239 1 : double BAGRasterBand::GetMaximum( int * pbSuccess )
240 :
241 : {
242 1 : if( bMinMaxSet )
243 : {
244 1 : if( pbSuccess )
245 1 : *pbSuccess = TRUE;
246 1 : return dfMaximum;
247 : }
248 : else
249 0 : return GDALRasterBand::GetMaximum( pbSuccess );
250 : }
251 :
252 : /************************************************************************/
253 : /* GetNoDataValue() */
254 : /************************************************************************/
255 3 : double BAGRasterBand::GetNoDataValue( int * pbSuccess )
256 :
257 : {
258 3 : if( pbSuccess )
259 3 : *pbSuccess = TRUE;
260 :
261 3 : if( EQUAL(GetDescription(),"elevation") )
262 1 : return 1000000.0;
263 2 : else if( EQUAL(GetDescription(),"uncertainty") )
264 1 : return 0.0;
265 1 : else if( EQUAL(GetDescription(),"nominal_elevation") )
266 1 : return 1000000.0;
267 : else
268 0 : return GDALPamRasterBand::GetNoDataValue( pbSuccess );
269 : }
270 :
271 : /************************************************************************/
272 : /* IReadBlock() */
273 : /************************************************************************/
274 30 : CPLErr BAGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
275 : void * pImage )
276 : {
277 : herr_t status;
278 : hsize_t count[3];
279 : H5OFFSET_TYPE offset[3];
280 : hid_t memspace;
281 : hsize_t col_dims[3];
282 30 : hsize_t rank = 2;
283 :
284 30 : offset[0] = nRasterYSize - nBlockYOff*nBlockYSize - 1;
285 30 : offset[1] = nBlockXOff*nBlockXSize;
286 30 : count[0] = nBlockYSize;
287 30 : count[1] = nBlockXSize;
288 :
289 : /* -------------------------------------------------------------------- */
290 : /* Select block from file space */
291 : /* -------------------------------------------------------------------- */
292 : status = H5Sselect_hyperslab( dataspace,
293 : H5S_SELECT_SET,
294 : offset, NULL,
295 30 : count, NULL );
296 :
297 : /* -------------------------------------------------------------------- */
298 : /* Create memory space to receive the data */
299 : /* -------------------------------------------------------------------- */
300 30 : col_dims[0]=nBlockYSize;
301 30 : col_dims[1]=nBlockXSize;
302 30 : memspace = H5Screate_simple( (int) rank, col_dims, NULL );
303 30 : H5OFFSET_TYPE mem_offset[3] = {0, 0, 0};
304 : status = H5Sselect_hyperslab(memspace,
305 : H5S_SELECT_SET,
306 : mem_offset, NULL,
307 30 : count, NULL);
308 :
309 : status = H5Dread ( hDatasetID,
310 : native,
311 : memspace,
312 : dataspace,
313 : H5P_DEFAULT,
314 30 : pImage );
315 :
316 30 : H5Sclose(memspace);
317 30 : return CE_None;
318 : }
319 :
320 : /************************************************************************/
321 : /* ==================================================================== */
322 : /* BAGDataset */
323 : /* ==================================================================== */
324 : /************************************************************************/
325 :
326 : /************************************************************************/
327 : /* BAGDataset() */
328 : /************************************************************************/
329 :
330 1 : BAGDataset::BAGDataset()
331 : {
332 1 : hHDF5 = -1;
333 1 : pszXMLMetadata = NULL;
334 1 : pszProjection = NULL;
335 :
336 1 : adfGeoTransform[0] = 0.0;
337 1 : adfGeoTransform[1] = 1.0;
338 1 : adfGeoTransform[2] = 0.0;
339 1 : adfGeoTransform[3] = 0.0;
340 1 : adfGeoTransform[4] = 0.0;
341 1 : adfGeoTransform[5] = 1.0;
342 1 : }
343 :
344 : /************************************************************************/
345 : /* ~BAGDataset() */
346 : /************************************************************************/
347 1 : BAGDataset::~BAGDataset( )
348 : {
349 1 : FlushCache();
350 :
351 1 : if( hHDF5 >= 0 )
352 1 : H5Fclose( hHDF5 );
353 :
354 1 : CPLFree( pszXMLMetadata );
355 1 : CPLFree( pszProjection );
356 1 : }
357 :
358 : /************************************************************************/
359 : /* Identify() */
360 : /************************************************************************/
361 :
362 10720 : int BAGDataset::Identify( GDALOpenInfo * poOpenInfo )
363 :
364 : {
365 : /* -------------------------------------------------------------------- */
366 : /* Is it an HDF5 file? */
367 : /* -------------------------------------------------------------------- */
368 : static const char achSignature[] = "\211HDF\r\n\032\n";
369 :
370 10720 : if( poOpenInfo->pabyHeader == NULL
371 : || memcmp(poOpenInfo->pabyHeader,achSignature,8) != 0 )
372 10715 : return FALSE;
373 :
374 : /* -------------------------------------------------------------------- */
375 : /* Does it have the extension .bag? */
376 : /* -------------------------------------------------------------------- */
377 5 : if( !EQUAL(CPLGetExtension(poOpenInfo->pszFilename),"bag") )
378 4 : return FALSE;
379 :
380 1 : return TRUE;
381 : }
382 :
383 : /************************************************************************/
384 : /* Open() */
385 : /************************************************************************/
386 :
387 1475 : GDALDataset *BAGDataset::Open( GDALOpenInfo * poOpenInfo )
388 :
389 : {
390 : /* -------------------------------------------------------------------- */
391 : /* Confirm that this appears to be a BAG file. */
392 : /* -------------------------------------------------------------------- */
393 1475 : if( !Identify( poOpenInfo ) )
394 1474 : return NULL;
395 :
396 : /* -------------------------------------------------------------------- */
397 : /* Confirm the requested access is supported. */
398 : /* -------------------------------------------------------------------- */
399 1 : if( poOpenInfo->eAccess == GA_Update )
400 : {
401 : CPLError( CE_Failure, CPLE_NotSupported,
402 0 : "The BAG driver does not support update access." );
403 0 : return NULL;
404 : }
405 :
406 : /* -------------------------------------------------------------------- */
407 : /* Open the file as an HDF5 file. */
408 : /* -------------------------------------------------------------------- */
409 : hid_t hHDF5 = H5Fopen( poOpenInfo->pszFilename,
410 1 : H5F_ACC_RDONLY, H5P_DEFAULT );
411 :
412 1 : if( hHDF5 < 0 )
413 0 : return NULL;
414 :
415 : /* -------------------------------------------------------------------- */
416 : /* Confirm it is a BAG dataset by checking for the */
417 : /* BAG_Root/Bag Version attribute. */
418 : /* -------------------------------------------------------------------- */
419 1 : hid_t hBagRoot = H5Gopen( hHDF5, "/BAG_root" );
420 1 : hid_t hVersion = -1;
421 :
422 1 : if( hBagRoot >= 0 )
423 1 : hVersion = H5Aopen_name( hBagRoot, "Bag Version" );
424 :
425 1 : if( hVersion < 0 )
426 : {
427 0 : H5Fclose( hHDF5 );
428 0 : return NULL;
429 : }
430 1 : H5Aclose( hVersion );
431 :
432 : /* -------------------------------------------------------------------- */
433 : /* Create a corresponding dataset. */
434 : /* -------------------------------------------------------------------- */
435 1 : BAGDataset *poDS = new BAGDataset();
436 :
437 1 : poDS->hHDF5 = hHDF5;
438 :
439 : /* -------------------------------------------------------------------- */
440 : /* Extract version as metadata. */
441 : /* -------------------------------------------------------------------- */
442 1 : CPLString osVersion;
443 :
444 2 : if( GH5_FetchAttribute( hBagRoot, "Bag Version", osVersion ) )
445 1 : poDS->SetMetadataItem( "BagVersion", osVersion );
446 :
447 1 : H5Gclose( hBagRoot );
448 :
449 : /* -------------------------------------------------------------------- */
450 : /* Fetch the elevation dataset and attach as a band. */
451 : /* -------------------------------------------------------------------- */
452 1 : int nNextBand = 1;
453 1 : hid_t hElevation = H5Dopen( hHDF5, "/BAG_root/elevation" );
454 1 : if( hElevation < 0 )
455 : {
456 0 : delete poDS;
457 0 : return NULL;
458 : }
459 :
460 1 : BAGRasterBand *poElevBand = new BAGRasterBand( poDS, nNextBand );
461 :
462 2 : if( !poElevBand->Initialize( hElevation, "elevation" ) )
463 : {
464 0 : delete poElevBand;
465 0 : delete poDS;
466 0 : return NULL;
467 : }
468 :
469 1 : poDS->nRasterXSize = poElevBand->nRasterXSize;
470 1 : poDS->nRasterYSize = poElevBand->nRasterYSize;
471 :
472 1 : poDS->SetBand( nNextBand++, poElevBand );
473 :
474 : /* -------------------------------------------------------------------- */
475 : /* Try to do the same for the uncertainty band. */
476 : /* -------------------------------------------------------------------- */
477 1 : hid_t hUncertainty = H5Dopen( hHDF5, "/BAG_root/uncertainty" );
478 1 : BAGRasterBand *poUBand = new BAGRasterBand( poDS, nNextBand );
479 :
480 2 : if( hUncertainty >= 0 && poUBand->Initialize( hUncertainty, "uncertainty") )
481 : {
482 1 : poDS->SetBand( nNextBand++, poUBand );
483 : }
484 : else
485 0 : delete poUBand;
486 :
487 : /* -------------------------------------------------------------------- */
488 : /* Try to do the same for the uncertainty band. */
489 : /* -------------------------------------------------------------------- */
490 1 : hid_t hNominal = -1;
491 :
492 1 : H5E_BEGIN_TRY {
493 1 : hNominal = H5Dopen( hHDF5, "/BAG_root/nominal_elevation" );
494 1 : } H5E_END_TRY;
495 :
496 1 : BAGRasterBand *poNBand = new BAGRasterBand( poDS, nNextBand );
497 2 : if( hNominal >= 0 && poNBand->Initialize( hNominal,
498 : "nominal_elevation" ) )
499 : {
500 1 : poDS->SetBand( nNextBand++, poNBand );
501 : }
502 : else
503 0 : delete poNBand;
504 :
505 : /* -------------------------------------------------------------------- */
506 : /* Load the XML metadata. */
507 : /* -------------------------------------------------------------------- */
508 1 : poDS->LoadMetadata();
509 :
510 : /* -------------------------------------------------------------------- */
511 : /* Setup/check for pam .aux.xml. */
512 : /* -------------------------------------------------------------------- */
513 1 : poDS->SetDescription( poOpenInfo->pszFilename );
514 1 : poDS->TryLoadXML();
515 :
516 : /* -------------------------------------------------------------------- */
517 : /* Setup overviews. */
518 : /* -------------------------------------------------------------------- */
519 1 : poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
520 :
521 1 : return( poDS );
522 : }
523 :
524 : /************************************************************************/
525 : /* LoadMetadata() */
526 : /************************************************************************/
527 :
528 1 : void BAGDataset::LoadMetadata()
529 :
530 : {
531 : /* -------------------------------------------------------------------- */
532 : /* Load the metadata from the file. */
533 : /* -------------------------------------------------------------------- */
534 1 : hid_t hMDDS = H5Dopen( hHDF5, "/BAG_root/metadata" );
535 1 : hid_t datatype = H5Dget_type( hMDDS );
536 1 : hid_t dataspace = H5Dget_space( hMDDS );
537 1 : hid_t native = H5Tget_native_type( datatype, H5T_DIR_ASCEND );
538 : hsize_t dims[3], maxdims[3];
539 :
540 1 : H5Sget_simple_extent_dims( dataspace, dims, maxdims );
541 :
542 1 : pszXMLMetadata = (char *) CPLCalloc((int) (dims[0]+1),1);
543 :
544 1 : H5Dread( hMDDS, native, H5S_ALL, dataspace, H5P_DEFAULT, pszXMLMetadata );
545 :
546 1 : H5Tclose( native );
547 1 : H5Sclose( dataspace );
548 1 : H5Tclose( datatype );
549 1 : H5Dclose( hMDDS );
550 :
551 1 : if( strlen(pszXMLMetadata) == 0 )
552 0 : return;
553 :
554 : /* -------------------------------------------------------------------- */
555 : /* Try to get the geotransform. */
556 : /* -------------------------------------------------------------------- */
557 1 : CPLXMLNode *psRoot = CPLParseXMLString( pszXMLMetadata );
558 :
559 1 : if( psRoot == NULL )
560 0 : return;
561 :
562 1 : CPLStripXMLNamespace( psRoot, NULL, TRUE );
563 :
564 1 : CPLXMLNode *psGeo = CPLSearchXMLNode( psRoot, "=MD_Georectified" );
565 :
566 1 : if( psGeo != NULL )
567 : {
568 : char **papszCornerTokens =
569 : CSLTokenizeStringComplex(
570 : CPLGetXMLValue( psGeo, "cornerPoints.Point.coordinates", "" ),
571 1 : " ,", FALSE, FALSE );
572 :
573 1 : if( CSLCount(papszCornerTokens ) == 4 )
574 : {
575 1 : double dfLLX = atof( papszCornerTokens[0] );
576 1 : double dfLLY = atof( papszCornerTokens[1] );
577 1 : double dfURX = atof( papszCornerTokens[2] );
578 1 : double dfURY = atof( papszCornerTokens[3] );
579 :
580 1 : adfGeoTransform[0] = dfLLX;
581 1 : adfGeoTransform[1] = (dfURX - dfLLX) / (GetRasterXSize()-1);
582 1 : adfGeoTransform[3] = dfURY;
583 1 : adfGeoTransform[5] = (dfLLY - dfURY) / (GetRasterYSize()-1);
584 :
585 1 : adfGeoTransform[0] -= adfGeoTransform[1] * 0.5;
586 1 : adfGeoTransform[3] -= adfGeoTransform[5] * 0.5;
587 : }
588 1 : CSLDestroy( papszCornerTokens );
589 : }
590 :
591 1 : CPLDestroyXMLNode( psRoot );
592 :
593 : /* -------------------------------------------------------------------- */
594 : /* Try to get the coordinate system. */
595 : /* -------------------------------------------------------------------- */
596 1 : OGRSpatialReference oSRS;
597 :
598 1 : if( OGR_SRS_ImportFromISO19115( &oSRS, pszXMLMetadata )
599 : == OGRERR_NONE )
600 : {
601 0 : oSRS.exportToWkt( &pszProjection );
602 1 : }
603 : }
604 :
605 : /************************************************************************/
606 : /* GetGeoTransform() */
607 : /************************************************************************/
608 :
609 0 : CPLErr BAGDataset::GetGeoTransform( double *padfGeoTransform )
610 :
611 : {
612 0 : if( adfGeoTransform[0] != 0.0 || adfGeoTransform[3] != 0.0 )
613 : {
614 0 : memcpy( padfGeoTransform, adfGeoTransform, sizeof(double)*6 );
615 0 : return CE_None;
616 : }
617 : else
618 0 : return GDALPamDataset::GetGeoTransform( padfGeoTransform );
619 : }
620 :
621 : /************************************************************************/
622 : /* GetProjectionRef() */
623 : /************************************************************************/
624 :
625 0 : const char *BAGDataset::GetProjectionRef()
626 :
627 : {
628 0 : if( pszProjection )
629 0 : return pszProjection;
630 : else
631 0 : return GDALPamDataset::GetProjectionRef();
632 : }
633 :
634 : /************************************************************************/
635 : /* GetMetadata() */
636 : /************************************************************************/
637 :
638 1 : char **BAGDataset::GetMetadata( const char *pszDomain )
639 :
640 : {
641 1 : if( pszDomain != NULL && EQUAL(pszDomain,"xml:BAG") )
642 : {
643 1 : apszMDList[0] = pszXMLMetadata;
644 1 : apszMDList[1] = NULL;
645 :
646 1 : return apszMDList;
647 : }
648 : else
649 0 : return GDALPamDataset::GetMetadata( pszDomain );
650 : }
651 :
652 : /************************************************************************/
653 : /* GDALRegister_BAG() */
654 : /************************************************************************/
655 558 : void GDALRegister_BAG( )
656 :
657 : {
658 : GDALDriver *poDriver;
659 :
660 558 : if (! GDAL_CHECK_VERSION("BAG"))
661 0 : return;
662 :
663 558 : if( GDALGetDriverByName( "BAG" ) == NULL )
664 : {
665 537 : poDriver = new GDALDriver();
666 :
667 537 : poDriver->SetDescription( "BAG" );
668 : poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
669 537 : "Bathymetry Attributed Grid" );
670 : poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
671 537 : "frmt_bag.html" );
672 537 : poDriver->pfnOpen = BAGDataset::Open;
673 537 : poDriver->pfnIdentify = BAGDataset::Identify;
674 :
675 537 : GetGDALDriverManager( )->RegisterDriver( poDriver );
676 : }
677 : }
|