示例#1
0
int OGRSelafinDataSource::OpenTable(const char * pszFilename) {
#ifdef DEBUG_VERBOSE
    CPLDebug("Selafin", "OpenTable(%s,%i)",
             pszFilename, static_cast<int>(bUpdate));
#endif
    // Open the file
    VSILFILE *fp = nullptr;
    if( bUpdate )
    {
        fp = VSIFOpenExL( pszFilename, "rb+", true );
    }
    else
    {
        fp = VSIFOpenExL( pszFilename, "rb", true );
    }

    if( fp == nullptr ) {
        CPLError( CE_Warning, CPLE_OpenFailed, "Failed to open %s.", VSIGetLastErrorMsg() );
        return FALSE;
    }
    if( !bUpdate && strstr(pszFilename, "/vsigzip/") == nullptr && strstr(pszFilename, "/vsizip/") == nullptr ) fp = (VSILFILE*) VSICreateBufferedReaderHandle((VSIVirtualHandle*)fp);

    // Quickly check if the file is in Selafin format, before actually starting to read to make it faster
    char szBuf[9];
    VSIFReadL(szBuf,1,4,fp);
    if (szBuf[0]!=0 || szBuf[1]!=0 || szBuf[2]!=0 || szBuf[3]!=0x50) {
        VSIFCloseL(fp);
        return FALSE;
    }
    VSIFSeekL(fp,84,SEEK_SET);
    VSIFReadL(szBuf,1,8,fp);
    if (szBuf[0]!=0 || szBuf[1]!=0 || szBuf[2]!=0 || szBuf[3]!=0x50 || szBuf[4]!=0 || szBuf[5]!=0 || szBuf[6]!=0 || szBuf[7]!=8) {
        VSIFCloseL(fp);
        return FALSE;
    }
    /* VSIFSeekL(fp,76,SEEK_SET);
    VSIFReadL(szBuf,1,8,fp);
    if (STRNCASECMP(szBuf,"Seraphin",8)!=0 && STRNCASECMP(szBuf,"Serafin",7)!=0) {
        VSIFCloseL(fp);
        return FALSE;
    } */

    // Get layer base name
    CPLString osBaseLayerName = CPLGetBasename(pszFilename);
    CPLString osExt = CPLGetExtension(pszFilename);
    if( STARTS_WITH(pszFilename, "/vsigzip/") && EQUAL(osExt, "gz") ) {
        size_t nPos=std::string::npos;
        if (strlen(pszFilename)>3) nPos=osExt.find_last_of('.',strlen(pszFilename)-4);
        if (nPos!=std::string::npos) {
            osExt=osExt.substr(nPos+1,strlen(pszFilename)-4-nPos);
            osBaseLayerName=osBaseLayerName.substr(0,nPos);
        } else {
            osExt="";
        }
    }

    // Read header of file to get common information for all layers
    // poHeader now owns fp
    poHeader=Selafin::read_header(fp,pszFilename);
    if (poHeader==nullptr) {
        CPLError( CE_Failure, CPLE_OpenFailed, "Failed to open %s, wrong format.\n", pszFilename);
        return FALSE;
    }
    if (poHeader->nEpsg!=0) {
        poSpatialRef=new OGRSpatialReference();
        poSpatialRef->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
        if (poSpatialRef->importFromEPSG(poHeader->nEpsg)!=OGRERR_NONE) {
            CPLError( CE_Warning, CPLE_AppDefined, "EPSG %d not found. Could not set datasource SRS.\n", poHeader->nEpsg);
            delete poSpatialRef;
            poSpatialRef=nullptr;
        }
    }

    // To prevent int overflow in poRange.getSize() call where we do
    // nSteps * 2
    if( poHeader->nSteps >= INT_MAX / 2 )
    {
        CPLError( CE_Failure, CPLE_OpenFailed, "Invalid nSteps value" );
        return FALSE;
    }

    // Create two layers for each selected time step: one for points, the other for elements
    poRange.setMaxValue(poHeader->nSteps);
    const int nNewLayers = static_cast<int>(poRange.getSize());
    if (EQUAL(pszFilename, "/vsistdin/")) osBaseLayerName = "layer";
    CPLString osLayerName;
    papoLayers = (OGRSelafinLayer **) CPLRealloc(papoLayers, sizeof(void*) * (nLayers+nNewLayers));
    for (size_t j=0;j<2;++j) {
        SelafinTypeDef eType=(j==0)?POINTS:ELEMENTS;
        for (int i=0;i<poHeader->nSteps;++i) {
            if (poRange.contains(eType,i)) {
                char szTemp[30];
                double dfTime = 0.0;
                if( VSIFSeekL(fp, poHeader->getPosition(i)+4, SEEK_SET)!=0 ||
                    Selafin::read_float(fp, dfTime)==0 )
                {
                    CPLError( CE_Failure, CPLE_OpenFailed, "Failed to open %s, wrong format.\n", pszFilename);
                    return FALSE;
                }
                if (poHeader->panStartDate==nullptr) snprintf(szTemp,29,"%d",i); else {
                    struct tm sDate;
                    memset(&sDate, 0, sizeof(sDate));
                    sDate.tm_year=poHeader->panStartDate[0]-1900;
                    sDate.tm_mon=poHeader->panStartDate[1]-1;
                    sDate.tm_mday=poHeader->panStartDate[2];
                    sDate.tm_hour=poHeader->panStartDate[3];
                    sDate.tm_min=poHeader->panStartDate[4];
                    double dfSec=poHeader->panStartDate[5]+dfTime;
                    if( dfSec >= 0 && dfSec < 60 )
                        sDate.tm_sec=static_cast<int>(dfSec);
                    mktime(&sDate);
                    strftime(szTemp,29,"%Y_%m_%d_%H_%M_%S",&sDate);
                }
                if (eType==POINTS) osLayerName=osBaseLayerName+"_p"+szTemp; else osLayerName=osBaseLayerName+"_e"+szTemp;
                papoLayers[nLayers++] =
                    new OGRSelafinLayer( osLayerName, bUpdate, poSpatialRef,
                                         poHeader, i, eType);
                //poHeader->nRefCount++;
            }
        }
    }

    // Free allocated variables and exit
    return TRUE;
}
示例#2
0
int OGRSelafinDataSource::OpenTable(const char * pszFilename) {
    //CPLDebug("Selafin","OpenTable(%s,%i)",pszFilename,bUpdate);
    // Open the file
    VSILFILE * fp;
    if( bUpdate ) {
        // We have to implement this locking feature for write access because the same file may hold several layers, and some programs (like QGIS) open each layer in a single datasource,
        // so the same file might be opened several times for write access
        if (TakeLock(pszFilename)==0) {
            CPLError(CE_Failure,CPLE_OpenFailed,"Failed to open %s for write access, lock file found %s.",pszFilename,pszLockName);
            return FALSE;
        }
        fp = VSIFOpenL( pszFilename, "rb+" );
    } else fp = VSIFOpenL( pszFilename, "rb" );
    if( fp == NULL ) {
        CPLError( CE_Warning, CPLE_OpenFailed, "Failed to open %s, %s.", pszFilename, VSIStrerror( errno ) );
        return FALSE;
    }
    if( !bUpdate && strstr(pszFilename, "/vsigzip/") == NULL && strstr(pszFilename, "/vsizip/") == NULL ) fp = (VSILFILE*) VSICreateBufferedReaderHandle((VSIVirtualHandle*)fp);

    // Quickly check if the file is in Selafin format, before actually starting to read to make it faster
    char szBuf[9];
    VSIFReadL(szBuf,1,4,fp);
    if (szBuf[0]!=0 || szBuf[1]!=0 || szBuf[2]!=0 || szBuf[3]!=0x50) {
        VSIFCloseL(fp);
        return FALSE;
    }
    VSIFSeekL(fp,84,SEEK_SET);
    VSIFReadL(szBuf,1,8,fp);
    if (szBuf[0]!=0 || szBuf[1]!=0 || szBuf[2]!=0 || szBuf[3]!=0x50 || szBuf[4]!=0 || szBuf[5]!=0 || szBuf[6]!=0 || szBuf[7]!=8) {
        VSIFCloseL(fp);
        return FALSE;
    }
    /* VSIFSeekL(fp,76,SEEK_SET);
    VSIFReadL(szBuf,1,8,fp);
    if (STRNCASECMP(szBuf,"Seraphin",8)!=0 && STRNCASECMP(szBuf,"Serafin",7)!=0) {
        VSIFCloseL(fp);
        return FALSE;
    } */

    // Get layer base name
    CPLString osBaseLayerName = CPLGetBasename(pszFilename);
    CPLString osExt = CPLGetExtension(pszFilename);
    if( STARTS_WITH(pszFilename, "/vsigzip/") && EQUAL(osExt, "gz") ) {
        size_t nPos=std::string::npos;
        if (strlen(pszFilename)>3) nPos=osExt.find_last_of('.',strlen(pszFilename)-4);
        if (nPos!=std::string::npos) {
            osExt=osExt.substr(nPos+1,strlen(pszFilename)-4-nPos);
            osBaseLayerName=osBaseLayerName.substr(0,nPos);
        } else {
            osExt="";
        }
    }

    // Read header of file to get common information for all layers
    poHeader=Selafin::read_header(fp,pszFilename);
    if (poHeader==NULL) {
        VSIFCloseL(fp);
        CPLError( CE_Failure, CPLE_OpenFailed, "Failed to open %s, wrong format.\n", pszFilename);
        return FALSE;
    }
    if (poHeader->nEpsg!=0) {
        poSpatialRef=new OGRSpatialReference();
        if (poSpatialRef->importFromEPSG(poHeader->nEpsg)!=OGRERR_NONE) {
            CPLError( CE_Warning, CPLE_AppDefined, "EPSG %d not found. Could not set datasource SRS.\n", poHeader->nEpsg);
            delete poSpatialRef;
            poSpatialRef=NULL;
        }
    }

    // Create two layers for each selected time step: one for points, the other for elements
    int nNewLayers;
    poRange.setMaxValue(poHeader->nSteps);
    nNewLayers=static_cast<int>(poRange.getSize());
    if (EQUAL(pszFilename, "/vsistdin/")) osBaseLayerName = "layer";
    CPLString osLayerName;
    papoLayers = (OGRSelafinLayer **) CPLRealloc(papoLayers, sizeof(void*) * (nLayers+nNewLayers));
    for (size_t j=0;j<2;++j) {
        SelafinTypeDef eType=(j==0)?POINTS:ELEMENTS;
        for (int i=0;i<poHeader->nSteps;++i) {
            if (poRange.contains(eType,i)) {
                char szTemp[30];
                double dfTime;
                if (VSIFSeekL(fp,poHeader->getPosition(i)+4,SEEK_SET)!=0 || Selafin::read_float(fp,dfTime)==0) {
                    VSIFCloseL(fp);
                    CPLError( CE_Failure, CPLE_OpenFailed, "Failed to open %s, wrong format.\n", pszFilename);
                    return FALSE;
                }
                if (poHeader->panStartDate==NULL) snprintf(szTemp,29,"%d",i); else {
                    struct tm sDate;
                    memset(&sDate, 0, sizeof(sDate));
                    sDate.tm_year=poHeader->panStartDate[0]-1900;
                    sDate.tm_mon=poHeader->panStartDate[1]-1;
                    sDate.tm_mday=poHeader->panStartDate[2];
                    sDate.tm_hour=poHeader->panStartDate[3];
                    sDate.tm_min=poHeader->panStartDate[4];
                    sDate.tm_sec=poHeader->panStartDate[5]+(int)dfTime;
                    mktime(&sDate);
                    strftime(szTemp,29,"%Y_%m_%d_%H_%M_%S",&sDate);
                }
                if (eType==POINTS) osLayerName=osBaseLayerName+"_p"+szTemp; else osLayerName=osBaseLayerName+"_e"+szTemp;
                papoLayers[nLayers++] = new OGRSelafinLayer( osLayerName, bUpdate, poSpatialRef, poHeader,i,eType);
                //poHeader->nRefCount++;
            }
        }
    }

    // Free allocated variables and exit
    return TRUE;
}
示例#3
0
GDALDataset *ERSDataset::Open( GDALOpenInfo * poOpenInfo )

