LCOV - code coverage report
Current view: directory - frmts/hdf5 - bagdataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 313 224 71.6 %
Date: 2013-03-30 Functions: 23 15 65.2 %

       1                 : /******************************************************************************
       2                 :  * $Id: bagdataset.cpp 25774 2013-03-20 20:19:13Z rouault $
       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 25774 2013-03-20 20:19:13Z rouault $");
      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                 :     OGRErr ParseWKTFromXML( const char *pszISOXML );
      78                 : };
      79                 : 
      80                 : /************************************************************************/
      81                 : /* ==================================================================== */
      82                 : /*                               BAGRasterBand                          */
      83                 : /* ==================================================================== */
      84                 : /************************************************************************/
      85                 : class BAGRasterBand : public GDALPamRasterBand
      86                 : {
      87                 :     friend class BAGDataset;
      88                 : 
      89                 :     hid_t       hDatasetID;
      90                 :     hid_t       native;
      91                 :     hid_t       dataspace;
      92                 : 
      93                 :     bool        bMinMaxSet;
      94                 :     double      dfMinimum;
      95                 :     double      dfMaximum;
      96                 : 
      97                 : public:
      98                 :   
      99                 :     BAGRasterBand( BAGDataset *, int );
     100                 :     ~BAGRasterBand();
     101                 : 
     102                 :     bool                    Initialize( hid_t hDataset, const char *pszName );
     103                 : 
     104                 :     virtual CPLErr          IReadBlock( int, int, void * );
     105                 :     virtual double      GetNoDataValue( int * ); 
     106                 : 
     107                 :     virtual double GetMinimum( int *pbSuccess = NULL );
     108                 :     virtual double GetMaximum(int *pbSuccess = NULL );
     109                 : };
     110                 : 
     111                 : /************************************************************************/
     112                 : /*                           BAGRasterBand()                            */
     113                 : /************************************************************************/
     114               3 : BAGRasterBand::BAGRasterBand( BAGDataset *poDS, int nBand )
     115                 : 
     116                 : {
     117               3 :     this->poDS       = poDS;
     118               3 :     this->nBand      = nBand;
     119                 :     
     120               3 :     hDatasetID = -1;
     121               3 :     dataspace = -1;
     122               3 :     native = -1;
     123               3 :     bMinMaxSet = false;
     124               3 : }
     125                 : 
     126                 : /************************************************************************/
     127                 : /*                           ~BAGRasterBand()                           */
     128                 : /************************************************************************/
     129                 : 
     130               3 : BAGRasterBand::~BAGRasterBand()
     131                 : {
     132               3 :   if( dataspace > 0 )
     133               3 :     H5Sclose(dataspace);
     134                 : 
     135               3 :   if( native > 0 )
     136               3 :     H5Tclose( native );
     137                 : 
     138               3 :   if( hDatasetID > 0 )
     139               3 :     H5Dclose( hDatasetID );
     140               3 : }
     141                 : 
     142                 : /************************************************************************/
     143                 : /*                             Initialize()                             */
     144                 : /************************************************************************/
     145                 : 
     146               3 : bool BAGRasterBand::Initialize( hid_t hDatasetID, const char *pszName )
     147                 : 
     148                 : {
     149               3 :     SetDescription( pszName );
     150                 : 
     151               3 :     this->hDatasetID = hDatasetID;
     152                 : 
     153               3 :     hid_t datatype     = H5Dget_type( hDatasetID );
     154               3 :     dataspace          = H5Dget_space( hDatasetID );
     155               3 :     hid_t n_dims       = H5Sget_simple_extent_ndims( dataspace );
     156               3 :     native             = H5Tget_native_type( datatype, H5T_DIR_ASCEND );
     157                 :     hsize_t dims[3], maxdims[3];
     158                 : 
     159               3 :     eDataType = GH5_GetDataType( native );
     160                 : 
     161               3 :     if( n_dims == 2 )
     162                 :     {
     163               3 :         H5Sget_simple_extent_dims( dataspace, dims, maxdims );
     164                 : 
     165               3 :         nRasterXSize = (int) dims[1];
     166               3 :         nRasterYSize = (int) dims[0];
     167                 :     }
     168                 :     else
     169                 :     {
     170                 :         CPLError( CE_Failure, CPLE_AppDefined,
     171               0 :                   "Dataset not of rank 2." );
     172               0 :         return false;
     173                 :     }
     174                 : 
     175               3 :     nBlockXSize   = nRasterXSize;
     176               3 :     nBlockYSize   = 1;
     177                 : 
     178                 : /* -------------------------------------------------------------------- */
     179                 : /*      Check for chunksize, and use it as blocksize for optimized      */
     180                 : /*      reading.                                                        */
     181                 : /* -------------------------------------------------------------------- */
     182               3 :     hid_t listid = H5Dget_create_plist( hDatasetID );
     183               3 :     if (listid>0)
     184                 :     {
     185               3 :         if(H5Pget_layout(listid) == H5D_CHUNKED)
     186                 :         {
     187                 :             hsize_t panChunkDims[3];
     188               0 :             int nDimSize = H5Pget_chunk(listid, 3, panChunkDims);
     189               0 :             nBlockXSize  = (int) panChunkDims[nDimSize-1];
     190               0 :             nBlockYSize  = (int) panChunkDims[nDimSize-2];
     191                 :         }
     192                 : 
     193               3 :         int nfilters = H5Pget_nfilters( listid );
     194                 : 
     195                 :         H5Z_filter_t filter;
     196                 :         char         name[120];
     197               3 :         size_t       cd_nelmts = 20;
     198                 :         unsigned int cd_values[20];
     199                 :         unsigned int flags;
     200               3 :         for (int i = 0; i < nfilters; i++) 
     201                 :         {
     202               0 :           filter = H5Pget_filter(listid, i, &flags, (size_t *)&cd_nelmts, cd_values, 120, name);
     203               0 :           if (filter == H5Z_FILTER_DEFLATE)
     204               0 :             poDS->SetMetadataItem( "COMPRESSION", "DEFLATE", "IMAGE_STRUCTURE" );
     205               0 :           else if (filter == H5Z_FILTER_NBIT)
     206               0 :             poDS->SetMetadataItem( "COMPRESSION", "NBIT", "IMAGE_STRUCTURE" );
     207               0 :           else if (filter == H5Z_FILTER_SCALEOFFSET)
     208               0 :             poDS->SetMetadataItem( "COMPRESSION", "SCALEOFFSET", "IMAGE_STRUCTURE" );
     209               0 :           else if (filter == H5Z_FILTER_SZIP)
     210               0 :             poDS->SetMetadataItem( "COMPRESSION", "SZIP", "IMAGE_STRUCTURE" );
     211                 :         }
     212                 : 
     213               3 :         H5Pclose(listid);
     214                 :     }
     215                 : 
     216                 : /* -------------------------------------------------------------------- */
     217                 : /*      Load min/max information.                                       */
     218                 : /* -------------------------------------------------------------------- */
     219               3 :     if( EQUAL(pszName,"elevation") 
     220                 :         && GH5_FetchAttribute( hDatasetID, "Maximum Elevation Value", 
     221                 :                             dfMaximum ) 
     222                 :         && GH5_FetchAttribute( hDatasetID, "Minimum Elevation Value", 
     223                 :                                dfMinimum ) )
     224               1 :         bMinMaxSet = true;
     225               2 :     else if( EQUAL(pszName,"uncertainty") 
     226                 :              && GH5_FetchAttribute( hDatasetID, "Maximum Uncertainty Value", 
     227                 :                                     dfMaximum ) 
     228                 :              && GH5_FetchAttribute( hDatasetID, "Minimum Uncertainty Value", 
     229                 :                                     dfMinimum ) )
     230               1 :         bMinMaxSet = true;
     231               1 :     else if( EQUAL(pszName,"nominal_elevation") 
     232                 :              && GH5_FetchAttribute( hDatasetID, "max_value", 
     233                 :                                     dfMaximum ) 
     234                 :              && GH5_FetchAttribute( hDatasetID, "min_value", 
     235                 :                                     dfMinimum ) )
     236               1 :         bMinMaxSet = true;
     237                 : 
     238               3 :     return true;
     239                 : }
     240                 : 
     241                 : /************************************************************************/
     242                 : /*                             GetMinimum()                             */
     243                 : /************************************************************************/
     244                 : 
     245               1 : double BAGRasterBand::GetMinimum( int * pbSuccess )
     246                 : 
     247                 : {
     248               1 :     if( bMinMaxSet )
     249                 :     {
     250               1 :         if( pbSuccess )
     251               1 :             *pbSuccess = TRUE;
     252               1 :         return dfMinimum;
     253                 :     }
     254                 :     else
     255               0 :         return GDALRasterBand::GetMinimum( pbSuccess );
     256                 : }
     257                 : 
     258                 : /************************************************************************/
     259                 : /*                             GetMaximum()                             */
     260                 : /************************************************************************/
     261                 : 
     262               1 : double BAGRasterBand::GetMaximum( int * pbSuccess )
     263                 : 
     264                 : {
     265               1 :     if( bMinMaxSet )
     266                 :     {
     267               1 :         if( pbSuccess )
     268               1 :             *pbSuccess = TRUE;
     269               1 :         return dfMaximum;
     270                 :     }
     271                 :     else
     272               0 :         return GDALRasterBand::GetMaximum( pbSuccess );
     273                 : }
     274                 : 
     275                 : /************************************************************************/
     276                 : /*                           GetNoDataValue()                           */
     277                 : /************************************************************************/
     278               3 : double BAGRasterBand::GetNoDataValue( int * pbSuccess )
     279                 : 
     280                 : {
     281               3 :     if( pbSuccess )
     282               3 :         *pbSuccess = TRUE;
     283                 : 
     284               3 :     if( EQUAL(GetDescription(),"elevation") )
     285               1 :         return  1000000.0;
     286               2 :     else if( EQUAL(GetDescription(),"uncertainty") )
     287               1 :         return 0.0;
     288               1 :     else if( EQUAL(GetDescription(),"nominal_elevation") )
     289               1 :         return 1000000.0;
     290                 :     else
     291               0 :         return GDALPamRasterBand::GetNoDataValue( pbSuccess );
     292                 : }
     293                 : 
     294                 : /************************************************************************/
     295                 : /*                             IReadBlock()                             */
     296                 : /************************************************************************/
     297              30 : CPLErr BAGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     298                 :                                   void * pImage )
     299                 : {
     300                 :     herr_t      status;
     301                 :     hsize_t     count[3];
     302                 :     H5OFFSET_TYPE offset[3];
     303                 :     int         nSizeOfData;
     304                 :     hid_t       memspace;
     305                 :     hsize_t     col_dims[3];
     306                 :     hsize_t     rank;
     307                 : 
     308              30 :     rank=2;
     309                 : 
     310              30 :     offset[0] = MAX(0,nRasterYSize - (nBlockYOff+1)*nBlockYSize);
     311              30 :     offset[1] = nBlockXOff*nBlockXSize;
     312              30 :     count[0]  = nBlockYSize;
     313              30 :     count[1]  = nBlockXSize;
     314                 : 
     315              30 :     nSizeOfData = H5Tget_size( native );
     316              30 :     memset( pImage,0,nBlockXSize*nBlockYSize*nSizeOfData );
     317                 : 
     318                 : /*  blocksize may not be a multiple of imagesize */
     319              30 :     count[0]  = MIN( size_t(nBlockYSize), GetYSize() - offset[0]);
     320              30 :     count[1]  = MIN( size_t(nBlockXSize), GetXSize() - offset[1]);
     321                 : 
     322              30 :     if( nRasterYSize - (nBlockYOff+1)*nBlockYSize < 0 )
     323                 :     {
     324               0 :         count[0] += (nRasterYSize - (nBlockYOff+1)*nBlockYSize);
     325                 :     }
     326                 : 
     327                 : /* -------------------------------------------------------------------- */
     328                 : /*      Select block from file space                                    */
     329                 : /* -------------------------------------------------------------------- */
     330                 :     status =  H5Sselect_hyperslab( dataspace,
     331                 :                                    H5S_SELECT_SET,
     332                 :                                    offset, NULL,
     333              30 :                                    count, NULL );
     334                 : 
     335                 : /* -------------------------------------------------------------------- */
     336                 : /*      Create memory space to receive the data                         */
     337                 : /* -------------------------------------------------------------------- */
     338              30 :     col_dims[0]=nBlockYSize;
     339              30 :     col_dims[1]=nBlockXSize;
     340              30 :     memspace = H5Screate_simple( (int) rank, col_dims, NULL );
     341              30 :     H5OFFSET_TYPE mem_offset[3] = {0, 0, 0};
     342                 :     status =  H5Sselect_hyperslab(memspace,
     343                 :                                   H5S_SELECT_SET,
     344                 :                                   mem_offset, NULL,
     345              30 :                                   count, NULL);
     346                 : 
     347                 :     status = H5Dread ( hDatasetID,
     348                 :                        native,
     349                 :                        memspace,
     350                 :                        dataspace,
     351                 :                        H5P_DEFAULT,
     352              30 :                        pImage );
     353                 : 
     354              30 :     H5Sclose( memspace );
     355                 : 
     356                 : /* -------------------------------------------------------------------- */
     357                 : /*      Y flip the data.                                                */
     358                 : /* -------------------------------------------------------------------- */
     359              30 :     int nLinesToFlip = count[0];
     360              30 :     int nLineSize = nSizeOfData * nBlockXSize;
     361              30 :     GByte *pabyTemp = (GByte *) CPLMalloc(nLineSize);
     362                 : 
     363              30 :     for( int iY = 0; iY < nLinesToFlip/2; iY++ )
     364                 :     {
     365                 :         memcpy( pabyTemp, 
     366                 :                 ((GByte *)pImage) + iY * nLineSize,
     367               0 :                 nLineSize );
     368                 :         memcpy( ((GByte *)pImage) + iY * nLineSize,
     369                 :                 ((GByte *)pImage) + (nLinesToFlip-iY-1) * nLineSize,
     370               0 :                 nLineSize );
     371                 :         memcpy( ((GByte *)pImage) + (nLinesToFlip-iY-1) * nLineSize,
     372                 :                 pabyTemp,
     373               0 :                 nLineSize );
     374                 :     }
     375                 : 
     376              30 :     CPLFree( pabyTemp );
     377                 : 
     378                 : /* -------------------------------------------------------------------- */
     379                 : /*      Return success or failure.                                      */
     380                 : /* -------------------------------------------------------------------- */
     381              30 :     if( status < 0 )
     382                 :     {
     383                 :         CPLError( CE_Failure, CPLE_AppDefined,
     384               0 :                   "H5Dread() failed for block." );
     385               0 :         return CE_Failure;
     386                 :     }
     387                 :     else
     388              30 :         return CE_None;
     389                 : }
     390                 : 
     391                 : /************************************************************************/
     392                 : /* ==================================================================== */
     393                 : /*                              BAGDataset                              */
     394                 : /* ==================================================================== */
     395                 : /************************************************************************/
     396                 : 
     397                 : /************************************************************************/
     398                 : /*                             BAGDataset()                             */
     399                 : /************************************************************************/
     400                 : 
     401               1 : BAGDataset::BAGDataset()
     402                 : {
     403               1 :     hHDF5 = -1;
     404               1 :     pszXMLMetadata = NULL;
     405               1 :     pszProjection = NULL;
     406                 : 
     407               1 :     adfGeoTransform[0] = 0.0;
     408               1 :     adfGeoTransform[1] = 1.0;
     409               1 :     adfGeoTransform[2] = 0.0;
     410               1 :     adfGeoTransform[3] = 0.0;
     411               1 :     adfGeoTransform[4] = 0.0;
     412               1 :     adfGeoTransform[5] = 1.0;
     413               1 : }
     414                 : 
     415                 : /************************************************************************/
     416                 : /*                            ~BAGDataset()                             */
     417                 : /************************************************************************/
     418               1 : BAGDataset::~BAGDataset( )
     419                 : {
     420               1 :     FlushCache();
     421                 : 
     422               1 :     if( hHDF5 >= 0 )
     423               1 :         H5Fclose( hHDF5 );
     424                 : 
     425               1 :     CPLFree( pszXMLMetadata );
     426               1 :     CPLFree( pszProjection );
     427               1 : }
     428                 : 
     429                 : /************************************************************************/
     430                 : /*                              Identify()                              */
     431                 : /************************************************************************/
     432                 : 
     433           11867 : int BAGDataset::Identify( GDALOpenInfo * poOpenInfo )
     434                 : 
     435                 : {
     436                 : /* -------------------------------------------------------------------- */
     437                 : /*      Is it an HDF5 file?                                             */
     438                 : /* -------------------------------------------------------------------- */
     439                 :     static const char achSignature[] = "\211HDF\r\n\032\n";
     440                 : 
     441           11867 :     if( poOpenInfo->pabyHeader == NULL
     442                 :         || memcmp(poOpenInfo->pabyHeader,achSignature,8) != 0 )
     443           11862 :         return FALSE;
     444                 : 
     445                 : /* -------------------------------------------------------------------- */
     446                 : /*      Does it have the extension .bag?                                */
     447                 : /* -------------------------------------------------------------------- */
     448               5 :     if( !EQUAL(CPLGetExtension(poOpenInfo->pszFilename),"bag") )
     449               4 :         return FALSE;
     450                 : 
     451               1 :     return TRUE;
     452                 : }
     453                 : 
     454                 : /************************************************************************/
     455                 : /*                                Open()                                */
     456                 : /************************************************************************/
     457                 : 
     458            1738 : GDALDataset *BAGDataset::Open( GDALOpenInfo * poOpenInfo )
     459                 : 
     460                 : {
     461                 : /* -------------------------------------------------------------------- */
     462                 : /*      Confirm that this appears to be a BAG file.                     */
     463                 : /* -------------------------------------------------------------------- */
     464            1738 :     if( !Identify( poOpenInfo ) )
     465            1737 :         return NULL;
     466                 : 
     467                 : /* -------------------------------------------------------------------- */
     468                 : /*      Confirm the requested access is supported.                      */
     469                 : /* -------------------------------------------------------------------- */
     470               1 :     if( poOpenInfo->eAccess == GA_Update )
     471                 :     {
     472                 :         CPLError( CE_Failure, CPLE_NotSupported, 
     473               0 :                   "The BAG driver does not support update access." );
     474               0 :         return NULL;
     475                 :     }
     476                 :     
     477                 : /* -------------------------------------------------------------------- */
     478                 : /*      Open the file as an HDF5 file.                                  */
     479                 : /* -------------------------------------------------------------------- */
     480                 :     hid_t hHDF5 = H5Fopen( poOpenInfo->pszFilename, 
     481               1 :                            H5F_ACC_RDONLY, H5P_DEFAULT );
     482                 : 
     483               1 :     if( hHDF5 < 0 )  
     484               0 :         return NULL;
     485                 : 
     486                 : /* -------------------------------------------------------------------- */
     487                 : /*      Confirm it is a BAG dataset by checking for the                 */
     488                 : /*      BAG_Root/Bag Version attribute.                                 */
     489                 : /* -------------------------------------------------------------------- */
     490               1 :     hid_t hBagRoot = H5Gopen( hHDF5, "/BAG_root" );
     491               1 :     hid_t hVersion = -1;
     492                 : 
     493               1 :     if( hBagRoot >= 0 )
     494               1 :         hVersion = H5Aopen_name( hBagRoot, "Bag Version" );
     495                 : 
     496               1 :     if( hVersion < 0 )
     497                 :     {
     498               0 :         H5Fclose( hHDF5 );
     499               0 :         return NULL;
     500                 :     }
     501               1 :     H5Aclose( hVersion );
     502                 : 
     503                 : /* -------------------------------------------------------------------- */
     504                 : /*      Create a corresponding dataset.                                 */
     505                 : /* -------------------------------------------------------------------- */
     506               1 :     BAGDataset *poDS = new BAGDataset();
     507                 : 
     508               1 :     poDS->hHDF5 = hHDF5;
     509                 : 
     510                 : /* -------------------------------------------------------------------- */
     511                 : /*      Extract version as metadata.                                    */
     512                 : /* -------------------------------------------------------------------- */
     513               1 :     CPLString osVersion;
     514                 : 
     515               2 :     if( GH5_FetchAttribute( hBagRoot, "Bag Version", osVersion ) )
     516               1 :         poDS->SetMetadataItem( "BagVersion", osVersion );
     517                 : 
     518               1 :     H5Gclose( hBagRoot );
     519                 : 
     520                 : /* -------------------------------------------------------------------- */
     521                 : /*      Fetch the elevation dataset and attach as a band.               */
     522                 : /* -------------------------------------------------------------------- */
     523               1 :     int nNextBand = 1;
     524               1 :     hid_t hElevation = H5Dopen( hHDF5, "/BAG_root/elevation" );
     525               1 :     if( hElevation < 0 )
     526                 :     {
     527               0 :         delete poDS;
     528               0 :         return NULL;
     529                 :     }
     530                 : 
     531               1 :     BAGRasterBand *poElevBand = new BAGRasterBand( poDS, nNextBand );
     532                 : 
     533               2 :     if( !poElevBand->Initialize( hElevation, "elevation" ) )
     534                 :     {
     535               0 :         delete poElevBand;
     536               0 :         delete poDS;
     537               0 :         return NULL;
     538                 :     }
     539                 : 
     540               1 :     poDS->nRasterXSize = poElevBand->nRasterXSize;
     541               1 :     poDS->nRasterYSize = poElevBand->nRasterYSize;
     542                 : 
     543               1 :     poDS->SetBand( nNextBand++, poElevBand );
     544                 : 
     545                 : /* -------------------------------------------------------------------- */
     546                 : /*      Try to do the same for the uncertainty band.                    */
     547                 : /* -------------------------------------------------------------------- */
     548               1 :     hid_t hUncertainty = H5Dopen( hHDF5, "/BAG_root/uncertainty" );
     549               1 :     BAGRasterBand *poUBand = new BAGRasterBand( poDS, nNextBand );
     550                 : 
     551               2 :     if( hUncertainty >= 0 && poUBand->Initialize( hUncertainty, "uncertainty") )
     552                 :     {
     553               1 :         poDS->SetBand( nNextBand++, poUBand );
     554                 :     }
     555                 :     else
     556               0 :         delete poUBand;
     557                 : 
     558                 : /* -------------------------------------------------------------------- */
     559                 : /*      Try to do the same for the uncertainty band.                    */
     560                 : /* -------------------------------------------------------------------- */
     561               1 :     hid_t hNominal = -1;
     562                 : 
     563               1 :     H5E_BEGIN_TRY {
     564               1 :         hNominal = H5Dopen( hHDF5, "/BAG_root/nominal_elevation" );
     565               1 :     } H5E_END_TRY;
     566                 : 
     567               1 :     BAGRasterBand *poNBand = new BAGRasterBand( poDS, nNextBand );
     568               2 :     if( hNominal >= 0 && poNBand->Initialize( hNominal,
     569                 :                                               "nominal_elevation" ) )
     570                 :     {
     571               1 :         poDS->SetBand( nNextBand++, poNBand );
     572                 :     }
     573                 :     else
     574               0 :         delete poNBand;
     575                 :         
     576                 : /* -------------------------------------------------------------------- */
     577                 : /*      Load the XML metadata.                                          */
     578                 : /* -------------------------------------------------------------------- */
     579               1 :     poDS->LoadMetadata();
     580                 : 
     581                 : /* -------------------------------------------------------------------- */
     582                 : /*      Setup/check for pam .aux.xml.                                   */
     583                 : /* -------------------------------------------------------------------- */
     584               1 :     poDS->SetDescription( poOpenInfo->pszFilename );
     585               1 :     poDS->TryLoadXML();
     586                 : 
     587                 : /* -------------------------------------------------------------------- */
     588                 : /*      Setup overviews.                                                */
     589                 : /* -------------------------------------------------------------------- */
     590               1 :     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
     591                 : 
     592               1 :     return( poDS );
     593                 : }
     594                 : 
     595                 : /************************************************************************/
     596                 : /*                            LoadMetadata()                            */
     597                 : /************************************************************************/
     598                 : 
     599               1 : void BAGDataset::LoadMetadata()
     600                 : 
     601                 : {
     602                 : /* -------------------------------------------------------------------- */
     603                 : /*      Load the metadata from the file.                                */
     604                 : /* -------------------------------------------------------------------- */
     605               1 :     hid_t hMDDS = H5Dopen( hHDF5, "/BAG_root/metadata" );
     606               1 :     hid_t datatype     = H5Dget_type( hMDDS );
     607               1 :     hid_t dataspace    = H5Dget_space( hMDDS );
     608               1 :     hid_t native       = H5Tget_native_type( datatype, H5T_DIR_ASCEND );
     609                 :     hsize_t dims[3], maxdims[3];
     610                 : 
     611               1 :     H5Sget_simple_extent_dims( dataspace, dims, maxdims );
     612                 : 
     613               1 :     pszXMLMetadata = (char *) CPLCalloc((int) (dims[0]+1),1);
     614                 : 
     615               1 :     H5Dread( hMDDS, native, H5S_ALL, dataspace, H5P_DEFAULT, pszXMLMetadata );
     616                 : 
     617               1 :     H5Tclose( native );
     618               1 :     H5Sclose( dataspace );
     619               1 :     H5Tclose( datatype );
     620               1 :     H5Dclose( hMDDS );
     621                 : 
     622               1 :     if( strlen(pszXMLMetadata) == 0 )
     623               0 :         return;
     624                 : 
     625                 : /* -------------------------------------------------------------------- */
     626                 : /*      Try to get the geotransform.                                    */
     627                 : /* -------------------------------------------------------------------- */
     628               1 :     CPLXMLNode *psRoot = CPLParseXMLString( pszXMLMetadata );
     629                 : 
     630               1 :     if( psRoot == NULL )
     631               0 :         return;
     632                 : 
     633               1 :     CPLStripXMLNamespace( psRoot, NULL, TRUE );
     634                 : 
     635               1 :     CPLXMLNode *psGeo = CPLSearchXMLNode( psRoot, "=MD_Georectified" );
     636                 : 
     637               1 :     if( psGeo != NULL )
     638                 :     {
     639                 :         char **papszCornerTokens = 
     640                 :             CSLTokenizeStringComplex( 
     641                 :                 CPLGetXMLValue( psGeo, "cornerPoints.Point.coordinates", "" ),
     642               1 :                 " ,", FALSE, FALSE );
     643                 : 
     644               1 :         if( CSLCount(papszCornerTokens ) == 4 )
     645                 :         {
     646               1 :             double dfLLX = atof( papszCornerTokens[0] );
     647               1 :             double dfLLY = atof( papszCornerTokens[1] );
     648               1 :             double dfURX = atof( papszCornerTokens[2] );
     649               1 :             double dfURY = atof( papszCornerTokens[3] );
     650                 : 
     651               1 :             adfGeoTransform[0] = dfLLX;
     652               1 :             adfGeoTransform[1] = (dfURX - dfLLX) / (GetRasterXSize()-1);
     653               1 :             adfGeoTransform[3] = dfURY;
     654               1 :             adfGeoTransform[5] = (dfLLY - dfURY) / (GetRasterYSize()-1);
     655                 : 
     656               1 :             adfGeoTransform[0] -= adfGeoTransform[1] * 0.5;
     657               1 :             adfGeoTransform[3] -= adfGeoTransform[5] * 0.5;
     658                 :         }
     659               1 :         CSLDestroy( papszCornerTokens );
     660                 :     }
     661                 : 
     662                 : /* -------------------------------------------------------------------- */
     663                 : /*      Try to get the coordinate system.                               */
     664                 : /* -------------------------------------------------------------------- */
     665               1 :     OGRSpatialReference oSRS;
     666                 : 
     667               1 :     if( OGR_SRS_ImportFromISO19115( &oSRS, pszXMLMetadata )
     668                 :         == OGRERR_NONE )
     669                 :     {
     670               0 :         oSRS.exportToWkt( &pszProjection );
     671                 :     } 
     672                 :     else
     673                 :     {
     674               1 :         ParseWKTFromXML( pszXMLMetadata );
     675                 :     }
     676                 : 
     677                 : /* -------------------------------------------------------------------- */
     678                 : /*      Fetch acquisition date.                                         */
     679                 : /* -------------------------------------------------------------------- */
     680               1 :     CPLXMLNode *psDateTime = CPLSearchXMLNode( psRoot, "=dateTime" );
     681               1 :     if( psDateTime != NULL )
     682                 :     {
     683               1 :         const char *pszDateTimeValue = CPLGetXMLValue( psDateTime, NULL, "" );
     684               1 :         if( pszDateTimeValue )
     685               1 :             SetMetadataItem( "BAG_DATETIME", pszDateTimeValue );
     686                 :     }
     687                 : 
     688               1 :     CPLDestroyXMLNode( psRoot );
     689                 : }
     690                 : 
     691                 : /************************************************************************/
     692                 : /*                          ParseWKTFromXML()                           */
     693                 : /************************************************************************/
     694               1 : OGRErr BAGDataset::ParseWKTFromXML( const char *pszISOXML )
     695                 : {
     696               1 :     OGRSpatialReference oSRS;
     697               1 :     CPLXMLNode *psRoot = CPLParseXMLString( pszISOXML );
     698               1 :     OGRErr eOGRErr = OGRERR_FAILURE;
     699                 : 
     700               1 :     if( psRoot == NULL )
     701               0 :         return eOGRErr;
     702                 : 
     703               1 :     CPLStripXMLNamespace( psRoot, NULL, TRUE ); 
     704                 : 
     705               1 :     CPLXMLNode *psRSI = CPLSearchXMLNode( psRoot, "=referenceSystemInfo" );
     706               1 :     if( psRSI == NULL )
     707                 :     {
     708                 :         CPLError( CE_Failure, CPLE_AppDefined,
     709               0 :           "Unable to find <referenceSystemInfo> in metadata." );
     710               0 :         CPLDestroyXMLNode( psRoot );
     711               0 :         return eOGRErr;
     712                 :     }
     713                 : 
     714               1 :     oSRS.Clear();
     715                 : 
     716                 :     const char *pszSRCodeString = 
     717               1 :         CPLGetXMLValue( psRSI, "MD_ReferenceSystem.referenceSystemIdentifier.RS_Identifier.code.CharacterString", NULL );
     718               1 :     if( pszSRCodeString == NULL )
     719                 :     {
     720                 :         CPLDebug("BAG",
     721               1 :           "Unable to find /MI_Metadata/referenceSystemInfo[1]/MD_ReferenceSystem[1]/referenceSystemIdentifier[1]/RS_Identifier[1]/code[1]/CharacterString[1] in metadata." );
     722               1 :         CPLDestroyXMLNode( psRoot );
     723               1 :         return eOGRErr;
     724                 :     }
     725                 :     
     726                 :     const char *pszSRCodeSpace = 
     727               0 :         CPLGetXMLValue( psRSI, "MD_ReferenceSystem.referenceSystemIdentifier.RS_Identifier.codeSpace.CharacterString", "" );
     728               0 :     if( !EQUAL( pszSRCodeSpace, "WKT" ) )
     729                 :     {
     730                 :         CPLError( CE_Failure, CPLE_AppDefined,
     731               0 :             "Spatial reference string is not in WKT." );
     732               0 :         CPLDestroyXMLNode( psRoot );
     733               0 :         return eOGRErr;
     734                 :     }
     735                 : 
     736               0 :     char* pszWKT = const_cast< char* >( pszSRCodeString );
     737               0 :     if( oSRS.importFromWkt( &pszWKT ) != OGRERR_NONE )
     738                 :     {
     739                 :         CPLError( CE_Failure, CPLE_AppDefined,
     740               0 :           "Failed parsing WKT string \"%s\".", pszSRCodeString );
     741               0 :         CPLDestroyXMLNode( psRoot );
     742               0 :         return eOGRErr;
     743                 :     }
     744                 : 
     745               0 :     oSRS.exportToWkt( &pszProjection );
     746               0 :     eOGRErr = OGRERR_NONE;
     747                 : 
     748               0 :     psRSI = CPLSearchXMLNode( psRSI->psNext, "=referenceSystemInfo" );
     749               0 :     if( psRSI == NULL )
     750                 :     {
     751                 :         CPLError( CE_Failure, CPLE_AppDefined,
     752               0 :             "Unable to find second instance of <referenceSystemInfo> in metadata." );
     753               0 :         CPLDestroyXMLNode( psRoot );
     754               0 :         return eOGRErr;
     755                 :     }
     756                 : 
     757                 :     pszSRCodeString = 
     758               0 :       CPLGetXMLValue( psRSI, "MD_ReferenceSystem.referenceSystemIdentifier.RS_Identifier.code.CharacterString", NULL );
     759               0 :     if( pszSRCodeString == NULL )
     760                 :     {
     761                 :         CPLError( CE_Failure, CPLE_AppDefined,
     762               0 :             "Unable to find /MI_Metadata/referenceSystemInfo[2]/MD_ReferenceSystem[1]/referenceSystemIdentifier[1]/RS_Identifier[1]/code[1]/CharacterString[1] in metadata." );
     763               0 :         CPLDestroyXMLNode( psRoot );
     764               0 :         return eOGRErr;
     765                 :     }
     766                 : 
     767                 :     pszSRCodeSpace = 
     768               0 :         CPLGetXMLValue( psRSI, "MD_ReferenceSystem.referenceSystemIdentifier.RS_Identifier.codeSpace.CharacterString", "" );
     769               0 :     if( !EQUAL( pszSRCodeSpace, "WKT" ) )
     770                 :     {
     771                 :         CPLError( CE_Failure, CPLE_AppDefined,
     772               0 :             "Spatial reference string is not in WKT." );
     773               0 :         CPLDestroyXMLNode( psRoot );
     774               0 :         return eOGRErr;
     775                 :     }
     776                 : 
     777               0 :     if( EQUALN(pszSRCodeString, "VERTCS", 6 ) )
     778                 :     {
     779               0 :         CPLString oString( pszProjection );
     780               0 :         oString += ",";
     781               0 :         oString += pszSRCodeString;
     782               0 :         if ( pszProjection )
     783               0 :             CPLFree( pszProjection );
     784               0 :         pszProjection = CPLStrdup( oString );
     785                 :     }
     786                 : 
     787               0 :     CPLDestroyXMLNode( psRoot );
     788                 :     
     789               0 :     return eOGRErr;
     790                 : }
     791                 : 
     792                 : /************************************************************************/
     793                 : /*                          GetGeoTransform()                           */
     794                 : /************************************************************************/
     795                 : 
     796               0 : CPLErr BAGDataset::GetGeoTransform( double *padfGeoTransform )
     797                 : 
     798                 : {
     799               0 :     if( adfGeoTransform[0] != 0.0 || adfGeoTransform[3] != 0.0 )
     800                 :     {
     801               0 :         memcpy( padfGeoTransform, adfGeoTransform, sizeof(double)*6 );
     802               0 :         return CE_None;
     803                 :     }
     804                 :     else
     805               0 :         return GDALPamDataset::GetGeoTransform( padfGeoTransform );
     806                 : }
     807                 : 
     808                 : /************************************************************************/
     809                 : /*                          GetProjectionRef()                          */
     810                 : /************************************************************************/
     811                 : 
     812               0 : const char *BAGDataset::GetProjectionRef()
     813                 : 
     814                 : {
     815               0 :     if( pszProjection )
     816               0 :         return pszProjection;
     817                 :     else 
     818               0 :         return GDALPamDataset::GetProjectionRef();
     819                 : }
     820                 : 
     821                 : /************************************************************************/
     822                 : /*                            GetMetadata()                             */
     823                 : /************************************************************************/
     824                 : 
     825               1 : char **BAGDataset::GetMetadata( const char *pszDomain )
     826                 : 
     827                 : {
     828               1 :     if( pszDomain != NULL && EQUAL(pszDomain,"xml:BAG") )
     829                 :     {
     830               1 :         apszMDList[0] = pszXMLMetadata;
     831               1 :         apszMDList[1] = NULL;
     832                 : 
     833               1 :         return apszMDList;
     834                 :     }
     835                 :     else
     836               0 :         return GDALPamDataset::GetMetadata( pszDomain );
     837                 : }
     838                 : 
     839                 : /************************************************************************/
     840                 : /*                          GDALRegister_BAG()                          */
     841                 : /************************************************************************/
     842             610 : void GDALRegister_BAG( )
     843                 : 
     844                 : {
     845                 :     GDALDriver  *poDriver;
     846                 :     
     847             610 :     if (! GDAL_CHECK_VERSION("BAG"))
     848               0 :         return;
     849                 : 
     850             610 :     if(  GDALGetDriverByName( "BAG" ) == NULL )
     851                 :     {
     852             588 :         poDriver = new GDALDriver();
     853                 :         
     854             588 :         poDriver->SetDescription( "BAG" );
     855                 :         poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
     856             588 :                                    "Bathymetry Attributed Grid" );
     857                 :         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
     858             588 :                                    "frmt_bag.html" );
     859             588 :         poDriver->pfnOpen = BAGDataset::Open;
     860             588 :         poDriver->pfnIdentify = BAGDataset::Identify;
     861                 : 
     862             588 :         GetGDALDriverManager( )->RegisterDriver( poDriver );
     863                 :     }
     864                 : }

Generated by: LCOV version 1.7