Пример #1
0
SEXP
RGDAL_CreateDataset(SEXP sxpDriver, SEXP sDim, SEXP sType,
		    SEXP sOpts, SEXP sFile) {

  GDALDriver *pDriver = getGDALDriverPtr(sxpDriver);
  GDALDataset *pDataset;
  const char *filename = asString(sFile);

  int i, n;

#ifdef RGDALDEBUG
  fprintf(stderr, "Opening dataset: %s\n", filename);
  fflush(stderr);
#endif

  if (filename == NULL) error("Invalid file name\n");

  GDALDataType eGDALType = (GDALDataType) asInteger(sType);

  if (isNull(sOpts)) {
    char **opts = NULL;
    pDataset = pDriver->Create(filename,
			  INTEGER(sDim)[0],
			  INTEGER(sDim)[1],
			  INTEGER(sDim)[2],
			  eGDALType, opts);
  } else {
    n = length(sOpts);
    char *opts[n];
    for (i=0; i < n; i++) opts[i] = CHAR(STRING_ELT(sOpts, i));
#ifdef RGDALDEBUG
    for (i=0; i < n; i++) Rprintf("option: %s\n", opts[i]);
#endif
    pDataset = pDriver->Create(filename,
			  INTEGER(sDim)[0],
			  INTEGER(sDim)[1],
			  INTEGER(sDim)[2],
			  eGDALType, opts);
  }

  if (pDataset == NULL) error("Unable to create dataset\n");

  pDataset->SetDescription(filename);

  SEXP sxpHandle = R_MakeExternalPtr((void *) pDataset,
				     mkChar("GDAL Dataset"),
				     R_NilValue);

  return(sxpHandle);

}
Пример #2
0
SEXP
RGDAL_CreateDataset(SEXP sxpDriver, SEXP sDim, SEXP sType,
		    SEXP sOpts, SEXP sFile) {

  GDALDriver *pDriver = getGDALDriverPtr(sxpDriver);
  GDALDataset *pDataset;
  const char *filename = asString(sFile);
  int i/*, n*/;
  char **papszCreateOptions = NULL;

#ifdef RGDALDEBUG
  Rprintf("Opening dataset: %s\n", filename);
//  fflush(stderr);
#endif

  if (filename == NULL) error("Invalid file name\n");

  GDALDataType eGDALType = (GDALDataType) asInteger(sType);

  installErrorHandler();
  for (i=0; i < length(sOpts); i++) papszCreateOptions = CSLAddString( 
    papszCreateOptions, CHAR(STRING_ELT(sOpts, i)) );
#ifdef RGDALDEBUG
  for (i=0; i < CSLCount(papszCreateOptions); i++)
    Rprintf("option %d: %s\n", i, CSLGetField(papszCreateOptions, i));
#endif
  uninstallErrorHandlerAndTriggerError();
  installErrorHandler();
  pDataset = pDriver->Create(filename,
			  INTEGER(sDim)[0],
			  INTEGER(sDim)[1],
			  INTEGER(sDim)[2],
			  eGDALType, papszCreateOptions);
  uninstallErrorHandlerAndTriggerError();
  installErrorHandler();
  CSLDestroy(papszCreateOptions);
  uninstallErrorHandlerAndTriggerError();

  if (pDataset == NULL) error("Unable to create dataset\n");

  installErrorHandler();
  pDataset->SetDescription(filename);
  uninstallErrorHandlerAndTriggerError();

  SEXP sxpHandle = R_MakeExternalPtr((void *) pDataset,
				     mkChar("GDAL Dataset"),
				     R_NilValue);

  return(sxpHandle);

}
Пример #3
0
GDALDataset *
VRTDataset::Create( const char * pszName,
                    int nXSize, int nYSize, int nBands,
                    GDALDataType eType, char ** papszOptions )

{
    VRTDataset *poDS = NULL;
    int        iBand = 0;

    (void) papszOptions;

    if( EQUALN(pszName,"<VRTDataset",11) )
    {
        GDALDataset *poDS = OpenXML( pszName, NULL, GA_Update );
        if (poDS)
            poDS->SetDescription( "<FromXML>" );
        return poDS;
    }
    else
    {
        const char *pszSubclass = CSLFetchNameValue( papszOptions,
                                                     "SUBCLASS" );

        if( pszSubclass == NULL || EQUAL(pszSubclass,"VRTDataset") )
            poDS = new VRTDataset( nXSize, nYSize );
        else if( EQUAL(pszSubclass,"VRTWarpedDataset") )
        {
            poDS = new VRTWarpedDataset( nXSize, nYSize );
        }
        else
        {
            CPLError( CE_Failure, CPLE_AppDefined, 
                      "SUBCLASS=%s not recognised.", 
                      pszSubclass );
            return NULL;
        }
        poDS->eAccess = GA_Update;

        poDS->SetDescription( pszName );
        
        for( iBand = 0; iBand < nBands; iBand++ )
            poDS->AddBand( eType, NULL );
        
        poDS->bNeedsFlush = 1;

        poDS->oOvManager.Initialize( poDS, pszName );
        
        return poDS;
    }
}
Пример #4
0
GDALDataset *HDF4Dataset::Open( GDALOpenInfo * poOpenInfo )