{
/* -------------------------------------------------------------------- */
/*      We assume the user selects the .ers file.                       */
/* -------------------------------------------------------------------- */
    if( poOpenInfo->nHeaderBytes > 15
        && EQUALN((const char *) poOpenInfo->pabyHeader,"Algorithm Begin",15) )
    {
        CPLError( CE_Failure, CPLE_OpenFailed, 
                  "%s appears to be an algorithm ERS file, which is not currently supported.", 
                  poOpenInfo->pszFilename );
        return NULL;
    }

/* -------------------------------------------------------------------- */
/*      We assume the user selects the .ers file.                       */
/* -------------------------------------------------------------------- */
    if( poOpenInfo->nHeaderBytes < 15 
        || !EQUALN((const char *) poOpenInfo->pabyHeader,"DatasetHeader ",14) )
        return NULL;

/* -------------------------------------------------------------------- */
/*      Open the .ers file, and read the first line.                    */
/* -------------------------------------------------------------------- */
    VSILFILE *fpERS = VSIFOpenL( poOpenInfo->pszFilename, "rb" );
    
    if( fpERS == NULL )
        return NULL;

    CPLReadLineL( fpERS );

/* -------------------------------------------------------------------- */
/*      Now ingest the rest of the file as a tree of header nodes.      */
/* -------------------------------------------------------------------- */
    ERSHdrNode *poHeader = new ERSHdrNode();

    if( !poHeader->ParseChildren( fpERS ) )
    {
        delete poHeader;
        VSIFCloseL( fpERS );
        return NULL;
    }

    VSIFCloseL( fpERS );

/* -------------------------------------------------------------------- */
/*      Do we have the minimum required information from this header?   */
/* -------------------------------------------------------------------- */
    if( poHeader->Find( "RasterInfo.NrOfLines" ) == NULL 
        || poHeader->Find( "RasterInfo.NrOfCellsPerLine" ) == NULL 
        || poHeader->Find( "RasterInfo.NrOfBands" ) == NULL )
    {
        if( poHeader->FindNode( "Algorithm" ) != NULL )
        {
            CPLError( CE_Failure, CPLE_OpenFailed, 
                      "%s appears to be an algorithm ERS file, which is not currently supported.", 
                      poOpenInfo->pszFilename );
        }
        delete poHeader;
        return NULL;
    }

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

    poDS = new ERSDataset();
    poDS->poHeader = poHeader;
    poDS->eAccess = poOpenInfo->eAccess;

/* -------------------------------------------------------------------- */
/*      Capture some information from the file that is of interest.     */
/* -------------------------------------------------------------------- */
    int nBands = atoi(poHeader->Find( "RasterInfo.NrOfBands" ));
    poDS->nRasterXSize = atoi(poHeader->Find( "RasterInfo.NrOfCellsPerLine" ));
    poDS->nRasterYSize = atoi(poHeader->Find( "RasterInfo.NrOfLines" ));
    
    if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize) ||
        !GDALCheckBandCount(nBands, FALSE))
    {
        delete poDS;
        return NULL;
    }

