CPLErr PAuxDataset::GetGeoTransform( double * padfGeoTransform ) { if( CSLFetchNameValue(papszAuxLines, "UpLeftX") != NULL && CSLFetchNameValue(papszAuxLines, "UpLeftY") != NULL && CSLFetchNameValue(papszAuxLines, "LoRightX") != NULL && CSLFetchNameValue(papszAuxLines, "LoRightY") != NULL ) { const double dfUpLeftX = CPLAtof(CSLFetchNameValue(papszAuxLines, "UpLeftX" )); const double dfUpLeftY = CPLAtof(CSLFetchNameValue(papszAuxLines, "UpLeftY" )); const double dfLoRightX = CPLAtof(CSLFetchNameValue(papszAuxLines, "LoRightX" )); const double dfLoRightY = CPLAtof(CSLFetchNameValue(papszAuxLines, "LoRightY" )); padfGeoTransform[0] = dfUpLeftX; padfGeoTransform[1] = (dfLoRightX - dfUpLeftX) / GetRasterXSize(); padfGeoTransform[2] = 0.0; padfGeoTransform[3] = dfUpLeftY; padfGeoTransform[4] = 0.0; padfGeoTransform[5] = (dfLoRightY - dfUpLeftY) / GetRasterYSize(); return CE_None; } else { padfGeoTransform[0] = 0.0; padfGeoTransform[1] = 1.0; padfGeoTransform[2] = 0.0; padfGeoTransform[3] = 0.0; padfGeoTransform[4] = 0.0; padfGeoTransform[5] = 1.0; return CE_Failure; } }
CPLErr MEMDataset::AddBand( GDALDataType eType, char **papszOptions ) { int nBandId = GetRasterCount() + 1; GByte *pData; int nPixelSize = (GDALGetDataTypeSize(eType) / 8); /* -------------------------------------------------------------------- */ /* Do we need to allocate the memory ourselves? This is the */ /* simple case. */ /* -------------------------------------------------------------------- */ if( CSLFetchNameValue( papszOptions, "DATAPOINTER" ) == NULL ) { pData = (GByte *) VSICalloc(nPixelSize * GetRasterXSize(), GetRasterYSize() ); if( pData == NULL ) { CPLError( CE_Failure, CPLE_OutOfMemory, "Unable to create band arrays ... out of memory." ); return CE_Failure; } SetBand( nBandId, new MEMRasterBand( this, nBandId, pData, eType, nPixelSize, nPixelSize * GetRasterXSize(), TRUE ) ); return CE_None; } /* -------------------------------------------------------------------- */ /* Get layout of memory and other flags. */ /* -------------------------------------------------------------------- */ const char *pszOption; int nPixelOffset, nLineOffset; const char *pszDataPointer; pszDataPointer = CSLFetchNameValue(papszOptions,"DATAPOINTER"); pData = (GByte *) CPLScanPointer(pszDataPointer, strlen(pszDataPointer)); pszOption = CSLFetchNameValue(papszOptions,"PIXELOFFSET"); if( pszOption == NULL ) nPixelOffset = nPixelSize; else nPixelOffset = atoi(pszOption); pszOption = CSLFetchNameValue(papszOptions,"LINEOFFSET"); if( pszOption == NULL ) nLineOffset = GetRasterXSize() * nPixelOffset; else nLineOffset = atoi(pszOption); SetBand( nBandId, new MEMRasterBand( this, nBandId, pData, eType, nPixelOffset, nLineOffset, FALSE ) ); return CE_None; }
CPLErr PAuxDataset::SetGeoTransform( double * padfGeoTransform ) { char szUpLeftX[128] = { '\0' }; char szUpLeftY[128] = { '\0' }; char szLoRightX[128] = { '\0' }; char szLoRightY[128] = { '\0' }; if( std::abs(padfGeoTransform[0]) < 181 && std::abs(padfGeoTransform[1]) < 1 ) { CPLsnprintf( szUpLeftX, sizeof(szUpLeftX), "%.12f", padfGeoTransform[0] ); CPLsnprintf( szUpLeftY, sizeof(szUpLeftY), "%.12f", padfGeoTransform[3] ); CPLsnprintf( szLoRightX, sizeof(szLoRightX), "%.12f", padfGeoTransform[0] + padfGeoTransform[1] * GetRasterXSize() ); CPLsnprintf( szLoRightY, sizeof(szLoRightY), "%.12f", padfGeoTransform[3] + padfGeoTransform[5] * GetRasterYSize() ); } else { CPLsnprintf( szUpLeftX, sizeof(szUpLeftX), "%.3f", padfGeoTransform[0] ); CPLsnprintf( szUpLeftY, sizeof(szUpLeftY), "%.3f", padfGeoTransform[3] ); CPLsnprintf( szLoRightX, sizeof(szLoRightX), "%.3f", padfGeoTransform[0] + padfGeoTransform[1] * GetRasterXSize() ); CPLsnprintf( szLoRightY, sizeof(szLoRightY), "%.3f", padfGeoTransform[3] + padfGeoTransform[5] * GetRasterYSize() ); } papszAuxLines = CSLSetNameValue( papszAuxLines, "UpLeftX", szUpLeftX ); papszAuxLines = CSLSetNameValue( papszAuxLines, "UpLeftY", szUpLeftY ); papszAuxLines = CSLSetNameValue( papszAuxLines, "LoRightX", szLoRightX ); papszAuxLines = CSLSetNameValue( papszAuxLines, "LoRightY", szLoRightY ); bAuxUpdated = TRUE; return CE_None; }
CPLErr SDEDataset::GetGeoTransform( double * padfTransform ) { if (dfMinX == 0.0 && dfMinY == 0.0 && dfMaxX == 0.0 && dfMaxY == 0.0) return CE_Fatal; padfTransform[0] = dfMinX - 0.5*(dfMaxX - dfMinX) / (GetRasterXSize()-1); padfTransform[3] = dfMaxY + 0.5*(dfMaxY - dfMinY) / (GetRasterYSize()-1); padfTransform[1] = (dfMaxX - dfMinX) / (GetRasterXSize()-1); padfTransform[2] = 0.0; padfTransform[4] = 0.0; padfTransform[5] = -1 * (dfMaxY - dfMinY) / (GetRasterYSize()-1); return CE_None; }
CPLErr JDEMDataset::GetGeoTransform( double * padfTransform ) { const double dfLLLat = JDEMGetAngle( (char *) abyHeader + 29 ); const double dfLLLong = JDEMGetAngle( (char *) abyHeader + 36 ); const double dfURLat = JDEMGetAngle( (char *) abyHeader + 43 ); const double dfURLong = JDEMGetAngle( (char *) abyHeader + 50 ); padfTransform[0] = dfLLLong; padfTransform[3] = dfURLat; padfTransform[1] = (dfURLong - dfLLLong) / GetRasterXSize(); padfTransform[2] = 0.0; padfTransform[4] = 0.0; padfTransform[5] = -1 * (dfURLat - dfLLLat) / GetRasterYSize(); return CE_None; }
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 ); }
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 ); }
CPLErr VRTDataset::AddBand( GDALDataType eType, char **papszOptions ) { int i; const char *pszSubClass = CSLFetchNameValue(papszOptions, "subclass"); bNeedsFlush = 1; /* ==================================================================== */ /* Handle a new raw band. */ /* ==================================================================== */ if( pszSubClass != NULL && EQUAL(pszSubClass,"VRTRawRasterBand") ) { int nWordDataSize = GDALGetDataTypeSize( eType ) / 8; vsi_l_offset nImageOffset = 0; int nPixelOffset = nWordDataSize; int nLineOffset = nWordDataSize * GetRasterXSize(); const char *pszFilename; const char *pszByteOrder = NULL; int bRelativeToVRT = FALSE; /* -------------------------------------------------------------------- */ /* Collect required information. */ /* -------------------------------------------------------------------- */ if( CSLFetchNameValue(papszOptions, "ImageOffset") != NULL ) nImageOffset = atoi(CSLFetchNameValue(papszOptions, "ImageOffset")); if( CSLFetchNameValue(papszOptions, "PixelOffset") != NULL ) nPixelOffset = atoi(CSLFetchNameValue(papszOptions,"PixelOffset")); if( CSLFetchNameValue(papszOptions, "LineOffset") != NULL ) nLineOffset = atoi(CSLFetchNameValue(papszOptions, "LineOffset")); if( CSLFetchNameValue(papszOptions, "ByteOrder") != NULL ) pszByteOrder = CSLFetchNameValue(papszOptions, "ByteOrder"); if( CSLFetchNameValue(papszOptions, "SourceFilename") != NULL ) pszFilename = CSLFetchNameValue(papszOptions, "SourceFilename"); else { CPLError( CE_Failure, CPLE_AppDefined, "AddBand() requires a SourceFilename option for VRTRawRasterBands." ); return CE_Failure; } bRelativeToVRT = CSLFetchBoolean( papszOptions, "RelativeToVRT", FALSE ); /* -------------------------------------------------------------------- */ /* Create and initialize the band. */ /* -------------------------------------------------------------------- */ CPLErr eErr; VRTRawRasterBand *poBand = new VRTRawRasterBand( this, GetRasterCount() + 1, eType ); eErr = poBand->SetRawLink( pszFilename, NULL, FALSE, nImageOffset, nPixelOffset, nLineOffset, pszByteOrder ); if( eErr != CE_None ) { delete poBand; return eErr; } SetBand( GetRasterCount() + 1, poBand ); return CE_None; } /* ==================================================================== */ /* Handle a new "sourced" band. */ /* ==================================================================== */ else { VRTSourcedRasterBand *poBand; /* ---- Check for our sourced band 'derived' subclass ---- */ if(pszSubClass != NULL && EQUAL(pszSubClass,"VRTDerivedRasterBand")) { /* We'll need a pointer to the subclass in case we need */ /* to set the new band's pixel function below. */ VRTDerivedRasterBand* poDerivedBand; poDerivedBand = new VRTDerivedRasterBand (this, GetRasterCount() + 1, eType, GetRasterXSize(), GetRasterYSize()); /* Set the pixel function options it provided. */ const char* pszFuncName = CSLFetchNameValue(papszOptions, "PixelFunctionType"); if (pszFuncName != NULL) poDerivedBand->SetPixelFunctionName(pszFuncName); const char* pszTransferTypeName = CSLFetchNameValue(papszOptions, "SourceTransferType"); if (pszTransferTypeName != NULL) { GDALDataType eTransferType = GDALGetDataTypeByName(pszTransferTypeName); if (eTransferType == GDT_Unknown) { CPLError( CE_Failure, CPLE_AppDefined, "invalid SourceTransferType: \"%s\".", pszTransferTypeName); delete poDerivedBand; return CE_Failure; } poDerivedBand->SetSourceTransferType(eTransferType); } /* We're done with the derived band specific stuff, so */ /* we can assigned the base class pointer now. */ poBand = poDerivedBand; } else { /* ---- Standard sourced band ---- */ poBand = new VRTSourcedRasterBand (this, GetRasterCount() + 1, eType, GetRasterXSize(), GetRasterYSize()); } SetBand( GetRasterCount() + 1, poBand ); for( i=0; papszOptions != NULL && papszOptions[i] != NULL; i++ ) { if( EQUALN(papszOptions[i],"AddFuncSource=", 14) ) { VRTImageReadFunc pfnReadFunc = NULL; void *pCBData = NULL; double dfNoDataValue = VRT_NODATA_UNSET; char **papszTokens = CSLTokenizeStringComplex( papszOptions[i]+14, ",", TRUE, FALSE ); if( CSLCount(papszTokens) < 1 ) { CPLError( CE_Failure, CPLE_AppDefined, "AddFuncSource() ... required argument missing." ); } sscanf( papszTokens[0], "%p", &pfnReadFunc ); if( CSLCount(papszTokens) > 1 ) sscanf( papszTokens[1], "%p", &pCBData ); if( CSLCount(papszTokens) > 2 ) dfNoDataValue = atof( papszTokens[2] ); poBand->AddFuncSource( pfnReadFunc, pCBData, dfNoDataValue ); } } return CE_None; } }
CPLXMLNode *VRTDataset::SerializeToXML( const char *pszVRTPath ) { /* -------------------------------------------------------------------- */ /* Setup root node and attributes. */ /* -------------------------------------------------------------------- */ CPLXMLNode *psDSTree = NULL; CPLXMLNode *psMD = NULL; char szNumber[128]; psDSTree = CPLCreateXMLNode( NULL, CXT_Element, "VRTDataset" ); sprintf( szNumber, "%d", GetRasterXSize() ); CPLSetXMLValue( psDSTree, "#rasterXSize", szNumber ); sprintf( szNumber, "%d", GetRasterYSize() ); CPLSetXMLValue( psDSTree, "#rasterYSize", szNumber ); /* -------------------------------------------------------------------- */ /* SRS */ /* -------------------------------------------------------------------- */ if( pszProjection != NULL && strlen(pszProjection) > 0 ) CPLSetXMLValue( psDSTree, "SRS", pszProjection ); /* -------------------------------------------------------------------- */ /* Geotransform. */ /* -------------------------------------------------------------------- */ if( bGeoTransformSet ) { CPLSetXMLValue( psDSTree, "GeoTransform", CPLSPrintf( "%24.16e,%24.16e,%24.16e,%24.16e,%24.16e,%24.16e", adfGeoTransform[0], adfGeoTransform[1], adfGeoTransform[2], adfGeoTransform[3], adfGeoTransform[4], adfGeoTransform[5] ) ); } /* -------------------------------------------------------------------- */ /* Metadata */ /* -------------------------------------------------------------------- */ psMD = oMDMD.Serialize(); if( psMD != NULL ) CPLAddXMLChild( psDSTree, psMD ); /* -------------------------------------------------------------------- */ /* GCPs */ /* -------------------------------------------------------------------- */ if( nGCPCount > 0 ) { CPLXMLNode *psGCPList = CPLCreateXMLNode( psDSTree, CXT_Element, "GCPList" ); CPLXMLNode* psLastChild = NULL; if( pszGCPProjection != NULL && strlen(pszGCPProjection) > 0 ) { CPLSetXMLValue( psGCPList, "#Projection", pszGCPProjection ); psLastChild = psGCPList->psChild; } for( int iGCP = 0; iGCP < nGCPCount; iGCP++ ) { CPLXMLNode *psXMLGCP; GDAL_GCP *psGCP = pasGCPList + iGCP; psXMLGCP = CPLCreateXMLNode( NULL, CXT_Element, "GCP" ); if( psLastChild == NULL ) psGCPList->psChild = psXMLGCP; else psLastChild->psNext = psXMLGCP; psLastChild = psXMLGCP; CPLSetXMLValue( psXMLGCP, "#Id", psGCP->pszId ); if( psGCP->pszInfo != NULL && strlen(psGCP->pszInfo) > 0 ) CPLSetXMLValue( psXMLGCP, "Info", psGCP->pszInfo ); CPLSetXMLValue( psXMLGCP, "#Pixel", CPLSPrintf( "%.4f", psGCP->dfGCPPixel ) ); CPLSetXMLValue( psXMLGCP, "#Line", CPLSPrintf( "%.4f", psGCP->dfGCPLine ) ); CPLSetXMLValue( psXMLGCP, "#X", CPLSPrintf( "%.12E", psGCP->dfGCPX ) ); CPLSetXMLValue( psXMLGCP, "#Y", CPLSPrintf( "%.12E", psGCP->dfGCPY ) ); if( psGCP->dfGCPZ != 0.0 ) CPLSetXMLValue( psXMLGCP, "#GCPZ", CPLSPrintf( "%.12E", psGCP->dfGCPZ ) ); } } /* -------------------------------------------------------------------- */ /* Serialize bands. */ /* -------------------------------------------------------------------- */ for( int iBand = 0; iBand < nBands; iBand++ ) { CPLXMLNode *psBandTree = ((VRTRasterBand *) papoBands[iBand])->SerializeToXML(pszVRTPath); if( psBandTree != NULL ) CPLAddXMLChild( psDSTree, psBandTree ); } /* -------------------------------------------------------------------- */ /* Serialize dataset mask band. */ /* -------------------------------------------------------------------- */ if (poMaskBand) { CPLXMLNode *psBandTree = poMaskBand->SerializeToXML(pszVRTPath); if( psBandTree != NULL ) { CPLXMLNode *psMaskBandElement = CPLCreateXMLNode( psDSTree, CXT_Element, "MaskBand" ); CPLAddXMLChild( psMaskBandElement, psBandTree ); } } return psDSTree; }
void BAGDataset::LoadMetadata() { /* -------------------------------------------------------------------- */ /* Load the metadata from the file. */ /* -------------------------------------------------------------------- */ hid_t hMDDS = H5Dopen( hHDF5, "/BAG_root/metadata" ); hid_t datatype = H5Dget_type( hMDDS ); hid_t dataspace = H5Dget_space( hMDDS ); hid_t native = H5Tget_native_type( datatype, H5T_DIR_ASCEND ); hsize_t dims[3], maxdims[3]; H5Sget_simple_extent_dims( dataspace, dims, maxdims ); pszXMLMetadata = (char *) CPLCalloc(dims[0]+1,1); H5Dread( hMDDS, native, H5S_ALL, dataspace, H5P_DEFAULT, pszXMLMetadata ); H5Sclose( dataspace ); H5Tclose( datatype ); H5Dclose( hMDDS ); if( strlen(pszXMLMetadata) == 0 ) return; /* -------------------------------------------------------------------- */ /* Try to get the geotransform. */ /* -------------------------------------------------------------------- */ CPLXMLNode *psRoot = CPLParseXMLString( pszXMLMetadata ); if( psRoot == NULL ) return; CPLStripXMLNamespace( psRoot, NULL, TRUE ); CPLXMLNode *psGeo = CPLSearchXMLNode( psRoot, "=MD_Georectified" ); if( psGeo != NULL ) { char **papszCornerTokens = CSLTokenizeStringComplex( CPLGetXMLValue( psGeo, "cornerPoints.Point.coordinates", "" ), " ,", FALSE, FALSE ); if( CSLCount(papszCornerTokens ) == 4 ) { double dfLLX = atof( papszCornerTokens[0] ); double dfLLY = atof( papszCornerTokens[1] ); double dfURX = atof( papszCornerTokens[2] ); double dfURY = atof( papszCornerTokens[3] ); adfGeoTransform[0] = dfLLX; adfGeoTransform[1] = (dfURX - dfLLX) / (GetRasterXSize()-1); adfGeoTransform[3] = dfURY; adfGeoTransform[5] = (dfLLY - dfURY) / (GetRasterYSize()-1); adfGeoTransform[0] -= adfGeoTransform[1] * 0.5; adfGeoTransform[3] -= adfGeoTransform[5] * 0.5; } CSLDestroy( papszCornerTokens ); } CPLDestroyXMLNode( psRoot ); /* -------------------------------------------------------------------- */ /* Try to get the coordinate system. */ /* -------------------------------------------------------------------- */ OGRSpatialReference oSRS; if( OGR_SRS_ImportFromISO19115( &oSRS, pszXMLMetadata ) == OGRERR_NONE ) { oSRS.exportToWkt( &pszProjection ); } }
bool OsmAnd::HeightmapTileProvider_P::obtainData( const TileId tileId, const ZoomLevel zoom, std::shared_ptr<MapTiledData>& outTiledData, const IQueryController* const queryController) { // Obtain raw data from DB QByteArray data; bool ok = _tileDb.obtainTileData(tileId, zoom, data); if (!ok || data.length() == 0) { // There was no data at all, to avoid further requests, mark this tile as empty outTiledData.reset(); return true; } // We have the data, use GDAL to decode this GeoTIFF const auto tileSize = getTileSize(); bool success = false; QString vmemFilename; vmemFilename.sprintf("/vsimem/heightmapTile@%p", data.data()); VSIFileFromMemBuffer(qPrintable(vmemFilename), reinterpret_cast<GByte*>(data.data()), data.length(), FALSE); auto dataset = reinterpret_cast<GDALDataset*>(GDALOpen(qPrintable(vmemFilename), GA_ReadOnly)); if (dataset != nullptr) { bool bad = false; bad = bad || dataset->GetRasterCount() != 1; bad = bad || dataset->GetRasterXSize() != tileSize; bad = bad || dataset->GetRasterYSize() != tileSize; if (bad) { if (dataset->GetRasterCount() != 1) LogPrintf(LogSeverityLevel::Error, "Height tile %dx%d@%d has %d bands instead of 1", tileId.x, tileId.y, zoom, dataset->GetRasterCount()); if (dataset->GetRasterXSize() != tileSize || dataset->GetRasterYSize() != tileSize) { LogPrintf(LogSeverityLevel::Error, "Height tile %dx%d@%d has %dx%x size instead of %d", tileId.x, tileId.y, zoom, dataset->GetRasterXSize(), dataset->GetRasterYSize(), tileSize); } } else { auto band = dataset->GetRasterBand(1); bad = bad || band->GetColorTable() != nullptr; bad = bad || band->GetRasterDataType() != GDT_Int16; if (bad) { if (band->GetColorTable() != nullptr) LogPrintf(LogSeverityLevel::Error, "Height tile %dx%d@%d has color table", tileId.x, tileId.y, zoom); if (band->GetRasterDataType() != GDT_Int16) LogPrintf(LogSeverityLevel::Error, "Height tile %dx%d@%d has %s data type in band 1", tileId.x, tileId.y, zoom, GDALGetDataTypeName(band->GetRasterDataType())); } else { auto buffer = new float[tileSize*tileSize]; auto res = dataset->RasterIO(GF_Read, 0, 0, tileSize, tileSize, buffer, tileSize, tileSize, GDT_Float32, 1, nullptr, 0, 0, 0); if (res != CE_None) { delete[] buffer; LogPrintf(LogSeverityLevel::Error, "Failed to decode height tile %dx%d@%d: %s", tileId.x, tileId.y, zoom, CPLGetLastErrorMsg()); } else { outTiledData.reset(new ElevationDataTile(buffer, sizeof(float)*tileSize, tileSize, tileId, zoom)); success = true; } } } GDALClose(dataset); } VSIUnlink(qPrintable(vmemFilename)); return success; }
CPLErr VRTWarpedDataset::IBuildOverviews( const char *pszResampling, int nOverviews, int *panOverviewList, int nListBands, int *panBandList, GDALProgressFunc pfnProgress, void * pProgressData ) { /* -------------------------------------------------------------------- */ /* Initial progress result. */ /* -------------------------------------------------------------------- */ if( !pfnProgress( 0.0, NULL, pProgressData ) ) { CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" ); return CE_Failure; } /* -------------------------------------------------------------------- */ /* Establish which of the overview levels we already have, and */ /* which are new. */ /* -------------------------------------------------------------------- */ int i, nNewOverviews, *panNewOverviewList = NULL; nNewOverviews = 0; panNewOverviewList = (int *) CPLCalloc(sizeof(int),nOverviews); for( i = 0; i < nOverviews; i++ ) { int j; for( j = 0; j < nOverviewCount; j++ ) { int nOvFactor; VRTWarpedDataset *poOverview = papoOverviews[j]; nOvFactor = (int) (0.5+GetRasterXSize() / (double) poOverview->GetRasterXSize()); if( nOvFactor == panOverviewList[i] || nOvFactor == GDALOvLevelAdjust( panOverviewList[i], GetRasterXSize() ) ) panOverviewList[i] *= -1; } if( panOverviewList[i] > 0 ) panNewOverviewList[nNewOverviews++] = panOverviewList[i]; } /* -------------------------------------------------------------------- */ /* Create each missing overview (we don't need to do anything */ /* to update existing overviews). */ /* -------------------------------------------------------------------- */ for( i = 0; i < nNewOverviews; i++ ) { int nOXSize, nOYSize, iBand; VWOTInfo *psInfo; VRTWarpedDataset *poOverviewDS; /* -------------------------------------------------------------------- */ /* What size should this overview be. */ /* -------------------------------------------------------------------- */ nOXSize = (GetRasterXSize() + panNewOverviewList[i] - 1) / panNewOverviewList[i]; nOYSize = (GetRasterYSize() + panNewOverviewList[i] - 1) / panNewOverviewList[i]; /* -------------------------------------------------------------------- */ /* Create the overview dataset. */ /* -------------------------------------------------------------------- */ poOverviewDS = new VRTWarpedDataset( nOXSize, nOYSize ); for( iBand = 0; iBand < GetRasterCount(); iBand++ ) { GDALRasterBand *poOldBand = GetRasterBand(iBand+1); VRTWarpedRasterBand *poNewBand = new VRTWarpedRasterBand( poOverviewDS, iBand+1, poOldBand->GetRasterDataType() ); poNewBand->CopyCommonInfoFrom( poOldBand ); poOverviewDS->SetBand( iBand+1, poNewBand ); } nOverviewCount++; papoOverviews = (VRTWarpedDataset **) CPLRealloc( papoOverviews, sizeof(void*) * nOverviewCount ); papoOverviews[nOverviewCount-1] = poOverviewDS; /* -------------------------------------------------------------------- */ /* Prepare update transformation information that will apply */ /* the overview decimation. */ /* -------------------------------------------------------------------- */ GDALWarpOptions *psWO = (GDALWarpOptions *) poWarper->GetOptions(); psInfo = (VWOTInfo *) CPLCalloc(sizeof(VWOTInfo),1); strcpy( psInfo->sTI.szSignature, "GTI" ); psInfo->sTI.pszClassName = "VRTWarpedOverviewTransform"; psInfo->sTI.pfnTransform = VRTWarpedOverviewTransform; psInfo->sTI.pfnCleanup = VRTWarpedOverviewCleanup; psInfo->sTI.pfnSerialize = NULL; psInfo->pfnBaseTransformer = psWO->pfnTransformer; psInfo->pBaseTransformerArg = psWO->pTransformerArg; psInfo->dfXOverviewFactor = GetRasterXSize() / (double) nOXSize; psInfo->dfYOverviewFactor = GetRasterYSize() / (double) nOYSize; /* -------------------------------------------------------------------- */ /* Initialize the new dataset with adjusted warp options, and */ /* then restore to original condition. */ /* -------------------------------------------------------------------- */ psWO->pfnTransformer = VRTWarpedOverviewTransform; psWO->pTransformerArg = psInfo; poOverviewDS->Initialize( psWO ); psWO->pfnTransformer = psInfo->pfnBaseTransformer; psWO->pTransformerArg = psInfo->pBaseTransformerArg; } CPLFree( panNewOverviewList ); /* -------------------------------------------------------------------- */ /* Progress finished. */ /* -------------------------------------------------------------------- */ pfnProgress( 1.0, NULL, pProgressData ); SetNeedsFlush(); return CE_None; }
bool TerragenDataset::write_header() { char szHeader[16]; memcpy(szHeader, "TERRAGENTERRAIN ", sizeof(szHeader)); if(1 != VSIFWriteL( reinterpret_cast<void *>( szHeader ), sizeof(szHeader), 1, m_fp )) { CPLError( CE_Failure, CPLE_FileIO, "Couldn't write to Terragen file %s.\n" "Is file system full?", m_pszFilename ); VSIFCloseL( m_fp ); return false; } // -------------------------------------------------------------------- // Write out the heightfield dimensions, etc. // -------------------------------------------------------------------- const int nXSize = GetRasterXSize(); const int nYSize = GetRasterYSize(); write_next_tag( "SIZE" ); put( static_cast<GInt16>( std::min( nXSize, nYSize ) - 1 ) ); pad( sizeof(GInt16) ); if(nXSize != nYSize) { write_next_tag( "XPTS" ); put( static_cast<GInt16>( nXSize ) ); pad( sizeof(GInt16) ); write_next_tag( "YPTS" ); put( static_cast<GInt16>( nYSize ) ); pad( sizeof(GInt16) ); } if(m_bIsGeo) { /* With a geographic projection (degrees), m_dGroundScale will be in degrees and m_dMetersPerGroundUnit is undefined. So we're going to estimate a m_dMetersPerGroundUnit value here (i.e., meters per degree). We figure out the degree size of one pixel, and then the latitude degrees of the heightfield's center. The circumference of the latitude's great circle lets us know how wide the pixel is in meters, and we average that with the pixel's meter breadth, which is based on the polar circumference. */ /*const double m_dDegLongPerPixel = fabs(m_adfTransform[1]);*/ const double m_dDegLatPerPixel = std::abs(m_adfTransform[5]); /*const double m_dCenterLongitude = m_adfTransform[0] + (0.5 * m_dDegLongPerPixel * (nXSize-1));*/ const double m_dCenterLatitude = m_adfTransform[3] + (0.5 * m_dDegLatPerPixel * (nYSize-1)); const double dLatCircum = kdEarthCircumEquat * std::sin( degrees_to_radians( 90.0 - m_dCenterLatitude ) ); const double dMetersPerDegLongitude = dLatCircum / 360; /*const double dMetersPerPixelX = (m_dDegLongPerPixel / 360) * dLatCircum;*/ const double dMetersPerDegLatitude = kdEarthCircumPolar / 360; /*const double dMetersPerPixelY = (m_dDegLatPerPixel / 360) * kdEarthCircumPolar;*/ m_dMetersPerGroundUnit = average(dMetersPerDegLongitude, dMetersPerDegLatitude); } m_dSCAL = m_dGroundScale * m_dMetersPerGroundUnit; if(m_dSCAL != 30.0) { const float sc = static_cast<float>( m_dSCAL ); write_next_tag( "SCAL" ); put( sc ); put( sc ); put( sc ); } if( !write_next_tag( "ALTW" ) ) { CPLError( CE_Failure, CPLE_FileIO, "Couldn't write to Terragen file %s.\n" "Is file system full?", m_pszFilename ); VSIFCloseL( m_fp ); return false; } // Compute physical scales and offsets. m_span_m[0] = m_dLogSpan[0] * m_dMetersPerElevUnit; m_span_m[1] = m_dLogSpan[1] * m_dMetersPerElevUnit; m_span_px[0] = m_span_m[0] / m_dSCAL; m_span_px[1] = m_span_m[1] / m_dSCAL; const double span_px = m_span_px[1] - m_span_px[0]; m_nHeightScale = static_cast<GInt16>( span_px ); if(m_nHeightScale == 0) m_nHeightScale++; // TODO(schwehr): Make static functions. #define P2L_PX(n, hs, bh) (static_cast<double>( n ) / 65536.0 * (hs) + (bh)) #define L2P_PX(n, hs, bh) (static_cast<int>( ((n)-(bh)) * 65536.0 / (hs) ) ) // Increase the heightscale until the physical span // fits within a 16-bit range. The smaller the logical span, // the more necessary this becomes. int hs = m_nHeightScale; int bh = 0; for( ; hs <= 32767; hs++) { double prevdelta = 1.0e30; for( bh = -32768; bh <= 32767; bh++ ) { const int nValley = L2P_PX(m_span_px[0], hs, bh); if(nValley < -32768) continue; const int nPeak = L2P_PX(m_span_px[1], hs, bh); if(nPeak > 32767) continue; // now see how closely the baseheight gets // to the pixel span. const double d = P2L_PX(nValley, hs, bh); const double delta = std::abs(d - m_span_px[0]); if(delta < prevdelta) // Converging? prevdelta = delta; else { // We're diverging, so use the previous bh // and stop looking. bh--; break; } } if(bh != 32768) break; } if(hs == 32768) { CPLError( CE_Failure, CPLE_FileIO, "Couldn't write to Terragen file %s.\n" "Cannot find adequate heightscale/baseheight combination.", m_pszFilename ); VSIFCloseL( m_fp ); return false; } m_nHeightScale = static_cast<GInt16>( hs ); m_nBaseHeight = static_cast<GInt16>( bh ); // m_nHeightScale is the one that gives us the // widest use of the 16-bit space. However, there // might be larger heightscales that, even though // the reduce the space usage, give us a better fit // for preserving the span extents. return put(m_nHeightScale) && put(m_nBaseHeight); }
/** * Retrieves and stores the GCPs from a COSMO-SKYMED dataset * It only retrieves the GCPs for L0, L1A and L1B products * for L1C and L1D products, geotransform is provided. * The GCPs provided will be the Image's corners. * @param iProductType type of CSK product @see HDF5CSKProductEnum */ void HDF5ImageDataset::CaptureCSKGCPs(int iProductType) { //Only retrieve GCPs for L0,L1A and L1B products if(iProductType == PROD_CSK_L0||iProductType == PROD_CSK_L1A|| iProductType == PROD_CSK_L1B) { int i; double *pdCornerCoordinates; nGCPCount=4; pasGCPList = (GDAL_GCP *) CPLCalloc(sizeof(GDAL_GCP),4); CPLString osCornerName[4]; double pdCornerPixel[4]; double pdCornerLine[4]; const char *pszSubdatasetName = GetSubdatasetName(); //Load the subdataset name first for(i=0;i <4;i++) osCornerName[i] = pszSubdatasetName; //Load the attribute name, and raster coordinates for //all the corners osCornerName[0] += "/Top Left Geodetic Coordinates"; pdCornerPixel[0] = 0; pdCornerLine[0] = 0; osCornerName[1] += "/Top Right Geodetic Coordinates"; pdCornerPixel[1] = GetRasterXSize(); pdCornerLine[1] = 0; osCornerName[2] += "/Bottom Left Geodetic Coordinates"; pdCornerPixel[2] = 0; pdCornerLine[2] = GetRasterYSize(); osCornerName[3] += "/Bottom Right Geodetic Coordinates"; pdCornerPixel[3] = GetRasterXSize(); pdCornerLine[3] = GetRasterYSize(); //For all the image's corners for(i=0;i<4;i++) { GDALInitGCPs( 1, pasGCPList + i ); CPLFree( pasGCPList[i].pszId ); pasGCPList[i].pszId = NULL; //Retrieve the attributes if(HDF5ReadDoubleAttr(osCornerName[i].c_str(), &pdCornerCoordinates) == CE_Failure) { CPLError( CE_Failure, CPLE_OpenFailed, "Error retrieving CSK GCPs\n" ); // Free on failure, e.g. in case of QLK subdataset. for( int i = 0; i < 4; i++ ) { if( pasGCPList[i].pszId ) CPLFree( pasGCPList[i].pszId ); if( pasGCPList[i].pszInfo ) CPLFree( pasGCPList[i].pszInfo ); } CPLFree( pasGCPList ); pasGCPList = NULL; nGCPCount = 0; break; } //Fill the GCPs name pasGCPList[i].pszId = CPLStrdup( osCornerName[i].c_str() ); //Fill the coordinates pasGCPList[i].dfGCPX = pdCornerCoordinates[1]; pasGCPList[i].dfGCPY = pdCornerCoordinates[0]; pasGCPList[i].dfGCPZ = pdCornerCoordinates[2]; pasGCPList[i].dfGCPPixel = pdCornerPixel[i]; pasGCPList[i].dfGCPLine = pdCornerLine[i]; //Free the returned coordinates CPLFree(pdCornerCoordinates); } } }
CPLErr MEMDataset::AddBand( GDALDataType eType, char **papszOptions ) { const int nBandId = GetRasterCount() + 1; const GSpacing nPixelSize = GDALGetDataTypeSizeBytes(eType); /* -------------------------------------------------------------------- */ /* Do we need to allocate the memory ourselves? This is the */ /* simple case. */ /* -------------------------------------------------------------------- */ if( CSLFetchNameValue( papszOptions, "DATAPOINTER" ) == NULL ) { const GSpacing nTmp = nPixelSize * GetRasterXSize(); GByte *pData = NULL; #if SIZEOF_VOIDP == 4 if( nTmp > INT_MAX ) pData = NULL; else #endif pData = reinterpret_cast<GByte *>( VSI_CALLOC_VERBOSE((size_t)nTmp, GetRasterYSize() ) ); if( pData == NULL ) { return CE_Failure; } SetBand( nBandId, new MEMRasterBand( this, nBandId, pData, eType, nPixelSize, nPixelSize * GetRasterXSize(), TRUE ) ); return CE_None; } /* -------------------------------------------------------------------- */ /* Get layout of memory and other flags. */ /* -------------------------------------------------------------------- */ const char *pszDataPointer = CSLFetchNameValue(papszOptions, "DATAPOINTER"); GByte *pData = reinterpret_cast<GByte *>( CPLScanPointer( pszDataPointer, static_cast<int>(strlen(pszDataPointer)) ) ); const char *pszOption = CSLFetchNameValue(papszOptions, "PIXELOFFSET"); GSpacing nPixelOffset; if( pszOption == NULL ) nPixelOffset = nPixelSize; else nPixelOffset = CPLAtoGIntBig(pszOption); pszOption = CSLFetchNameValue(papszOptions, "LINEOFFSET"); GSpacing nLineOffset; if( pszOption == NULL ) nLineOffset = GetRasterXSize() * static_cast<size_t>( nPixelOffset ); else nLineOffset = CPLAtoGIntBig(pszOption); SetBand( nBandId, new MEMRasterBand( this, nBandId, pData, eType, nPixelOffset, nLineOffset, FALSE ) ); return CE_None; }
void BAGDataset::LoadMetadata() { // Load the metadata from the file. const hid_t hMDDS = H5Dopen(hHDF5, "/BAG_root/metadata"); const hid_t datatype = H5Dget_type(hMDDS); const hid_t dataspace = H5Dget_space(hMDDS); const hid_t native = H5Tget_native_type(datatype, H5T_DIR_ASCEND); hsize_t dims[3] = { static_cast<hsize_t>(0), static_cast<hsize_t>(0), static_cast<hsize_t>(0) }; hsize_t maxdims[3] = { static_cast<hsize_t>(0), static_cast<hsize_t>(0), static_cast<hsize_t>(0) }; H5Sget_simple_extent_dims(dataspace, dims, maxdims); pszXMLMetadata = static_cast<char *>(CPLCalloc(static_cast<int>(dims[0] + 1), 1)); H5Dread(hMDDS, native, H5S_ALL, dataspace, H5P_DEFAULT, pszXMLMetadata); H5Tclose(native); H5Sclose(dataspace); H5Tclose(datatype); H5Dclose(hMDDS); if( strlen(pszXMLMetadata) == 0 ) return; // Try to get the geotransform. CPLXMLNode *psRoot = CPLParseXMLString(pszXMLMetadata); if( psRoot == nullptr ) return; CPLStripXMLNamespace(psRoot, nullptr, TRUE); CPLXMLNode *const psGeo = CPLSearchXMLNode(psRoot, "=MD_Georectified"); if( psGeo != nullptr ) { char **papszCornerTokens = CSLTokenizeStringComplex( CPLGetXMLValue(psGeo, "cornerPoints.Point.coordinates", ""), " ,", FALSE, FALSE); if( CSLCount(papszCornerTokens) == 4 ) { const double dfLLX = CPLAtof(papszCornerTokens[0]); const double dfLLY = CPLAtof(papszCornerTokens[1]); const double dfURX = CPLAtof(papszCornerTokens[2]); const double dfURY = CPLAtof(papszCornerTokens[3]); adfGeoTransform[0] = dfLLX; adfGeoTransform[1] = (dfURX - dfLLX) / (GetRasterXSize() - 1); adfGeoTransform[3] = dfURY; adfGeoTransform[5] = (dfLLY - dfURY) / (GetRasterYSize() - 1); adfGeoTransform[0] -= adfGeoTransform[1] * 0.5; adfGeoTransform[3] -= adfGeoTransform[5] * 0.5; } CSLDestroy(papszCornerTokens); } // Try to get the coordinate system. OGRSpatialReference oSRS; if( OGR_SRS_ImportFromISO19115(&oSRS, pszXMLMetadata) == OGRERR_NONE ) { oSRS.exportToWkt(&pszProjection); } else { ParseWKTFromXML(pszXMLMetadata); } // Fetch acquisition date. CPLXMLNode *const psDateTime = CPLSearchXMLNode(psRoot, "=dateTime"); if( psDateTime != nullptr ) { const char *pszDateTimeValue = CPLGetXMLValue(psDateTime, nullptr, ""); if( pszDateTimeValue ) SetMetadataItem("BAG_DATETIME", pszDateTimeValue); } CPLDestroyXMLNode(psRoot); }