int EnvisatFile_GetCurrentLength( EnvisatFile *self ) { int length; int ds; int ds_offset; int ds_size; length = MPH_SIZE + EnvisatFile_GetKeyValueAsInt( self, MPH, "SPH_SIZE", 0 ); for( ds = 0; EnvisatFile_GetDatasetInfo( self, ds, NULL, NULL, NULL, &ds_offset, &ds_size, NULL, NULL ) != FAILURE; ds++ ) { if( ds_offset != 0 && (ds_offset+ds_size) > length ) length = ds_offset + ds_size; } return length; }
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 ); }
void EnvisatDataset::ScanForGCPs_MERIS() { int nDatasetIndex, nNumDSR, nDSRSize, iRecord; /* -------------------------------------------------------------------- */ /* Do we have a meaningful geolocation grid? Seach for a */ /* DS_TYPE=A and a name containing "geolocation" or "tie */ /* points". */ /* -------------------------------------------------------------------- */ nDatasetIndex = EnvisatFile_GetDatasetIndex( hEnvisatFile, "Tie points ADS" ); if( nDatasetIndex == -1 ) return; if( EnvisatFile_GetDatasetInfo( hEnvisatFile, nDatasetIndex, NULL, NULL, NULL, NULL, NULL, &nNumDSR, &nDSRSize ) != SUCCESS ) return; if( nNumDSR == 0 ) return; /* -------------------------------------------------------------------- */ /* Figure out the tiepoint space, and how many we have. */ /* -------------------------------------------------------------------- */ int nLinesPerTiePoint, nSamplesPerTiePoint; int nTPPerLine, nTPPerColumn = nNumDSR; if( nNumDSR == 0 ) return; nLinesPerTiePoint = EnvisatFile_GetKeyValueAsInt( hEnvisatFile, SPH, "LINES_PER_TIE_PT", 0 ); nSamplesPerTiePoint = EnvisatFile_GetKeyValueAsInt( hEnvisatFile, SPH, "SAMPLES_PER_TIE_PT", 0 ); if( nLinesPerTiePoint == 0 || nSamplesPerTiePoint == 0 ) return; nTPPerLine = (GetRasterXSize() + nSamplesPerTiePoint - 1) / nSamplesPerTiePoint; if( (GetRasterYSize() + nLinesPerTiePoint - 1) / nLinesPerTiePoint != nTPPerColumn ) { CPLDebug( "EnvisatDataset", "Got %d instead of %d nTPPerColumn.", (GetRasterYSize()+nLinesPerTiePoint-1)/nLinesPerTiePoint, nTPPerColumn ); return; } if( 50*nTPPerLine + 13 != nDSRSize ) { CPLDebug( "EnvisatDataset", "DSRSize=%d instead of expected %d for tiepoints ADS.", nDSRSize, 50*nTPPerLine + 13 ); return; } /* -------------------------------------------------------------------- */ /* Collect the first GCP set from each record. */ /* -------------------------------------------------------------------- */ GByte *pabyRecord = (GByte *) CPLMalloc(nDSRSize); int iGCP; GUInt32 unValue; nGCPCount = 0; pasGCPList = (GDAL_GCP *) CPLCalloc(sizeof(GDAL_GCP),nNumDSR * nTPPerLine); for( iRecord = 0; iRecord < nNumDSR; iRecord++ ) { if( EnvisatFile_ReadDatasetRecord( hEnvisatFile, nDatasetIndex, iRecord, pabyRecord ) != SUCCESS ) continue; memcpy( &unValue, pabyRecord + 13, 4 ); for( iGCP = 0; iGCP < nTPPerLine; iGCP++ ) { char szId[128]; GDALInitGCPs( 1, pasGCPList + nGCPCount ); CPLFree( pasGCPList[nGCPCount].pszId ); sprintf( szId, "%d", nGCPCount+1 ); pasGCPList[nGCPCount].pszId = CPLStrdup( szId ); memcpy( &unValue, pabyRecord + 13 + nTPPerLine*4 + iGCP*4, 4 ); pasGCPList[nGCPCount].dfGCPX = ((int)CPL_MSBWORD32(unValue))*0.000001; memcpy( &unValue, pabyRecord + 13 + iGCP*4, 4 ); pasGCPList[nGCPCount].dfGCPY = ((int)CPL_MSBWORD32(unValue))*0.000001; pasGCPList[nGCPCount].dfGCPZ = 0.0; pasGCPList[nGCPCount].dfGCPLine = iRecord*nLinesPerTiePoint + 0.5; pasGCPList[nGCPCount].dfGCPPixel = iGCP*nSamplesPerTiePoint + 0.5; nGCPCount++; } } CPLFree( pabyRecord ); }
static int EnvisatFile_RewriteHeader( EnvisatFile *self ) { int dsd, dsd_size; /* * Rewrite MPH and SPH headers. */ if( S_NameValueList_Rewrite( self->fp, self->mph_count, self->mph_entries ) == FAILURE ) return FAILURE; if( S_NameValueList_Rewrite( self->fp, self->sph_count, self->sph_entries ) == FAILURE ) return FAILURE; /* * Rewrite DSDs. We actually have to read each, and reparse to set * the individual parameters properly. */ dsd_size = EnvisatFile_GetKeyValueAsInt( self, MPH, "DSD_SIZE", 0 ); if( dsd_size == 0 ) return FAILURE; for( dsd = 0; dsd < self->ds_count; dsd++ ) { char *dsd_text; int dsdh_count = 0, key_index; EnvisatNameValue **dsdh_entries = NULL; dsd_text = (char *) calloc(1,dsd_size+1); if( fseek( self->fp, self->dsd_offset + dsd * dsd_size, SEEK_SET ) != 0 ) { SendError( "fseek() failed in EnvisatFile_RewriteHeader()" ); return FAILURE; } if( (int) fread( dsd_text, 1, dsd_size, self->fp ) != dsd_size ) { SendError( "fread() failed in EnvisatFile_RewriteHeader()" ); return FAILURE; } if( S_NameValueList_Parse( dsd_text, self->dsd_offset + dsd*dsd_size, &dsdh_count, &dsdh_entries ) == FAILURE ) return FAILURE; free( dsd_text ); key_index = S_NameValueList_FindKey( "DS_OFFSET", dsdh_count, dsdh_entries ); if( key_index == -1 ) continue; sprintf( dsdh_entries[key_index]->value, "%+021d", self->ds_info[dsd]->ds_offset ); key_index = S_NameValueList_FindKey( "DS_SIZE", dsdh_count, dsdh_entries ); sprintf( dsdh_entries[key_index]->value, "%+021d", self->ds_info[dsd]->ds_size ); key_index = S_NameValueList_FindKey( "NUM_DSR", dsdh_count, dsdh_entries ); sprintf( dsdh_entries[key_index]->value, "%+011d", self->ds_info[dsd]->num_dsr ); key_index = S_NameValueList_FindKey( "DSR_SIZE", dsdh_count, dsdh_entries ); sprintf( dsdh_entries[key_index]->value, "%+011d", self->ds_info[dsd]->dsr_size ); if( S_NameValueList_Rewrite( self->fp, dsdh_count, dsdh_entries ) == FAILURE ) return FAILURE; S_NameValueList_Destroy( &dsdh_count, &dsdh_entries ); } self->header_dirty = 0; return SUCCESS; }
int EnvisatFile_Open( EnvisatFile **self_ptr, const char *filename, const char *mode ) { FILE *fp; EnvisatFile *self; char mph_data[1248]; char *sph_data, *ds_data; int sph_size, num_dsd, dsd_size, i; *self_ptr = NULL; /* * Check for legal mode argument. Force to be binary for correct * operation on DOS file systems. */ if( strcmp(mode,"r") == 0 ) mode = "rb"; else if( strcmp(mode,"r+") == 0 ) mode = "rb+"; else { SendError( "Illegal mode value used in EnvisatFile_Open(), only " "\"r\" and \"r+\" are supported." ); return FAILURE; } /* * Try to open the file, and report failure. */ fp = fopen( filename, mode ); if( fp == NULL ) { char error_buf[2048]; sprintf( error_buf, "Unable to open file \"%s\" in EnvisatFile_Open().", filename ); SendError( error_buf ); return FAILURE; } /* * Create, and initialize the EnvisatFile structure. */ self = (EnvisatFile *) calloc(sizeof(EnvisatFile),1); if( self == NULL ) return FAILURE; self->fp = fp; self->filename = strdup( filename ); self->header_dirty = 0; self->updatable = (strcmp(mode,"rb+") == 0); /* * Read the MPH, and process it as a group of name/value pairs. */ if( fread( mph_data, 1, MPH_SIZE, fp ) != MPH_SIZE ) { free( self ); SendError( "fread() for mph failed." ); return FAILURE; } mph_data[MPH_SIZE] = '\0'; if( S_NameValueList_Parse( mph_data, 0, &(self->mph_count), &(self->mph_entries) ) == FAILURE ) return FAILURE; /* * Is this an incomplete level 0 file? */ if( EnvisatFile_GetKeyValueAsInt( self, MPH, "SPH_SIZE", -1 ) == 0 && strncmp(EnvisatFile_GetKeyValueAsString( self, MPH, "PRODUCT", ""), "ASA_IM__0P", 10) == 0 ) { if( EnvisatFile_SetupLevel0( self ) == FAILURE ) { EnvisatFile_Close( self ); return FAILURE; } else { *self_ptr = self; return SUCCESS; } } /* * Read the SPH, and process it as a group of name/value pairs. */ sph_size = EnvisatFile_GetKeyValueAsInt( self, MPH, "SPH_SIZE", 0 ); if( sph_size == 0 ) { SendError( "File does not appear to have SPH," " SPH_SIZE not set, or zero." ); return FAILURE; } sph_data = (char *) malloc(sph_size + 1 ); if( sph_data == NULL ) return FAILURE; if( (int) fread( sph_data, 1, sph_size, fp ) != sph_size ) { free( self ); SendError( "fread() for sph failed." ); return FAILURE; } sph_data[sph_size] = '\0'; ds_data = strstr(sph_data,"DS_NAME"); if( ds_data != NULL ) { self->dsd_offset = (int) (ds_data - sph_data) + MPH_SIZE; *(ds_data-1) = '\0'; } if( S_NameValueList_Parse( sph_data, MPH_SIZE, &(self->sph_count), &(self->sph_entries) ) == FAILURE ) return FAILURE; /* * Parse the Dataset Definitions. */ num_dsd = EnvisatFile_GetKeyValueAsInt( self, MPH, "NUM_DSD", 0 ); dsd_size = EnvisatFile_GetKeyValueAsInt( self, MPH, "DSD_SIZE", 0 ); if( num_dsd > 0 && ds_data == NULL ) { SendError( "DSDs indicated in MPH, but not found in SPH." ); return FAILURE; } self->ds_info = (EnvisatDatasetInfo **) calloc(sizeof(EnvisatDatasetInfo*),num_dsd); if( self->ds_info == NULL ) return FAILURE; for( i = 0; i < num_dsd; i++ ) { int dsdh_count = 0; EnvisatNameValue **dsdh_entries = NULL; char *dsd_data; EnvisatDatasetInfo *ds_info; /* * We parse each DSD grouping into a name/value list. */ dsd_data = ds_data + i * dsd_size; dsd_data[dsd_size-1] = '\0'; if( S_NameValueList_Parse( dsd_data, 0, &dsdh_count, &dsdh_entries ) == FAILURE ) return FAILURE; /* * Then build the dataset into structure from that. */ ds_info = (EnvisatDatasetInfo *) calloc(sizeof(EnvisatDatasetInfo),1); ds_info->ds_name = strdup( S_NameValueList_FindValue( "DS_NAME", dsdh_count, dsdh_entries, "" )); ds_info->ds_type = strdup( S_NameValueList_FindValue( "DS_TYPE", dsdh_count, dsdh_entries, "" )); ds_info->filename = strdup( S_NameValueList_FindValue( "FILENAME", dsdh_count, dsdh_entries, "" )); ds_info->ds_offset = atoi( S_NameValueList_FindValue( "DS_OFFSET", dsdh_count, dsdh_entries, "0" )); ds_info->ds_size = atoi( S_NameValueList_FindValue( "DS_SIZE", dsdh_count, dsdh_entries, "0" )); ds_info->num_dsr = atoi( S_NameValueList_FindValue( "NUM_DSR", dsdh_count, dsdh_entries, "0" )); ds_info->dsr_size = atoi( S_NameValueList_FindValue( "DSR_SIZE", dsdh_count, dsdh_entries, "0" )); S_NameValueList_Destroy( &dsdh_count, &dsdh_entries ); self->ds_info[i] = ds_info; self->ds_count++; } free( sph_data ); /* * Return successfully. */ *self_ptr = self; return SUCCESS; }
void EnvisatDataset::ScanForGCPs_MERIS() { int nDatasetIndex, nNumDSR, nDSRSize; bool isBrowseProduct ; /* -------------------------------------------------------------------- */ /* Do we have a meaningful geolocation grid? Seach for a */ /* DS_TYPE=A and a name containing "geolocation" or "tie */ /* points". */ /* -------------------------------------------------------------------- */ nDatasetIndex = EnvisatFile_GetDatasetIndex( hEnvisatFile, "Tie points ADS" ); if( nDatasetIndex == -1 ) return; if( EnvisatFile_GetDatasetInfo( hEnvisatFile, nDatasetIndex, NULL, NULL, NULL, NULL, NULL, &nNumDSR, &nDSRSize ) != SUCCESS ) return; if( nNumDSR == 0 ) return; /* -------------------------------------------------------------------- */ /* Figure out the tiepoint space, and how many we have. */ /* -------------------------------------------------------------------- */ int nLinesPerTiePoint, nSamplesPerTiePoint; int nTPPerLine, nTPPerColumn = nNumDSR; if( nNumDSR == 0 ) return; nLinesPerTiePoint = EnvisatFile_GetKeyValueAsInt( hEnvisatFile, SPH, "LINES_PER_TIE_PT", 0 ); nSamplesPerTiePoint = EnvisatFile_GetKeyValueAsInt( hEnvisatFile, SPH, "SAMPLES_PER_TIE_PT", 0 ); if( nLinesPerTiePoint == 0 || nSamplesPerTiePoint == 0 ) return; nTPPerLine = (GetRasterXSize() + nSamplesPerTiePoint - 1) / nSamplesPerTiePoint; /* -------------------------------------------------------------------- */ /* Find a Mesurement type dataset to use as a reference raster */ /* band. */ /* -------------------------------------------------------------------- */ int nMDSIndex; for( nMDSIndex = 0; TRUE; nMDSIndex++ ) { char *pszDSType; if( EnvisatFile_GetDatasetInfo( hEnvisatFile, nMDSIndex, NULL, &pszDSType, NULL, NULL, NULL, NULL, NULL ) == FAILURE ) { CPLDebug("EnvisatDataset", "Unable to find MDS in Envisat file.") ; return ; } if( EQUAL(pszDSType,"M") ) break; } /* -------------------------------------------------------------------- */ /* Get subset of TP ADS records matching the MDS records */ /* -------------------------------------------------------------------- */ /* get the MDS line sampling time interval */ TimeDelta tdMDSSamplingInterval( 0 , 0 , EnvisatFile_GetKeyValueAsInt( hEnvisatFile, SPH, "LINE_TIME_INTERVAL", 0 ) ); /* get range of TiePoint ADS records matching the measurements */ ADSRangeLastAfter arTP( *hEnvisatFile , nDatasetIndex, nMDSIndex , tdMDSSamplingInterval ) ; /* check if there are any TPs to be used */ if ( arTP.getDSRCount() <= 0 ) { CPLDebug( "EnvisatDataset" , "No tiepoint covering " "the measurement records." ) ; return; /* No TPs - no extraction. */ } /* check if TPs cover the whole range of MDSRs */ if(( arTP.getFirstOffset() < 0 )||( arTP.getLastOffset() < 0 )) { CPLDebug( "EnvisatDataset" , "The tiepoints do not cover " "whole range of measurement records." ) ; /* Not good but we can still extract some of the TPS, can we? */ } /* check TP records spacing */ if ((1+(arTP.getFirstOffset()+arTP.getLastOffset()+GetRasterYSize()-1) / nLinesPerTiePoint ) != arTP.getDSRCount() ) { CPLDebug( "EnvisatDataset", "Not enough tieponts per column! " "received=%d expected=%d", nTPPerColumn , 1 + (arTP.getFirstOffset()+arTP.getLastOffset()+ GetRasterYSize()-1) / nLinesPerTiePoint ) ; return; /* That is far more serious - we risk missplaces TPs. */ } if ( 50*nTPPerLine + 13 == nDSRSize ) /* regular product */ { isBrowseProduct = false ; } else if ( 8*nTPPerLine + 13 == nDSRSize ) /* browse product */ { /* although BPs are rare there is no reason not to support them */ isBrowseProduct = true ; } else { CPLDebug( "EnvisatDataset", "Unexpectd size of 'Tie points ADS' !" " received=%d expected=%d or %d" , nDSRSize , 50*nTPPerLine+13, 8*nTPPerLine+13 ) ; return; } /* -------------------------------------------------------------------- */ /* Collect the first GCP set from each record. */ /* -------------------------------------------------------------------- */ GByte *pabyRecord = (GByte *) CPLMalloc(nDSRSize-13); int iGCP; GUInt32 *tpLat = ((GUInt32*)pabyRecord) + nTPPerLine*0 ; /* latitude */ GUInt32 *tpLon = ((GUInt32*)pabyRecord) + nTPPerLine*1 ; /* longitude */ GUInt32 *tpLtc = ((GUInt32*)pabyRecord) + nTPPerLine*4 ; /* lat. DEM correction */ GUInt32 *tpLnc = ((GUInt32*)pabyRecord) + nTPPerLine*5 ; /* lon. DEM correction */ nGCPCount = 0; pasGCPList = (GDAL_GCP *) CPLCalloc( sizeof(GDAL_GCP), arTP.getDSRCount() * nTPPerLine ); for( int ir = 0 ; ir < arTP.getDSRCount() ; ir++ ) { int iRecord = ir + arTP.getFirstIndex() ; double dfGCPLine = 0.5 + ( iRecord*nLinesPerTiePoint - arTP.getFirstOffset() ) ; if( EnvisatFile_ReadDatasetRecordChunk( hEnvisatFile, nDatasetIndex, iRecord , pabyRecord, 13 , -1 ) != SUCCESS ) continue; for( iGCP = 0; iGCP < nTPPerLine; iGCP++ ) { char szId[128]; GDALInitGCPs( 1, pasGCPList + nGCPCount ); CPLFree( pasGCPList[nGCPCount].pszId ); sprintf( szId, "%d", nGCPCount+1 ); pasGCPList[nGCPCount].pszId = CPLStrdup( szId ); #define INT32(x) ((GInt32)CPL_MSBWORD32(x)) pasGCPList[nGCPCount].dfGCPX = 1e-6*INT32(tpLon[iGCP]) ; pasGCPList[nGCPCount].dfGCPY = 1e-6*INT32(tpLat[iGCP]) ; pasGCPList[nGCPCount].dfGCPZ = 0.0; if( !isBrowseProduct ) /* add DEM corrections */ { pasGCPList[nGCPCount].dfGCPX += 1e-6*INT32(tpLnc[iGCP]) ; pasGCPList[nGCPCount].dfGCPY += 1e-6*INT32(tpLtc[iGCP]) ; } #undef INT32 pasGCPList[nGCPCount].dfGCPLine = dfGCPLine ; pasGCPList[nGCPCount].dfGCPPixel = iGCP*nSamplesPerTiePoint + 0.5; nGCPCount++; } } CPLFree( pabyRecord ); }