/* -------------------------------------------------------------------- */
/*     Get the HeaderOffset if it exists in the header                  */
/* -------------------------------------------------------------------- */
    GIntBig nHeaderOffset = 0;
    if( poHeader->Find( "HeaderOffset" ) != NULL )
    {
        nHeaderOffset = atoi(poHeader->Find( "HeaderOffset" ));
    }

/* -------------------------------------------------------------------- */
/*      Establish the data type.                                        */
/* -------------------------------------------------------------------- */
    GDALDataType eType;
    CPLString osCellType = poHeader->Find( "RasterInfo.CellType", 
                                           "Unsigned8BitInteger" );
    if( EQUAL(osCellType,"Unsigned8BitInteger") )
        eType = GDT_Byte;
    else if( EQUAL(osCellType,"Signed8BitInteger") )
        eType = GDT_Byte;
    else if( EQUAL(osCellType,"Unsigned16BitInteger") )
        eType = GDT_UInt16;
    else if( EQUAL(osCellType,"Signed16BitInteger") )
        eType = GDT_Int16;
    else if( EQUAL(osCellType,"Unsigned32BitInteger") )
        eType = GDT_UInt32;
    else if( EQUAL(osCellType,"Signed32BitInteger") )
        eType = GDT_Int32;
    else if( EQUAL(osCellType,"IEEE4ByteReal") )
        eType = GDT_Float32;
    else if( EQUAL(osCellType,"IEEE8ByteReal") )
        eType = GDT_Float64;
    else
    {
        CPLDebug( "ERS", "Unknown CellType '%s'", osCellType.c_str() );
        eType = GDT_Byte;
    }

