Ejemplo n.º 1
0
GDALDataset *AAIGDataset::CommonOpen( GDALOpenInfo *poOpenInfo,
                                      GridFormat eFormat )
{
    if( poOpenInfo->fpL == nullptr )
        return nullptr;

    // Create a corresponding GDALDataset.
    AAIGDataset *poDS = nullptr;

    if (eFormat == FORMAT_AAIG)
        poDS = new AAIGDataset();
    else
        poDS = new GRASSASCIIDataset();

    const char *pszDataTypeOption =
        eFormat == FORMAT_AAIG ?
        "AAIGRID_DATATYPE" : "GRASSASCIIGRID_DATATYPE";

    const char *pszDataType = CPLGetConfigOption(pszDataTypeOption, nullptr);
    if( pszDataType == nullptr )
        pszDataType =
            CSLFetchNameValue(poOpenInfo->papszOpenOptions, "DATATYPE");
    if (pszDataType != nullptr)
    {
        poDS->eDataType = GDALGetDataTypeByName(pszDataType);
        if (!(poDS->eDataType == GDT_Int32 || poDS->eDataType == GDT_Float32 ||
              poDS->eDataType == GDT_Float64))
        {
            CPLError(CE_Warning, CPLE_NotSupported,
                     "Unsupported value for %s : %s",
                     pszDataTypeOption, pszDataType);
            poDS->eDataType = GDT_Int32;
            pszDataType = nullptr;
        }
    }

    // Parse the header.
    if (!poDS->ParseHeader((const char *)poOpenInfo->pabyHeader, pszDataType))
    {
        delete poDS;
        return nullptr;
    }

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

    // Find the start of real data.
    int nStartOfData = 0;

    for( int i = 2; true; i++ )
    {
        if( poOpenInfo->pabyHeader[i] == '\0' )
        {
            CPLError(CE_Failure, CPLE_AppDefined,
                     "Couldn't find data values in ASCII Grid file.");
            delete poDS;
            return nullptr;
        }

        if( poOpenInfo->pabyHeader[i - 1] == '\n' ||
            poOpenInfo->pabyHeader[i - 2] == '\n' ||
            poOpenInfo->pabyHeader[i - 1] == '\r' ||
            poOpenInfo->pabyHeader[i - 2] == '\r' )
        {
            if( !isalpha(poOpenInfo->pabyHeader[i]) &&
                poOpenInfo->pabyHeader[i] != '\n' &&
                poOpenInfo->pabyHeader[i] != '\r')
            {
                nStartOfData = i;

                // Beginning of real data found.
                break;
            }
        }
    }

    // Recognize the type of data.
    CPLAssert(nullptr != poDS->fp);

    if( pszDataType == nullptr &&
        poDS->eDataType != GDT_Float32 && poDS->eDataType != GDT_Float64)
    {
        // Allocate 100K chunk + 1 extra byte for NULL character.
        constexpr size_t nChunkSize = 1024 * 100;
        GByte *pabyChunk = static_cast<GByte *>(
            VSI_CALLOC_VERBOSE(nChunkSize + 1, sizeof(GByte)));
        if (pabyChunk == nullptr)
        {
            delete poDS;
            return nullptr;
        }
        pabyChunk[nChunkSize] = '\0';

        if( VSIFSeekL(poDS->fp, nStartOfData, SEEK_SET) < 0 )
        {
            delete poDS;
            VSIFree(pabyChunk);
            return nullptr;
        }

        // Scan for dot in subsequent chunks of data.
        while( !VSIFEofL(poDS->fp) )
        {
            CPL_IGNORE_RET_VAL(VSIFReadL(pabyChunk, nChunkSize, 1, poDS->fp));

            for( int i = 0; i < static_cast<int>(nChunkSize); i++)
            {
                GByte ch = pabyChunk[i];
                if (ch == '.' || ch == ',' || ch == 'e' || ch == 'E')
                {
                    poDS->eDataType = GDT_Float32;
                    break;
                }
            }
        }

        // Deallocate chunk.
        VSIFree(pabyChunk);
    }

    // Create band information objects.
    AAIGRasterBand *band = new AAIGRasterBand(poDS, nStartOfData);
    poDS->SetBand(1, band);
    if (band->panLineOffset == nullptr)
    {
        delete poDS;
        return nullptr;
    }

    // Try to read projection file.
    char *const pszDirname = CPLStrdup(CPLGetPath(poOpenInfo->pszFilename));
    char *const pszBasename =
        CPLStrdup(CPLGetBasename(poOpenInfo->pszFilename));

    poDS->osPrjFilename = CPLFormFilename(pszDirname, pszBasename, "prj");
    int nRet = 0;
    {
        VSIStatBufL sStatBuf;
        nRet = VSIStatL(poDS->osPrjFilename, &sStatBuf);
    }
    if( nRet != 0 && VSIIsCaseSensitiveFS(poDS->osPrjFilename) )
    {
        poDS->osPrjFilename = CPLFormFilename(pszDirname, pszBasename, "PRJ");

        VSIStatBufL sStatBuf;
        nRet = VSIStatL(poDS->osPrjFilename, &sStatBuf);
    }

    if( nRet == 0 )
    {
        poDS->papszPrj = CSLLoad(poDS->osPrjFilename);

        CPLDebug("AAIGrid", "Loaded SRS from %s", poDS->osPrjFilename.c_str());

        OGRSpatialReference oSRS;
        if( oSRS.importFromESRI(poDS->papszPrj) == OGRERR_NONE )
        {
            // If geographic values are in seconds, we must transform.
            // Is there a code for minutes too?
            if( oSRS.IsGeographic() &&
                EQUAL(OSR_GDS(poDS->papszPrj, "Units", ""), "DS") )
            {
                poDS->adfGeoTransform[0] /= 3600.0;
                poDS->adfGeoTransform[1] /= 3600.0;
                poDS->adfGeoTransform[2] /= 3600.0;
                poDS->adfGeoTransform[3] /= 3600.0;
                poDS->adfGeoTransform[4] /= 3600.0;
                poDS->adfGeoTransform[5] /= 3600.0;
            }

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

    CPLFree(pszDirname);
    CPLFree(pszBasename);

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

    // Check for external overviews.
    poDS->oOvManager.Initialize(
        poDS, poOpenInfo->pszFilename, poOpenInfo->GetSiblingFiles());

    return poDS;
}
Ejemplo n.º 2
0
void LANDataset::CheckForStatistics()

{
/* -------------------------------------------------------------------- */
/*      Do we have a statistics file?                                   */
/* -------------------------------------------------------------------- */
    osSTAFilename = CPLResetExtension(GetDescription(),"sta");

    VSILFILE *fpSTA = VSIFOpenL( osSTAFilename, "r" );

    if( fpSTA == NULL && VSIIsCaseSensitiveFS(osSTAFilename) )
    {
        osSTAFilename = CPLResetExtension(GetDescription(),"STA");
        fpSTA = VSIFOpenL( osSTAFilename, "r" );
    }

    if( fpSTA == NULL )
    {
        osSTAFilename = "";
        return;
    }

/* -------------------------------------------------------------------- */
/*      Read it one band at a time.                                     */
/* -------------------------------------------------------------------- */
    GByte abyBandInfo[1152] = { '\0' };

    for( int iBand = 0; iBand < nBands; iBand++ )
    {
        if( VSIFReadL( abyBandInfo, 1152, 1, fpSTA ) != 1 )
            break;

        const int nBandNumber = abyBandInfo[7];
        GDALRasterBand *poBand = GetRasterBand(nBandNumber);
        if( poBand == NULL )
            break;

        GInt16 nMin = 0;
        GInt16 nMax = 0;

        if( poBand->GetRasterDataType() != GDT_Byte )
        {
            memcpy( &nMin, abyBandInfo + 28, 2 );
            memcpy( &nMax, abyBandInfo + 30, 2 );
            CPL_LSBPTR16( &nMin );
            CPL_LSBPTR16( &nMax );
        }
        else
        {
            nMin = abyBandInfo[9];
            nMax = abyBandInfo[8];
        }

        float fMean = 0.0;
        float fStdDev = 0.0;
        memcpy( &fMean, abyBandInfo + 12, 4 );
        memcpy( &fStdDev, abyBandInfo + 24, 4 );
        CPL_LSBPTR32( &fMean );
        CPL_LSBPTR32( &fStdDev );

        poBand->SetStatistics( nMin, nMax, fMean, fStdDev );
    }

    CPL_IGNORE_RET_VAL(VSIFCloseL( fpSTA ));
}
Ejemplo n.º 3
0
GDALDataset *SIGDEMDataset::Open(GDALOpenInfo * poOpenInfo) {
    VSILFILE* fp = poOpenInfo->fpL;

    SIGDEMHeader sHeader;
    if (SIGDEMDataset::Identify(poOpenInfo) != TRUE || fp == nullptr) {
        return nullptr;
    }

    sHeader.Read(poOpenInfo->pabyHeader);

    if (!GDALCheckDatasetDimensions(sHeader.nCols, sHeader.nRows)) {
        return nullptr;
    }

    OGRSpatialReference oSRS;

    if (sHeader.nCoordinateSystemId > 0) {
        if (oSRS.importFromEPSG(sHeader.nCoordinateSystemId) != OGRERR_NONE) {
            CPLError(CE_Failure, CPLE_NotSupported,
                    "SIGDEM unable to find coordinateSystemId=%d.",
                    sHeader.nCoordinateSystemId);
            return nullptr;
        }
    } else {
        CPLString osPrjFilename = CPLResetExtension(poOpenInfo->pszFilename,
                "prj");
        VSIStatBufL sStatBuf;
        int nRet = VSIStatL(osPrjFilename, &sStatBuf);
        if (nRet != 0 && VSIIsCaseSensitiveFS(osPrjFilename)) {
            osPrjFilename = CPLResetExtension(poOpenInfo->pszFilename, "PRJ");
            nRet = VSIStatL(osPrjFilename, &sStatBuf);
        }

        if (nRet == 0) {
            char** papszPrj = CSLLoad(osPrjFilename);
            if (oSRS.importFromESRI(papszPrj) != OGRERR_NONE) {
                CPLError(CE_Failure, CPLE_NotSupported,
                        "SIGDEM unable to read projection from %s.",
                        osPrjFilename.c_str());
                CSLDestroy(papszPrj);
                return nullptr;
            }
            CSLDestroy(papszPrj);
        } else {
            CPLError(CE_Failure, CPLE_NotSupported,
                    "SIGDEM unable to find projection.");
            return nullptr;
        }
    }

    if (sHeader.nCols > std::numeric_limits<int>::max() / (CELL_SIZE_MEM)) {
        CPLError(CE_Failure, CPLE_AppDefined, "Int overflow occurred.");
        return nullptr;
    }

    if( !RAWDatasetCheckMemoryUsage(sHeader.nCols, sHeader.nRows, 1,
                    4, 4, 4 * sHeader.nCols, 0, 0, poOpenInfo->fpL) )
    {
        return nullptr;
    }
    SIGDEMDataset *poDS = new SIGDEMDataset(sHeader);

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

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

    poDS->SetDescription(poOpenInfo->pszFilename);
    poDS->PamInitialize();

    poDS->nBands = 1;
    CPLErrorReset();
    SIGDEMRasterBand *poBand = new SIGDEMRasterBand(poDS, poDS->fpImage,
            sHeader.dfMinZ, sHeader.dfMaxZ);

    poDS->SetBand(1, poBand);
    if (CPLGetLastErrorType() != CE_None) {
        poDS->nBands = 1;
        delete poDS;
        return nullptr;
    }

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

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

    return poDS;
}
Ejemplo n.º 4
0
const char *CPLFormCIFilename( const char * pszPath,
                               const char * pszBasename,
                               const char * pszExtension )

{
    // On case insensitive filesystems, just default to
    // CPLFormFilename()
    if( !VSIIsCaseSensitiveFS(pszPath) )
        return CPLFormFilename( pszPath, pszBasename, pszExtension );

    const char  *pszAddedExtSep = "";
    char        *pszFilename;
    const char  *pszFullPath;
    int         nLen = strlen(pszBasename)+2, i;
    VSIStatBufL sStatBuf;
    int         nStatRet;

    if( pszExtension != NULL )
        nLen += strlen(pszExtension);

    pszFilename = (char *) CPLMalloc(nLen);

    if( pszExtension == NULL )
        pszExtension = "";
    else if( pszExtension[0] != '.' && strlen(pszExtension) > 0 )
        pszAddedExtSep = ".";

    sprintf( pszFilename, "%s%s%s", 
             pszBasename, pszAddedExtSep, pszExtension );

    pszFullPath = CPLFormFilename( pszPath, pszFilename, NULL );
    nStatRet = VSIStatExL( pszFullPath, &sStatBuf, VSI_STAT_EXISTS_FLAG );
    if( nStatRet != 0 )
    {
        for( i = 0; pszFilename[i] != '\0'; i++ )
        {
            if( islower(pszFilename[i]) )
                pszFilename[i] = (char) toupper(pszFilename[i]);
        }

        pszFullPath = CPLFormFilename( pszPath, pszFilename, NULL );
        nStatRet = VSIStatExL( pszFullPath, &sStatBuf, VSI_STAT_EXISTS_FLAG );
    }

    if( nStatRet != 0 )
    {
        for( i = 0; pszFilename[i] != '\0'; i++ )
        {
            if( isupper(pszFilename[i]) )
                pszFilename[i] = (char) tolower(pszFilename[i]);
        }

        pszFullPath = CPLFormFilename( pszPath, pszFilename, NULL );
        nStatRet = VSIStatExL( pszFullPath, &sStatBuf, VSI_STAT_EXISTS_FLAG );
    }

    if( nStatRet != 0 )
        pszFullPath = CPLFormFilename( pszPath, pszBasename, pszExtension );

    CPLFree( pszFilename );

    return pszFullPath;
}
Ejemplo n.º 5
0
GDALDataset *LCPDataset::Open( GDALOpenInfo * poOpenInfo )

{
    /* -------------------------------------------------------------------- */
    /*      Verify that this is a FARSITE LCP file    */
    /* -------------------------------------------------------------------- */
    if( !Identify( poOpenInfo ) )
        return NULL;

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

    /* -------------------------------------------------------------------- */
    /*      Create a corresponding GDALDataset.                             */
    /* -------------------------------------------------------------------- */
    LCPDataset  *poDS;
    VSILFILE        *fpImage;

    fpImage = VSIFOpenL(poOpenInfo->pszFilename, "rb");
    if (fpImage == NULL)
        return NULL;

    poDS = new LCPDataset();
    poDS->fpImage = fpImage;

    /* -------------------------------------------------------------------- */
    /*      Read the header and extract some information.                   */
    /* -------------------------------------------------------------------- */
    int bHaveCrownFuels, bHaveGroundFuels;
    int nBands, i;
    long nWidth = -1, nHeight = -1;
    int nTemp, nTemp2;
    char szTemp[32];
    char* pszList;

    VSIFSeekL( poDS->fpImage, 0, SEEK_SET );
    if (VSIFReadL( poDS->pachHeader, 1, LCP_HEADER_SIZE, poDS->fpImage ) != LCP_HEADER_SIZE)
    {
        CPLError(CE_Failure, CPLE_FileIO, "File too short");
        delete poDS;
        return NULL;
    }

    nWidth = CPL_LSBINT32PTR (poDS->pachHeader + 4164);
    nHeight = CPL_LSBINT32PTR (poDS->pachHeader + 4168);

    poDS->nRasterXSize = nWidth;
    poDS->nRasterYSize = nHeight;

    if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize))
    {
        delete poDS;
        return NULL;
    }

    // crown fuels = canopy height, canopy base height, canopy bulk density
    // 21 = have them, 20 = don't have them
    bHaveCrownFuels = ( CPL_LSBINT32PTR (poDS->pachHeader + 0) - 20 );
    // ground fuels = duff loading, coarse woody
    bHaveGroundFuels = ( CPL_LSBINT32PTR (poDS->pachHeader + 4) - 20 );

    if( bHaveCrownFuels )
    {
        if( bHaveGroundFuels )
            nBands = 10;
        else
            nBands = 8;
    }
    else
    {
        if( bHaveGroundFuels )
            nBands = 7;
        else
            nBands = 5;
    }

    // add dataset-level metadata

    nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 8);
    sprintf(szTemp, "%d", nTemp);
    poDS->SetMetadataItem( "LATITUDE", szTemp );

    nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 4204);
    if ( nTemp == 0 )
        poDS->SetMetadataItem( "LINEAR_UNIT", "Meters" );
    if ( nTemp == 1 )
        poDS->SetMetadataItem( "LINEAR_UNIT", "Feet" );

    poDS->pachHeader[LCP_HEADER_SIZE-1] = '\0';
    poDS->SetMetadataItem( "DESCRIPTION", poDS->pachHeader + 6804 );


    /* -------------------------------------------------------------------- */
    /*      Create band information objects.                                */
    /* -------------------------------------------------------------------- */

    int          iPixelSize;
    iPixelSize = nBands * 2;
    int          bNativeOrder;

    if (nWidth > INT_MAX / iPixelSize)
    {
        CPLError( CE_Failure, CPLE_AppDefined,  "Int overflow occured");
        delete poDS;
        return NULL;
    }

