Exemple #1
0
// static function- pointer set in driver
GDALDataset *KEADataset::Create( const char * pszFilename,
                                  int nXSize, int nYSize, int nBands,
                                  GDALDataType eType,
                                  char ** papszParmList  )
{
    H5::H5File *keaImgH5File = CreateLL( pszFilename, nXSize, nYSize, nBands,
                                         eType, papszParmList  );
    if( keaImgH5File == NULL )
        return NULL;

    bool bThematic =
        CPLTestBool(CSLFetchNameValueDef( papszParmList, "THEMATIC", "FALSE" ));

    try
    {
        // create our dataset object
        KEADataset *pDataset = new KEADataset( keaImgH5File, GA_Update );

        pDataset->SetDescription( pszFilename );

        // set all to thematic if asked
        if( bThematic )
        {
            for( int nCount = 0; nCount < nBands; nCount++ )
            {
                GDALRasterBand *pBand = pDataset->GetRasterBand(nCount+1);
                pBand->SetMetadataItem("LAYER_TYPE", "thematic");
            }
        }

        return pDataset;
    }
    catch (kealib::KEAIOException &e)
    {
        CPLError( CE_Failure, CPLE_OpenFailed,
                  "Attempt to create file `%s' failed. Error: %s\n",
                  pszFilename, e.what() );
        return NULL;
    }
}
Exemple #2
0
GDALDataset *KEADataset::CreateCopy( const char * pszFilename, GDALDataset *pSrcDs,
                                CPL_UNUSED int bStrict, char **  papszParmList, 
                                GDALProgressFunc pfnProgress, void *pProgressData )
{
    // get the data out of the input dataset
    int nXSize = pSrcDs->GetRasterXSize();
    int nYSize = pSrcDs->GetRasterYSize();
    int nBands = pSrcDs->GetRasterCount();

    GDALDataType eType = (nBands == 0) ? GDT_Unknown : pSrcDs->GetRasterBand(1)->GetRasterDataType();
    H5::H5File *keaImgH5File = CreateLL( pszFilename, nXSize, nYSize, nBands,
                                         eType, papszParmList  );
    if( keaImgH5File == NULL )
        return NULL;

    bool bThematic = CSLTestBoolean(CSLFetchNameValueDef( papszParmList, "THEMATIC", "FALSE" ));

    try
    {
        // create the imageio
        kealib::KEAImageIO *pImageIO = new kealib::KEAImageIO();
        
        // open the file
        pImageIO->openKEAImageHeader( keaImgH5File );

        // copy file
        if( !KEACopyFile( pSrcDs, pImageIO, pfnProgress, pProgressData) )
        {
            delete pImageIO;
            return NULL;
        }

        // close it
        try
        {
            pImageIO->close();
        }
        catch (kealib::KEAIOException &e)
        {
        }
        delete pImageIO;

        // now open it again - because the constructor loads all the info
        // in we need to copy the data first....
        keaImgH5File = kealib::KEAImageIO::openKeaH5RW( pszFilename );

        // and wrap it in a dataset
        KEADataset *pDataset = new KEADataset( keaImgH5File, GA_Update );
        pDataset->SetDescription( pszFilename );

        // set all to thematic if asked - overrides whatever set by CopyFile
        if( bThematic )
        {
            for( int nCount = 0; nCount < nBands; nCount++ )
            {
                GDALRasterBand *pBand = pDataset->GetRasterBand(nCount+1);
                pBand->SetMetadataItem("LAYER_TYPE", "thematic");
            }
        }

        for( int nCount = 0; nCount < nBands; nCount++ )
        {
            pDataset->GetRasterBand(nCount+1)->SetColorInterpretation(
                pSrcDs->GetRasterBand(nCount+1)->GetColorInterpretation());
        }
        
        // KEA has no concept of per-dataset mask band for now.
        for( int nCount = 0; nCount < nBands; nCount++ )
        {
            if( pSrcDs->GetRasterBand(nCount+1)->GetMaskFlags() == 0 ) // Per-band mask
            {
                pDataset->GetRasterBand(nCount+1)->CreateMaskBand(0);
                GDALRasterBandCopyWholeRaster(
                    (GDALRasterBandH)pSrcDs->GetRasterBand(nCount+1)->GetMaskBand(),
                    (GDALRasterBandH)pDataset->GetRasterBand(nCount+1)->GetMaskBand(),
                    NULL, NULL, NULL);
            }
        }

        return pDataset;
    }
    catch (kealib::KEAException &e)
    {
        CPLError( CE_Failure, CPLE_OpenFailed,
                  "Attempt to create file `%s' failed. Error: %s\n",
                  pszFilename, e.what() );
        return NULL;
    }

}
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 );
}