/* -------------------------------------------------------------------- */
/*      Pick up the word order.                                         */
/* -------------------------------------------------------------------- */
    int bNative;

#ifdef CPL_LSB
    bNative = EQUAL(poHeader->Find( "ByteOrder", "LSBFirst" ),
                    "LSBFirst");
#else
    bNative = EQUAL(poHeader->Find( "ByteOrder", "MSBFirst" ),
                    "MSBFirst");
#endif

/* -------------------------------------------------------------------- */
/*      Figure out the name of the target file.                         */
/* -------------------------------------------------------------------- */
    CPLString osPath = CPLGetPath( poOpenInfo->pszFilename );
    CPLString osDataFile = poHeader->Find( "DataFile", "" );
    CPLString osDataFilePath;

    if( osDataFile.length() == 0 ) // just strip off extension.
    {
        osDataFile = CPLGetFilename( poOpenInfo->pszFilename );
        osDataFile = osDataFile.substr( 0, osDataFile.find_last_of('.') );
    }
        
    osDataFilePath = CPLFormFilename( osPath, osDataFile, NULL );

/* -------------------------------------------------------------------- */
/*      DataSetType = Translated files are links to things like ecw     */
/*      files.                                                          */
/* -------------------------------------------------------------------- */
    if( EQUAL(poHeader->Find("DataSetType",""),"Translated") )
    {
        poDS->poDepFile = (GDALDataset *) 
            GDALOpenShared( osDataFilePath, poOpenInfo->eAccess );

        if( poDS->poDepFile != NULL 
            && poDS->poDepFile->GetRasterCount() >= nBands )
        {
            int iBand;

            for( iBand = 0; iBand < nBands; iBand++ )
            {
                // Assume pixel interleaved.
                poDS->SetBand( iBand+1, 
                               poDS->poDepFile->GetRasterBand( iBand+1 ) );
            }
        }
    }

