LCOV - code coverage report
Current view: directory - frmts/hdf4 - hdf4dataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 390 142 36.4 %
Date: 2010-01-09 Functions: 17 13 76.5 %

       1                 : /******************************************************************************
       2                 :  * $Id: hdf4dataset.cpp 17664 2009-09-21 21:16:45Z rouault $
       3                 :  *
       4                 :  * Project:  Hierarchical Data Format Release 4 (HDF4)
       5                 :  * Purpose:  HDF4 Datasets. Open HDF4 file, fetch metadata and list of
       6                 :  *           subdatasets.
       7                 :  *           This driver initially based on code supplied by Markus Neteler
       8                 :  * Author:   Andrey Kiselev, dron@ak4719.spb.edu
       9                 :  *
      10                 :  ******************************************************************************
      11                 :  * Copyright (c) 2002, Andrey Kiselev <dron@ak4719.spb.edu>
      12                 :  *
      13                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      14                 :  * copy of this software and associated documentation files (the "Software"),
      15                 :  * to deal in the Software without restriction, including without limitation
      16                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      17                 :  * and/or sell copies of the Software, and to permit persons to whom the
      18                 :  * Software is furnished to do so, subject to the following conditions:
      19                 :  *
      20                 :  * The above copyright notice and this permission notice shall be included
      21                 :  * in all copies or substantial portions of the Software.
      22                 :  *
      23                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      24                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      25                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      26                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      27                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      28                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      29                 :  * DEALINGS IN THE SOFTWARE.
      30                 :  ****************************************************************************/
      31                 : 
      32                 : #include "hdf.h"
      33                 : #include "mfhdf.h"
      34                 : 
      35                 : #include "HdfEosDef.h"
      36                 : 
      37                 : #include "gdal_priv.h"
      38                 : #include "cpl_string.h"
      39                 : #include "hdf4compat.h"
      40                 : #include "hdf4dataset.h"
      41                 : 
      42                 : CPL_CVSID("$Id: hdf4dataset.cpp 17664 2009-09-21 21:16:45Z rouault $");
      43                 : 
      44                 : CPL_C_START
      45                 : void  GDALRegister_HDF4(void);
      46                 : CPL_C_END
      47                 : 
      48                 : extern const char *pszGDALSignature;
      49                 : 
      50                 : /************************************************************************/
      51                 : /* ==================================================================== */
      52                 : /*        HDF4Dataset       */
      53                 : /* ==================================================================== */
      54                 : /************************************************************************/
      55                 : 
      56                 : /************************************************************************/
      57                 : /*                           HDF4Dataset()                              */
      58                 : /************************************************************************/
      59                 : 
      60             582 : HDF4Dataset::HDF4Dataset()
      61                 : 
      62                 : {
      63             582 :     fp = NULL;
      64             582 :     hSD = 0;
      65             582 :     hGR = 0;
      66             582 :     papszGlobalMetadata = NULL;
      67             582 :     papszSubDatasets = NULL;
      68             582 :     bIsHDFEOS = 0;
      69             582 : }
      70                 : 
      71                 : /************************************************************************/
      72                 : /*                            ~HDF4Dataset()                            */
      73                 : /************************************************************************/
      74                 : 
      75             806 : HDF4Dataset::~HDF4Dataset()
      76                 : 
      77                 : {
      78             582 :     if ( hSD )
      79             358 :   SDend( hSD );
      80             582 :     if ( hGR )
      81               0 :   GRend( hGR );
      82             582 :     if ( papszSubDatasets )
      83             224 :   CSLDestroy( papszSubDatasets );
      84             582 :     if ( papszGlobalMetadata )
      85             448 :   CSLDestroy( papszGlobalMetadata );
      86             582 :     if( fp != NULL )
      87             224 :         VSIFClose( fp );
      88             806 : }
      89                 : 
      90                 : /************************************************************************/
      91                 : /*                            GetMetadata()                             */
      92                 : /************************************************************************/
      93                 : 
      94             197 : char **HDF4Dataset::GetMetadata( const char *pszDomain )
      95                 : 
      96                 : {
      97             197 :     if( pszDomain != NULL && EQUALN( pszDomain, "SUBDATASETS", 11 ) )
      98               0 :         return papszSubDatasets;
      99                 :     else
     100             197 :         return GDALDataset::GetMetadata( pszDomain );
     101                 : }
     102                 : 
     103                 : /************************************************************************/
     104                 : /*                           SPrintArray()                              */
     105                 : /*  Prints numerical arrays in string buffer.     */
     106                 : /*  This function takes pfaDataArray as a pointer to printed array, */
     107                 : /*  nValues as a number of values to print and pszDelimiter as a  */
     108                 : /*  field delimiting strings.         */
     109                 : /*  Pointer to filled buffer will be returned.      */
     110                 : /************************************************************************/
     111                 : 
     112             224 : char *SPrintArray( GDALDataType eDataType, const void *paDataArray,
     113                 :                           int nValues, const char *pszDelimiter )
     114                 : {
     115                 :     char        *pszString, *pszField;
     116                 :     int         i, iFieldSize, iStringSize;
     117                 : 
     118             224 :     iFieldSize = 32 + strlen( pszDelimiter );
     119             224 :     pszField = (char *)CPLMalloc( iFieldSize + 1 );
     120             224 :     iStringSize = nValues * iFieldSize + 1;
     121             224 :     pszString = (char *)CPLMalloc( iStringSize );
     122             224 :     memset( pszString, 0, iStringSize );
     123             791 :     for ( i = 0; i < nValues; i++ )
     124                 :     {
     125             567 :         switch ( eDataType )
     126                 :         {
     127                 :             case GDT_Byte:
     128               0 :                 sprintf( pszField, "%d%s", ((GByte *)paDataArray)[i],
     129               0 :                      (i < nValues - 1)?pszDelimiter:"" );
     130               0 :                 break;
     131                 :             case GDT_UInt16:
     132               0 :                 sprintf( pszField, "%u%s", ((GUInt16 *)paDataArray)[i],
     133               0 :                      (i < nValues - 1)?pszDelimiter:"" );
     134               0 :                 break;
     135                 :             case GDT_Int16:
     136                 :             default:
     137               0 :                 sprintf( pszField, "%d%s", ((GInt16 *)paDataArray)[i],
     138               0 :                      (i < nValues - 1)?pszDelimiter:"" );
     139               0 :                 break;
     140                 :             case GDT_UInt32:
     141                 :                 sprintf( pszField, "%u%s", ((GUInt32 *)paDataArray)[i],
     142             567 :                      (i < nValues - 1)?pszDelimiter:"" );
     143             567 :                 break;
     144                 :             case GDT_Int32:
     145                 :                 sprintf( pszField, "%d%s", ((GInt32 *)paDataArray)[i],
     146               0 :                      (i < nValues - 1)?pszDelimiter:"" );
     147               0 :                 break;
     148                 :             case GDT_Float32:
     149               0 :                 sprintf( pszField, "%.7g%s", ((float *)paDataArray)[i],
     150               0 :                      (i < nValues - 1)?pszDelimiter:"" );
     151               0 :                 break;
     152                 :             case GDT_Float64:
     153                 :                 sprintf( pszField, "%.15g%s", ((double *)paDataArray)[i],
     154               0 :                      (i < nValues - 1)?pszDelimiter:"" );
     155                 :                 break;
     156                 :         }
     157             567 :         strcat( pszString, pszField );
     158                 :     }
     159                 :     
     160             224 :     CPLFree( pszField );
     161             224 :     return pszString;
     162                 : }
     163                 : 
     164                 : /************************************************************************/
     165                 : /*              Translate HDF4 data type into GDAL data type            */
     166                 : /************************************************************************/
     167             256 : GDALDataType HDF4Dataset::GetDataType( int32 iNumType )
     168                 : {
     169             256 :     switch (iNumType)
     170                 :     {
     171                 :         case DFNT_CHAR8: // The same as DFNT_CHAR
     172                 :         case DFNT_UCHAR8: // The same as DFNT_UCHAR
     173                 :         case DFNT_INT8:
     174                 :         case DFNT_UINT8:
     175              64 :             return GDT_Byte;
     176                 :         case DFNT_INT16:
     177              32 :             return GDT_Int16;
     178                 :         case DFNT_UINT16:
     179              32 :             return GDT_UInt16;
     180                 :         case DFNT_INT32:
     181              32 :             return GDT_Int32;
     182                 :         case DFNT_UINT32:
     183              32 :             return GDT_UInt32;
     184                 :         case DFNT_INT64:
     185               0 :             return GDT_Unknown;
     186                 :         case DFNT_UINT64:
     187               0 :             return GDT_Unknown;
     188                 :         case DFNT_FLOAT32:
     189              32 :             return GDT_Float32;
     190                 :         case DFNT_FLOAT64:
     191              32 :             return GDT_Float64;
     192                 :         default:
     193               0 :             return GDT_Unknown;
     194                 :     }
     195                 : }
     196                 : 
     197                 : /************************************************************************/
     198                 : /*    Return the human readable name of data type   */
     199                 : /************************************************************************/
     200                 : 
     201             224 : const char *HDF4Dataset::GetDataTypeName( int32 iNumType )
     202                 : {
     203             224 :     switch (iNumType)
     204                 :     {
     205                 :         case DFNT_CHAR8: // The same as DFNT_CHAR
     206               0 :       return "8-bit character";
     207                 :   case DFNT_UCHAR8: // The same as DFNT_UCHAR
     208               0 :       return "8-bit unsigned character";
     209                 :         case DFNT_INT8:
     210               0 :       return "8-bit integer";
     211                 :         case DFNT_UINT8:
     212              56 :       return "8-bit unsigned integer";
     213                 :         case DFNT_INT16:
     214              28 :       return "16-bit integer";
     215                 :         case DFNT_UINT16:
     216              28 :       return "16-bit unsigned integer";
     217                 :         case DFNT_INT32:
     218              28 :       return "32-bit integer";
     219                 :         case DFNT_UINT32:
     220              28 :       return "32-bit unsigned integer";
     221                 :         case DFNT_INT64:
     222               0 :       return "64-bit integer";
     223                 :         case DFNT_UINT64:
     224               0 :       return "64-bit unsigned integer";
     225                 :         case DFNT_FLOAT32:
     226              28 :       return "32-bit floating-point";
     227                 :         case DFNT_FLOAT64:
     228              28 :       return "64-bit floating-point";
     229                 :   default:
     230               0 :       return "unknown type";
     231                 :     }
     232                 : }
     233                 : 
     234                 : /************************************************************************/
     235                 : /*  Return the size of data type in bytes                         */
     236                 : /************************************************************************/
     237                 : 
     238            1312 : int HDF4Dataset::GetDataTypeSize( int32 iNumType )
     239                 : {
     240            1312 :     switch (iNumType)
     241                 :     {
     242                 :         case DFNT_CHAR8: // The same as DFNT_CHAR
     243                 :   case DFNT_UCHAR8: // The same as DFNT_UCHAR
     244                 :         case DFNT_INT8:
     245                 :         case DFNT_UINT8:
     246            1312 :       return 1;
     247                 :         case DFNT_INT16:
     248                 :         case DFNT_UINT16:
     249               0 :       return 2;
     250                 :         case DFNT_INT32:
     251                 :         case DFNT_UINT32:
     252                 :         case DFNT_FLOAT32:
     253               0 :       return 4;
     254                 :         case DFNT_INT64:
     255                 :         case DFNT_UINT64:
     256                 :         case DFNT_FLOAT64:
     257               0 :       return 8;
     258                 :   default:
     259               0 :       return 0;
     260                 :     }
     261                 : }
     262                 : 
     263                 : /************************************************************************/
     264                 : /*  Convert value stored in the input buffer to double value.           */
     265                 : /************************************************************************/
     266                 : 
     267               0 : double HDF4Dataset::AnyTypeToDouble( int32 iNumType, void *pData )
     268                 : {
     269               0 :     switch ( iNumType )
     270                 :     {
     271                 :         case DFNT_INT8:
     272               0 :             return (double)*(char *)pData;
     273                 :         case DFNT_UINT8:
     274               0 :             return (double)*(unsigned char *)pData;
     275                 :         case DFNT_INT16:
     276               0 :             return (double)*(short *)pData;
     277                 :         case DFNT_UINT16:
     278               0 :             return (double)*(unsigned short *)pData;
     279                 :         case DFNT_INT32:
     280               0 :             return (double)*(long *)pData;
     281                 :         case DFNT_UINT32:
     282               0 :             return (double)*(unsigned long *)pData;
     283                 :         case DFNT_INT64:
     284               0 :             return (double)*(char *)pData;
     285                 :         case DFNT_UINT64:
     286               0 :             return (double)*(GIntBig *)pData;
     287                 :         case DFNT_FLOAT32:
     288               0 :             return (double)*(float *)pData;
     289                 :         case DFNT_FLOAT64:
     290               0 :             return (double)*(double *)pData;
     291                 :         default:
     292               0 :             return 0.0;
     293                 :     }
     294                 : }
     295                 : 
     296                 : /************************************************************************/
     297                 : /*         Tokenize HDF-EOS attributes.                                 */
     298                 : /************************************************************************/
     299                 : 
     300               0 : char **HDF4Dataset::HDF4EOSTokenizeAttrs( const char * pszString ) 
     301                 : 
     302                 : {
     303               0 :     const char  *pszDelimiters = " \t\n\r";
     304               0 :     char        **papszRetList = NULL;
     305                 :     char        *pszToken;
     306                 :     int         nTokenMax, nTokenLen;
     307                 : 
     308               0 :     pszToken = (char *) CPLCalloc( 10, 1 );
     309               0 :     nTokenMax = 10;
     310                 :     
     311               0 :     while( pszString != NULL && *pszString != '\0' )
     312                 :     {
     313               0 :         int     bInString = FALSE, bInBracket = FALSE;
     314                 : 
     315               0 :         nTokenLen = 0;
     316                 :         
     317                 :         // Try to find the next delimeter, marking end of token
     318               0 :         for( ; *pszString != '\0'; pszString++ )
     319                 :         {
     320                 : 
     321                 :             // End if this is a delimeter skip it and break.
     322               0 :             if ( !bInBracket && !bInString
     323                 :                  && strchr(pszDelimiters, *pszString) != NULL )
     324                 :             {
     325               0 :                 pszString++;
     326               0 :                 break;
     327                 :             }
     328                 : 
     329                 :             // Sometimes in bracketed tokens we may found a sort of
     330                 :             // paragraph formatting. We will remove unneeded spaces and new
     331                 :             // lines. 
     332               0 :             if ( bInBracket )
     333               0 :                 if ( strchr("\r\n", *pszString) != NULL
     334                 :                      || ( *pszString == ' '
     335                 :                           && strchr(" \r\n", *(pszString - 1)) != NULL ) )
     336               0 :                 continue;
     337                 :             
     338               0 :             if ( *pszString == '"' )
     339                 :             {
     340               0 :                 if ( bInString )
     341                 :                 {
     342               0 :                     bInString = FALSE;
     343               0 :                     continue;
     344                 :                 }
     345                 :                 else
     346                 :                 {
     347               0 :                     bInString = TRUE;
     348               0 :                     continue;
     349                 :                 }
     350                 :             }
     351               0 :             else if ( *pszString == '(' )
     352                 :       {
     353               0 :                 bInBracket = TRUE;
     354               0 :     continue;
     355                 :       }
     356               0 :       else if ( *pszString == ')' )
     357                 :       {
     358               0 :     bInBracket = FALSE;
     359               0 :     continue;
     360                 :       }
     361                 : 
     362               0 :       if( nTokenLen >= nTokenMax - 2 )
     363                 :             {
     364               0 :                 nTokenMax = nTokenMax * 2 + 10;
     365               0 :                 pszToken = (char *) CPLRealloc( pszToken, nTokenMax );
     366                 :             }
     367                 : 
     368               0 :             pszToken[nTokenLen] = *pszString;
     369               0 :             nTokenLen++;
     370                 :         }
     371                 : 
     372               0 :         pszToken[nTokenLen] = '\0';
     373                 : 
     374               0 :         if( pszToken[0] != '\0' )
     375                 :         {
     376               0 :             papszRetList = CSLAddString( papszRetList, pszToken );
     377                 :         }
     378                 : 
     379                 :         // If the last token is an empty token, then we have to catch
     380                 :         // it now, otherwise we won't reenter the loop and it will be lost. 
     381               0 :         if ( *pszString == '\0' && strchr(pszDelimiters, *(pszString-1)) )
     382                 :         {
     383               0 :             papszRetList = CSLAddString( papszRetList, "" );
     384                 :         }
     385                 :     }
     386                 : 
     387               0 :     if( papszRetList == NULL )
     388               0 :         papszRetList = (char **) CPLCalloc( sizeof(char *), 1 );
     389                 : 
     390               0 :     CPLFree( pszToken );
     391                 : 
     392               0 :     return papszRetList;
     393                 : }
     394                 : 
     395                 : /************************************************************************/
     396                 : /*     Find object name and its value in HDF-EOS attributes.            */
     397                 : /*     Function returns pointer to the string in list next behind       */
     398                 : /*     recognized object.                                               */
     399                 : /************************************************************************/
     400                 : 
     401               0 : char **HDF4Dataset::HDF4EOSGetObject( char **papszAttrList, char **ppszAttrName,
     402                 :                                       char **ppszAttrValue )
     403                 : {
     404                 :     int     iCount, i, j;
     405               0 :     *ppszAttrName = NULL;
     406               0 :     *ppszAttrValue = NULL;
     407                 : 
     408               0 :     iCount = CSLCount( papszAttrList );
     409               0 :     for ( i = 0; i < iCount - 2; i++ )
     410                 :     {
     411               0 :   if ( EQUAL( papszAttrList[i], "OBJECT" ) )
     412                 :   {
     413               0 :       i += 2;
     414               0 :       for ( j = 1; i + j < iCount - 2; j++ )
     415                 :       {
     416               0 :           if ( EQUAL( papszAttrList[i + j], "END_OBJECT" ) ||
     417               0 :          EQUAL( papszAttrList[i + j], "OBJECT" ) )
     418               0 :               return &papszAttrList[i + j];
     419               0 :           else if ( EQUAL( papszAttrList[i + j], "VALUE" ) )
     420                 :           {
     421               0 :         *ppszAttrName = papszAttrList[i];
     422               0 :               *ppszAttrValue = papszAttrList[i + j + 2];
     423                 : 
     424               0 :         return &papszAttrList[i + j + 2];
     425                 :           }
     426                 :       }
     427                 :   }
     428                 :     }
     429                 : 
     430               0 :     return NULL;
     431                 : }
     432                 : 
     433                 : /************************************************************************/
     434                 : /*         Translate HDF4-EOS attributes in GDAL metadata items         */
     435                 : /************************************************************************/
     436                 : 
     437               0 : char** HDF4Dataset::TranslateHDF4EOSAttributes( int32 iHandle,
     438                 :     int32 iAttribute, int32 nValues, char **papszMetadata )
     439                 : {
     440                 :     char  *pszData;
     441                 :     
     442               0 :     pszData = (char *)CPLMalloc( (nValues + 1) * sizeof(char) );
     443               0 :     pszData[nValues] = '\0';
     444               0 :     SDreadattr( iHandle, iAttribute, pszData );
     445                 :     // HDF4-EOS attributes has followed structure:
     446                 :     // 
     447                 :     // GROUP = <name>
     448                 :     //   GROUPTYPE = <name>
     449                 :     //
     450                 :     //   GROUP = <name>
     451                 :     //   
     452                 :     //     OBJECT = <name>
     453                 :     //       CLASS = <string>
     454                 :     //       NUM_VAL = <number>
     455                 :     //       VALUE = <string> or <number>
     456                 :     //     END_OBJECT = <name>
     457                 :     //     
     458                 :     //     .......
     459                 :     //     .......
     460                 :     //     .......
     461                 :     //     
     462                 :     //   END_GROUP = <name>
     463                 :     //   
     464                 :     // .......
     465                 :     // .......
     466                 :     // .......
     467                 :     //
     468                 :     // END_GROUP = <name>
     469                 :     // END
     470                 :     //
     471                 :     // Used data types:
     472                 :     // <name>   --- unquoted character strings
     473                 :     // <string> --- quoted character strings
     474                 :     // <number> --- numerical value
     475                 :     // If NUM_VAL != 1 then values combined in lists:
     476                 :     // (<string>,<string>,...)
     477                 :     // or
     478                 :     // (<number>,<number>,...)
     479                 :     //
     480                 :     // Records within objects may follows in any order, objects may contains
     481                 :     // other objects (and lacks VALUE record), groups contains other groups
     482                 :     // and objects. Names of groups and objects are not unique and may repeat.
     483                 :     // Objects may contains other types of records.
     484                 :     //
     485                 :     // We are interested in OBJECTS structures only.
     486                 : 
     487                 :     char *pszAttrName, *pszAttrValue;
     488               0 :     char *pszAddAttrName = NULL;
     489                 :     char **papszAttrList, **papszAttrs;
     490                 :     
     491               0 :     papszAttrList = HDF4EOSTokenizeAttrs( pszData );
     492               0 :     papszAttrs = papszAttrList;
     493               0 :     while ( papszAttrs )
     494                 :     {
     495                 :   papszAttrs =
     496               0 :       HDF4EOSGetObject( papszAttrs, &pszAttrName, &pszAttrValue );
     497               0 :   if ( pszAttrName && pszAttrValue )
     498                 :   {
     499                 :       // Now we should recognize special type of HDF EOS metastructures:
     500                 :       // ADDITIONALATTRIBUTENAME = <name>
     501                 :       // PARAMETERVALUE = <value>
     502               0 :       if ( EQUAL( pszAttrName, "ADDITIONALATTRIBUTENAME" ) )
     503               0 :     pszAddAttrName = pszAttrValue;
     504               0 :       else if ( pszAddAttrName && EQUAL( pszAttrName, "PARAMETERVALUE" ) )
     505                 :       {
     506                 :     papszMetadata =
     507               0 :         CSLAddNameValue( papszMetadata, pszAddAttrName, pszAttrValue );
     508               0 :     pszAddAttrName = NULL;
     509                 :       }
     510                 :       else
     511                 :       {
     512                 :     papszMetadata =
     513               0 :         CSLAddNameValue( papszMetadata, pszAttrName, pszAttrValue );
     514                 :       }
     515                 :   }
     516                 :     }
     517                 :     
     518               0 :     CSLDestroy( papszAttrList );
     519               0 :     CPLFree( pszData );
     520                 : 
     521               0 :     return papszMetadata;
     522                 : }
     523                 : 
     524                 : /************************************************************************/
     525                 : /*         Translate HDF4 attributes in GDAL metadata items             */
     526                 : /************************************************************************/
     527                 : 
     528            1312 : char** HDF4Dataset::TranslateHDF4Attributes( int32 iHandle,
     529                 :     int32 iAttribute, char *pszAttrName, int32 iNumType, int32 nValues,
     530                 :     char **papszMetadata )
     531                 : {
     532            1312 :     void  *pData = NULL;
     533            1312 :     char  *pszTemp = NULL;
     534                 :     
     535                 : /* -------------------------------------------------------------------- */
     536                 : /*     Allocate a buffer to hold the attribute data.                    */
     537                 : /* -------------------------------------------------------------------- */
     538            2624 :     if ( iNumType == DFNT_CHAR8 || iNumType == DFNT_UCHAR8 )
     539            1312 :         pData = CPLMalloc( (nValues + 1) * GetDataTypeSize(iNumType) );
     540                 :     else
     541               0 :         pData = CPLMalloc( nValues * GetDataTypeSize(iNumType) );
     542                 : 
     543                 : /* -------------------------------------------------------------------- */
     544                 : /*     Read the attribute data.                                         */
     545                 : /* -------------------------------------------------------------------- */
     546            1312 :     SDreadattr( iHandle, iAttribute, pData );
     547            2624 :     if ( iNumType == DFNT_CHAR8 || iNumType == DFNT_UCHAR8 )
     548                 :     {
     549            1312 :         ((char *)pData)[nValues] = '\0';
     550                 :         papszMetadata = CSLAddNameValue( papszMetadata, pszAttrName, 
     551            1312 :                                          (const char *) pData );
     552                 :     }
     553                 :     else
     554                 :     {
     555               0 :         pszTemp = SPrintArray( GetDataType(iNumType), pData, nValues, ", " );
     556               0 :         papszMetadata = CSLAddNameValue( papszMetadata, pszAttrName, pszTemp );
     557               0 :         if ( pszTemp )
     558               0 :       CPLFree( pszTemp );
     559                 :     }
     560                 :     
     561            1312 :     if ( pData )
     562            1312 :   CPLFree( pData );
     563                 : 
     564            1312 :     return papszMetadata;
     565                 : }
     566                 : 
     567                 : /************************************************************************/
     568                 : /*                       ReadGlobalAttributes()                         */
     569                 : /************************************************************************/
     570                 : 
     571             448 : CPLErr HDF4Dataset::ReadGlobalAttributes( int32 iHandler )
     572                 : {
     573                 :     int32 iAttribute, nValues, iNumType, nDatasets, nAttributes;
     574                 :     char  szAttrName[H4_MAX_NC_NAME];
     575                 : 
     576                 : /* -------------------------------------------------------------------- */
     577                 : /*     Obtain number of SDSs and global attributes in input file.       */
     578                 : /* -------------------------------------------------------------------- */
     579             448 :     if ( SDfileinfo( iHandler, &nDatasets, &nAttributes ) != 0 )
     580               0 :   return CE_Failure;
     581                 : 
     582                 :     // Loop through the all attributes
     583            1760 :     for ( iAttribute = 0; iAttribute < nAttributes; iAttribute++ )
     584                 :     {
     585                 :         // Get information about the attribute. Note that the first
     586                 :         // parameter is an SD interface identifier.
     587            1312 :         SDattrinfo( iHandler, iAttribute, szAttrName, &iNumType, &nValues );
     588                 : 
     589            1312 :         if ( EQUALN( szAttrName, "coremetadata.", 13 )    ||
     590                 :        EQUALN( szAttrName, "archivemetadata.", 16 ) ||
     591                 :        EQUALN( szAttrName, "productmetadata.", 16 ) ||
     592                 :              EQUALN( szAttrName, "badpixelinformation", 19 ) ||
     593                 :        EQUALN( szAttrName, "product_summary", 15 ) ||
     594                 :        EQUALN( szAttrName, "dem_specific", 12 ) ||
     595                 :        EQUALN( szAttrName, "bts_specific", 12 ) ||
     596                 :        EQUALN( szAttrName, "etse_specific", 13 ) ||
     597                 :        EQUALN( szAttrName, "dst_specific", 12 ) ||
     598                 :        EQUALN( szAttrName, "acv_specific", 12 ) ||
     599                 :        EQUALN( szAttrName, "act_specific", 12 ) ||
     600                 :        EQUALN( szAttrName, "etst_specific", 13 ) ||
     601                 :        EQUALN( szAttrName, "level_1_carryover", 17 ) )
     602                 :         {
     603               0 :             bIsHDFEOS = 1;
     604                 :             papszGlobalMetadata = TranslateHDF4EOSAttributes( iHandler,
     605               0 :     iAttribute, nValues, papszGlobalMetadata );
     606                 :         }
     607                 : 
     608                 :         // Skip "StructMetadata.N" records. We will fetch information
     609                 :         // from them using HDF-EOS API
     610            1312 :   else if ( EQUALN( szAttrName, "structmetadata.", 15 ) )
     611                 :         {
     612               0 :             bIsHDFEOS = 1;
     613               0 :             continue;
     614                 :         }
     615                 : 
     616                 :         else
     617                 :         {
     618                 :       papszGlobalMetadata = TranslateHDF4Attributes( iHandler,
     619            1312 :     iAttribute, szAttrName, iNumType, nValues, papszGlobalMetadata );
     620                 :         }
     621                 :     }
     622                 : 
     623             448 :     return CE_None;
     624                 : }
     625                 : 
     626                 : /************************************************************************/
     627                 : /*                              Identify()                              */
     628                 : /************************************************************************/
     629                 : 
     630            9479 : int HDF4Dataset::Identify( GDALOpenInfo * poOpenInfo )
     631                 : 
     632                 : {
     633            9479 :     if( poOpenInfo->nHeaderBytes < 4 )
     634            8615 :         return FALSE;
     635                 : 
     636             864 :     if( memcmp(poOpenInfo->pabyHeader,"\016\003\023\001",4) != 0 )
     637             640 :         return FALSE;
     638                 : 
     639             224 :     return TRUE;
     640                 : }
     641                 : 
     642                 : /************************************************************************/
     643                 : /*                                Open()                                */
     644                 : /************************************************************************/
     645                 : 
     646            1750 : GDALDataset *HDF4Dataset::Open( GDALOpenInfo * poOpenInfo )
     647                 : 
     648                 : {
     649                 :     int32 i;
     650                 : 
     651            1750 :     if( !Identify( poOpenInfo ) )
     652            1526 :         return NULL;
     653                 : 
     654                 : /* -------------------------------------------------------------------- */
     655                 : /*      Try opening the dataset.                                        */
     656                 : /* -------------------------------------------------------------------- */
     657                 :     int32 hHDF4;
     658                 :     
     659             224 :     hHDF4 = Hopen(poOpenInfo->pszFilename, DFACC_READ, 0);
     660                 :     
     661             224 :     if( hHDF4 <= 0 )
     662               0 :         return( NULL );
     663                 : 
     664             224 :     Hclose( hHDF4 );
     665                 : 
     666                 : /* -------------------------------------------------------------------- */
     667                 : /*      Create a corresponding GDALDataset.                             */
     668                 : /* -------------------------------------------------------------------- */
     669                 :     HDF4Dataset *poDS;
     670                 : 
     671             224 :     poDS = new HDF4Dataset();
     672                 : 
     673             224 :     poDS->fp = poOpenInfo->fp;
     674             224 :     poOpenInfo->fp = NULL;
     675                 :     
     676                 : /* -------------------------------------------------------------------- */
     677                 : /*          Open HDF SDS Interface.                                     */
     678                 : /* -------------------------------------------------------------------- */
     679             224 :     poDS->hSD = SDstart( poOpenInfo->pszFilename, DFACC_READ );
     680                 : 
     681             224 :     if ( poDS->hSD == -1 )
     682                 :     {
     683               0 :   delete poDS;
     684               0 :         return NULL;
     685                 :     }
     686                 :    
     687                 : /* -------------------------------------------------------------------- */
     688                 : /*    Now read Global Attributes.       */
     689                 : /* -------------------------------------------------------------------- */
     690             224 :     if ( poDS->ReadGlobalAttributes( poDS->hSD ) != CE_None )
     691                 :     {
     692               0 :   delete poDS;
     693               0 :         return NULL;
     694                 :     }
     695                 : 
     696             224 :     poDS->SetMetadata( poDS->papszGlobalMetadata, "" );
     697                 : 
     698                 : /* -------------------------------------------------------------------- */
     699                 : /*    Determine type of file we read.       */
     700                 : /* -------------------------------------------------------------------- */
     701                 :     const char  *pszValue;
     702                 :     
     703             224 :     if ( (pszValue = CSLFetchNameValue(poDS->papszGlobalMetadata,
     704                 :                                        "Signature"))
     705                 :    && EQUAL( pszValue, pszGDALSignature ) )
     706                 :     {
     707             224 :   poDS->iSubdatasetType = H4ST_GDAL;
     708             224 :   poDS->pszSubdatasetType = "GDAL_HDF4";
     709                 :     }
     710                 : 
     711               0 :     else if ( (pszValue = CSLFetchNameValue(poDS->papszGlobalMetadata, "Title"))
     712                 :    && EQUAL( pszValue, "SeaWiFS Level-1A Data" ) )
     713                 :     {
     714               0 :   poDS->iSubdatasetType = H4ST_SEAWIFS_L1A;
     715               0 :   poDS->pszSubdatasetType = "SEAWIFS_L1A";
     716                 :     }
     717                 : 
     718               0 :     else if ( (pszValue = CSLFetchNameValue(poDS->papszGlobalMetadata, "Title"))
     719                 :   && EQUAL( pszValue, "SeaWiFS Level-2 Data" ) )
     720                 :     {
     721               0 :   poDS->iSubdatasetType = H4ST_SEAWIFS_L2;
     722               0 :   poDS->pszSubdatasetType = "SEAWIFS_L2";
     723                 :     }
     724                 : 
     725               0 :     else if ( (pszValue = CSLFetchNameValue(poDS->papszGlobalMetadata, "Title"))
     726                 :   && EQUAL( pszValue, "SeaWiFS Level-3 Standard Mapped Image" ) )
     727                 :     {
     728               0 :   poDS->iSubdatasetType = H4ST_SEAWIFS_L3;
     729               0 :   poDS->pszSubdatasetType = "SEAWIFS_L3";
     730                 :     }
     731                 : 
     732               0 :     else if ( (pszValue = CSLFetchNameValue(poDS->papszGlobalMetadata,
     733                 :                                             "L1 File Generated By"))
     734                 :   && EQUALN( pszValue, "HYP version ", 12 ) )
     735                 :     {
     736               0 :   poDS->iSubdatasetType = H4ST_HYPERION_L1;
     737               0 :   poDS->pszSubdatasetType = "HYPERION_L1";
     738                 :     }
     739                 : 
     740                 :     else
     741                 :     {
     742               0 :   poDS->iSubdatasetType = H4ST_UNKNOWN;
     743               0 :   poDS->pszSubdatasetType = "UNKNOWN";
     744                 :     }
     745                 : 
     746                 : /* -------------------------------------------------------------------- */
     747                 : /*  If we have HDF-EOS dataset, process it here.                  */
     748                 : /* -------------------------------------------------------------------- */
     749                 :     char  szName[VSNAMELENMAX + 1], szTemp[8192];
     750                 :     char  *pszString;
     751                 :     const char  *pszName;
     752                 :     int   nCount;
     753                 :     int32 aiDimSizes[H4_MAX_VAR_DIMS];
     754                 :     int32 iRank, iNumType, nAttrs;
     755                 : 
     756                 :     // Sometimes "HDFEOSVersion" attribute is not defined and we will
     757                 :     // determine HDF-EOS datasets using other records
     758                 :     // (see ReadGlobalAttributes() method).
     759             224 :     if ( poDS->bIsHDFEOS
     760                 :          || CSLFetchNameValue(poDS->papszGlobalMetadata, "HDFEOSVersion") )
     761                 :     {
     762                 :         int32   nSubDatasets, nStrBufSize;
     763                 : 
     764                 : /* -------------------------------------------------------------------- */
     765                 : /*  Process swath layers.                                               */
     766                 : /* -------------------------------------------------------------------- */
     767               0 :         hHDF4 = SWopen( poOpenInfo->pszFilename, DFACC_READ );
     768               0 :         nSubDatasets = SWinqswath(poOpenInfo->pszFilename, NULL, &nStrBufSize);
     769                 : #if DEBUG
     770                 :         CPLDebug( "HDF4", "Number of HDF-EOS swaths: %d", (int)nSubDatasets );
     771                 : #endif
     772               0 :         if ( nSubDatasets > 0 && nStrBufSize > 0 )
     773                 :         {
     774                 :             char    *pszSwathList;
     775                 :             char    **papszSwaths;
     776                 : 
     777               0 :             pszSwathList = (char *)CPLMalloc( nStrBufSize + 1 );
     778               0 :             SWinqswath( poOpenInfo->pszFilename, pszSwathList, &nStrBufSize );
     779               0 :             pszSwathList[nStrBufSize] = '\0';
     780                 : 
     781                 : #if DEBUG
     782                 :             CPLDebug( "HDF4", "List of HDF-EOS swaths: %s", pszSwathList );
     783                 : #endif
     784                 : 
     785                 :             papszSwaths =
     786               0 :                 CSLTokenizeString2( pszSwathList, ",", CSLT_HONOURSTRINGS );
     787               0 :             CPLFree( pszSwathList );
     788                 : 
     789               0 :             if ( nSubDatasets != CSLCount(papszSwaths) )
     790                 :             {
     791               0 :                 CSLDestroy( papszSwaths );
     792               0 :                 delete poDS;
     793               0 :                 CPLDebug( "HDF4", "Can not parse list of HDF-EOS grids." );
     794               0 :                 return NULL;
     795                 :             }
     796                 : 
     797               0 :             for ( i = 0; i < nSubDatasets; i++)
     798                 :             {
     799                 :                 char    *pszFieldList;
     800                 :                 char    **papszFields;
     801                 :                 int32   *paiRank, *paiNumType;
     802                 :                 int32   hSW, nFields, j;
     803                 : 
     804               0 :                 hSW = SWattach( hHDF4, papszSwaths[i] );
     805                 : 
     806               0 :                 nFields = SWnentries( hSW, HDFE_NENTDFLD, &nStrBufSize );
     807               0 :                 pszFieldList = (char *)CPLMalloc( nStrBufSize + 1 );
     808               0 :                 paiRank = (int32 *)CPLMalloc( nFields * sizeof(int32) );
     809               0 :                 paiNumType = (int32 *)CPLMalloc( nFields * sizeof(int32) );
     810                 : 
     811               0 :                 SWinqdatafields( hSW, pszFieldList, paiRank, paiNumType );
     812                 : 
     813                 : #if DEBUG
     814                 :                 {
     815                 :                     char *pszTmp =
     816                 :                         SPrintArray( GDT_UInt32, paiRank, nFields, "," );
     817                 : 
     818                 :                     CPLDebug( "HDF4", "Number of data fields in swath %d: %d",
     819                 :                               (int) i, (int) nFields );
     820                 :                     CPLDebug( "HDF4", "List of data fields in swath %d: %s",
     821                 :                               (int) i, pszFieldList );
     822                 :                     CPLDebug( "HDF4", "Data fields ranks: %s", pszTmp );
     823                 : 
     824                 :                     CPLFree( pszTmp );
     825                 :                 }
     826                 : #endif
     827                 : 
     828                 :                 papszFields = CSLTokenizeString2( pszFieldList, ",",
     829               0 :                                                   CSLT_HONOURSTRINGS );
     830                 :                 
     831               0 :                 for ( j = 0; j < nFields; j++ )
     832                 :                 {
     833               0 :                     SWfieldinfo( hSW, papszFields[j], &iRank, aiDimSizes,
     834               0 :                                  &iNumType, NULL );
     835                 : 
     836               0 :                     if ( iRank < 2 )
     837               0 :                         continue;
     838                 : 
     839                 :               // Add field to the list of GDAL subdatasets
     840               0 :                     nCount = CSLCount( poDS->papszSubDatasets ) / 2;
     841               0 :                     sprintf( szTemp, "SUBDATASET_%d_NAME", nCount + 1 );
     842                 :               // We will use the field index as an identificator.
     843                 :                     poDS->papszSubDatasets =
     844                 :                         CSLSetNameValue( poDS->papszSubDatasets, szTemp,
     845                 :                                 CPLSPrintf("HDF4_EOS:EOS_SWATH:\"%s\":%s:%s",
     846                 :                                            poOpenInfo->pszFilename,
     847               0 :                                            papszSwaths[i], papszFields[j]) );
     848                 : 
     849               0 :                     sprintf( szTemp, "SUBDATASET_%d_DESC", nCount + 1 );
     850                 :                     pszString = SPrintArray( GDT_UInt32, aiDimSizes,
     851               0 :                                              iRank, "x" );
     852                 :                     poDS->papszSubDatasets =
     853                 :                         CSLSetNameValue( poDS->papszSubDatasets, szTemp,
     854                 :                                          CPLSPrintf( "[%s] %s %s (%s)", pszString,
     855                 :                                          papszFields[j],
     856                 :                                          papszSwaths[i],
     857               0 :                                          poDS->GetDataTypeName(iNumType) ) );
     858               0 :                     CPLFree( pszString );
     859                 :                 }
     860                 : 
     861               0 :                 CSLDestroy( papszFields );
     862               0 :                 CPLFree( paiNumType );
     863               0 :                 CPLFree( paiRank );
     864               0 :                 CPLFree( pszFieldList );
     865               0 :                 SWdetach( hSW );
     866                 :             }
     867                 : 
     868               0 :             CSLDestroy( papszSwaths );
     869                 :         }
     870               0 :         SWclose( hHDF4 );
     871                 : 
     872                 : /* -------------------------------------------------------------------- */
     873                 : /*  Process grid layers.                                                */
     874                 : /* -------------------------------------------------------------------- */
     875               0 :         hHDF4 = GDopen( poOpenInfo->pszFilename, DFACC_READ );
     876               0 :         nSubDatasets = GDinqgrid( poOpenInfo->pszFilename, NULL, &nStrBufSize );
     877                 : #if DEBUG
     878                 :         CPLDebug( "HDF4", "Number of HDF-EOS grids: %d", (int)nSubDatasets );
     879                 : #endif
     880               0 :         if ( nSubDatasets > 0 && nStrBufSize > 0 )
     881                 :         {
     882                 :             char    *pszGridList;
     883                 :             char    **papszGrids;
     884                 : 
     885               0 :             pszGridList = (char *)CPLMalloc( nStrBufSize + 1 );
     886               0 :             GDinqgrid( poOpenInfo->pszFilename, pszGridList, &nStrBufSize );
     887                 : 
     888                 : #if DEBUG
     889                 :             CPLDebug( "HDF4", "List of HDF-EOS grids: %s", pszGridList );
     890                 : #endif
     891                 : 
     892                 :             papszGrids =
     893               0 :                 CSLTokenizeString2( pszGridList, ",", CSLT_HONOURSTRINGS );
     894               0 :             CPLFree( pszGridList );
     895                 : 
     896               0 :             if ( nSubDatasets != CSLCount(papszGrids) )
     897                 :             {
     898               0 :                 CSLDestroy( papszGrids );
     899               0 :                 delete poDS;
     900               0 :                 CPLDebug( "HDF4", "Can not parse list of HDF-EOS grids." );
     901               0 :                 return NULL;
     902                 :             }
     903                 : 
     904               0 :             for ( i = 0; i < nSubDatasets; i++)
     905                 :             {
     906                 :                 char    *pszFieldList;
     907                 :                 char    **papszFields;
     908                 :                 int32   *paiRank, *paiNumType;
     909                 :                 int32   hGD, nFields, j;
     910                 : 
     911               0 :                 hGD = GDattach( hHDF4, papszGrids[i] );
     912                 : 
     913               0 :                 nFields = GDnentries( hGD, HDFE_NENTDFLD, &nStrBufSize );
     914               0 :                 pszFieldList = (char *)CPLMalloc( nStrBufSize + 1 );
     915               0 :                 paiRank = (int32 *)CPLMalloc( nFields * sizeof(int32) );
     916               0 :                 paiNumType = (int32 *)CPLMalloc( nFields * sizeof(int32) );
     917                 : 
     918               0 :                 GDinqfields( hGD, pszFieldList, paiRank, paiNumType );
     919                 : 
     920                 : #if DEBUG
     921                 :                 {
     922                 :                     char* pszTmp =
     923                 :                             SPrintArray( GDT_UInt32, paiRank, nFields, "," );
     924                 :                     CPLDebug( "HDF4", "Number of fields in grid %d: %d",
     925                 :                             (int) i, (int) nFields );
     926                 :                     CPLDebug( "HDF4", "List of fields in grid %d: %s",
     927                 :                             (int) i, pszFieldList );
     928                 :                     CPLDebug( "HDF4", "Fields ranks: %s",
     929                 :                             pszTmp );
     930                 :                     CPLFree( pszTmp );
     931                 :                 }
     932                 : #endif
     933                 : 
     934                 :                 papszFields = CSLTokenizeString2( pszFieldList, ",",
     935               0 :                                                   CSLT_HONOURSTRINGS );
     936                 :                 
     937               0 :                 for ( j = 0; j < nFields; j++ )
     938                 :                 {
     939                 :                     GDfieldinfo( hGD, papszFields[j], &iRank, aiDimSizes,
     940               0 :                                  &iNumType, NULL );
     941                 : 
     942               0 :                     if ( iRank < 2 )
     943               0 :                         continue;
     944                 : 
     945                 :               // Add field to the list of GDAL subdatasets
     946               0 :                     nCount = CSLCount( poDS->papszSubDatasets ) / 2;
     947               0 :                     sprintf( szTemp, "SUBDATASET_%d_NAME", nCount + 1 );
     948                 :               // We will use the field index as an identificator.
     949                 :                     poDS->papszSubDatasets =
     950                 :                         CSLSetNameValue(poDS->papszSubDatasets, szTemp,
     951                 :                                 CPLSPrintf( "HDF4_EOS:EOS_GRID:\"%s\":%s:%s",
     952                 :                                             poOpenInfo->pszFilename,
     953               0 :                                             papszGrids[i], papszFields[j]));
     954                 : 
     955               0 :                     sprintf( szTemp, "SUBDATASET_%d_DESC", nCount + 1 );
     956                 :                     pszString = SPrintArray( GDT_UInt32, aiDimSizes,
     957               0 :                                              iRank, "x" );
     958                 :                     poDS->papszSubDatasets =
     959                 :                         CSLSetNameValue( poDS->papszSubDatasets, szTemp,
     960                 :                                          CPLSPrintf("[%s] %s %s (%s)", pszString,
     961                 :                                              papszFields[j],
     962                 :                                              papszGrids[i],
     963               0 :                                              poDS->GetDataTypeName(iNumType)) );
     964               0 :                     CPLFree( pszString );
     965                 :                 }
     966                 : 
     967               0 :                 CSLDestroy( papszFields );
     968               0 :                 CPLFree( paiNumType );
     969               0 :                 CPLFree( paiRank );
     970               0 :                 CPLFree( pszFieldList );
     971               0 :                 GDdetach( hGD );
     972                 :             }
     973                 : 
     974               0 :             CSLDestroy( papszGrids );
     975               0 :             GDclose( hHDF4 );
     976                 :         }
     977               0 :         GDclose( hHDF4 );
     978                 :     }
     979                 : 
     980                 :     else
     981                 :     {
     982                 : 
     983                 : /* -------------------------------------------------------------------- */
     984                 : /*  Make a list of subdatasets from SDSs contained in input HDF file. */
     985                 : /* -------------------------------------------------------------------- */
     986                 :         int32   nDatasets;
     987                 : 
     988             224 :         if ( SDfileinfo( poDS->hSD, &nDatasets, &nAttrs ) != 0 )
     989               0 :       return NULL;
     990                 : 
     991             448 :         for ( i = 0; i < nDatasets; i++ )
     992                 :         {
     993                 :             int32 iSDS;
     994                 : 
     995             224 :             iSDS = SDselect( poDS->hSD, i );
     996             224 :             if ( SDgetinfo( iSDS, szName, &iRank, aiDimSizes, &iNumType, &nAttrs) != 0 )
     997               0 :                 return NULL;
     998                 :             
     999             224 :             if ( iRank == 1 )   // Skip 1D datsets
    1000               0 :                     continue;
    1001                 : 
    1002                 :             // Do sort of known datasets. We will display only image bands
    1003             224 :             if ( (poDS->iSubdatasetType == H4ST_SEAWIFS_L1A ) &&
    1004                 :                       !EQUALN( szName, "l1a_data", 8 ) )
    1005               0 :                     continue;
    1006                 :             else
    1007             224 :                 pszName = szName;
    1008                 :             
    1009                 :             // Add datasets with multiple dimensions to the list of GDAL subdatasets
    1010             224 :             nCount = CSLCount( poDS->papszSubDatasets ) / 2;
    1011             224 :             sprintf( szTemp, "SUBDATASET_%d_NAME", nCount + 1 );
    1012                 :             // We will use SDS index as an identificator, because SDS names
    1013                 :             // are not unique. Filename also needed for further file opening
    1014                 :             poDS->papszSubDatasets = CSLSetNameValue(poDS->papszSubDatasets, szTemp, 
    1015                 :                   CPLSPrintf( "HDF4_SDS:%s:\"%s\":%ld", poDS->pszSubdatasetType,
    1016             224 :                               poOpenInfo->pszFilename, (long)i) );
    1017             224 :             sprintf( szTemp, "SUBDATASET_%d_DESC", nCount + 1 );
    1018             224 :             pszString = SPrintArray( GDT_UInt32, aiDimSizes, iRank, "x" );
    1019                 :             poDS->papszSubDatasets = CSLSetNameValue(poDS->papszSubDatasets, szTemp,
    1020                 :                 CPLSPrintf( "[%s] %s (%s)", pszString,
    1021             224 :                             pszName, poDS->GetDataTypeName(iNumType)) );
    1022             224 :             CPLFree( pszString );
    1023                 : 
    1024             224 :             SDendaccess( iSDS );
    1025                 :         }
    1026                 : 
    1027             224 :         SDend( poDS->hSD );
    1028             224 :         poDS->hSD = 0;
    1029                 :     }
    1030                 : 
    1031                 : /* -------------------------------------------------------------------- */
    1032                 : /*      Build a list of raster images. Note, that HDF-EOS dataset may   */
    1033                 : /*      contain a raster image as well.                                 */
    1034                 : /* -------------------------------------------------------------------- */
    1035             224 :     hHDF4 = Hopen(poOpenInfo->pszFilename, DFACC_READ, 0);
    1036             224 :     poDS->hGR = GRstart( hHDF4 );
    1037                 : 
    1038             224 :     if ( poDS->hGR != -1 )
    1039                 :     {
    1040             224 :         if ( GRfileinfo( poDS->hGR, &poDS->nImages, &nAttrs ) == -1 )
    1041               0 :             return NULL;
    1042                 :         
    1043             224 :         for ( i = 0; i < poDS->nImages; i++ )
    1044                 :         {
    1045                 :             int32   iInterlaceMode; 
    1046               0 :             int32   iGR = GRselect( poDS->hGR, i );
    1047                 : 
    1048                 :             // iRank in GR interface has another meaning. It represents number
    1049                 :             // of samples per pixel. aiDimSizes has only two dimensions.
    1050               0 :             if ( GRgetiminfo( iGR, szName, &iRank, &iNumType, &iInterlaceMode,
    1051                 :                               aiDimSizes, &nAttrs ) != 0 )
    1052               0 :                 return NULL;
    1053               0 :             nCount = CSLCount( poDS->papszSubDatasets ) / 2;
    1054               0 :             sprintf( szTemp, "SUBDATASET_%d_NAME", nCount + 1 );
    1055                 :             poDS->papszSubDatasets = CSLSetNameValue(poDS->papszSubDatasets,
    1056                 :                 szTemp,CPLSPrintf( "HDF4_GR:UNKNOWN:\"%s\":%ld",
    1057               0 :                                    poOpenInfo->pszFilename, (long)i));
    1058               0 :             sprintf( szTemp, "SUBDATASET_%d_DESC", nCount + 1 );
    1059               0 :             pszString = SPrintArray( GDT_UInt32, aiDimSizes, 2, "x" );
    1060                 :             poDS->papszSubDatasets = CSLSetNameValue(poDS->papszSubDatasets,
    1061                 :                 szTemp, CPLSPrintf( "[%sx%ld] %s (%s)", pszString, (long)iRank,
    1062               0 :                                     szName, poDS->GetDataTypeName(iNumType)) );
    1063               0 :             CPLFree( pszString );
    1064                 : 
    1065               0 :             GRendaccess( iGR );
    1066                 :         }
    1067                 : 
    1068             224 :         GRend( poDS->hGR );
    1069             224 :         poDS->hGR = 0;
    1070                 :     }
    1071                 : 
    1072             224 :     Hclose( hHDF4 );
    1073                 : 
    1074             224 :     poDS->nRasterXSize = poDS->nRasterYSize = 512; // XXX: bogus values
    1075                 : 
    1076                 :     // Make sure we don't try to do any pam stuff with this dataset.
    1077             224 :     poDS->nPamFlags |= GPF_NOSAVE;
    1078                 : 
    1079                 : /* -------------------------------------------------------------------- */
    1080                 : /*      If we have single subdataset only, open it immediately          */
    1081                 : /* -------------------------------------------------------------------- */
    1082             224 :     if ( CSLCount( poDS->papszSubDatasets ) / 2 == 1 )
    1083                 :     {
    1084                 :         char *pszSDSName;
    1085                 :         pszSDSName = CPLStrdup( CSLFetchNameValue( poDS->papszSubDatasets,
    1086             224 :                             "SUBDATASET_1_NAME" ));
    1087             224 :         delete poDS;
    1088             224 :         poDS = (HDF4Dataset *) GDALOpen( pszSDSName, poOpenInfo->eAccess );
    1089             224 :         CPLFree( pszSDSName );
    1090                 :     }
    1091                 :     else
    1092                 :     {
    1093                 : /* -------------------------------------------------------------------- */
    1094                 : /*      Confirm the requested access is supported.                      */
    1095                 : /* -------------------------------------------------------------------- */
    1096               0 :         if( poOpenInfo->eAccess == GA_Update )
    1097                 :         {
    1098               0 :             delete poDS;
    1099                 :             CPLError( CE_Failure, CPLE_NotSupported, 
    1100                 :                       "The HDF4 driver does not support update access to existing"
    1101               0 :                       " datasets.\n" );
    1102               0 :             return NULL;
    1103                 :         }
    1104                 :     
    1105                 :     }
    1106                 : 
    1107             224 :     return( poDS );
    1108                 : }
    1109                 : 
    1110                 : /************************************************************************/
    1111                 : /*                        GDALRegister_HDF4()       */
    1112                 : /************************************************************************/
    1113                 : 
    1114             338 : void GDALRegister_HDF4()
    1115                 : 
    1116                 : {
    1117                 :     GDALDriver  *poDriver;
    1118                 :     
    1119             338 :     if (! GDAL_CHECK_VERSION("HDF4 driver"))
    1120               0 :         return;
    1121                 : 
    1122             338 :     if( GDALGetDriverByName( "HDF4" ) == NULL )
    1123                 :     {
    1124             336 :         poDriver = new GDALDriver();
    1125                 :         
    1126             336 :         poDriver->SetDescription( "HDF4" );
    1127                 :         poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
    1128             336 :                                    "Hierarchical Data Format Release 4" );
    1129                 :         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
    1130             336 :                                    "frmt_hdf4.html" );
    1131                 : 
    1132             336 :         poDriver->pfnOpen = HDF4Dataset::Open;
    1133             336 :         poDriver->pfnIdentify = HDF4Dataset::Identify;
    1134                 : 
    1135             336 :         GetGDALDriverManager()->RegisterDriver( poDriver );
    1136                 :     }
    1137                 : }
    1138                 : 

Generated by: LCOV version 1.7