{
    int32	i;

    if( !Identify( poOpenInfo ) )
        return NULL;

/* -------------------------------------------------------------------- */
/*      Try opening the dataset.                                        */
/* -------------------------------------------------------------------- */
    int32	hHDF4;
    
    hHDF4 = Hopen(poOpenInfo->pszFilename, DFACC_READ, 0);
    
    if( hHDF4 <= 0 )
        return( NULL );

    Hclose( hHDF4 );

/* -------------------------------------------------------------------- */
/*      Create a corresponding GDALDataset.                             */
/* -------------------------------------------------------------------- */
    HDF4Dataset *poDS;

    poDS = new HDF4Dataset();

    poDS->fp = poOpenInfo->fp;
    poOpenInfo->fp = NULL;
    
/* -------------------------------------------------------------------- */
/*          Open HDF SDS Interface.                                     */
/* -------------------------------------------------------------------- */
    poDS->hSD = SDstart( poOpenInfo->pszFilename, DFACC_READ );

    if ( poDS->hSD == -1 )
    {
	delete poDS;
        return NULL;
    }
   
/* -------------------------------------------------------------------- */
/*		Now read Global Attributes.				*/
/* -------------------------------------------------------------------- */
    if ( poDS->ReadGlobalAttributes( poDS->hSD ) != CE_None )
    {
	delete poDS;
        return NULL;
    }

    poDS->SetMetadata( poDS->papszGlobalMetadata, "" );

/* -------------------------------------------------------------------- */
/*		Determine type of file we read.				*/
/* -------------------------------------------------------------------- */
    const char	*pszValue;
    
    if ( (pszValue = CSLFetchNameValue(poDS->papszGlobalMetadata,
                                       "Signature"))
	 && EQUAL( pszValue, pszGDALSignature ) )
    {
	poDS->iSubdatasetType = H4ST_GDAL;
	poDS->pszSubdatasetType = "GDAL_HDF4";
    }

    else if ( (pszValue = CSLFetchNameValue(poDS->papszGlobalMetadata, "Title"))
	 && EQUAL( pszValue, "SeaWiFS Level-1A Data" ) )
    {
	poDS->iSubdatasetType = H4ST_SEAWIFS_L1A;
	poDS->pszSubdatasetType = "SEAWIFS_L1A";
    }

    else if ( (pszValue = CSLFetchNameValue(poDS->papszGlobalMetadata, "Title"))
	&& EQUAL( pszValue, "SeaWiFS Level-2 Data" ) )
    {
	poDS->iSubdatasetType = H4ST_SEAWIFS_L2;
	poDS->pszSubdatasetType = "SEAWIFS_L2";
    }

    else if ( (pszValue = CSLFetchNameValue(poDS->papszGlobalMetadata, "Title"))
	&& EQUAL( pszValue, "SeaWiFS Level-3 Standard Mapped Image" ) )
    {
	poDS->iSubdatasetType = H4ST_SEAWIFS_L3;
	poDS->pszSubdatasetType = "SEAWIFS_L3";
    }

    else if ( (pszValue = CSLFetchNameValue(poDS->papszGlobalMetadata,
                                            "L1 File Generated By"))
	&& EQUALN( pszValue, "HYP version ", 12 ) )
    {
	poDS->iSubdatasetType = H4ST_HYPERION_L1;
	poDS->pszSubdatasetType = "HYPERION_L1";
    }

    else
    {
	poDS->iSubdatasetType = H4ST_UNKNOWN;
	poDS->pszSubdatasetType = "UNKNOWN";
    }

/* -------------------------------------------------------------------- */
/*  If we have HDF-EOS dataset, process it here.	                */
/* -------------------------------------------------------------------- */
    char	szName[VSNAMELENMAX + 1], szTemp[8192];
    char	*pszString;
    const char  *pszName;
    int		nCount;
    int32	aiDimSizes[H4_MAX_VAR_DIMS];
    int32	iRank, iNumType, nAttrs;
    bool        bIsHDF = true;
    
    // Sometimes "HDFEOSVersion" attribute is not defined and we will
    // determine HDF-EOS datasets using other records
    // (see ReadGlobalAttributes() method).
    if ( poDS->bIsHDFEOS
         || CSLFetchNameValue(poDS->papszGlobalMetadata, "HDFEOSVersion") )
    {
        bIsHDF  = false;

        int32   nSubDatasets, nStrBufSize;

/* -------------------------------------------------------------------- */
/*  Process swath layers.                                               */
/* -------------------------------------------------------------------- */
        hHDF4 = SWopen( poOpenInfo->pszFilename, DFACC_READ );
        if( hHDF4 < 0)
        {
            delete poDS;
            CPLError( CE_Failure, CPLE_OpenFailed, "Failed to open HDF4 `%s'.\n", poOpenInfo->pszFilename );
            return NULL;
        } 
        nSubDatasets = SWinqswath(poOpenInfo->pszFilename, NULL, &nStrBufSize);
#if DEBUG
        CPLDebug( "HDF4", "Number of HDF-EOS swaths: %d", (int)nSubDatasets );
#endif
        if ( nSubDatasets > 0 && nStrBufSize > 0 )
        {
            char    *pszSwathList;
            char    **papszSwaths;

            pszSwathList = (char *)CPLMalloc( nStrBufSize + 1 );
            SWinqswath( poOpenInfo->pszFilename, pszSwathList, &nStrBufSize );
            pszSwathList[nStrBufSize] = '\0';

#if DEBUG
            CPLDebug( "HDF4", "List of HDF-EOS swaths: %s", pszSwathList );
#endif

            papszSwaths =
                CSLTokenizeString2( pszSwathList, ",", CSLT_HONOURSTRINGS );
            CPLFree( pszSwathList );

            if ( nSubDatasets != CSLCount(papszSwaths) )
            {
                CSLDestroy( papszSwaths );
                delete poDS;
                CPLDebug( "HDF4", "Can not parse list of HDF-EOS grids." );
                return NULL;
            }

            for ( i = 0; i < nSubDatasets; i++)
            {
                char    *pszFieldList;
                char    **papszFields;
                int32   *paiRank, *paiNumType;
                int32   hSW, nFields, j;

                hSW = SWattach( hHDF4, papszSwaths[i] );

                nFields = SWnentries( hSW, HDFE_NENTDFLD, &nStrBufSize );
                pszFieldList = (char *)CPLMalloc( nStrBufSize + 1 );
                paiRank = (int32 *)CPLMalloc( nFields * sizeof(int32) );
                paiNumType = (int32 *)CPLMalloc( nFields * sizeof(int32) );

                SWinqdatafields( hSW, pszFieldList, paiRank, paiNumType );

#if DEBUG
                {
                    char *pszTmp =
                        SPrintArray( GDT_UInt32, paiRank, nFields, "," );

                    CPLDebug( "HDF4", "Number of data fields in swath %d: %d",
                              (int) i, (int) nFields );
                    CPLDebug( "HDF4", "List of data fields in swath %d: %s",
                              (int) i, pszFieldList );
                    CPLDebug( "HDF4", "Data fields ranks: %s", pszTmp );

                    CPLFree( pszTmp );
                }
#endif

                papszFields = CSLTokenizeString2( pszFieldList, ",",
                                                  CSLT_HONOURSTRINGS );
                
                for ( j = 0; j < nFields; j++ )
                {
                    SWfieldinfo( hSW, papszFields[j], &iRank, aiDimSizes,
                                 &iNumType, NULL );

                    if ( iRank < 2 )
                        continue;

	            // Add field to the list of GDAL subdatasets
                    nCount = CSLCount( poDS->papszSubDatasets ) / 2;
                    sprintf( szTemp, "SUBDATASET_%d_NAME", nCount + 1 );
	            // We will use the field index as an identificator.
                    poDS->papszSubDatasets =
                        CSLSetNameValue( poDS->papszSubDatasets, szTemp,
                                CPLSPrintf("HDF4_EOS:EOS_SWATH:\"%s\":%s:%s",
                                           poOpenInfo->pszFilename,
                                           papszSwaths[i], papszFields[j]) );

                    sprintf( szTemp, "SUBDATASET_%d_DESC", nCount + 1 );
                    pszString = SPrintArray( GDT_UInt32, aiDimSizes,
                                             iRank, "x" );
                    poDS->papszSubDatasets =
                        CSLSetNameValue( poDS->papszSubDatasets, szTemp,
                                         CPLSPrintf( "[%s] %s %s (%s)", pszString,
                                         papszFields[j],
                                         papszSwaths[i],
                                         poDS->GetDataTypeName(iNumType) ) );
                    CPLFree( pszString );
                }

                CSLDestroy( papszFields );
                CPLFree( paiNumType );
                CPLFree( paiRank );
                CPLFree( pszFieldList );
                SWdetach( hSW );
            }

            CSLDestroy( papszSwaths );
        }
        SWclose( hHDF4 );

/* -------------------------------------------------------------------- */
/*  Process grid layers.                                                */
/* -------------------------------------------------------------------- */
        hHDF4 = GDopen( poOpenInfo->pszFilename, DFACC_READ );
        nSubDatasets = GDinqgrid( poOpenInfo->pszFilename, NULL, &nStrBufSize );
#if DEBUG
        CPLDebug( "HDF4", "Number of HDF-EOS grids: %d", (int)nSubDatasets );
#endif
        if ( nSubDatasets > 0 && nStrBufSize > 0 )
        {
            char    *pszGridList;
            char    **papszGrids;

            pszGridList = (char *)CPLMalloc( nStrBufSize + 1 );
            GDinqgrid( poOpenInfo->pszFilename, pszGridList, &nStrBufSize );

#if DEBUG
            CPLDebug( "HDF4", "List of HDF-EOS grids: %s", pszGridList );
#endif

            papszGrids =
                CSLTokenizeString2( pszGridList, ",", CSLT_HONOURSTRINGS );
            CPLFree( pszGridList );

            if ( nSubDatasets != CSLCount(papszGrids) )
            {
                CSLDestroy( papszGrids );
                delete poDS;
                CPLDebug( "HDF4", "Can not parse list of HDF-EOS grids." );
                return NULL;
            }

            for ( i = 0; i < nSubDatasets; i++)
            {
                char    *pszFieldList;
                char    **papszFields;
                int32   *paiRank, *paiNumType;
                int32   hGD, nFields, j;

                hGD = GDattach( hHDF4, papszGrids[i] );

                nFields = GDnentries( hGD, HDFE_NENTDFLD, &nStrBufSize );
                pszFieldList = (char *)CPLMalloc( nStrBufSize + 1 );
                paiRank = (int32 *)CPLMalloc( nFields * sizeof(int32) );
                paiNumType = (int32 *)CPLMalloc( nFields * sizeof(int32) );

                GDinqfields( hGD, pszFieldList, paiRank, paiNumType );

#if DEBUG
                {
                    char* pszTmp =
                            SPrintArray( GDT_UInt32, paiRank, nFields, "," );
                    CPLDebug( "HDF4", "Number of fields in grid %d: %d",
                            (int) i, (int) nFields );
                    CPLDebug( "HDF4", "List of fields in grid %d: %s",
                            (int) i, pszFieldList );
                    CPLDebug( "HDF4", "Fields ranks: %s",
                            pszTmp );
                    CPLFree( pszTmp );
                }
#endif

                papszFields = CSLTokenizeString2( pszFieldList, ",",
                                                  CSLT_HONOURSTRINGS );
                
                for ( j = 0; j < nFields; j++ )
                {
                    GDfieldinfo( hGD, papszFields[j], &iRank, aiDimSizes,
                                 &iNumType, NULL );

                    if ( iRank < 2 )
                        continue;

	            // Add field to the list of GDAL subdatasets
                    nCount = CSLCount( poDS->papszSubDatasets ) / 2;
                    sprintf( szTemp, "SUBDATASET_%d_NAME", nCount + 1 );
	            // We will use the field index as an identificator.
                    poDS->papszSubDatasets =
                        CSLSetNameValue(poDS->papszSubDatasets, szTemp,
                                CPLSPrintf( "HDF4_EOS:EOS_GRID:\"%s\":%s:%s",
                                            poOpenInfo->pszFilename,
                                            papszGrids[i], papszFields[j]));

                    sprintf( szTemp, "SUBDATASET_%d_DESC", nCount + 1 );
                    pszString = SPrintArray( GDT_UInt32, aiDimSizes,
                                             iRank, "x" );
                    poDS->papszSubDatasets =
                        CSLSetNameValue( poDS->papszSubDatasets, szTemp,
                                         CPLSPrintf("[%s] %s %s (%s)", pszString,
                                             papszFields[j],
                                             papszGrids[i],
                                             poDS->GetDataTypeName(iNumType)) );
                    CPLFree( pszString );
                }

                CSLDestroy( papszFields );
                CPLFree( paiNumType );
                CPLFree( paiRank );
                CPLFree( pszFieldList );
                GDdetach( hGD );
            }

            CSLDestroy( papszGrids );
            GDclose( hHDF4 );
        }
        GDclose( hHDF4 );

        bIsHDF = ( nSubDatasets == 0 ); // Try to read as HDF
    }

    if( bIsHDF )
    {

/* -------------------------------------------------------------------- */
/*  Make a list of subdatasets from SDSs contained in input HDF file.	*/
/* -------------------------------------------------------------------- */
        int32   nDatasets;

        if ( SDfileinfo( poDS->hSD, &nDatasets, &nAttrs ) != 0 )
	    return NULL;

        for ( i = 0; i < nDatasets; i++ )
        {
            int32	iSDS;

            iSDS = SDselect( poDS->hSD, i );
            if ( SDgetinfo( iSDS, szName, &iRank, aiDimSizes, &iNumType, &nAttrs) != 0 )
                return NULL;
            
            if ( iRank == 1 )		// Skip 1D datsets
                    continue;

            // Do sort of known datasets. We will display only image bands
            if ( (poDS->iSubdatasetType == H4ST_SEAWIFS_L1A ) &&
                      !EQUALN( szName, "l1a_data", 8 ) )
                    continue;
            else
                pszName = szName;
            
            // Add datasets with multiple dimensions to the list of GDAL subdatasets
            nCount = CSLCount( poDS->papszSubDatasets ) / 2;
            sprintf( szTemp, "SUBDATASET_%d_NAME", nCount + 1 );
            // We will use SDS index as an identificator, because SDS names
            // are not unique. Filename also needed for further file opening
            poDS->papszSubDatasets = CSLSetNameValue(poDS->papszSubDatasets, szTemp, 
                  CPLSPrintf( "HDF4_SDS:%s:\"%s\":%ld", poDS->pszSubdatasetType,
                              poOpenInfo->pszFilename, (long)i) );
            sprintf( szTemp, "SUBDATASET_%d_DESC", nCount + 1 );
            pszString = SPrintArray( GDT_UInt32, aiDimSizes, iRank, "x" );
            poDS->papszSubDatasets = CSLSetNameValue(poDS->papszSubDatasets, szTemp,
                CPLSPrintf( "[%s] %s (%s)", pszString,
                            pszName, poDS->GetDataTypeName(iNumType)) );
            CPLFree( pszString );

            SDendaccess( iSDS );
        }

        SDend( poDS->hSD );
        poDS->hSD = 0;
    }

/* -------------------------------------------------------------------- */
/*      Build a list of raster images. Note, that HDF-EOS dataset may   */
/*      contain a raster image as well.                                 */
/* -------------------------------------------------------------------- */
    hHDF4 = Hopen(poOpenInfo->pszFilename, DFACC_READ, 0);
    poDS->hGR = GRstart( hHDF4 );

    if ( poDS->hGR != -1 )
    {
        if ( GRfileinfo( poDS->hGR, &poDS->nImages, &nAttrs ) == -1 )
            return NULL;
        
        for ( i = 0; i < poDS->nImages; i++ )
        {
            int32   iInterlaceMode; 
            int32   iGR = GRselect( poDS->hGR, i );

            // iRank in GR interface has another meaning. It represents number
            // of samples per pixel. aiDimSizes has only two dimensions.
            if ( GRgetiminfo( iGR, szName, &iRank, &iNumType, &iInterlaceMode,
                              aiDimSizes, &nAttrs ) != 0 )
                return NULL;
            nCount = CSLCount( poDS->papszSubDatasets ) / 2;
            sprintf( szTemp, "SUBDATASET_%d_NAME", nCount + 1 );
            poDS->papszSubDatasets = CSLSetNameValue(poDS->papszSubDatasets,
                szTemp,CPLSPrintf( "HDF4_GR:UNKNOWN:\"%s\":%ld",
                                   poOpenInfo->pszFilename, (long)i));
            sprintf( szTemp, "SUBDATASET_%d_DESC", nCount + 1 );
            pszString = SPrintArray( GDT_UInt32, aiDimSizes, 2, "x" );
            poDS->papszSubDatasets = CSLSetNameValue(poDS->papszSubDatasets,
                szTemp, CPLSPrintf( "[%sx%ld] %s (%s)", pszString, (long)iRank,
                                    szName, poDS->GetDataTypeName(iNumType)) );
            CPLFree( pszString );

            GRendaccess( iGR );
        }

        GRend( poDS->hGR );
        poDS->hGR = 0;
    }

    Hclose( hHDF4 );

    poDS->nRasterXSize = poDS->nRasterYSize = 512; // XXX: bogus values

    // Make sure we don't try to do any pam stuff with this dataset.
    poDS->nPamFlags |= GPF_NOSAVE;

/* -------------------------------------------------------------------- */
/*      If we have single subdataset only, open it immediately          */
/* -------------------------------------------------------------------- */
    if ( CSLCount( poDS->papszSubDatasets ) / 2 == 1 )
    {
        char *pszSDSName;
        pszSDSName = CPLStrdup( CSLFetchNameValue( poDS->papszSubDatasets,
                            "SUBDATASET_1_NAME" ));
        delete poDS;
        poDS = NULL;

        GDALDataset* poRetDS = (GDALDataset*) GDALOpen( pszSDSName, poOpenInfo->eAccess );
        CPLFree( pszSDSName );

        if (poRetDS)
        {
            poRetDS->SetDescription(poOpenInfo->pszFilename);
        }

        return poRetDS;
    }
    else
    {
/* -------------------------------------------------------------------- */
/*      Confirm the requested access is supported.                      */
/* -------------------------------------------------------------------- */
        if( poOpenInfo->eAccess == GA_Update )
        {
            delete poDS;
            CPLError( CE_Failure, CPLE_NotSupported, 
                      "The HDF4 driver does not support update access to existing"
                      " datasets.\n" );
            return NULL;
        }
    
    }

    return( poDS );
}
Пример #5
0
GDALDataset* SRTMHGTDataset::Open(GDALOpenInfo* poOpenInfo)
{
  if (!Identify(poOpenInfo))
      return nullptr;

  const char* fileName = CPLGetFilename(poOpenInfo->pszFilename);
  CPLString osLCFilename(CPLString(fileName).tolower());
  if( !STARTS_WITH(fileName, "/vsizip/") &&
      osLCFilename.endsWith(".hgt.zip") )
  {
      CPLString osFilename ("/vsizip/");
      osFilename += poOpenInfo->pszFilename;
      osFilename += "/";
      osFilename += CPLString(fileName).substr(0, 7);
      osFilename += ".hgt";
      GDALOpenInfo oOpenInfo(osFilename, poOpenInfo->eAccess);
      GDALDataset* poDS = Open(&oOpenInfo);
      if( poDS != nullptr )
      {
          // override description with the main one
          poDS->SetDescription(poOpenInfo->pszFilename);
      }
      return poDS;
  }

  if( !STARTS_WITH(fileName, "/vsizip/") &&
      osLCFilename.endsWith(".srtmswbd.raw.zip") )
  {
      CPLString osFilename("/vsizip/");
      osFilename += poOpenInfo->pszFilename;
      osFilename += "/";
      osFilename += CPLString(fileName).substr(0, 7);
      osFilename += ".raw";
      GDALOpenInfo oOpenInfo(osFilename, poOpenInfo->eAccess);
      GDALDataset* poDS = Open(&oOpenInfo);
      if( poDS != nullptr )
      {
          // override description with the main one
          poDS->SetDescription(poOpenInfo->pszFilename);
      }
      return poDS;
  }

  char latLonValueString[4];
  memset(latLonValueString, 0, 4);
  strncpy(latLonValueString, &fileName[1], 2);
  int southWestLat = atoi(latLonValueString);
  memset(latLonValueString, 0, 4);
  // cppcheck-suppress redundantCopy
  strncpy(latLonValueString, &fileName[4], 3);
  int southWestLon = atoi(latLonValueString);

  if(fileName[0] == 'N' || fileName[0] == 'n')
    /*southWestLat = southWestLat */;
  else if(fileName[0] == 'S' || fileName[0] == 's')
    southWestLat = southWestLat * -1;
  else
    return nullptr;

  if(fileName[3] == 'E' || fileName[3] == 'e')
    /*southWestLon = southWestLon */;
  else if(fileName[3] == 'W' || fileName[3] == 'w')
    southWestLon = southWestLon * -1;
  else
    return nullptr;

/* -------------------------------------------------------------------- */
/*      Create a corresponding GDALDataset.                             */
/* -------------------------------------------------------------------- */
  SRTMHGTDataset* poDS  = new SRTMHGTDataset();

  poDS->fpImage = poOpenInfo->fpL;
  poOpenInfo->fpL = nullptr;

  VSIStatBufL fileStat;
  if(VSIStatL(poOpenInfo->pszFilename, &fileStat) != 0)
  {
      delete poDS;
      return nullptr;
  }

  int numPixels_x, numPixels_y;

  GDALDataType eDT = GDT_Int16;
  switch (fileStat.st_size) {
  case 3601 * 3601:
    numPixels_x = numPixels_y = 3601;
    eDT = GDT_Byte;
    break;
  case 3601 * 3601 * 2:
    numPixels_x = numPixels_y = 3601;
    break;
  case 1801 * 3601 * 2:
    numPixels_x = 1801;
    numPixels_y = 3601;
    break;
  case 1201 * 1201 * 2:
    numPixels_x = numPixels_y = 1201;
    break;
  default:
    numPixels_x = numPixels_y = 0;
    break;
  }

  poDS->eAccess = poOpenInfo->eAccess;
#ifdef CPL_LSB
  if(poDS->eAccess == GA_Update && eDT == GDT_Int16)
  {
      poDS->panBuffer
          = reinterpret_cast<GInt16 *>( CPLMalloc(numPixels_x * sizeof(GInt16)) );
  }
#endif

/* -------------------------------------------------------------------- */
/*      Capture some information from the file that is of interest.     */
/* -------------------------------------------------------------------- */
  poDS->nRasterXSize = numPixels_x;
  poDS->nRasterYSize = numPixels_y;
  poDS->nBands = 1;

  poDS->adfGeoTransform[0] = southWestLon - 0.5 / (numPixels_x - 1);
  poDS->adfGeoTransform[1] = 1.0 / (numPixels_x-1);
  poDS->adfGeoTransform[2] = 0.0;
  poDS->adfGeoTransform[3] = southWestLat + 1 + 0.5 / (numPixels_y - 1);
  poDS->adfGeoTransform[4] = 0.0;
  poDS->adfGeoTransform[5] = -1.0 / (numPixels_y-1);

  poDS->SetMetadataItem( GDALMD_AREA_OR_POINT, GDALMD_AOP_POINT );

/* -------------------------------------------------------------------- */
/*      Create band information object.                                 */
/* -------------------------------------------------------------------- */
  SRTMHGTRasterBand* tmpBand = new SRTMHGTRasterBand(poDS, 1, eDT);
  poDS->SetBand(1, tmpBand);

/* -------------------------------------------------------------------- */
/*      Initialize any PAM information.                                 */
/* -------------------------------------------------------------------- */
  poDS->SetDescription(poOpenInfo->pszFilename);
  poDS->TryLoadXML();

/* -------------------------------------------------------------------- */
/*      Support overviews.                                              */
/* -------------------------------------------------------------------- */
  poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );

  return poDS;
}
Пример #6
0
GDALDataset* ECRGTOCDataset::Build(const char* pszTOCFilename,
                                   CPLXMLNode* psXML,
                                   CPLString osProduct,
                                   CPLString osDiscId,
                                   const char* pszOpenInfoFilename)
{
    CPLXMLNode* psTOC = CPLGetXMLNode(psXML, "=Table_of_Contents");
    if (psTOC == NULL)
    {
        CPLError(CE_Warning, CPLE_AppDefined,
                 "Cannot find Table_of_Contents element");
        return NULL;
    }

    double dfGlobalMinX = 0, dfGlobalMinY = 0, dfGlobalMaxX = 0, dfGlobalMaxY= 0;
    double dfGlobalPixelXSize = 0, dfGlobalPixelYSize = 0;
    int bGlobalExtentValid = FALSE;

    ECRGTOCDataset* poDS = new ECRGTOCDataset();
    int nSubDatasets = 0;

    int bLookForSubDataset = osProduct.size() != 0 && osDiscId.size() != 0;

    int nCountSubDataset = 0;

    poDS->SetDescription( pszOpenInfoFilename );
    poDS->papszFileList = poDS->GDALDataset::GetFileList();

    for(CPLXMLNode* psIter1 = psTOC->psChild;
                    psIter1 != NULL;
                    psIter1 = psIter1->psNext)
    {
        if (!(psIter1->eType == CXT_Element && psIter1->pszValue != NULL &&
              strcmp(psIter1->pszValue, "product") == 0))
            continue;

        const char* pszProductTitle =
            CPLGetXMLValue(psIter1, "product_title", NULL);
        if (pszProductTitle == NULL)
        {
            CPLError(CE_Warning, CPLE_AppDefined,
                        "Cannot find product_title attribute");
            continue;
        }

        if (bLookForSubDataset && strcmp(pszProductTitle, osProduct.c_str()) != 0)
            continue;

        for(CPLXMLNode* psIter2 = psIter1->psChild;
                        psIter2 != NULL;
                        psIter2 = psIter2->psNext)
        {
            if (!(psIter2->eType == CXT_Element && psIter2->pszValue != NULL &&
                  strcmp(psIter2->pszValue, "disc") == 0))
                continue;

            const char* pszDiscId = CPLGetXMLValue(psIter2, "id", NULL);
            if (pszDiscId == NULL)
            {
                CPLError(CE_Warning, CPLE_AppDefined,
                            "Cannot find id attribute");
                continue;
            }

            if (bLookForSubDataset && strcmp(pszDiscId, osDiscId.c_str()) != 0)
                continue;

            nCountSubDataset ++;

            CPLXMLNode* psFrameList = CPLGetXMLNode(psIter2, "frame_list");
            if (psFrameList == NULL)
            {
                CPLError(CE_Warning, CPLE_AppDefined,
                            "Cannot find frame_list element");
                continue;
            }

            int nValidFrames = 0;

            std::vector<FrameDesc> aosFrameDesc;

            int nSubDatasetScale = -1;

            for(CPLXMLNode* psIter3 = psFrameList->psChild;
                            psIter3 != NULL;
                            psIter3 = psIter3->psNext)
            {
                if (!(psIter3->eType == CXT_Element &&
                      psIter3->pszValue != NULL &&
                      strcmp(psIter3->pszValue, "scale") == 0))
                    continue;

                const char* pszSize = CPLGetXMLValue(psIter3, "size", NULL);
                if (pszSize == NULL)
                {
                    CPLError(CE_Warning, CPLE_AppDefined,
                                "Cannot find size attribute");
                    continue;
                }

                int nScale = GetScaleFromString(pszSize);
                if (nScale <= 0)
                {
                    CPLError(CE_Warning, CPLE_AppDefined,
                             "Invalid scale %s", pszSize);
                    continue;
                }

                if (nValidFrames == 0)
                    nSubDatasetScale = nScale;
                else
                    nSubDatasetScale = -1;

                for(CPLXMLNode* psIter4 = psIter3->psChild;
                                psIter4 != NULL;
                                psIter4 = psIter4->psNext)
                {
                    if (!(psIter4->eType == CXT_Element &&
                          psIter4->pszValue != NULL &&
                          strcmp(psIter4->pszValue, "frame") == 0))
                        continue;

                    const char* pszFrameName =
                        CPLGetXMLValue(psIter4, "name", NULL);
                    if (pszFrameName == NULL)
                    {
                        CPLError(CE_Warning, CPLE_AppDefined,
                                 "Cannot find name element");
                        continue;
                    }

                    if (strlen(pszFrameName) != 18)
                    {
                        CPLError(CE_Warning, CPLE_AppDefined,
                                 "Invalid value for name element : %s",
                                 pszFrameName);
                        continue;
                    }

                    const char* pszFramePath =
                        CPLGetXMLValue(psIter4, "frame_path", NULL);
                    if (pszFramePath == NULL)
                    {
                        CPLError(CE_Warning, CPLE_AppDefined,
                                 "Cannot find frame_path element");
                        continue;
                    }

                    const char* pszFrameZone =
                        CPLGetXMLValue(psIter4, "frame_zone", NULL);
                    if (pszFrameZone == NULL)
                    {
                        CPLError(CE_Warning, CPLE_AppDefined,
                                 "Cannot find frame_zone element");
                        continue;
                    }
                    if (strlen(pszFrameZone) != 1)
                    {
                        CPLError(CE_Warning, CPLE_AppDefined,
                                 "Invalid value for frame_zone element : %s",
                                 pszFrameZone);
                        continue;
                    }
                    char chZone = pszFrameZone[0];
                    int nZone = 0;
                    if (chZone >= '1' && chZone <= '9')
                        nZone = chZone - '0';
                    else if (chZone >= 'a' && chZone <= 'h')
                        nZone = -(chZone - 'a' + 1);
                    else if (chZone >= 'A' && chZone <= 'H')
                        nZone = -(chZone - 'A' + 1);
                    else if (chZone == 'j' || chZone == 'J')
                        nZone = -9;
                    else
                    {
                        CPLError(CE_Warning, CPLE_AppDefined,
                                 "Invalid value for frame_zone element : %s",
                                  pszFrameZone);
                        continue;
                    }
                    if (nZone == 9 || nZone == -9)
                    {
                        CPLError(CE_Warning, CPLE_AppDefined,
                                 "Polar zones unhandled by current implementation");
                        continue;
                    }

                    double dfMinX = 0, dfMaxX = 0,
                           dfMinY = 0, dfMaxY = 0,
                           dfPixelXSize = 0, dfPixelYSize = 0;
                    if (!GetExtent(pszFrameName, nScale, nZone,
                                   dfMinX, dfMaxX, dfMinY, dfMaxY,
                                   dfPixelXSize, dfPixelYSize))
                    {
                        continue;
                    }

                    nValidFrames ++;

                    const char* pszFullName = BuildFullName(pszTOCFilename,
                                                        pszFramePath,
                                                        pszFrameName);
                    poDS->papszFileList = CSLAddString(poDS->papszFileList, pszFullName);

                    if (!bGlobalExtentValid)
                    {
                        dfGlobalMinX = dfMinX;
                        dfGlobalMinY = dfMinY;
                        dfGlobalMaxX = dfMaxX;
                        dfGlobalMaxY = dfMaxY;
                        dfGlobalPixelXSize = dfPixelXSize;
                        dfGlobalPixelYSize = dfPixelYSize;
                        bGlobalExtentValid = TRUE;
                    }
                    else
                    {
                        if (dfMinX < dfGlobalMinX) dfGlobalMinX = dfMinX;
                        if (dfMinY < dfGlobalMinY) dfGlobalMinY = dfMinY;
                        if (dfMaxX > dfGlobalMaxX) dfGlobalMaxX = dfMaxX;
                        if (dfMaxY > dfGlobalMaxY) dfGlobalMaxY = dfMaxY;
                        if (dfPixelXSize < dfGlobalPixelXSize)
                            dfGlobalPixelXSize = dfPixelXSize;
                        if (dfPixelYSize < dfGlobalPixelYSize)
                            dfGlobalPixelYSize = dfPixelYSize;
                    }

                    if (bLookForSubDataset)
                    {
                        FrameDesc frameDesc;
                        frameDesc.pszName = pszFrameName;
                        frameDesc.pszPath = pszFramePath;
                        frameDesc.nScale = nScale;
                        frameDesc.nZone = nZone;
                        aosFrameDesc.push_back(frameDesc);
                    }
                }
            }

            if (bLookForSubDataset)
            {
                delete poDS;
                if (nValidFrames == 0)
                    return NULL;
                return ECRGTOCSubDataset::Build(pszProductTitle,
                                                pszDiscId,
                                                nSubDatasetScale,
                                                nCountSubDataset,
                                                pszTOCFilename,
                                                aosFrameDesc,
                                                dfGlobalMinX,
                                                dfGlobalMinY,
                                                dfGlobalMaxX,
                                                dfGlobalMaxY,
                                                dfGlobalPixelXSize,
                                                dfGlobalPixelYSize);
            }

            if (nValidFrames)
            {
                poDS->AddSubDataset(pszOpenInfoFilename,
                                    pszProductTitle, pszDiscId);
                nSubDatasets ++;
            }
        }
    }

    if (!bGlobalExtentValid)
    {
        delete poDS;
        return NULL;
    }

    if (nSubDatasets == 1)
    {
        const char* pszSubDatasetName = CSLFetchNameValue(
            poDS->GetMetadata("SUBDATASETS"), "SUBDATASET_1_NAME");
        GDALOpenInfo oOpenInfo(pszSubDatasetName, GA_ReadOnly);
        delete poDS;
        GDALDataset* poRetDS = Open(&oOpenInfo);
        if (poRetDS)
            poRetDS->SetDescription(pszOpenInfoFilename);
        return poRetDS;
    }

    poDS->adfGeoTransform[0] = dfGlobalMinX;
    poDS->adfGeoTransform[1] = dfGlobalPixelXSize;
    poDS->adfGeoTransform[2] = 0.0;
    poDS->adfGeoTransform[3] = dfGlobalMaxY;
    poDS->adfGeoTransform[4] = 0.0;
    poDS->adfGeoTransform[5] = - dfGlobalPixelYSize;

    poDS->nRasterXSize = (int)(0.5 + (dfGlobalMaxX - dfGlobalMinX) / dfGlobalPixelXSize);
    poDS->nRasterYSize = (int)(0.5 + (dfGlobalMaxY - dfGlobalMinY) / dfGlobalPixelYSize);

/* -------------------------------------------------------------------- */
/*      Initialize any PAM information.                                 */
/* -------------------------------------------------------------------- */
    poDS->TryLoadXML();

    return poDS;
}
Пример #7
0
GDALDataset *HDF4Dataset::Open( GDALOpenInfo * poOpenInfo )