/* ==================================================================== */
/*      While ERStorage indicates a raw file.                           */
/* ==================================================================== */
    else if( EQUAL(poHeader->Find("DataSetType",""),"ERStorage") )
    {
        // Open data file.
        if( poOpenInfo->eAccess == GA_Update )
            poDS->fpImage = VSIFOpenL( osDataFilePath, "r+" );
        else
            poDS->fpImage = VSIFOpenL( osDataFilePath, "r" );

        poDS->osRawFilename = osDataFilePath;

        if( poDS->fpImage != NULL )
        {
            int iWordSize = GDALGetDataTypeSize(eType) / 8;
            int iBand;

            for( iBand = 0; iBand < nBands; iBand++ )
            {
                // Assume pixel interleaved.
                poDS->SetBand( 
                    iBand+1, 
                    new RawRasterBand( poDS, iBand+1, poDS->fpImage,
                                       nHeaderOffset 
                                       + iWordSize * iBand * poDS->nRasterXSize,
                                       iWordSize,
                                       iWordSize * nBands * poDS->nRasterXSize,
                                       eType, bNative, TRUE ));
                if( EQUAL(osCellType,"Signed8BitInteger") )
                    poDS->GetRasterBand(iBand+1)->
                        SetMetadataItem( "PIXELTYPE", "SIGNEDBYTE", 
                                         "IMAGE_STRUCTURE" );
            }
        }
    }

/* -------------------------------------------------------------------- */
/*      Otherwise we have an error!                                     */
/* -------------------------------------------------------------------- */
    if( poDS->nBands == 0 )
    {
        delete poDS;
        return NULL;
    }

