Changeset 12325

Show
Ignore:
Timestamp:
10/04/07 16:10:53 (9 months ago)
Author:
warmerdam
Message:

Various updates for ENVI format driver. Includes support for RPC
metadata and NoData?? value, new unit types (ticket #1730). Also some
minor bug fixes, including fatal error when ENVI header contains
colormap that is missing elements and rejection of Meta File, Virtual
Mosaic, and Spectral library types which cannot be read.
(from Bruce Payne)

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • sandbox/warmerdam/1.4-esri/gdal/frmts/raw/envidataset.cpp

    r12293 r12325  
    228228    int         ReadHeader( FILE * ); 
    229229    int         ProcessMapinfo( const char * ); 
     230    void        ProcessRPCinfo( const char * ); 
    230231    void        SetENVIDatum( OGRSpatialReference *, const char * ); 
    231232    void        SetENVIEllipse( OGRSpatialReference *, char ** ); 
     
    948949    { 
    949950        CPLError( CE_Warning, CPLE_AppDefined, 
    950                   "Unrecognised datum '%s', defaulting to WGS84." ); 
     951                  "Unrecognised datum '%s', defaulting to WGS84.", pszENVIDatumName); 
    951952        poSRS->SetWellKnownGeogCS( "WGS84" ); 
    952953    } 
     
    11411142        if( osDatumName.find_first_of("abcdefghijklmnopqrstuvwxyz" 
    11421143                                      "ABCDEFGHIJKLMNOPQRSTUVWXYZ")  
    1143                                       != std::string::npos ) 
     1144            != std::string::npos ) 
    11441145        { 
    11451146            SetENVIDatum( &oSRS, osDatumName ); 
     
    11551156/*      Try to process specialized units.                               */ 
    11561157/* -------------------------------------------------------------------- */ 
    1157     if( EQUAL(papszFields[nCount-1],"units=Feet") ) 
    1158     { 
    1159         oSRS.SetLinearUnits( SRS_UL_US_FOOT, atof(SRS_UL_US_FOOT_CONV) ); 
    1160     } 
    1161     else if( EQUAL(papszFields[nCount-1],"units=Seconds")  
    1162              && oSRS.IsGeographic() ) 
    1163     { 
    1164         /* convert geographic coordinate systems in seconds to degrees */ 
    1165         adfGeoTransform[0] /= 3600.0; 
    1166         adfGeoTransform[1] /= 3600.0; 
    1167         adfGeoTransform[2] /= 3600.0; 
    1168         adfGeoTransform[3] /= 3600.0; 
    1169         adfGeoTransform[4] /= 3600.0; 
    1170         adfGeoTransform[5] /= 3600.0; 
    1171     } 
    1172  
     1158    if( EQUALN( papszFields[nCount-1],"units",5)) 
     1159    { 
     1160        /* Handle linear units first. */ 
     1161        if (EQUAL(papszFields[nCount-1],"units=Feet") ) 
     1162            oSRS.SetLinearUnitsAndUpdateParameters( SRS_UL_FOOT, atof(SRS_UL_FOOT_CONV) ); 
     1163        else if (EQUAL(papszFields[nCount-1],"units=Meters") ) 
     1164            oSRS.SetLinearUnitsAndUpdateParameters( SRS_UL_METER, 1. ); 
     1165        else if (EQUAL(papszFields[nCount-1],"units=Km") ) 
     1166            oSRS.SetLinearUnitsAndUpdateParameters( "Kilometer", 1000.  ); 
     1167        else if (EQUAL(papszFields[nCount-1],"units=Yards") ) 
     1168            oSRS.SetLinearUnitsAndUpdateParameters( "Yard", .9144 ); 
     1169        else if (EQUAL(papszFields[nCount-1],"units=Miles") ) 
     1170            oSRS.SetLinearUnitsAndUpdateParameters( "Mile", 1609.344 ); 
     1171        else if (EQUAL(papszFields[nCount-1],"units=Nautical Miles") ) 
     1172            oSRS.SetLinearUnitsAndUpdateParameters( SRS_UL_NAUTICAL_MILE, atof(SRS_UL_NAUTICAL_MILE_CONV) ); 
     1173             
     1174        /* Only handle angular units if we know the projection is geographic. */ 
     1175        if (oSRS.IsGeographic())  
     1176        { 
     1177            if (EQUAL(papszFields[nCount-1],"units=Radians") ) 
     1178                oSRS.SetAngularUnits( SRS_UA_RADIAN, 1. ); 
     1179            else  
     1180            { 
     1181                /* Degrees, minutes and seconds will all be represented as degrees. */ 
     1182                oSRS.SetAngularUnits( SRS_UA_DEGREE,  atof(SRS_UA_DEGREE_CONV)); 
     1183 
     1184                double conversionFactor = 1.; 
     1185                if (EQUAL(papszFields[nCount-1],"units=Minutes") ) 
     1186                    conversionFactor = 60.; 
     1187                else if( EQUAL(papszFields[nCount-1],"units=Seconds") ) 
     1188                    conversionFactor = 3600.; 
     1189                adfGeoTransform[0] /= conversionFactor; 
     1190                adfGeoTransform[1] /= conversionFactor; 
     1191                adfGeoTransform[2] /= conversionFactor; 
     1192                adfGeoTransform[3] /= conversionFactor; 
     1193                adfGeoTransform[4] /= conversionFactor; 
     1194                adfGeoTransform[5] /= conversionFactor; 
     1195            } 
     1196        } 
     1197    } 
    11731198/* -------------------------------------------------------------------- */ 
    11741199/*      Turn back into WKT.                                             */ 
     
    11881213    CSLDestroy( papszPI ); 
    11891214    return TRUE; 
     1215} 
     1216 
     1217/************************************************************************/ 
     1218/*                           ProcessRPCinfo()                           */ 
     1219/*                                                                      */ 
     1220/*      Extract RPC transformation coefficients if they are present     */ 
     1221/*      and sets into the standard metadata fields for RPC.             */ 
     1222/************************************************************************/ 
     1223 
     1224void ENVIDataset::ProcessRPCinfo( const char *pszRPCinfo ) 
     1225{ 
     1226    char        **papszFields; 
     1227    char    sVal[1280]; 
     1228    int         nCount; 
     1229 
     1230    papszFields = SplitList( pszRPCinfo ); 
     1231    nCount = CSLCount(papszFields); 
     1232 
     1233    if( nCount < 90 ) 
     1234    { 
     1235        CSLDestroy( papszFields ); 
     1236        return; 
     1237    } 
     1238         
     1239    snprintf(sVal, sizeof(sVal),  "%.16f",atof(papszFields[0])); 
     1240    SetMetadataItem("RPC_LINE_OFF",sVal); 
     1241    snprintf(sVal, sizeof(sVal),  "%.16f",atof(papszFields[5])); 
     1242    SetMetadataItem("RPC_LINE_SCALE",sVal); 
     1243    snprintf(sVal, sizeof(sVal),  "%.16f",atof(papszFields[1])); 
     1244    SetMetadataItem("RPC_SAMP_OFF",sVal); 
     1245    snprintf(sVal, sizeof(sVal),  "%.16f",atof(papszFields[6])); 
     1246    SetMetadataItem("RPC_SAMP_SCALE",sVal); 
     1247    snprintf(sVal, sizeof(sVal),  "%.16f",atof(papszFields[2])); 
     1248    SetMetadataItem("RPC_LAT_OFF",sVal); 
     1249    snprintf(sVal, sizeof(sVal),  "%.16f",atof(papszFields[7])); 
     1250    SetMetadataItem("RPC_LAT_SCALE",sVal); 
     1251    snprintf(sVal, sizeof(sVal),  "%.16f",atof(papszFields[3])); 
     1252    SetMetadataItem("RPC_LONG_OFF",sVal); 
     1253    snprintf(sVal, sizeof(sVal),  "%.16f",atof(papszFields[8])); 
     1254    SetMetadataItem("RPC_LONG_SCALE",sVal); 
     1255    snprintf(sVal, sizeof(sVal),  "%.16f",atof(papszFields[4])); 
     1256    SetMetadataItem("RPC_HEIGHT_OFF",sVal); 
     1257    snprintf(sVal, sizeof(sVal),  "%.16f",atof(papszFields[9])); 
     1258    SetMetadataItem("RPC_HEIGHT_SCALE",sVal); 
     1259 
     1260    sVal[0] = '\0';  
     1261    for(int i = 0; i < 20; i++ ) 
     1262       snprintf(sVal+strlen(sVal), sizeof(sVal),  "%.16f ",  
     1263           atof(papszFields[10+i])); 
     1264    SetMetadataItem("RPC_LINE_NUM_COEFF",sVal); 
     1265 
     1266    sVal[0] = '\0';  
     1267    for(int i = 0; i < 20; i++ ) 
     1268       snprintf(sVal+strlen(sVal), sizeof(sVal),  "%.16f ", 
     1269           atof(papszFields[30+i])); 
     1270    SetMetadataItem("RPC_LINE_DEN_COEFF",sVal); 
     1271       
     1272    sVal[0] = '\0';  
     1273    for(int i = 0; i < 20; i++ ) 
     1274       snprintf(sVal+strlen(sVal), sizeof(sVal),  "%.16f ", 
     1275           atof(papszFields[50+i])); 
     1276    SetMetadataItem("RPC_SAMP_NUM_COEFF",sVal); 
     1277       
     1278    sVal[0] = '\0';  
     1279    for(int i = 0; i < 20; i++ ) 
     1280       snprintf(sVal+strlen(sVal), sizeof(sVal),  "%.16f ", 
     1281           atof(papszFields[70+i])); 
     1282    SetMetadataItem("RPC_SAMP_DEN_COEFF",sVal); 
     1283         
     1284    snprintf(sVal, sizeof(sVal), "%.16f",  
     1285        atof(papszFields[3]) - atof(papszFields[8]) / 2.0 ); 
     1286    SetMetadataItem("RPC_MIN_LONG",sVal); 
     1287 
     1288    snprintf(sVal, sizeof(sVal), "%.16f",  
     1289        atof(papszFields[3]) + atof(papszFields[8]) / 2.0 ); 
     1290    SetMetadataItem("RPC_MAX_LONG",sVal); 
     1291 
     1292    snprintf(sVal, sizeof(sVal), "%.16f", 
     1293        atof(papszFields[2]) - atof(papszFields[7]) / 2.0 ); 
     1294    SetMetadataItem("RPC_MIN_LAT",sVal); 
     1295 
     1296    snprintf(sVal, sizeof(sVal), "%.16f", 
     1297        atof(papszFields[2]) + atof(papszFields[7]) / 2.0 ); 
     1298    SetMetadataItem("RPC_MAX_LAT",sVal); 
     1299 
    11901300} 
    11911301 
     
    13961506    if( nLines == 0 || nSamples == 0 || nBands == 0 || pszInterleave == NULL ) 
    13971507    { 
     1508        delete poDS; 
    13981509        CPLError( CE_Failure, CPLE_AppDefined,  
    13991510                  "The file appears to have an associated ENVI header, but\n" 
     
    14541565 
    14551566          default: 
     1567            delete poDS; 
    14561568            CPLError( CE_Failure, CPLE_AppDefined,  
    14571569                      "The file has a 'data type' value of '%s'.  This value\n" 
     
    14791591 
    14801592/* -------------------------------------------------------------------- */ 
     1593/*      Warn about unsupported file types virtual mosaic and meta file.*/ 
     1594/* -------------------------------------------------------------------- */ 
     1595    if( CSLFetchNameValue(poDS->papszHeader,"file_type" ) != NULL ) 
     1596    { 
     1597        const char * pszEnviFileType; 
     1598        pszEnviFileType = CSLFetchNameValue(poDS->papszHeader,"file_type"); 
     1599        if(!EQUAL(pszEnviFileType, "ENVI Standard") && 
     1600           !EQUAL(pszEnviFileType, "ENVI Classification")) 
     1601        { 
     1602            delete poDS; 
     1603            CPLError( CE_Failure, CPLE_OpenFailed,  
     1604                      "File %s contains an invalid file type in the ENVI .hdr\n" 
     1605                      "GDAL does not support '%s' type files.", 
     1606                      poOpenInfo->pszFilename, pszEnviFileType ); 
     1607            return NULL; 
     1608        } 
     1609    } 
     1610 
     1611/* -------------------------------------------------------------------- */ 
    14811612/*      Warn about compressed datasets.                                 */ 
    14821613/* -------------------------------------------------------------------- */ 
     
    14861617            != 0 ) 
    14871618        { 
    1488             CPLError( CE_Warning, CPLE_AppDefined,  
     1619            delete poDS; 
     1620                        CPLError( CE_Failure, CPLE_OpenFailed,  
    14891621                      "File %s is marked as compressed in the ENVI .hdr\n" 
    14901622                      "GDAL does not support auto-decompression of ENVI data\n" 
    1491                       "files.  If the data appears corrupt please decompress\n" 
    1492                       "manually and then retry.", 
     1623                      "files.", 
    14931624                      poOpenInfo->pszFilename ); 
     1625            return NULL; 
    14941626        } 
    14951627    } 
     
    15121644    if( poDS->fpImage == NULL ) 
    15131645    { 
     1646            delete poDS; 
    15141647        CPLError( CE_Failure, CPLE_OpenFailed,  
    15151648                  "Failed to re-open %s within ENVI driver.\n",  
    15161649                  poOpenInfo->pszFilename ); 
    1517         delete poDS; 
    15181650        return NULL; 
    15191651    } 
     
    15491681    else 
    15501682    { 
     1683            delete poDS; 
    15511684        CPLError( CE_Failure, CPLE_AppDefined,  
    15521685                  "The interleaving type of the file (%s) is not supported.", 
    15531686                  pszInterleave ); 
    1554         return NULL; 
     1687           return NULL; 
    15551688    } 
    15561689     
     
    16061739        int nColorValueCount = CSLCount(papszClassColors); 
    16071740        GDALColorTable oCT; 
    1608  
    1609         for( i = 0; i*3 < nColorValueCount; i++ ) 
     1741                 
     1742        for( i = 0; i*3+2 < nColorValueCount; i++ ) 
    16101743        { 
    16111744            GDALColorEntry sEntry; 
     
    16231756        poDS->GetRasterBand(1)->SetColorInterpretation( GCI_PaletteIndex ); 
    16241757    } 
    1625      
    1626 /* -------------------------------------------------------------------- */ 
    1627 /*      Look for mapinfo                                                */ 
     1758 
     1759/* -------------------------------------------------------------------- */ 
     1760/*      Set the nodata value if it is present                           */ 
     1761/* -------------------------------------------------------------------- */       
     1762    if( CSLFetchNameValue(poDS->papszHeader,"data_ignore_value" ) != NULL ) 
     1763        { 
     1764        for( i = 0; i < poDS->nBands; i++ ) 
     1765            ((RawRasterBand*)poDS->GetRasterBand(i+1))->StoreNoDataValue(atof( 
     1766                CSLFetchNameValue(poDS->papszHeader,"data_ignore_value"))); 
     1767        } 
     1768 
     1769/* -------------------------------------------------------------------- */ 
     1770/*      Look for mapinfo                                                */ 
    16281771/* -------------------------------------------------------------------- */ 
    16291772    if( CSLFetchNameValue( poDS->papszHeader, "map_info" ) != NULL ) 
     
    16321775            poDS->ProcessMapinfo(  
    16331776                CSLFetchNameValue(poDS->papszHeader,"map_info") ); 
     1777    } 
     1778 
     1779/* -------------------------------------------------------------------- */ 
     1780/*      Look for RPC mapinfo                                            */ 
     1781/* -------------------------------------------------------------------- */ 
     1782    if( CSLFetchNameValue( poDS->papszHeader, "rpc_info" ) != NULL ) 
     1783    { 
     1784                poDS->ProcessRPCinfo(  
     1785                        CSLFetchNameValue(poDS->papszHeader,"rpc_info") ); 
    16341786    } 
    16351787