int EnvisatFile_Create( EnvisatFile **self_ptr, const char *filename, const char *template_file ) { int template_size; char *template_data; FILE *fp; /* * Try to open the template file, and read it into memory. */ fp = fopen( template_file, "rb" ); if( fp == NULL ) { char error_buf[2048]; sprintf( error_buf, "Unable to open file \"%s\" in EnvisatFile_Create().", template_file ); SendError( error_buf ); return FAILURE; } fseek( fp, 0, SEEK_END ); template_size = (int) ftell( fp ); template_data = (char *) malloc(template_size); fseek( fp, 0, SEEK_SET ); fread( template_data, template_size, 1, fp ); fclose( fp ); /* * Try to write the template out to the new filename. */ fp = fopen( filename, "wb" ); if( fp == NULL ) { char error_buf[2048]; sprintf( error_buf, "Unable to open file \"%s\" in EnvisatFile_Create().", filename ); SendError( error_buf ); return FAILURE; } fwrite( template_data, template_size, 1, fp ); fclose( fp ); free( template_data ); /* * Now just open the file normally. */ return EnvisatFile_Open( self_ptr, filename, "r+" ); }
GDALDataset *EnvisatDataset::Open( GDALOpenInfo * poOpenInfo ) { EnvisatFile *hEnvisatFile; /* -------------------------------------------------------------------- */ /* Check the header. */ /* -------------------------------------------------------------------- */ if( poOpenInfo->nHeaderBytes < 8 ) return NULL; if( !EQUALN((const char *) poOpenInfo->pabyHeader, "PRODUCT=",8) ) return NULL; /* -------------------------------------------------------------------- */ /* Try opening the dataset. */ /* -------------------------------------------------------------------- */ int ds_index; if( EnvisatFile_Open( &hEnvisatFile, poOpenInfo->pszFilename, "r" ) == FAILURE ) return NULL; /* -------------------------------------------------------------------- */ /* Find a Mesurement type dataset to use as our reference */ /* raster band. */ /* -------------------------------------------------------------------- */ int dsr_size, num_dsr, ds_offset, bNative; char *pszDSType; for( ds_index = 0; TRUE; ds_index++ ) { if( EnvisatFile_GetDatasetInfo( hEnvisatFile, ds_index, NULL, &pszDSType, NULL, &ds_offset, NULL, &num_dsr, &dsr_size ) == FAILURE ) { CPLError( CE_Failure, CPLE_AppDefined, "Unable to find \"MDS1\" measurement datatset in Envisat file." ); EnvisatFile_Close( hEnvisatFile ); return NULL; } /* Have we found what we are looking for? A Measurement ds. */ if( EQUAL(pszDSType,"M") ) break; } /* -------------------------------------------------------------------- */ /* Confirm the requested access is supported. */ /* -------------------------------------------------------------------- */ if( poOpenInfo->eAccess == GA_Update ) { EnvisatFile_Close( hEnvisatFile ); CPLError( CE_Failure, CPLE_NotSupported, "The ENVISAT driver does not support update access to existing" " datasets.\n" ); return NULL; } /* -------------------------------------------------------------------- */ /* Create a corresponding GDALDataset. */ /* -------------------------------------------------------------------- */ EnvisatDataset *poDS; poDS = new EnvisatDataset(); poDS->hEnvisatFile = hEnvisatFile; /* -------------------------------------------------------------------- */ /* Setup image definition. */ /* -------------------------------------------------------------------- */ const char *pszDataType, *pszSampleType, *pszProduct; GDALDataType eDataType; int nPrefixBytes; EnvisatFile_GetDatasetInfo( hEnvisatFile, ds_index, NULL, NULL, NULL, &ds_offset, NULL, &num_dsr, &dsr_size ); poDS->nRasterXSize = EnvisatFile_GetKeyValueAsInt( hEnvisatFile, SPH, "LINE_LENGTH", 0 ); poDS->nRasterYSize = num_dsr; poDS->eAccess = GA_ReadOnly; pszProduct = EnvisatFile_GetKeyValueAsString( hEnvisatFile, MPH, "PRODUCT", "" ); pszDataType = EnvisatFile_GetKeyValueAsString( hEnvisatFile, SPH, "DATA_TYPE", "" ); pszSampleType = EnvisatFile_GetKeyValueAsString( hEnvisatFile, SPH, "SAMPLE_TYPE", "" ); if( EQUAL(pszDataType,"FLT32") && EQUALN(pszSampleType,"COMPLEX",7)) eDataType = GDT_CFloat32; else if( EQUAL(pszDataType,"FLT32") ) eDataType = GDT_Float32; else if( EQUAL(pszDataType,"UWORD") ) eDataType = GDT_UInt16; else if( EQUAL(pszDataType,"SWORD") && EQUALN(pszSampleType,"COMPLEX",7) ) eDataType = GDT_CInt16; else if( EQUAL(pszDataType,"SWORD") ) eDataType = GDT_Int16; else if( EQUALN(pszProduct,"ATS_TOA_1",8) ) { /* all 16bit data, no line length provided */ eDataType = GDT_Int16; poDS->nRasterXSize = (dsr_size - 20) / 2; } else if( poDS->nRasterXSize == 0 ) { CPLError( CE_Warning, CPLE_AppDefined, "Envisat product format not recognised. Assuming 8bit\n" "with no per-record prefix data. Results may be useless!" ); eDataType = GDT_Byte; poDS->nRasterXSize = dsr_size; } else { if( dsr_size >= 2 * poDS->nRasterXSize ) eDataType = GDT_UInt16; else eDataType = GDT_Byte; } #ifdef CPL_LSB bNative = FALSE; #else bNative = TRUE; #endif nPrefixBytes = dsr_size - ((GDALGetDataTypeSize(eDataType) / 8) * poDS->nRasterXSize); /* -------------------------------------------------------------------- */ /* Fail out if we didn't get non-zero sizes. */ /* -------------------------------------------------------------------- */ if( poDS->nRasterXSize < 1 || poDS->nRasterYSize < 1 ) { CPLError( CE_Failure, CPLE_AppDefined, "Unable to determine organization of dataset. It would\n" "appear this is an Envisat dataset, but an unsupported\n" "data product. Unable to utilize." ); delete poDS; return NULL; } poDS->fpImage = VSIFOpenL( poOpenInfo->pszFilename, "rb" ); if( poDS->fpImage == NULL ) { delete poDS; return NULL; } /* -------------------------------------------------------------------- */ /* Try to collect GCPs. */ /* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */ /* Scan for all datasets matching the reference dataset. */ /* -------------------------------------------------------------------- */ int num_dsr2, dsr_size2, iBand = 0; const char *pszDSName; char szBandName[128]; bool bMiltiChannel; for( ds_index = 0; EnvisatFile_GetDatasetInfo( hEnvisatFile, ds_index, (char **) &pszDSName, NULL, NULL, &ds_offset, NULL, &num_dsr2, &dsr_size2 ) == SUCCESS; ds_index++ ) { if( !EQUAL(pszDSType,"M") || num_dsr2 != num_dsr ) continue; if( EQUALN(pszProduct,"MER",3) && (pszProduct[8] == '2') && ( (strstr(pszDSName, "MDS(16)") != NULL) || (strstr(pszDSName, "MDS(19)") != NULL)) ) bMiltiChannel = true; else bMiltiChannel = false; if( (dsr_size2 == dsr_size) && !bMiltiChannel ) { poDS->SetBand( iBand+1, new RawRasterBand( poDS, iBand+1, poDS->fpImage, ds_offset + nPrefixBytes, GDALGetDataTypeSize(eDataType) / 8, dsr_size, eDataType, bNative, TRUE ) ); iBand++; poDS->GetRasterBand(iBand)->SetDescription( pszDSName ); } /* -------------------------------------------------------------------- */ /* Handle MERIS Level 2 datasets with data type different from */ /* the one declared in the SPH */ /* -------------------------------------------------------------------- */ else if( EQUALN(pszProduct,"MER",3) && (strstr(pszDSName, "Flags") != NULL) ) { if (pszProduct[8] == '1') { // Flags poDS->SetBand( iBand+1, new RawRasterBand( poDS, iBand+1, poDS->fpImage, ds_offset + nPrefixBytes, 3, dsr_size, GDT_Byte, bNative, TRUE ) ); iBand++; poDS->GetRasterBand(iBand)->SetDescription( pszDSName ); // Detector indices poDS->SetBand( iBand+1, new RawRasterBand( poDS, iBand+1, poDS->fpImage, ds_offset + nPrefixBytes + 1, 3, dsr_size, GDT_Int16, bNative, TRUE ) ); iBand++; const char *pszSuffix = strstr( pszDSName, "MDS" ); if ( pszSuffix != NULL) sprintf( szBandName, "Detector index %s", pszSuffix ); else sprintf( szBandName, "Detector index" ); poDS->GetRasterBand(iBand)->SetDescription( szBandName ); } else if ( (pszProduct[8] == '2') && (dsr_size2 >= 3 * poDS->nRasterXSize ) ) { int nFlagPrefixBytes = dsr_size2 - 3 * poDS->nRasterXSize; poDS->SetBand( iBand+1, new MerisL2FlagBand( poDS, iBand+1, poDS->fpImage, ds_offset, nFlagPrefixBytes ) ); iBand++; poDS->GetRasterBand(iBand)->SetDescription( pszDSName ); } } else if( EQUALN(pszProduct,"MER",3) && (pszProduct[8] == '2') ) { int nPrefixBytes2, nSubBands, nSubBandIdx, nSubBandOffset; int nPixelSize = 1; GDALDataType eDataType2 = GDT_Byte; nSubBands = dsr_size2 / poDS->nRasterXSize; if( (nSubBands < 1) || (nSubBands > 3) ) nSubBands = 0; nPrefixBytes2 = dsr_size2 - (nSubBands * nPixelSize * poDS->nRasterXSize); for (nSubBandIdx = 0; nSubBandIdx < nSubBands; ++nSubBandIdx) { nSubBandOffset = ds_offset + nPrefixBytes2 + nSubBandIdx * nPixelSize; poDS->SetBand( iBand+1, new RawRasterBand( poDS, iBand+1, poDS->fpImage, nSubBandOffset, nPixelSize * nSubBands, dsr_size2, eDataType2, bNative, TRUE ) ); iBand++; if (nSubBands > 1) { sprintf( szBandName, "%s (%d)", pszDSName, nSubBandIdx ); poDS->GetRasterBand(iBand)->SetDescription( szBandName ); } else poDS->GetRasterBand(iBand)->SetDescription( pszDSName ); } } } /* -------------------------------------------------------------------- */ /* Collect metadata. */ /* -------------------------------------------------------------------- */ poDS->CollectMetadata( MPH ); poDS->CollectMetadata( SPH ); poDS->CollectDSDMetadata(); poDS->CollectADSMetadata(); if( EQUALN(pszProduct,"MER",3) ) poDS->ScanForGCPs_MERIS(); else poDS->ScanForGCPs_ASAR(); /* -------------------------------------------------------------------- */ /* Initialize any PAM information. */ /* -------------------------------------------------------------------- */ poDS->SetDescription( poOpenInfo->pszFilename ); poDS->TryLoadXML(); /* -------------------------------------------------------------------- */ /* Check for overviews. */ /* -------------------------------------------------------------------- */ poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename ); return( poDS ); }
int main( int argc, char ** argv ) { EnvisatFile *es_file; int ds_index; int ds_offset, ds_size, num_dsr, dsr_size, i_record; if( argc != 2 ) { printf( "Usage: dumpgeo filename\n" ); exit( 1 ); } if( EnvisatFile_Open( &es_file, argv[1], "r" ) != 0 ) { printf( "EnvisatFile_Open(%s) failed.\n", argv[1] ); exit( 2 ); } ds_index = EnvisatFile_GetDatasetIndex( es_file, "GEOLOCATION GRID ADS" ); if( ds_index == -1 ) { printf( "Can't find geolocation grid ads.\n" ); exit( 3 ); } EnvisatFile_GetDatasetInfo( es_file, ds_index, NULL, NULL, NULL, &ds_offset, &ds_size, &num_dsr, &dsr_size ); if( ds_offset == 0 ) { printf( "No data for geolocation grid ads.\n" ); exit( 4 ); } CPLAssert( dsr_size == 521 ); for( i_record = 0; i_record < num_dsr; i_record++ ) { GByte abyRecord[521]; GUInt32 unValue; float fValue; int sample; EnvisatFile_ReadDatasetRecord( es_file, ds_index, i_record, abyRecord ); printf( "<====================== Record %d ==================>\n", i_record ); /* field 1 */ CPL_SWAP32PTR( abyRecord + 0 ); CPL_SWAP32PTR( abyRecord + 4 ); CPL_SWAP32PTR( abyRecord + 8 ); printf( "start line: mjd_days = %d, sec = %d, msec = %d\n", ((int *) abyRecord)[0], ((unsigned int *) abyRecord)[1], ((unsigned int *) abyRecord)[2] ); /* field 2 */ printf( "Attachment flag = %d\n", abyRecord[12] ); /* field 3 */ memcpy( &unValue, abyRecord + 13, 4 ); printf( "range line (first in granule) = %d\n", CPL_SWAP32( unValue ) ); /* field 4 */ memcpy( &unValue, abyRecord + 17, 4 ); printf( "lines in granule = %d\n", CPL_SWAP32( unValue ) ); /* field 5 */ memcpy( &fValue, abyRecord + 21, 4 ); CPL_SWAP32PTR( &fValue ); printf( "track heading (first line) = %f\n", fValue ); /* field 6 */ printf( "first line of granule:\n" ); for( sample = 0; sample < 11; sample++ ) { memcpy( &unValue, abyRecord + 25 + sample*4, 4 ); printf( " sample=%d ", CPL_SWAP32(unValue) ); memcpy( &fValue, abyRecord + 25 + 44 + sample * 4, 4 ); CPL_SWAP32PTR( &fValue ); printf( "time=%g ", fValue ); memcpy( &fValue, abyRecord + 25 + 88 + sample * 4, 4 ); CPL_SWAP32PTR( &fValue ); printf( "angle=%g ", fValue ); memcpy( &unValue, abyRecord + 25 + 132 + sample*4, 4 ); printf( "(%.9f,", ((int) CPL_SWAP32(unValue)) * 0.000001 ); memcpy( &unValue, abyRecord + 25 + 176 + sample*4, 4 ); printf( "%.9f)\n", ((int) CPL_SWAP32(unValue)) * 0.000001 ); } /* field 8 */ CPL_SWAP32PTR( abyRecord + 267 ); CPL_SWAP32PTR( abyRecord + 271 ); CPL_SWAP32PTR( abyRecord + 275 ); printf( "end line: mjd_days = %d, sec = %d, msec = %d\n", ((int *) (abyRecord + 267))[0], ((unsigned int *) (abyRecord + 267))[1], ((unsigned int *) (abyRecord + 267))[2] ); /* field 9 */ printf( "final line of granule:\n" ); for( sample = 0; sample < 11; sample++ ) { memcpy( &unValue, abyRecord + 279 + sample*4, 4 ); printf( " sample=%d ", CPL_SWAP32(unValue) ); memcpy( &fValue, abyRecord + 279 + 44 + sample * 4, 4 ); CPL_SWAP32PTR( &fValue ); printf( "time=%g ", fValue ); memcpy( &fValue, abyRecord + 279 + 88 + sample * 4, 4 ); CPL_SWAP32PTR( &fValue ); printf( "angle=%g ", fValue ); memcpy( &unValue, abyRecord + 279 + 132 + sample*4, 4 ); printf( "(%.9f,", ((int) CPL_SWAP32(unValue)) * 0.000001 ); memcpy( &unValue, abyRecord + 279 + 176 + sample*4, 4 ); printf( "%.9f)\n", ((int) CPL_SWAP32(unValue)) * 0.000001 ); } } EnvisatFile_Close( es_file ); exit( 0 ); }