{
    if( !Identify( poOpenInfo ) )
        return NULL;

    CPLMutexHolderD(&hHDF4Mutex);

/* -------------------------------------------------------------------- */
/*      Try opening the dataset.                                        */
/* -------------------------------------------------------------------- */

    // Attempt to increase maximum number of opened HDF files.
#ifdef HDF4_HAS_MAXOPENFILES
    intn nCurrMax = 0;
    intn nSysLimit = 0;

    if ( SDget_maxopenfiles(&nCurrMax, &nSysLimit) >= 0
         && nCurrMax < nSysLimit )
    {
        /*intn res = */SDreset_maxopenfiles( nSysLimit );
    }
#endif /* HDF4_HAS_MAXOPENFILES */

    int32 hHDF4 = Hopen(poOpenInfo->pszFilename, DFACC_READ, 0);

    if( hHDF4 <= 0 )
        return NULL;

    Hclose( hHDF4 );

/* -------------------------------------------------------------------- */
/*      Create a corresponding GDALDataset.                             */
/* -------------------------------------------------------------------- */
    // Release mutex otherwise we will deadlock with GDALDataset own mutex.
    CPLReleaseMutex(hHDF4Mutex);
    HDF4Dataset *poDS = new HDF4Dataset();
    CPLAcquireMutex(hHDF4Mutex, 1000.0);

    if( poOpenInfo->fpL != NULL )
    {
        VSIFCloseL(poOpenInfo->fpL);
        poOpenInfo->fpL = NULL;
    }

/* -------------------------------------------------------------------- */
/*          Open HDF SDS Interface.                                     */
/* -------------------------------------------------------------------- */
    poDS->hSD = SDstart( poOpenInfo->pszFilename, DFACC_READ );

    if ( poDS->hSD == -1 )
    {
      // Release mutex otherwise we will deadlock with GDALDataset own mutex.
        CPLReleaseMutex(hHDF4Mutex);
        delete poDS;
        CPLAcquireMutex(hHDF4Mutex, 1000.0);
        CPLError( CE_Failure, CPLE_OpenFailed,
                  "Failed to open HDF4 file \"%s\" for SDS reading.",
                  poOpenInfo->pszFilename );
        return NULL;
    }

/* -------------------------------------------------------------------- */
/*              Now read Global Attributes.                             */
/* -------------------------------------------------------------------- */
    if ( poDS->ReadGlobalAttributes( poDS->hSD ) != CE_None )
    {
        // Release mutex otherwise we will deadlock with GDALDataset own mutex.
        CPLReleaseMutex(hHDF4Mutex);
        delete poDS;
        CPLAcquireMutex(hHDF4Mutex, 1000.0);
        CPLError( CE_Failure, CPLE_OpenFailed,
                  "Failed to read global attributes from HDF4 file \"%s\".",
                  poOpenInfo->pszFilename );
        return NULL;
    }

    poDS->SetMetadata( poDS->papszGlobalMetadata, "" );

/* -------------------------------------------------------------------- */
/*              Determine type of file we read.                         */
/* -------------------------------------------------------------------- */
    const char *pszValue = CSLFetchNameValue(poDS->papszGlobalMetadata,
                                             "Signature");

    if ( pszValue != NULL && EQUAL( pszValue, pszGDALSignature ) )
    {
        poDS->iSubdatasetType = H4ST_GDAL;
        poDS->pszSubdatasetType = "GDAL_HDF4";
    }

    else if ( (pszValue = CSLFetchNameValue(poDS->papszGlobalMetadata,
                                            "Title")) != NULL
         && EQUAL( pszValue, "SeaWiFS Level-1A Data" ) )
    {
        poDS->iSubdatasetType = H4ST_SEAWIFS_L1A;
        poDS->pszSubdatasetType = "SEAWIFS_L1A";
    }

    else if ( (pszValue = CSLFetchNameValue(poDS->papszGlobalMetadata,
                                            "Title")) != NULL
        && EQUAL( pszValue, "SeaWiFS Level-2 Data" ) )
    {
        poDS->iSubdatasetType = H4ST_SEAWIFS_L2;
        poDS->pszSubdatasetType = "SEAWIFS_L2";
    }

    else if ( (pszValue = CSLFetchNameValue(poDS->papszGlobalMetadata,
                                            "Title")) != NULL
        && EQUAL( pszValue, "SeaWiFS Level-3 Standard Mapped Image" ) )
    {
        poDS->iSubdatasetType = H4ST_SEAWIFS_L3;
        poDS->pszSubdatasetType = "SEAWIFS_L3";
    }

    else if ( (pszValue = CSLFetchNameValue(poDS->papszGlobalMetadata,
                                            "L1 File Generated By")) != NULL
        && STARTS_WITH_CI(pszValue, "HYP version ") )
    {
        poDS->iSubdatasetType = H4ST_HYPERION_L1;
        poDS->pszSubdatasetType = "HYPERION_L1";
    }

    else
    {
        poDS->iSubdatasetType = H4ST_UNKNOWN;
        poDS->pszSubdatasetType = "UNKNOWN";
    }

/* -------------------------------------------------------------------- */
/*  If we have HDF-EOS dataset, process it here.                        */
/* -------------------------------------------------------------------- */
    int32 aiDimSizes[H4_MAX_VAR_DIMS] = {};  // TODO: Get this off of the stack.
    int32 iRank = 0;
    int32 iNumType = 0;
    int32 nAttrs = 0;
    bool bIsHDF = true;

    // Sometimes "HDFEOSVersion" attribute is not defined and we will
    // determine HDF-EOS datasets using other records
    // (see ReadGlobalAttributes() method).
    if ( poDS->bIsHDFEOS
         || CSLFetchNameValue(poDS->papszGlobalMetadata, "HDFEOSVersion") )
    {
/* -------------------------------------------------------------------- */
/*  Process swath layers.                                               */
/* -------------------------------------------------------------------- */
        hHDF4 = SWopen( poOpenInfo->pszFilename, DFACC_READ );
        if( hHDF4 < 0)
        {
            // Release mutex otherwise we will deadlock with GDALDataset own
            // mutex.
            CPLReleaseMutex(hHDF4Mutex);
            delete poDS;
            CPLAcquireMutex(hHDF4Mutex, 1000.0);
            CPLError( CE_Failure, CPLE_OpenFailed,
                      "Failed to open HDF-EOS file \"%s\" for swath reading.",
                      poOpenInfo->pszFilename );
            return NULL;
        }
        int32 nStrBufSize = 0;
        int32 nSubDatasets =
            SWinqswath(poOpenInfo->pszFilename, NULL, &nStrBufSize);

#ifdef DEBUG
        CPLDebug( "HDF4", "Number of HDF-EOS swaths: %d",
                  static_cast<int>( nSubDatasets ) );
#endif

        if ( nSubDatasets > 0 && nStrBufSize > 0 )
        {
            char *pszSwathList =
                static_cast<char *>( CPLMalloc( nStrBufSize + 1 ) );
            SWinqswath( poOpenInfo->pszFilename, pszSwathList, &nStrBufSize );
            pszSwathList[nStrBufSize] = '\0';

#ifdef DEBUG
            CPLDebug( "HDF4", "List of HDF-EOS swaths: %s", pszSwathList );
#endif

            char **papszSwaths =
                CSLTokenizeString2( pszSwathList, ",", CSLT_HONOURSTRINGS );
            CPLFree( pszSwathList );

            if ( nSubDatasets != CSLCount(papszSwaths) )
            {
                CSLDestroy( papszSwaths );
                // Release mutex otherwise we will deadlock with GDALDataset own
                // mutex.
                CPLReleaseMutex(hHDF4Mutex);
                delete poDS;
                CPLAcquireMutex(hHDF4Mutex, 1000.0);
                CPLDebug( "HDF4", "Cannot parse list of HDF-EOS grids." );
                return NULL;
            }

            for( int32 i = 0; i < nSubDatasets; i++)
            {
                const int32 hSW = SWattach( hHDF4, papszSwaths[i] );

                const int32 nFields
                    = SWnentries( hSW, HDFE_NENTDFLD, &nStrBufSize );
                char *pszFieldList = static_cast<char *>(
                    CPLMalloc( nStrBufSize + 1 ) );
                int32 *paiRank = static_cast<int32 *>(
                    CPLMalloc( nFields * sizeof(int32) ) );
                int32 *paiNumType = static_cast<int32 *>(
                    CPLMalloc( nFields * sizeof(int32) ) );

                SWinqdatafields( hSW, pszFieldList, paiRank, paiNumType );

#ifdef DEBUG
                {
                    char * const pszTmp =
                        SPrintArray( GDT_UInt32, paiRank, nFields, "," );

                    CPLDebug( "HDF4", "Number of data fields in swath %d: %d",
                              static_cast<int>( i ),
                              static_cast<int>( nFields ) );
                    CPLDebug( "HDF4", "List of data fields in swath %d: %s",
                              static_cast<int>( i ), pszFieldList );
                    CPLDebug( "HDF4", "Data fields ranks: %s", pszTmp );

                    CPLFree( pszTmp );
                }
#endif

                char **papszFields = CSLTokenizeString2( pszFieldList, ",",
                                                         CSLT_HONOURSTRINGS );

                char szTemp[256] = {'\0'};  // TODO: Get this off the stack.
                for( int32 j = 0; j < nFields; j++ )
                {
                    SWfieldinfo( hSW, papszFields[j], &iRank, aiDimSizes,
                                 &iNumType, NULL );

                    if ( iRank < 2 )
                        continue;

                    // Add field to the list of GDAL subdatasets.
                    const int nCount = CSLCount( poDS->papszSubDatasets ) / 2;
                    snprintf( szTemp, sizeof(szTemp),
                              "SUBDATASET_%d_NAME", nCount + 1 );
                    // We will use the field index as an identificator.
                    poDS->papszSubDatasets =
                        CSLSetNameValue( poDS->papszSubDatasets, szTemp,
                                CPLSPrintf("HDF4_EOS:EOS_SWATH:\"%s\":%s:%s",
                                           poOpenInfo->pszFilename,
                                           papszSwaths[i], papszFields[j]) );

                    snprintf( szTemp, sizeof(szTemp),
                              "SUBDATASET_%d_DESC", nCount + 1 );
                    char *pszString = SPrintArray( GDT_UInt32, aiDimSizes,
                                                   iRank, "x" );
                    poDS->papszSubDatasets =
                        CSLSetNameValue( poDS->papszSubDatasets, szTemp,
                                         CPLSPrintf( "[%s] %s %s (%s)",
                                                     pszString,
                                         papszFields[j],
                                         papszSwaths[i],
                                         poDS->GetDataTypeName(iNumType) ) );
                    CPLFree( pszString );
                    szTemp[0] = '\0';
                }

                CSLDestroy( papszFields );
                CPLFree( paiNumType );
                CPLFree( paiRank );
                CPLFree( pszFieldList );
                SWdetach( hSW );
            }

            CSLDestroy( papszSwaths );
        }
        SWclose( hHDF4 );

/* -------------------------------------------------------------------- */
/*  Process grid layers.                                                */
/* -------------------------------------------------------------------- */
        hHDF4 = GDopen( poOpenInfo->pszFilename, DFACC_READ );
        nSubDatasets = GDinqgrid( poOpenInfo->pszFilename, NULL, &nStrBufSize );

#ifdef DEBUG
        CPLDebug( "HDF4", "Number of HDF-EOS grids: %d",
                  static_cast<int>( nSubDatasets ) );
#endif

        if ( nSubDatasets > 0 && nStrBufSize > 0 )
        {
            char *pszGridList
                = static_cast<char *>( CPLMalloc( nStrBufSize + 1 ) );
            GDinqgrid( poOpenInfo->pszFilename, pszGridList, &nStrBufSize );

#ifdef DEBUG
            CPLDebug( "HDF4", "List of HDF-EOS grids: %s", pszGridList );
#endif

            char **papszGrids =
                CSLTokenizeString2( pszGridList, ",", CSLT_HONOURSTRINGS );
            CPLFree( pszGridList );

            if ( nSubDatasets != CSLCount(papszGrids) )
            {
                CSLDestroy( papszGrids );
                GDclose( hHDF4 );
                // Release mutex otherwise we will deadlock with GDALDataset own
                // mutex.
                CPLReleaseMutex(hHDF4Mutex);
                delete poDS;
                CPLAcquireMutex(hHDF4Mutex, 1000.0);
                CPLDebug( "HDF4", "Cannot parse list of HDF-EOS grids." );
                return NULL;
            }

            for( int32 i = 0; i < nSubDatasets; i++)
            {
                const int32 hGD = GDattach( hHDF4, papszGrids[i] );

                const int32 nFields
                    = GDnentries( hGD, HDFE_NENTDFLD, &nStrBufSize );
                char *pszFieldList = static_cast<char *>(
                    CPLMalloc( nStrBufSize + 1 ) );
                int32 *paiRank = static_cast<int32 *>(
                    CPLMalloc( nFields * sizeof(int32) ) );
                int32 *paiNumType = static_cast<int32 *>(
                    CPLMalloc( nFields * sizeof(int32) ) );

                GDinqfields( hGD, pszFieldList, paiRank, paiNumType );

#ifdef DEBUG
                {
                    char* pszTmp =
                            SPrintArray( GDT_UInt32, paiRank, nFields, "," );
                    CPLDebug( "HDF4", "Number of fields in grid %d: %d",
                              static_cast<int>( i ),
                              static_cast<int>( nFields ) );
                    CPLDebug( "HDF4", "List of fields in grid %d: %s",
                              static_cast<int>( i ), pszFieldList );
                    CPLDebug( "HDF4", "Fields ranks: %s", pszTmp );
                    CPLFree( pszTmp );
                }
#endif

                char **papszFields = CSLTokenizeString2( pszFieldList, ",",
                                                  CSLT_HONOURSTRINGS );

                char szTemp[256];
                for( int32 j = 0; j < nFields; j++ )
                {
                    GDfieldinfo( hGD, papszFields[j], &iRank, aiDimSizes,
                                 &iNumType, NULL );

                    if ( iRank < 2 )
                        continue;

                    // Add field to the list of GDAL subdatasets
                    const int nCount = CSLCount( poDS->papszSubDatasets ) / 2;
                    snprintf( szTemp, sizeof(szTemp),
                              "SUBDATASET_%d_NAME", nCount + 1 );
                    // We will use the field index as an identificator.
                    poDS->papszSubDatasets =
                        CSLSetNameValue(poDS->papszSubDatasets, szTemp,
                                CPLSPrintf( "HDF4_EOS:EOS_GRID:\"%s\":%s:%s",
                                            poOpenInfo->pszFilename,
                                            papszGrids[i], papszFields[j]));

                    snprintf( szTemp, sizeof(szTemp),
                              "SUBDATASET_%d_DESC", nCount + 1 );
                    char *pszString = SPrintArray( GDT_UInt32, aiDimSizes,
                                                   iRank, "x" );
                    poDS->papszSubDatasets =
                        CSLSetNameValue( poDS->papszSubDatasets, szTemp,
                                         CPLSPrintf("[%s] %s %s (%s)",
                                                    pszString,
                                             papszFields[j],
                                             papszGrids[i],
                                             poDS->GetDataTypeName(iNumType)) );
                    CPLFree( pszString );
                }

                CSLDestroy( papszFields );
                CPLFree( paiNumType );
                CPLFree( paiRank );
                CPLFree( pszFieldList );
                GDdetach( hGD );
            }

            CSLDestroy( papszGrids );
        }
        GDclose( hHDF4 );

        bIsHDF = ( nSubDatasets == 0 ); // Try to read as HDF
    }

    char szName[VSNAMELENMAX + 1];

    if( bIsHDF )
    {

/* -------------------------------------------------------------------- */
/*  Make a list of subdatasets from SDSs contained in input HDF file.   */
/* -------------------------------------------------------------------- */
        int32 nDatasets = 0;

        if ( SDfileinfo( poDS->hSD, &nDatasets, &nAttrs ) != 0 )
            return NULL;

        char szTemp[256] = {'\0'};  // TODO: Get this off the stack.
        const char *pszName = NULL;

        for( int32 i = 0; i < nDatasets; i++ )
        {
            const int32 iSDS = SDselect( poDS->hSD, i );
            if ( SDgetinfo( iSDS, szName, &iRank, aiDimSizes, &iNumType,
                            &nAttrs) != 0 )
                return NULL;

            if ( iRank == 1 )  // Skip 1D datsets
                    continue;

            // Do sort of known datasets. We will display only image bands
            if ( (poDS->iSubdatasetType == H4ST_SEAWIFS_L1A ) &&
                      !STARTS_WITH_CI(szName, "l1a_data") )
                    continue;
            else
                pszName = szName;

            // Add datasets with multiple dimensions to the list of GDAL
            // subdatasets.
            const int nCount = CSLCount( poDS->papszSubDatasets ) / 2;
            snprintf( szTemp, sizeof(szTemp),
                      "SUBDATASET_%d_NAME", nCount + 1 );
            // We will use SDS index as an identificator, because SDS names
            // are not unique. Filename also needed for further file opening
            poDS->papszSubDatasets = CSLSetNameValue(
                  poDS->papszSubDatasets,
                  szTemp,
                  CPLSPrintf( "HDF4_SDS:%s:\"%s\":%ld", poDS->pszSubdatasetType,
                              poOpenInfo->pszFilename,
                              static_cast<long>( i ) ) );
            snprintf( szTemp, sizeof(szTemp),
                      "SUBDATASET_%d_DESC", nCount + 1 );
            char *pszString = SPrintArray( GDT_UInt32, aiDimSizes, iRank, "x" );
            poDS->papszSubDatasets = CSLSetNameValue(
                poDS->papszSubDatasets,
                szTemp,
                CPLSPrintf( "[%s] %s (%s)", pszString,
                            pszName, poDS->GetDataTypeName(iNumType)) );
            CPLFree( pszString );

            SDendaccess( iSDS );
            szTemp[0] = '\0';
        }

        SDend( poDS->hSD );
        poDS->hSD = 0;
    }

/* -------------------------------------------------------------------- */
/*      Build a list of raster images. Note, that HDF-EOS dataset may   */
/*      contain a raster image as well.                                 */
/* -------------------------------------------------------------------- */

    hHDF4 = Hopen(poOpenInfo->pszFilename, DFACC_READ, 0);
    poDS->hGR = GRstart( hHDF4 );

    if ( poDS->hGR != -1 )
    {
        if ( GRfileinfo( poDS->hGR, &poDS->nImages, &nAttrs ) == -1 )
        {
            // Release mutex otherwise we will deadlock with GDALDataset own
            // mutex.
            CPLReleaseMutex(hHDF4Mutex);
            GRend( poDS->hGR );
            poDS->hGR = 0;
            Hclose( hHDF4 );
            delete poDS;
            CPLAcquireMutex(hHDF4Mutex, 1000.0);
            return NULL;
        }

        char szTemp[256] = {'\0'};  // TODO: Get this off the stack.
        for( int32 i = 0; i < poDS->nImages; i++ )
        {
            const int32 iGR = GRselect( poDS->hGR, i );

            // iRank in GR interface has another meaning. It represents number
            // of samples per pixel. aiDimSizes has only two dimensions.
            int32 iInterlaceMode = 0;
            if ( GRgetiminfo( iGR, szName, &iRank, &iNumType, &iInterlaceMode,
                              aiDimSizes, &nAttrs ) != 0 )
            {
                // Release mutex otherwise we will deadlock with GDALDataset
                // own mutex.
                CPLReleaseMutex(hHDF4Mutex);
                GRend( poDS->hGR );
                poDS->hGR = 0;
                Hclose( hHDF4 );
                delete poDS;
                CPLAcquireMutex(hHDF4Mutex, 1000.0);
                return NULL;
            }
            const int nCount = CSLCount( poDS->papszSubDatasets ) / 2;
            snprintf( szTemp, sizeof(szTemp),
                      "SUBDATASET_%d_NAME", nCount + 1 );
            poDS->papszSubDatasets = CSLSetNameValue(poDS->papszSubDatasets,
                szTemp,CPLSPrintf( "HDF4_GR:UNKNOWN:\"%s\":%ld",
                                   poOpenInfo->pszFilename,
                                   static_cast<long>( i ) ) );
            snprintf( szTemp, sizeof(szTemp),
                      "SUBDATASET_%d_DESC", nCount + 1 );
            char *pszString = SPrintArray( GDT_UInt32, aiDimSizes, 2, "x" );
            poDS->papszSubDatasets = CSLSetNameValue(poDS->papszSubDatasets,
                szTemp, CPLSPrintf( "[%sx%ld] %s (%s)", pszString,
                                    static_cast<long>( iRank ),
                                    szName, poDS->GetDataTypeName(iNumType)) );
            CPLFree( pszString );

            GRendaccess( iGR );
            szTemp[0] = '\0';
        }

        GRend( poDS->hGR );
        poDS->hGR = 0;
    }

    Hclose( hHDF4 );

    poDS->nRasterXSize = poDS->nRasterYSize = 512; // XXX: bogus values

    // Make sure we don't try to do any pam stuff with this dataset.
    poDS->nPamFlags |= GPF_NOSAVE;

/* -------------------------------------------------------------------- */
/*      If we have single subdataset only, open it immediately          */
/* -------------------------------------------------------------------- */
    if ( CSLCount( poDS->papszSubDatasets ) / 2 == 1 )
    {
        char *pszSDSName = CPLStrdup( CSLFetchNameValue( poDS->papszSubDatasets,
                                                         "SUBDATASET_1_NAME" ));
        // Release mutex otherwise we will deadlock with GDALDataset own mutex.
        CPLReleaseMutex(hHDF4Mutex);
        delete poDS;
        poDS = NULL;

        GDALDataset* poRetDS = reinterpret_cast<GDALDataset*>(
            GDALOpen( pszSDSName, poOpenInfo->eAccess ) );
        CPLFree( pszSDSName );

        CPLAcquireMutex(hHDF4Mutex, 1000.0);

        if (poRetDS)
        {
            poRetDS->SetDescription(poOpenInfo->pszFilename);
        }

        return poRetDS;
    }
    else
    {
/* -------------------------------------------------------------------- */
/*      Confirm the requested access is supported.                      */
/* -------------------------------------------------------------------- */
        if( poOpenInfo->eAccess == GA_Update )
        {
            // Release mutex otherwise we will deadlock with GDALDataset own
            // mutex.
            CPLReleaseMutex(hHDF4Mutex);
            delete poDS;
            CPLAcquireMutex(hHDF4Mutex, 1000.0);

            CPLError( CE_Failure, CPLE_NotSupported,
                      "The HDF4 driver does not support update access to "
                      "existing datasets." );
            return NULL;
        }

    }

    return poDS;
}
Пример #8
0
GDALDataset* OGRPLScenesDataset::OpenRasterScene(GDALOpenInfo* poOpenInfo,
                                                 CPLString osScene,
                                                 char** papszOptions)
{
    if( !(poOpenInfo->nOpenFlags & GDAL_OF_RASTER) )
    {
        return NULL;
    }

    for( char** papszIter = papszOptions; papszIter && *papszIter; papszIter ++ )
    {
        char* pszKey;
        const char* pszValue = CPLParseNameValue(*papszIter, &pszKey);
        if( pszValue != NULL )
        {
            if( !EQUAL(pszKey, "api_key") &&
                !EQUAL(pszKey, "scene") &&
                !EQUAL(pszKey, "product_type") )
            {
                CPLError(CE_Failure, CPLE_NotSupported, "Unsupported option %s", pszKey);
                CPLFree(pszKey);
                return NULL;
            }
            CPLFree(pszKey);
        }
    }

    const char* pszProductType = CSLFetchNameValueDef(papszOptions, "product_type",
                CSLFetchNameValueDef(poOpenInfo->papszOpenOptions, "PRODUCT_TYPE", "visual"));

    CPLString osRasterURL;
    osRasterURL = osBaseURL;
    osRasterURL += "ortho/";
    osRasterURL += osScene;
    json_object* poObj = RunRequest( osRasterURL );
    if( poObj == NULL )
        return NULL;
    json_object* poProperties = json_object_object_get(poObj, "properties");
    if( poProperties == NULL || json_object_get_type(poProperties) != json_type_object )
    {
        CPLError(CE_Failure, CPLE_AppDefined, "Cannot find properties object");
        json_object_put(poObj);
        return NULL;
    }

    const char* pszLink = NULL;
    if( EQUAL(pszProductType, "thumb") )
    {
        json_object* poLinks = json_object_object_get(poProperties, "links");
        if( poLinks != NULL && json_object_get_type(poLinks) == json_type_object )
        {
            json_object* poThumbnail = json_object_object_get(poLinks, "thumbnail");
            if( poThumbnail && json_object_get_type(poThumbnail) == json_type_string )
                pszLink = json_object_get_string(poThumbnail);
        }
    }
    else
    {
        json_object* poData = json_object_object_get(poProperties, "data");
        if( poData != NULL && json_object_get_type(poData) == json_type_object )
        {
            json_object* poProducts = json_object_object_get(poData, "products");
            if( poProducts != NULL && json_object_get_type(poProducts) == json_type_object )
            {
                json_object* poProduct = json_object_object_get(poProducts, pszProductType);
                if( poProduct != NULL && json_object_get_type(poProduct) == json_type_object )
                {
                    json_object* poFull = json_object_object_get(poProduct, "full");
                    if( poFull && json_object_get_type(poFull) == json_type_string )
                        pszLink = json_object_get_string(poFull);
                }
            }
        }
    }
    osRasterURL = pszLink ? pszLink : "";
    json_object_put(poObj);
    if( osRasterURL.size() == 0 )
    {
        CPLError(CE_Failure, CPLE_AppDefined, "Cannot find link to scene %s",
                 osScene.c_str());
        return NULL;
    }
    
    if( strncmp(osRasterURL, "http://", strlen("http://")) == 0 )
    {
        osRasterURL = "http://" + osAPIKey + ":@" + osRasterURL.substr(strlen("http://"));
    }
    else if( strncmp(osRasterURL, "https://", strlen("https://")) == 0 )
    {
        osRasterURL = "https://" + osAPIKey + ":@" + osRasterURL.substr(strlen("https://"));
    }

    CPLString osOldHead(CPLGetConfigOption("CPL_VSIL_CURL_USE_HEAD", ""));
    CPLString osOldExt(CPLGetConfigOption("CPL_VSIL_CURL_ALLOWED_EXTENSIONS", ""));

    int bUseVSICURL = CSLFetchBoolean(poOpenInfo->papszOpenOptions, "RANDOM_ACCESS", TRUE);
    if( bUseVSICURL && !(strncmp(osBaseURL, "/vsimem/", strlen("/vsimem/")) == 0) )
    {
        CPLSetThreadLocalConfigOption("CPL_VSIL_CURL_USE_HEAD", "NO");
        CPLSetThreadLocalConfigOption("CPL_VSIL_CURL_ALLOWED_EXTENSIONS", "{noext}");

        VSIStatBufL sStat;
        if( VSIStatL(("/vsicurl/" + osRasterURL).c_str(), &sStat) == 0 &&
            sStat.st_size > 0 )
        {
            osRasterURL = "/vsicurl/" + osRasterURL;
        }
        else
        {
            CPLDebug("PLSCENES", "Cannot use random access for that file");
        }
    }

    GDALDataset* poOutDS = (GDALDataset*) GDALOpen(osRasterURL, GA_ReadOnly);
    if( poOutDS )
    {
        poOutDS->SetDescription(poOpenInfo->pszFilename);
        poOutDS->GetFileList(); /* so as to probe all auxiliary files before reseting the allowed extensions */

        if( !EQUAL(pszProductType, "thumb") )
        {
            OGRPLScenesLayer* poLayer = new OGRPLScenesLayer(this, "ortho",
                                            (osBaseURL + "ortho/").c_str());
            papoLayers = (OGRPLScenesLayer**) CPLRealloc(papoLayers,
                                        sizeof(OGRPLScenesLayer*) * (nLayers + 1));
            papoLayers[nLayers ++] = poLayer;

            /* Attach scene matadata */
            poLayer->SetAttributeFilter(CPLSPrintf("id = '%s'", osScene.c_str()));
            OGRFeature* poFeat = poLayer->GetNextFeature();
            if( poFeat )
            {
                for(int i=0;i<poFeat->GetFieldCount();i++)
                {
                    if( poFeat->IsFieldSet(i) )
                    {
                        const char* pszKey = poFeat->GetFieldDefnRef(i)->GetNameRef();
                        const char* pszVal = poFeat->GetFieldAsString(i);
                        if( strstr(pszKey, "file_size") == NULL &&
                            strstr(pszVal, "https://") == NULL )
                        {
                            poOutDS->SetMetadataItem(pszKey, pszVal);
                        }
                    }
                }
            }
            delete poFeat;
        }
    }
    
    if( bUseVSICURL )
    {
        CPLSetThreadLocalConfigOption("CPL_VSIL_CURL_USE_HEAD",
                                    osOldHead.size() ? osOldHead.c_str(): NULL);
        CPLSetThreadLocalConfigOption("CPL_VSIL_CURL_ALLOWED_EXTENSIONS",
                                    osOldExt.size() ? osOldExt.c_str(): NULL);
    }

    return poOutDS;
}