/* -------------------------------------------------------------------- */
/*      Look for band descriptions.                                     */
/* -------------------------------------------------------------------- */
    int iChild, iBand = 0;
    ERSHdrNode *poRI = poHeader->FindNode( "RasterInfo" );

    for( iChild = 0; 
         poRI != NULL && iChild < poRI->nItemCount && iBand < poDS->nBands; 
         iChild++ )
    {
        if( poRI->papoItemChild[iChild] != NULL
            && EQUAL(poRI->papszItemName[iChild],"BandId") )
        {
            const char *pszValue = 
                poRI->papoItemChild[iChild]->Find( "Value", NULL );

            iBand++;
            if( pszValue )
            {
                CPLPushErrorHandler( CPLQuietErrorHandler );
                poDS->GetRasterBand( iBand )->SetDescription( pszValue );
                CPLPopErrorHandler();
            }

            pszValue = poRI->papoItemChild[iChild]->Find( "Units", NULL );
            if ( pszValue )
            {
                CPLPushErrorHandler( CPLQuietErrorHandler );
                poDS->GetRasterBand( iBand )->SetUnitType( pszValue );
                CPLPopErrorHandler();
            }
        }
    }

/* -------------------------------------------------------------------- */
/*      Look for projection.                                            */
/* -------------------------------------------------------------------- */
    OGRSpatialReference oSRS;

    CPLString osProjection = poHeader->Find( "CoordinateSpace.Projection", 
                                             "RAW" );
    CPLString osDatum = poHeader->Find( "CoordinateSpace.Datum", "WGS84" );
    CPLString osUnits = poHeader->Find( "CoordinateSpace.Units", "METERS" );

    oSRS.importFromERM( osProjection, osDatum, osUnits );

    CPLFree( poDS->pszProjection );
    oSRS.exportToWkt( &(poDS->pszProjection) );

/* -------------------------------------------------------------------- */
/*      Look for the geotransform.                                      */
/* -------------------------------------------------------------------- */
    if( poHeader->Find( "RasterInfo.RegistrationCoord.Eastings", NULL )
        && poHeader->Find( "RasterInfo.CellInfo.Xdimension", NULL ) )
    {
        poDS->bGotTransform = TRUE;
        poDS->adfGeoTransform[0] = CPLAtof( 
            poHeader->Find( "RasterInfo.RegistrationCoord.Eastings", "" ));
        poDS->adfGeoTransform[1] = CPLAtof( 
            poHeader->Find( "RasterInfo.CellInfo.Xdimension", "" ));
        poDS->adfGeoTransform[2] = 0.0;
        poDS->adfGeoTransform[3] = CPLAtof( 
            poHeader->Find( "RasterInfo.RegistrationCoord.Northings", "" ));
        poDS->adfGeoTransform[4] = 0.0;
        poDS->adfGeoTransform[5] = -CPLAtof( 
            poHeader->Find( "RasterInfo.CellInfo.Ydimension", "" ));
    }
    else if( poHeader->Find( "RasterInfo.RegistrationCoord.Latitude", NULL )
             && poHeader->Find( "RasterInfo.CellInfo.Xdimension", NULL ) )
    {
        poDS->bGotTransform = TRUE;
        poDS->adfGeoTransform[0] = ERSDMS2Dec( 
            poHeader->Find( "RasterInfo.RegistrationCoord.Longitude", "" ));
        poDS->adfGeoTransform[1] = CPLAtof( 
            poHeader->Find( "RasterInfo.CellInfo.Xdimension", "" ));
        poDS->adfGeoTransform[2] = 0.0;
        poDS->adfGeoTransform[3] = ERSDMS2Dec( 
            poHeader->Find( "RasterInfo.RegistrationCoord.Latitude", "" ));
        poDS->adfGeoTransform[4] = 0.0;
        poDS->adfGeoTransform[5] = -CPLAtof( 
            poHeader->Find( "RasterInfo.CellInfo.Ydimension", "" ));
    }

/* -------------------------------------------------------------------- */
/*      Adjust if we have a registration cell.                          */
/* -------------------------------------------------------------------- */
    int iCellX = atoi(poHeader->Find("RasterInfo.RegistrationCellX", "1"));
    int iCellY = atoi(poHeader->Find("RasterInfo.RegistrationCellY", "1"));

    if( poDS->bGotTransform )
    {
        poDS->adfGeoTransform[0] -=
            (iCellX-1) * poDS->adfGeoTransform[1]
            + (iCellY-1) * poDS->adfGeoTransform[2];
        poDS->adfGeoTransform[3] -= 
            (iCellX-1) * poDS->adfGeoTransform[4]
            + (iCellY-1) * poDS->adfGeoTransform[5];
    }