#ifdef CPL_LSB
    bNativeOrder = TRUE;
#else
    bNativeOrder = FALSE;
#endif

    pszList = (char*)CPLMalloc(2048);

    for( int iBand = 1; iBand <= nBands; iBand++ )
    {
        GDALRasterBand  *poBand = NULL;

        poBand = new RawRasterBand(
            poDS, iBand, poDS->fpImage, LCP_HEADER_SIZE + ((iBand-1)*2),
            iPixelSize, iPixelSize * nWidth, GDT_Int16, bNativeOrder, TRUE );

        poDS->SetBand(iBand, poBand);

        switch ( iBand ) {
        case 1:
            poBand->SetDescription("Elevation");

            nTemp = CPL_LSBINT16PTR (poDS->pachHeader + 4224);
            sprintf(szTemp, "%d", nTemp);
            poBand->SetMetadataItem( "ELEVATION_UNIT", szTemp );

            if ( nTemp == 0 )
                poBand->SetMetadataItem( "ELEVATION_UNIT_NAME", "Meters" );
            if ( nTemp == 1 )
                poBand->SetMetadataItem( "ELEVATION_UNIT_NAME", "Feet" );

            nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 44);
            sprintf(szTemp, "%d", nTemp);
            poBand->SetMetadataItem( "ELEVATION_MIN", szTemp );

            nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 48);
            sprintf(szTemp, "%d", nTemp);
            poBand->SetMetadataItem( "ELEVATION_MAX", szTemp );

            nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 52);
            sprintf(szTemp, "%d", nTemp);
            poBand->SetMetadataItem( "ELEVATION_NUM_CLASSES", szTemp );

            *(poDS->pachHeader + 4244 + 255) = '\0';
            poBand->SetMetadataItem( "ELEVATION_FILE", poDS->pachHeader + 4244 );

            break;

        case 2:
            poBand->SetDescription("Slope");

            nTemp = CPL_LSBINT16PTR (poDS->pachHeader + 4226);
            sprintf(szTemp, "%d", nTemp);
            poBand->SetMetadataItem( "SLOPE_UNIT", szTemp );

            if ( nTemp == 0 )
                poBand->SetMetadataItem( "SLOPE_UNIT_NAME", "Degrees" );
            if ( nTemp == 1 )
                poBand->SetMetadataItem( "SLOPE_UNIT_NAME", "Percent" );

            nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 456);
            sprintf(szTemp, "%d", nTemp);
            poBand->SetMetadataItem( "SLOPE_MIN", szTemp );

            nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 460);
            sprintf(szTemp, "%d", nTemp);
            poBand->SetMetadataItem( "SLOPE_MAX", szTemp );

            nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 464);
            sprintf(szTemp, "%d", nTemp);
            poBand->SetMetadataItem( "SLOPE_NUM_CLASSES", szTemp );

            *(poDS->pachHeader + 4500 + 255) = '\0';
            poBand->SetMetadataItem( "SLOPE_FILE", poDS->pachHeader + 4500 );

            break;

        case 3:
            poBand->SetDescription("Aspect");

            nTemp = CPL_LSBINT16PTR (poDS->pachHeader + 4228);
            sprintf(szTemp, "%d", nTemp);
            poBand->SetMetadataItem( "ASPECT_UNIT", szTemp );

            if ( nTemp == 0 )
                poBand->SetMetadataItem( "ASPECT_UNIT_NAME", "Grass categories" );
            if ( nTemp == 1 )
                poBand->SetMetadataItem( "ASPECT_UNIT_NAME", "Grass degrees" );
            if ( nTemp == 2 )
                poBand->SetMetadataItem( "ASPECT_UNIT_NAME", "Azimuth degrees" );

            nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 868);
            sprintf(szTemp, "%d", nTemp);
            poBand->SetMetadataItem( "ASPECT_MIN", szTemp );

            nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 872);
            sprintf(szTemp, "%d", nTemp);
            poBand->SetMetadataItem( "ASPECT_MAX", szTemp );

            nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 876);
            sprintf(szTemp, "%d", nTemp);
            poBand->SetMetadataItem( "ASPECT_NUM_CLASSES", szTemp );

            *(poDS->pachHeader + 4756 + 255) = '\0';
            poBand->SetMetadataItem( "ASPECT_FILE", poDS->pachHeader + 4756 );

            break;

        case 4:
            int nMinFM, nMaxFM;

            poBand->SetDescription("Fuel models");

            nTemp = CPL_LSBINT16PTR (poDS->pachHeader + 4230);
            sprintf(szTemp, "%d", nTemp);
            poBand->SetMetadataItem( "FUEL_MODEL_OPTION", szTemp );

            if ( nTemp == 0 )
                poBand->SetMetadataItem( "FUEL_MODEL_OPTION_DESC", "no custom models AND no conversion file needed" );
            if ( nTemp == 1 )
                poBand->SetMetadataItem( "FUEL_MODEL_OPTION_DESC", "custom models BUT no conversion file needed" );
            if ( nTemp == 2 )
                poBand->SetMetadataItem( "FUEL_MODEL_OPTION_DESC", "no custom models BUT conversion file needed" );
            if ( nTemp == 3 )
                poBand->SetMetadataItem( "FUEL_MODEL_OPTION_DESC", "custom models AND conversion file needed" );

            nMinFM = CPL_LSBINT32PTR (poDS->pachHeader + 1280);
            sprintf(szTemp, "%d", nMinFM);
            poBand->SetMetadataItem( "FUEL_MODEL_MIN", szTemp );

            nMaxFM = CPL_LSBINT32PTR (poDS->pachHeader + 1284);
            sprintf(szTemp, "%d", nMaxFM);
            poBand->SetMetadataItem( "FUEL_MODEL_MAX", szTemp );

            nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 1288);
            sprintf(szTemp, "%d", nTemp);
            poBand->SetMetadataItem( "FUEL_MODEL_NUM_CLASSES", szTemp );

            if (nTemp > 0 && nTemp <= 100) {
                strcpy(pszList, "");
                for ( i = 0; i <= nTemp; i++ ) {
                    nTemp2 = CPL_LSBINT32PTR (poDS->pachHeader + (1292+(i*4))) ;
                    if ( nTemp2 >= nMinFM && nTemp2 <= nMaxFM ) {
                        sprintf(szTemp, "%d", nTemp2);
                        strcat(pszList, szTemp);
                        if (i < (nTemp) )
                            strcat(pszList, ",");
                    }
                }
            }
            poBand->SetMetadataItem( "FUEL_MODEL_VALUES", pszList );

            *(poDS->pachHeader + 5012 + 255) = '\0';
            poBand->SetMetadataItem( "FUEL_MODEL_FILE", poDS->pachHeader + 5012 );

            break;

        case 5:
            poBand->SetDescription("Canopy cover");

            nTemp = CPL_LSBINT16PTR (poDS->pachHeader + 4232);
            sprintf(szTemp, "%d", nTemp);
            poBand->SetMetadataItem( "CANOPY_COV_UNIT", szTemp );

            if ( nTemp == 0 )
                poBand->SetMetadataItem( "CANOPY_COV_UNIT_NAME", "Categories (0-4)" );
            if ( nTemp == 1 )
                poBand->SetMetadataItem( "CANOPY_COV_UNIT_NAME", "Percent" );

            nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 1692);
            sprintf(szTemp, "%d", nTemp);
            poBand->SetMetadataItem( "CANOPY_COV_MIN", szTemp );

            nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 1696);
            sprintf(szTemp, "%d", nTemp);
            poBand->SetMetadataItem( "CANOPY_COV_MAX", szTemp );

            nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 1700);
            sprintf(szTemp, "%d", nTemp);
            poBand->SetMetadataItem( "CANOPY_COV_NUM_CLASSES", szTemp );

            *(poDS->pachHeader + 5268 + 255) = '\0';
            poBand->SetMetadataItem( "CANOPY_COV_FILE", poDS->pachHeader + 5268 );

            break;

        case 6:
            if(bHaveCrownFuels) {
                poBand->SetDescription("Canopy height");

                nTemp = CPL_LSBINT16PTR (poDS->pachHeader + 4234);
                sprintf(szTemp, "%d", nTemp);
                poBand->SetMetadataItem( "CANOPY_HT_UNIT", szTemp );

                if ( nTemp == 1 )
                    poBand->SetMetadataItem( "CANOPY_HT_UNIT_NAME", "Meters" );
                if ( nTemp == 2 )
                    poBand->SetMetadataItem( "CANOPY_HT_UNIT_NAME", "Feet" );
                if ( nTemp == 3 )
                    poBand->SetMetadataItem( "CANOPY_HT_UNIT_NAME", "Meters x 10" );
                if ( nTemp == 4 )
                    poBand->SetMetadataItem( "CANOPY_HT_UNIT_NAME", "Feet x 10" );

                nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 2104);
                sprintf(szTemp, "%d", nTemp);
                poBand->SetMetadataItem( "CANOPY_HT_MIN", szTemp );

                nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 2108);
                sprintf(szTemp, "%d", nTemp);
                poBand->SetMetadataItem( "CANOPY_HT_MAX", szTemp );

                nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 2112);
                sprintf(szTemp, "%d", nTemp);
                poBand->SetMetadataItem( "CANOPY_HT_NUM_CLASSES", szTemp );

                *(poDS->pachHeader + 5524 + 255) = '\0';
                poBand->SetMetadataItem( "CANOPY_HT_FILE", poDS->pachHeader + 5524 );
            }
            else {
                poBand->SetDescription("Duff");

                nTemp = CPL_LSBINT16PTR (poDS->pachHeader + 4240);
                sprintf(szTemp, "%d", nTemp);
                poBand->SetMetadataItem( "DUFF_UNIT", szTemp );

                if ( nTemp == 1 )
                    poBand->SetMetadataItem( "DUFF_UNIT_NAME", "Mg/ha" );
                if ( nTemp == 2 )
                    poBand->SetMetadataItem( "DUFF_UNIT_NAME", "t/ac" );

                nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 3340);
                sprintf(szTemp, "%d", nTemp);
                poBand->SetMetadataItem( "DUFF_MIN", szTemp );

                nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 3344);
                sprintf(szTemp, "%d", nTemp);
                poBand->SetMetadataItem( "DUFF_MAX", szTemp );

                nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 3348);
                sprintf(szTemp, "%d", nTemp);
                poBand->SetMetadataItem( "DUFF_NUM_CLASSES", szTemp );

                *(poDS->pachHeader + 6292 + 255) = '\0';
                poBand->SetMetadataItem( "DUFF_FILE", poDS->pachHeader + 6292 );
            }
            break;

        case 7:
            if(bHaveCrownFuels) {
                poBand->SetDescription("Canopy base height");

                nTemp = CPL_LSBINT16PTR (poDS->pachHeader + 4236);
                sprintf(szTemp, "%d", nTemp);
                poBand->SetMetadataItem( "CBH_UNIT", szTemp );

                if ( nTemp == 1 )
                    poBand->SetMetadataItem( "CBH_UNIT_NAME", "Meters" );
                if ( nTemp == 2 )
                    poBand->SetMetadataItem( "CBH_UNIT_NAME", "Feet" );
                if ( nTemp == 3 )
                    poBand->SetMetadataItem( "CBH_UNIT_NAME", "Meters x 10" );
                if ( nTemp == 4 )
                    poBand->SetMetadataItem( "CBH_UNIT_NAME", "Feet x 10" );

                nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 2516);
                sprintf(szTemp, "%d", nTemp);
                poBand->SetMetadataItem( "CBH_MIN", szTemp );

                nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 2520);
                sprintf(szTemp, "%d", nTemp);
                poBand->SetMetadataItem( "CBH_MAX", szTemp );

                nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 2524);
                sprintf(szTemp, "%d", nTemp);
                poBand->SetMetadataItem( "CBH_NUM_CLASSES", szTemp );

                *(poDS->pachHeader + 5780 + 255) = '\0';
                poBand->SetMetadataItem( "CBH_FILE", poDS->pachHeader + 5780 );
            }
            else {
                poBand->SetDescription("Coarse woody debris");

                nTemp = CPL_LSBINT16PTR (poDS->pachHeader + 4242);
                sprintf(szTemp, "%d", nTemp);
                poBand->SetMetadataItem( "CWD_OPTION", szTemp );

                //if ( nTemp == 1 )
                //   poBand->SetMetadataItem( "CWD_UNIT_DESC", "?" );
                //if ( nTemp == 2 )
                //   poBand->SetMetadataItem( "CWD_UNIT_DESC", "?" );

                nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 3752);
                sprintf(szTemp, "%d", nTemp);
                poBand->SetMetadataItem( "CWD_MIN", szTemp );

                nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 3756);
                sprintf(szTemp, "%d", nTemp);
                poBand->SetMetadataItem( "CWD_MAX", szTemp );

                nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 3760);
                sprintf(szTemp, "%d", nTemp);
                poBand->SetMetadataItem( "CWD_NUM_CLASSES", szTemp );

                *(poDS->pachHeader + 6548 + 255) = '\0';
                poBand->SetMetadataItem( "CWD_FILE", poDS->pachHeader + 6548 );
            }
            break;

        case 8:
            poBand->SetDescription("Canopy bulk density");

            nTemp = CPL_LSBINT16PTR (poDS->pachHeader + 4238);
            sprintf(szTemp, "%d", nTemp);
            poBand->SetMetadataItem( "CBD_UNIT", szTemp );

            if ( nTemp == 1 )
                poBand->SetMetadataItem( "CBD_UNIT_NAME", "kg/m^3" );
            if ( nTemp == 2 )
                poBand->SetMetadataItem( "CBD_UNIT_NAME", "lb/ft^3" );
            if ( nTemp == 3 )
                poBand->SetMetadataItem( "CBD_UNIT_NAME", "kg/m^3 x 100" );
            if ( nTemp == 4 )
                poBand->SetMetadataItem( "CBD_UNIT_NAME", "lb/ft^3 x 1000" );

            nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 2928);
            sprintf(szTemp, "%d", nTemp);
            poBand->SetMetadataItem( "CBD_MIN", szTemp );

            nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 2932);
            sprintf(szTemp, "%d", nTemp);
            poBand->SetMetadataItem( "CBD_MAX", szTemp );

            nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 2936);
            sprintf(szTemp, "%d", nTemp);
            poBand->SetMetadataItem( "CBD_NUM_CLASSES", szTemp );

            *(poDS->pachHeader + 6036 + 255) = '\0';
            poBand->SetMetadataItem( "CBD_FILE", poDS->pachHeader + 6036 );

            break;

        case 9:
            poBand->SetDescription("Duff");

            nTemp = CPL_LSBINT16PTR (poDS->pachHeader + 4240);
            sprintf(szTemp, "%d", nTemp);
            poBand->SetMetadataItem( "DUFF_UNIT", szTemp );

            if ( nTemp == 1 )
                poBand->SetMetadataItem( "DUFF_UNIT_NAME", "Mg/ha" );
            if ( nTemp == 2 )
                poBand->SetMetadataItem( "DUFF_UNIT_NAME", "t/ac" );

            nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 3340);
            sprintf(szTemp, "%d", nTemp);
            poBand->SetMetadataItem( "DUFF_MIN", szTemp );

            nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 3344);
            sprintf(szTemp, "%d", nTemp);
            poBand->SetMetadataItem( "DUFF_MAX", szTemp );

            nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 3348);
            sprintf(szTemp, "%d", nTemp);
            poBand->SetMetadataItem( "DUFF_NUM_CLASSES", szTemp );

            *(poDS->pachHeader + 6292 + 255) = '\0';
            poBand->SetMetadataItem( "DUFF_FILE", poDS->pachHeader + 6292 );

            break;

        case 10:
            poBand->SetDescription("Coarse woody debris");

            nTemp = CPL_LSBINT16PTR (poDS->pachHeader + 4242);
            sprintf(szTemp, "%d", nTemp);
            poBand->SetMetadataItem( "CWD_OPTION", szTemp );

            //if ( nTemp == 1 )
            //   poBand->SetMetadataItem( "CWD_UNIT_DESC", "?" );
            //if ( nTemp == 2 )
            //   poBand->SetMetadataItem( "CWD_UNIT_DESC", "?" );

            nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 3752);
            sprintf(szTemp, "%d", nTemp);
            poBand->SetMetadataItem( "CWD_MIN", szTemp );

            nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 3756);
            sprintf(szTemp, "%d", nTemp);
            poBand->SetMetadataItem( "CWD_MAX", szTemp );

            nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 3760);
            sprintf(szTemp, "%d", nTemp);
            poBand->SetMetadataItem( "CWD_NUM_CLASSES", szTemp );

            *(poDS->pachHeader + 6548 + 255) = '\0';
            poBand->SetMetadataItem( "CWD_FILE", poDS->pachHeader + 6548 );

            break;
        }
    }

    /* -------------------------------------------------------------------- */
    /*      Try to read projection file.                                    */
    /* -------------------------------------------------------------------- */
    char        *pszDirname, *pszBasename;
    VSIStatBufL   sStatBuf;

    pszDirname = CPLStrdup(CPLGetPath(poOpenInfo->pszFilename));
    pszBasename = CPLStrdup(CPLGetBasename(poOpenInfo->pszFilename));

    poDS->osPrjFilename = CPLFormFilename( pszDirname, pszBasename, "prj" );
    int nRet = VSIStatL( poDS->osPrjFilename, &sStatBuf );

    if( nRet != 0 && VSIIsCaseSensitiveFS(poDS->osPrjFilename))
    {
        poDS->osPrjFilename = CPLFormFilename( pszDirname, pszBasename, "PRJ" );
        nRet = VSIStatL( poDS->osPrjFilename, &sStatBuf );
    }

    if( nRet == 0 )
    {
        OGRSpatialReference     oSRS;

        char** papszPrj = CSLLoad( poDS->osPrjFilename );

        CPLDebug( "LCP", "Loaded SRS from %s",
                  poDS->osPrjFilename.c_str() );

        if( oSRS.importFromESRI( papszPrj ) == OGRERR_NONE )
        {
            oSRS.exportToWkt( &(poDS->pszProjection) );
        }

        CSLDestroy(papszPrj);
    }

    CPLFree( pszDirname );
    CPLFree( pszBasename );

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

    /* -------------------------------------------------------------------- */
    /*      Check for external overviews.                                   */
    /* -------------------------------------------------------------------- */
    poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename, poOpenInfo->papszSiblingFiles );

    CPLFree(pszList);

    return( poDS );
}