/* -------------------------------------------------------------------- */
/*      Check for null values.                                          */
/* -------------------------------------------------------------------- */
    if( poHeader->Find( "RasterInfo.NullCellValue", NULL ) )
    {
        CPLPushErrorHandler( CPLQuietErrorHandler );

        for( iBand = 1; iBand <= poDS->nBands; iBand++ )
            poDS->GetRasterBand(iBand)->SetNoDataValue(
                CPLAtofM(poHeader->Find( "RasterInfo.NullCellValue" )) );
        
        CPLPopErrorHandler();
    }

/* -------------------------------------------------------------------- */
/*      Do we have an "All" region?                                     */
/* -------------------------------------------------------------------- */
    ERSHdrNode *poAll = NULL;

    for( iChild = 0; 
         poRI != NULL && iChild < poRI->nItemCount; 
         iChild++ )
    {
        if( poRI->papoItemChild[iChild] != NULL
            && EQUAL(poRI->papszItemName[iChild],"RegionInfo") )
        {
            if( EQUAL(poRI->papoItemChild[iChild]->Find("RegionName",""), 
                      "All") )
                poAll = poRI->papoItemChild[iChild];
        }
    }

/* -------------------------------------------------------------------- */
/*      Do we have statistics?                                          */
/* -------------------------------------------------------------------- */
    if( poAll && poAll->FindNode( "Stats" ) )
    {
        CPLPushErrorHandler( CPLQuietErrorHandler );

        for( iBand = 1; iBand <= poDS->nBands; iBand++ )
        {
            const char *pszValue = 
                poAll->FindElem( "Stats.MinimumValue", iBand-1 );

            if( pszValue )
                poDS->GetRasterBand(iBand)->SetMetadataItem(
                    "STATISTICS_MINIMUM", pszValue );

            pszValue = poAll->FindElem( "Stats.MaximumValue", iBand-1 );

            if( pszValue )
                poDS->GetRasterBand(iBand)->SetMetadataItem(
                    "STATISTICS_MAXIMUM", pszValue );

            pszValue = poAll->FindElem( "Stats.MeanValue", iBand-1 );

            if( pszValue )
                poDS->GetRasterBand(iBand)->SetMetadataItem(
                    "STATISTICS_MEAN", pszValue );

            pszValue = poAll->FindElem( "Stats.MedianValue", iBand-1 );

            if( pszValue )
                poDS->GetRasterBand(iBand)->SetMetadataItem(
                    "STATISTICS_MEDIAN", pszValue );
        }
        
        CPLPopErrorHandler();
        
    }

/* -------------------------------------------------------------------- */
/*      Do we have GCPs.                                                */
/* -------------------------------------------------------------------- */
    if( poHeader->FindNode( "RasterInfo.WarpControl" ) )
        poDS->ReadGCPs();

/* -------------------------------------------------------------------- */
/*      Initialize any PAM information.                                 */
/* -------------------------------------------------------------------- */
    poDS->SetDescription( poOpenInfo->pszFilename );
    poDS->TryLoadXML();
    
    // if no SR in xml, try aux
    const char* pszPrj = poDS->GDALPamDataset::GetProjectionRef();
    if( !pszPrj || strlen(pszPrj) == 0 )
    {
        // try aux
        GDALDataset* poAuxDS = GDALFindAssociatedAuxFile( poOpenInfo->pszFilename, GA_ReadOnly, poDS );
        if( poAuxDS )
        {
            pszPrj = poAuxDS->GetProjectionRef();
            if( pszPrj && strlen(pszPrj) > 0 )
            {
                CPLFree( poDS->pszProjection );
                poDS->pszProjection = CPLStrdup(pszPrj);
            }

            GDALClose( poAuxDS );
        }
    }
/* -------------------------------------------------------------------- */
/*      Check for overviews.                                            */
/* -------------------------------------------------------------------- */
    poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );

    return( poDS );
}