void GDALPamRasterBand::PamInitialize() { if( psPam ) return; GDALPamDataset *poParentDS = (GDALPamDataset *) GetDataset(); if( poParentDS == NULL || !(poParentDS->GetMOFlags() & GMO_PAM_CLASS) ) return; poParentDS->PamInitialize(); if( poParentDS->psPam == NULL ) return; // Often (always?) initializing our parent will have initialized us. if( psPam != NULL ) return; psPam = (GDALRasterBandPamInfo *) CPLCalloc(sizeof(GDALRasterBandPamInfo),1); psPam->dfScale = 1.0; psPam->poParentDS = poParentDS; psPam->dfNoDataValue = -1e10; psPam->poDefaultRAT = NULL; }
void GDALPamRasterBand::PamInitialize() { if( psPam ) return; GDALDataset* poNonPamParentDS = GetDataset(); if( poNonPamParentDS == nullptr || !(poNonPamParentDS->GetMOFlags() & GMO_PAM_CLASS) ) return; GDALPamDataset *poParentDS = dynamic_cast<GDALPamDataset *>( poNonPamParentDS ); if( poParentDS == nullptr ) { // Should never happen. CPLAssert(false); return; } poParentDS->PamInitialize(); if( poParentDS->psPam == nullptr ) return; // Often (always?) initializing our parent will have initialized us. if( psPam != nullptr ) return; psPam = static_cast<GDALRasterBandPamInfo *>( VSI_CALLOC_VERBOSE(sizeof(GDALRasterBandPamInfo), 1) ); if( psPam == nullptr ) return; psPam->dfScale = 1.0; psPam->poParentDS = poParentDS; psPam->dfNoDataValue = -1e10; psPam->poDefaultRAT = nullptr; }
GDALDataset * AAIGDataset::CreateCopy( const char *pszFilename, GDALDataset *poSrcDS, int /* bStrict */, char **papszOptions, GDALProgressFunc pfnProgress, void *pProgressData ) { const int nBands = poSrcDS->GetRasterCount(); const int nXSize = poSrcDS->GetRasterXSize(); const int nYSize = poSrcDS->GetRasterYSize(); // Some rudimentary checks. if( nBands != 1 ) { CPLError(CE_Failure, CPLE_NotSupported, "AAIG driver doesn't support %d bands. Must be 1 band.", nBands); return nullptr; } if( !pfnProgress(0.0, nullptr, pProgressData) ) return nullptr; // Create the dataset. VSILFILE *fpImage = VSIFOpenL(pszFilename, "wt"); if( fpImage == nullptr ) { CPLError(CE_Failure, CPLE_OpenFailed, "Unable to create file %s.", pszFilename); return nullptr; } // Write ASCII Grid file header. double adfGeoTransform[6] = {}; char szHeader[2000] = {}; const char *pszForceCellsize = CSLFetchNameValue(papszOptions, "FORCE_CELLSIZE"); poSrcDS->GetGeoTransform(adfGeoTransform); if( std::abs(adfGeoTransform[1] + adfGeoTransform[5]) < 0.0000001 || std::abs(adfGeoTransform[1]-adfGeoTransform[5]) < 0.0000001 || (pszForceCellsize && CPLTestBool(pszForceCellsize)) ) { CPLsnprintf( szHeader, sizeof(szHeader), "ncols %d\n" "nrows %d\n" "xllcorner %.12f\n" "yllcorner %.12f\n" "cellsize %.12f\n", nXSize, nYSize, adfGeoTransform[0], adfGeoTransform[3] - nYSize * adfGeoTransform[1], adfGeoTransform[1]); } else { if( pszForceCellsize == nullptr ) CPLError(CE_Warning, CPLE_AppDefined, "Producing a Golden Surfer style file with DX and DY " "instead of CELLSIZE since the input pixels are " "non-square. Use the FORCE_CELLSIZE=TRUE creation " "option to force use of DX for even though this will " "be distorted. Most ASCII Grid readers (ArcGIS " "included) do not support the DX and DY parameters."); CPLsnprintf( szHeader, sizeof(szHeader), "ncols %d\n" "nrows %d\n" "xllcorner %.12f\n" "yllcorner %.12f\n" "dx %.12f\n" "dy %.12f\n", nXSize, nYSize, adfGeoTransform[0], adfGeoTransform[3] + nYSize * adfGeoTransform[5], adfGeoTransform[1], fabs(adfGeoTransform[5])); } // Builds the format string used for printing float values. char szFormatFloat[32] = { '\0' }; strcpy(szFormatFloat, " %.20g"); const char *pszDecimalPrecision = CSLFetchNameValue(papszOptions, "DECIMAL_PRECISION"); const char *pszSignificantDigits = CSLFetchNameValue(papszOptions, "SIGNIFICANT_DIGITS"); bool bIgnoreSigDigits = false; if( pszDecimalPrecision && pszSignificantDigits ) { CPLError(CE_Warning, CPLE_AppDefined, "Conflicting precision arguments, using DECIMAL_PRECISION"); bIgnoreSigDigits = true; } int nPrecision; if ( pszSignificantDigits && !bIgnoreSigDigits ) { nPrecision = atoi(pszSignificantDigits); if (nPrecision >= 0) snprintf(szFormatFloat, sizeof(szFormatFloat), " %%.%dg", nPrecision); CPLDebug("AAIGrid", "Setting precision format: %s", szFormatFloat); } else if( pszDecimalPrecision ) { nPrecision = atoi(pszDecimalPrecision); if ( nPrecision >= 0 ) snprintf(szFormatFloat, sizeof(szFormatFloat), " %%.%df", nPrecision); CPLDebug("AAIGrid", "Setting precision format: %s", szFormatFloat); } // Handle nodata (optionally). GDALRasterBand *poBand = poSrcDS->GetRasterBand(1); const bool bReadAsInt = poBand->GetRasterDataType() == GDT_Byte || poBand->GetRasterDataType() == GDT_Int16 || poBand->GetRasterDataType() == GDT_UInt16 || poBand->GetRasterDataType() == GDT_Int32; // Write `nodata' value to header if it is exists in source dataset int bSuccess = FALSE; const double dfNoData = poBand->GetNoDataValue(&bSuccess); if ( bSuccess ) { snprintf(szHeader + strlen(szHeader), sizeof(szHeader) - strlen(szHeader), "%s", "NODATA_value "); if( bReadAsInt ) snprintf(szHeader + strlen(szHeader), sizeof(szHeader) - strlen(szHeader), "%d", static_cast<int>(dfNoData)); else CPLsnprintf(szHeader + strlen(szHeader), sizeof(szHeader) - strlen(szHeader), szFormatFloat, dfNoData); snprintf(szHeader + strlen(szHeader), sizeof(szHeader) - strlen(szHeader), "%s", "\n"); } if( VSIFWriteL(szHeader, strlen(szHeader), 1, fpImage) != 1) { CPL_IGNORE_RET_VAL(VSIFCloseL(fpImage)); return nullptr; } // Loop over image, copying image data. // Write scanlines to output file int *panScanline = bReadAsInt ? static_cast<int *>(CPLMalloc( nXSize * GDALGetDataTypeSizeBytes(GDT_Int32))) : nullptr; double *padfScanline = bReadAsInt ? nullptr : static_cast<double *>(CPLMalloc( nXSize * GDALGetDataTypeSizeBytes(GDT_Float64))); CPLErr eErr = CE_None; bool bHasOutputDecimalDot = false; for( int iLine = 0; eErr == CE_None && iLine < nYSize; iLine++ ) { CPLString osBuf; eErr = poBand->RasterIO( GF_Read, 0, iLine, nXSize, 1, bReadAsInt ? reinterpret_cast<void *>(panScanline) : reinterpret_cast<void *>(padfScanline), nXSize, 1, bReadAsInt ? GDT_Int32 : GDT_Float64, 0, 0, nullptr); if( bReadAsInt ) { for ( int iPixel = 0; iPixel < nXSize; iPixel++ ) { snprintf(szHeader, sizeof(szHeader), " %d", panScanline[iPixel]); osBuf += szHeader; if( (iPixel & 1023) == 0 || iPixel == nXSize - 1 ) { if ( VSIFWriteL(osBuf, static_cast<int>(osBuf.size()), 1, fpImage) != 1 ) { eErr = CE_Failure; CPLError(CE_Failure, CPLE_AppDefined, "Write failed, disk full?"); break; } osBuf = ""; } } } else { for ( int iPixel = 0; iPixel < nXSize; iPixel++ ) { CPLsnprintf(szHeader, sizeof(szHeader), szFormatFloat, padfScanline[iPixel]); // Make sure that as least one value has a decimal point (#6060) if( !bHasOutputDecimalDot ) { if( strchr(szHeader, '.') || strchr(szHeader, 'e') || strchr(szHeader, 'E') ) { bHasOutputDecimalDot = true; } else if( !CPLIsInf(padfScanline[iPixel]) && !CPLIsNan(padfScanline[iPixel]) ) { strcat(szHeader, ".0"); bHasOutputDecimalDot = true; } } osBuf += szHeader; if( (iPixel & 1023) == 0 || iPixel == nXSize - 1 ) { if ( VSIFWriteL(osBuf, static_cast<int>(osBuf.size()), 1, fpImage) != 1 ) { eErr = CE_Failure; CPLError(CE_Failure, CPLE_AppDefined, "Write failed, disk full?"); break; } osBuf = ""; } } } if( VSIFWriteL("\n", 1, 1, fpImage) != 1 ) eErr = CE_Failure; if( eErr == CE_None && !pfnProgress((iLine + 1) / static_cast<double>(nYSize), nullptr, pProgressData) ) { eErr = CE_Failure; CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated CreateCopy()"); } } CPLFree(panScanline); CPLFree(padfScanline); if( VSIFCloseL(fpImage) != 0 ) eErr = CE_Failure; if( eErr != CE_None ) return nullptr; // Try to write projection file. const char *pszOriginalProjection = poSrcDS->GetProjectionRef(); if( !EQUAL(pszOriginalProjection, "") ) { char *pszDirname = CPLStrdup(CPLGetPath(pszFilename)); char *pszBasename = CPLStrdup(CPLGetBasename(pszFilename)); char *pszPrjFilename = CPLStrdup(CPLFormFilename(pszDirname, pszBasename, "prj")); VSILFILE *fp = VSIFOpenL(pszPrjFilename, "wt"); if (fp != nullptr) { OGRSpatialReference oSRS; oSRS.importFromWkt(pszOriginalProjection); oSRS.morphToESRI(); char *pszESRIProjection = nullptr; oSRS.exportToWkt(&pszESRIProjection); CPL_IGNORE_RET_VAL(VSIFWriteL(pszESRIProjection, 1, strlen(pszESRIProjection), fp)); CPL_IGNORE_RET_VAL(VSIFCloseL(fp)); CPLFree(pszESRIProjection); } else { CPLError(CE_Failure, CPLE_FileIO, "Unable to create file %s.", pszPrjFilename); } CPLFree(pszDirname); CPLFree(pszBasename); CPLFree(pszPrjFilename); } // Re-open dataset, and copy any auxiliary pam information. // If writing to stdout, we can't reopen it, so return // a fake dataset to make the caller happy. CPLPushErrorHandler(CPLQuietErrorHandler); GDALPamDataset *poDS = reinterpret_cast<GDALPamDataset *>(GDALOpen(pszFilename, GA_ReadOnly)); CPLPopErrorHandler(); if (poDS) { poDS->CloneInfo(poSrcDS, GCIF_PAM_DEFAULT); return poDS; } CPLErrorReset(); AAIGDataset *poAAIG_DS = new AAIGDataset(); poAAIG_DS->nRasterXSize = nXSize; poAAIG_DS->nRasterYSize = nYSize; poAAIG_DS->nBands = 1; poAAIG_DS->SetBand(1, new AAIGRasterBand(poAAIG_DS, 1)); return poAAIG_DS; }
GDALDataset * RCreateCopy( const char * pszFilename, GDALDataset *poSrcDS, CPL_UNUSED int bStrict, char ** papszOptions, GDALProgressFunc pfnProgress, void * pProgressData ) { const int nBands = poSrcDS->GetRasterCount(); const int nXSize = poSrcDS->GetRasterXSize(); const int nYSize = poSrcDS->GetRasterYSize(); const bool bASCII = CPLFetchBool(papszOptions, "ASCII", false); const bool bCompressed = CPLFetchBool(papszOptions, "COMPRESS", !bASCII); // Some some rudimentary checks. // Setup the filename to actually use. We prefix with // /vsigzip/ if we want compressed output. const CPLString osAdjustedFilename = std::string(bCompressed ? "/vsigzip/" : "") + pszFilename; // Create the file. VSILFILE *fp = VSIFOpenL(osAdjustedFilename, "wb"); if( fp == NULL ) { CPLError(CE_Failure, CPLE_OpenFailed, "Unable to create file %s.", pszFilename); return NULL; } // Write header with version, etc. if( bASCII ) { const char *pszHeader = "RDA2\nA\n"; VSIFWriteL(pszHeader, 1, strlen(pszHeader), fp); } else { const char *pszHeader = "RDX2\nX\n"; VSIFWriteL(pszHeader, 1, strlen(pszHeader), fp); } RWriteInteger(fp, bASCII, 2); RWriteInteger(fp, bASCII, 133377); RWriteInteger(fp, bASCII, 131840); // Establish the primary pairlist with one component object. RWriteInteger(fp, bASCII, 1026); RWriteInteger(fp, bASCII, 1); // Write the object name. Eventually we should derive this // from the filename, possible with override by a creation option. RWriteString(fp, bASCII, "gg"); // For now we write the raster as a numeric array with attributes (526). RWriteInteger(fp, bASCII, 526); RWriteInteger(fp, bASCII, nXSize * nYSize * nBands); // Write the raster data. CPLErr eErr = CE_None; double *padfScanline = static_cast<double *>(CPLMalloc(nXSize * sizeof(double))); for( int iBand = 0; iBand < nBands; iBand++ ) { GDALRasterBand *poBand = poSrcDS->GetRasterBand(iBand + 1); for( int iLine = 0; iLine < nYSize && eErr == CE_None; iLine++ ) { eErr = poBand->RasterIO(GF_Read, 0, iLine, nXSize, 1, padfScanline, nXSize, 1, GDT_Float64, sizeof(double), 0, NULL); if( bASCII ) { for( int iValue = 0; iValue < nXSize; iValue++ ) { char szValue[128] = { '\0' }; CPLsnprintf(szValue, sizeof(szValue), "%.16g\n", padfScanline[iValue]); VSIFWriteL(szValue, 1, strlen(szValue), fp); } } else { for( int iValue = 0; iValue < nXSize; iValue++ ) CPL_MSBPTR64(padfScanline + iValue); VSIFWriteL(padfScanline, 8, nXSize, fp); } if( eErr == CE_None && !pfnProgress((iLine + 1) / static_cast<double>(nYSize), NULL, pProgressData) ) { eErr = CE_Failure; CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated CreateCopy()"); } } } CPLFree(padfScanline); // Write out the dims attribute. RWriteInteger(fp, bASCII, 1026); RWriteInteger(fp, bASCII, 1); RWriteString(fp, bASCII, "dim"); RWriteInteger(fp, bASCII, 13); RWriteInteger(fp, bASCII, 3); RWriteInteger(fp, bASCII, nXSize); RWriteInteger(fp, bASCII, nYSize); RWriteInteger(fp, bASCII, nBands); RWriteInteger(fp, bASCII, 254); // Terminate overall pairlist. RWriteInteger(fp, bASCII, 254); // Cleanup. VSIFCloseL(fp); if( eErr != CE_None ) return NULL; // Re-open dataset, and copy any auxiliary pam information. GDALPamDataset *poDS = static_cast<GDALPamDataset *>(GDALOpen(pszFilename, GA_ReadOnly)); if( poDS ) poDS->CloneInfo(poSrcDS, GCIF_PAM_DEFAULT); return poDS; }
static GDALDataset * DTEDCreateCopy( const char * pszFilename, GDALDataset *poSrcDS, int bStrict, char ** papszOptions, GDALProgressFunc pfnProgress, void * pProgressData ) { (void) pProgressData; (void) pfnProgress; (void) papszOptions; (void) bStrict; /* -------------------------------------------------------------------- */ /* Some some rudimentary checks */ /* -------------------------------------------------------------------- */ int nBands = poSrcDS->GetRasterCount(); if (nBands == 0) { CPLError( CE_Failure, CPLE_NotSupported, "DTED driver does not support source dataset with zero band.\n"); return NULL; } if (nBands != 1) { CPLError( (bStrict) ? CE_Failure : CE_Warning, CPLE_NotSupported, "DTED driver only uses the first band of the dataset.\n"); if (bStrict) return NULL; } if( pfnProgress && !pfnProgress( 0.0, NULL, pProgressData ) ) return NULL; /* -------------------------------------------------------------------- */ /* Work out the level. */ /* -------------------------------------------------------------------- */ int nLevel; if( poSrcDS->GetRasterYSize() == 121 ) nLevel = 0; else if( poSrcDS->GetRasterYSize() == 1201 ) nLevel = 1; else if( poSrcDS->GetRasterYSize() == 3601 ) nLevel = 2; else { CPLError( CE_Warning, CPLE_AppDefined, "The source does not appear to be a properly formatted cell." ); nLevel = 1; } /* -------------------------------------------------------------------- */ /* Checks the input SRS */ /* -------------------------------------------------------------------- */ OGRSpatialReference ogrsr_input; OGRSpatialReference ogrsr_wgs84; char* c = (char*)poSrcDS->GetProjectionRef(); ogrsr_input.importFromWkt(&c); ogrsr_wgs84.SetWellKnownGeogCS( "WGS84" ); if ( ogrsr_input.IsSameGeogCS(&ogrsr_wgs84) == FALSE) { CPLError( CE_Warning, CPLE_AppDefined, "The source projection coordinate system is %s. Only WGS 84 is supported.\n" "The DTED driver will generate a file as if the source was WGS 84 projection coordinate system.", poSrcDS->GetProjectionRef() ); } /* -------------------------------------------------------------------- */ /* Work out the LL origin. */ /* -------------------------------------------------------------------- */ int nLLOriginLat, nLLOriginLong; double adfGeoTransform[6]; poSrcDS->GetGeoTransform( adfGeoTransform ); nLLOriginLat = (int) floor(adfGeoTransform[3] + poSrcDS->GetRasterYSize() * adfGeoTransform[5] + 0.5); nLLOriginLong = (int) floor(adfGeoTransform[0] + 0.5); if (fabs(nLLOriginLat - (adfGeoTransform[3] + (poSrcDS->GetRasterYSize() - 0.5) * adfGeoTransform[5])) > 1e-10 || fabs(nLLOriginLong - (adfGeoTransform[0] + 0.5 * adfGeoTransform[1])) > 1e-10) { CPLError( CE_Warning, CPLE_AppDefined, "The corner coordinates of the source are not properly " "aligned on plain latitude/longitude boundaries."); } /* -------------------------------------------------------------------- */ /* Check horizontal source size. */ /* -------------------------------------------------------------------- */ int expectedXSize; if( ABS(nLLOriginLat) >= 80 ) expectedXSize = (poSrcDS->GetRasterYSize() - 1) / 6 + 1; else if( ABS(nLLOriginLat) >= 75 ) expectedXSize = (poSrcDS->GetRasterYSize() - 1) / 4 + 1; else if( ABS(nLLOriginLat) >= 70 ) expectedXSize = (poSrcDS->GetRasterYSize() - 1) / 3 + 1; else if( ABS(nLLOriginLat) >= 50 ) expectedXSize = (poSrcDS->GetRasterYSize() - 1) / 2 + 1; else expectedXSize = poSrcDS->GetRasterYSize(); if (poSrcDS->GetRasterXSize() != expectedXSize) { CPLError( CE_Warning, CPLE_AppDefined, "The horizontal source size is not conformant with the one " "expected by DTED Level %d at this latitude (%d pixels found instead of %d).", nLevel, poSrcDS->GetRasterXSize(), expectedXSize); } /* -------------------------------------------------------------------- */ /* Create the output dted file. */ /* -------------------------------------------------------------------- */ const char *pszError; pszError = DTEDCreate( pszFilename, nLevel, nLLOriginLat, nLLOriginLong ); if( pszError != NULL ) { CPLError( CE_Failure, CPLE_AppDefined, "%s", pszError ); return NULL; } /* -------------------------------------------------------------------- */ /* Open the DTED file so we can output the data to it. */ /* -------------------------------------------------------------------- */ DTEDInfo *psDTED; psDTED = DTEDOpen( pszFilename, "rb+", FALSE ); if( psDTED == NULL ) return NULL; /* -------------------------------------------------------------------- */ /* Read all the data in a single buffer. */ /* -------------------------------------------------------------------- */ GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand( 1 ); GInt16 *panData; panData = (GInt16 *) VSIMalloc(sizeof(GInt16) * psDTED->nXSize * psDTED->nYSize); if (panData == NULL) { CPLError( CE_Failure, CPLE_OutOfMemory, "Out of memory"); DTEDClose(psDTED); return NULL; } for( int iY = 0; iY < psDTED->nYSize; iY++ ) { poSrcBand->RasterIO( GF_Read, 0, iY, psDTED->nXSize, 1, (void *) (panData + iY * psDTED->nXSize), psDTED->nXSize, 1, GDT_Int16, 0, 0, NULL ); if( pfnProgress && !pfnProgress(0.5 * (iY+1) / (double) psDTED->nYSize, NULL, pProgressData ) ) { CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated CreateCopy()" ); DTEDClose( psDTED ); CPLFree( panData ); return NULL; } } int bSrcBandHasNoData; double srcBandNoData = poSrcBand->GetNoDataValue(&bSrcBandHasNoData); /* -------------------------------------------------------------------- */ /* Write all the profiles. */ /* -------------------------------------------------------------------- */ GInt16 anProfData[3601]; int dfNodataCount=0; GByte iPartialCell; for( int iProfile = 0; iProfile < psDTED->nXSize; iProfile++ ) { for( int iY = 0; iY < psDTED->nYSize; iY++ ) { anProfData[iY] = panData[iProfile + iY * psDTED->nXSize]; if ( bSrcBandHasNoData && anProfData[iY] == srcBandNoData) { anProfData[iY] = DTED_NODATA_VALUE; dfNodataCount++; } else if ( anProfData[iY] == DTED_NODATA_VALUE ) dfNodataCount++; } DTEDWriteProfile( psDTED, iProfile, anProfData ); if( pfnProgress && !pfnProgress( 0.5 + 0.5 * (iProfile+1) / (double) psDTED->nXSize, NULL, pProgressData ) ) { CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated CreateCopy()" ); DTEDClose( psDTED ); CPLFree( panData ); return NULL; } } CPLFree( panData ); /* -------------------------------------------------------------------- */ /* Partial cell indicator: 0 for complete coverage; 1-99 for incomplete */ /* -------------------------------------------------------------------- */ char szPartialCell[3]; if ( dfNodataCount == 0 ) iPartialCell = 0; else { iPartialCell = (GByte)int(floor(100.0 - (dfNodataCount*100.0/(psDTED->nXSize * psDTED->nYSize)))); if (iPartialCell < 1) iPartialCell=1; } sprintf(szPartialCell,"%02d",iPartialCell); DTEDSetMetadata(psDTED, DTEDMD_PARTIALCELL_DSI, szPartialCell); /* -------------------------------------------------------------------- */ /* Try to copy any matching available metadata. */ /* -------------------------------------------------------------------- */ if( poSrcDS->GetMetadataItem( "DTED_VerticalAccuracy_UHL" ) != NULL ) DTEDSetMetadata( psDTED, DTEDMD_VERTACCURACY_UHL, poSrcDS->GetMetadataItem( "DTED_VerticalAccuracy_UHL" ) ); if( poSrcDS->GetMetadataItem( "DTED_VerticalAccuracy_ACC" ) != NULL ) DTEDSetMetadata( psDTED, DTEDMD_VERTACCURACY_ACC, poSrcDS->GetMetadataItem( "DTED_VerticalAccuracy_ACC" ) ); if( poSrcDS->GetMetadataItem( "DTED_SecurityCode_UHL" ) != NULL ) DTEDSetMetadata( psDTED, DTEDMD_SECURITYCODE_UHL, poSrcDS->GetMetadataItem( "DTED_SecurityCode_UHL" ) ); if( poSrcDS->GetMetadataItem( "DTED_SecurityCode_DSI" ) != NULL ) DTEDSetMetadata( psDTED, DTEDMD_SECURITYCODE_DSI, poSrcDS->GetMetadataItem( "DTED_SecurityCode_DSI" ) ); if( poSrcDS->GetMetadataItem( "DTED_UniqueRef_UHL" ) != NULL ) DTEDSetMetadata( psDTED, DTEDMD_UNIQUEREF_UHL, poSrcDS->GetMetadataItem( "DTED_UniqueRef_UHL" ) ); if( poSrcDS->GetMetadataItem( "DTED_UniqueRef_DSI" ) != NULL ) DTEDSetMetadata( psDTED, DTEDMD_UNIQUEREF_DSI, poSrcDS->GetMetadataItem( "DTED_UniqueRef_DSI" ) ); if( poSrcDS->GetMetadataItem( "DTED_DataEdition" ) != NULL ) DTEDSetMetadata( psDTED, DTEDMD_DATA_EDITION, poSrcDS->GetMetadataItem( "DTED_DataEdition" ) ); if( poSrcDS->GetMetadataItem( "DTED_MatchMergeVersion" ) != NULL ) DTEDSetMetadata( psDTED, DTEDMD_MATCHMERGE_VERSION, poSrcDS->GetMetadataItem( "DTED_MatchMergeVersion" ) ); if( poSrcDS->GetMetadataItem( "DTED_MaintenanceDate" ) != NULL ) DTEDSetMetadata( psDTED, DTEDMD_MAINT_DATE, poSrcDS->GetMetadataItem( "DTED_MaintenanceDate" ) ); if( poSrcDS->GetMetadataItem( "DTED_MatchMergeDate" ) != NULL ) DTEDSetMetadata( psDTED, DTEDMD_MATCHMERGE_DATE, poSrcDS->GetMetadataItem( "DTED_MatchMergeDate" ) ); if( poSrcDS->GetMetadataItem( "DTED_MaintenanceDescription" ) != NULL ) DTEDSetMetadata( psDTED, DTEDMD_MAINT_DESCRIPTION, poSrcDS->GetMetadataItem( "DTED_MaintenanceDescription" ) ); if( poSrcDS->GetMetadataItem( "DTED_Producer" ) != NULL ) DTEDSetMetadata( psDTED, DTEDMD_PRODUCER, poSrcDS->GetMetadataItem( "DTED_Producer" ) ); if( poSrcDS->GetMetadataItem( "DTED_VerticalDatum" ) != NULL ) DTEDSetMetadata( psDTED, DTEDMD_VERTDATUM, poSrcDS->GetMetadataItem( "DTED_VerticalDatum" ) ); if( poSrcDS->GetMetadataItem( "DTED_HorizontalDatum" ) != NULL ) DTEDSetMetadata( psDTED, DTEDMD_HORIZDATUM, poSrcDS->GetMetadataItem( "DTED_HorizontalDatum" ) ); if( poSrcDS->GetMetadataItem( "DTED_DigitizingSystem" ) != NULL ) DTEDSetMetadata( psDTED, DTEDMD_DIGITIZING_SYS, poSrcDS->GetMetadataItem( "DTED_DigitizingSystem" ) ); if( poSrcDS->GetMetadataItem( "DTED_CompilationDate" ) != NULL ) DTEDSetMetadata( psDTED, DTEDMD_COMPILATION_DATE, poSrcDS->GetMetadataItem( "DTED_CompilationDate" ) ); if( poSrcDS->GetMetadataItem( "DTED_HorizontalAccuracy" ) != NULL ) DTEDSetMetadata( psDTED, DTEDMD_HORIZACCURACY, poSrcDS->GetMetadataItem( "DTED_HorizontalAccuracy" ) ); if( poSrcDS->GetMetadataItem( "DTED_RelHorizontalAccuracy" ) != NULL ) DTEDSetMetadata( psDTED, DTEDMD_REL_HORIZACCURACY, poSrcDS->GetMetadataItem( "DTED_RelHorizontalAccuracy" ) ); if( poSrcDS->GetMetadataItem( "DTED_RelVerticalAccuracy" ) != NULL ) DTEDSetMetadata( psDTED, DTEDMD_REL_VERTACCURACY, poSrcDS->GetMetadataItem( "DTED_RelVerticalAccuracy" ) ); /* -------------------------------------------------------------------- */ /* Try to open the resulting DTED file. */ /* -------------------------------------------------------------------- */ DTEDClose( psDTED ); /* -------------------------------------------------------------------- */ /* Reopen and copy missing information into a PAM file. */ /* -------------------------------------------------------------------- */ GDALPamDataset *poDS = (GDALPamDataset *) GDALOpen( pszFilename, GA_ReadOnly ); if( poDS ) poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT ); return poDS; }
static GDALDataset * GMTCreateCopy( const char * pszFilename, GDALDataset *poSrcDS, int bStrict, CPL_UNUSED char ** papszOptions, CPL_UNUSED GDALProgressFunc pfnProgress, CPL_UNUSED void * pProgressData ) { /* -------------------------------------------------------------------- */ /* Figure out general characteristics. */ /* -------------------------------------------------------------------- */ nc_type nc_datatype; GDALRasterBand *poBand; int nXSize, nYSize; CPLMutexHolderD(&hNCMutex); if( poSrcDS->GetRasterCount() != 1 ) { CPLError( CE_Failure, CPLE_AppDefined, "Currently GMT export only supports 1 band datasets." ); return NULL; } poBand = poSrcDS->GetRasterBand(1); nXSize = poSrcDS->GetRasterXSize(); nYSize = poSrcDS->GetRasterYSize(); if( poBand->GetRasterDataType() == GDT_Int16 ) nc_datatype = NC_SHORT; else if( poBand->GetRasterDataType() == GDT_Int32 ) nc_datatype = NC_INT; else if( poBand->GetRasterDataType() == GDT_Float32 ) nc_datatype = NC_FLOAT; else if( poBand->GetRasterDataType() == GDT_Float64 ) nc_datatype = NC_DOUBLE; else if( bStrict ) { CPLError( CE_Failure, CPLE_AppDefined, "Band data type %s not supported in GMT, giving up.", GDALGetDataTypeName( poBand->GetRasterDataType() ) ); return NULL; } else if( poBand->GetRasterDataType() == GDT_Byte ) nc_datatype = NC_SHORT; else if( poBand->GetRasterDataType() == GDT_UInt16 ) nc_datatype = NC_INT; else if( poBand->GetRasterDataType() == GDT_UInt32 ) nc_datatype = NC_INT; else nc_datatype = NC_FLOAT; /* -------------------------------------------------------------------- */ /* Establish bounds from geotransform. */ /* -------------------------------------------------------------------- */ double adfGeoTransform[6]; double dfXMax, dfYMin; poSrcDS->GetGeoTransform( adfGeoTransform ); if( adfGeoTransform[2] != 0.0 || adfGeoTransform[4] != 0.0 ) { CPLError( bStrict ? CE_Failure : CE_Warning, CPLE_AppDefined, "Geotransform has rotational coefficients not supported in GMT." ); if( bStrict ) return NULL; } dfXMax = adfGeoTransform[0] + adfGeoTransform[1] * nXSize; dfYMin = adfGeoTransform[3] + adfGeoTransform[5] * nYSize; /* -------------------------------------------------------------------- */ /* Create base file. */ /* -------------------------------------------------------------------- */ int cdfid, err; err = nc_create (pszFilename, NC_CLOBBER,&cdfid); if( err != NC_NOERR ) { CPLError( CE_Failure, CPLE_AppDefined, "nc_create(%s): %s", pszFilename, nc_strerror( err ) ); return NULL; } /* -------------------------------------------------------------------- */ /* Define the dimensions and so forth. */ /* -------------------------------------------------------------------- */ int side_dim, xysize_dim, dims[1]; int x_range_id, y_range_id, z_range_id, inc_id, nm_id, z_id; nc_def_dim(cdfid, "side", 2, &side_dim); nc_def_dim(cdfid, "xysize", (int) (nXSize * nYSize), &xysize_dim); dims[0] = side_dim; nc_def_var (cdfid, "x_range", NC_DOUBLE, 1, dims, &x_range_id); nc_def_var (cdfid, "y_range", NC_DOUBLE, 1, dims, &y_range_id); nc_def_var (cdfid, "z_range", NC_DOUBLE, 1, dims, &z_range_id); nc_def_var (cdfid, "spacing", NC_DOUBLE, 1, dims, &inc_id); nc_def_var (cdfid, "dimension", NC_LONG, 1, dims, &nm_id); dims[0] = xysize_dim; nc_def_var (cdfid, "z", nc_datatype, 1, dims, &z_id); /* -------------------------------------------------------------------- */ /* Assign attributes. */ /* -------------------------------------------------------------------- */ double default_scale = 1.0; double default_offset = 0.0; int default_node_offset = 1; // pixel is area nc_put_att_text (cdfid, x_range_id, "units", 7, "meters"); nc_put_att_text (cdfid, y_range_id, "units", 7, "meters"); nc_put_att_text (cdfid, z_range_id, "units", 7, "meters"); nc_put_att_double (cdfid, z_id, "scale_factor", NC_DOUBLE, 1, &default_scale ); nc_put_att_double (cdfid, z_id, "add_offset", NC_DOUBLE, 1, &default_offset ); nc_put_att_int (cdfid, z_id, "node_offset", NC_LONG, 1, &default_node_offset ); nc_put_att_text (cdfid, NC_GLOBAL, "title", 1, ""); nc_put_att_text (cdfid, NC_GLOBAL, "source", 1, ""); /* leave define mode */ nc_enddef (cdfid); /* -------------------------------------------------------------------- */ /* Get raster min/max. */ /* -------------------------------------------------------------------- */ double adfMinMax[2]; GDALComputeRasterMinMax( (GDALRasterBandH) poBand, FALSE, adfMinMax ); /* -------------------------------------------------------------------- */ /* Set range variables. */ /* -------------------------------------------------------------------- */ size_t start[2], edge[2]; double dummy[2]; int nm[2]; start[0] = 0; edge[0] = 2; dummy[0] = adfGeoTransform[0]; dummy[1] = dfXMax; nc_put_vara_double(cdfid, x_range_id, start, edge, dummy); dummy[0] = dfYMin; dummy[1] = adfGeoTransform[3]; nc_put_vara_double(cdfid, y_range_id, start, edge, dummy); dummy[0] = adfGeoTransform[1]; dummy[1] = -adfGeoTransform[5]; nc_put_vara_double(cdfid, inc_id, start, edge, dummy); nm[0] = nXSize; nm[1] = nYSize; nc_put_vara_int(cdfid, nm_id, start, edge, nm); nc_put_vara_double(cdfid, z_range_id, start, edge, adfMinMax); /* -------------------------------------------------------------------- */ /* Write out the image one scanline at a time. */ /* -------------------------------------------------------------------- */ double *padfData; int iLine; padfData = (double *) CPLMalloc( sizeof(double) * nXSize ); edge[0] = nXSize; for( iLine = 0; iLine < nYSize; iLine++ ) { start[0] = iLine * nXSize; poBand->RasterIO( GF_Read, 0, iLine, nXSize, 1, padfData, nXSize, 1, GDT_Float64, 0, 0, NULL ); err = nc_put_vara_double( cdfid, z_id, start, edge, padfData ); if( err != NC_NOERR ) { CPLError( CE_Failure, CPLE_AppDefined, "nc_put_vara_double(%s): %s", pszFilename, nc_strerror( err ) ); nc_close (cdfid); return( NULL ); } } CPLFree( padfData ); /* -------------------------------------------------------------------- */ /* Close file, and reopen. */ /* -------------------------------------------------------------------- */ nc_close (cdfid); /* -------------------------------------------------------------------- */ /* Re-open dataset, and copy any auxiliary pam information. */ /* -------------------------------------------------------------------- */ GDALPamDataset *poDS = (GDALPamDataset *) GDALOpen( pszFilename, GA_ReadOnly ); if( poDS ) poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT ); return poDS; }
GDALDataset *GS7BGDataset::CreateCopy( const char *pszFilename, GDALDataset *poSrcDS, int bStrict, CPL_UNUSED char **papszOptions, GDALProgressFunc pfnProgress, void *pProgressData ) { if( pfnProgress == NULL ) pfnProgress = GDALDummyProgress; int nBands = poSrcDS->GetRasterCount(); if (nBands == 0) { CPLError( CE_Failure, CPLE_NotSupported, "Driver does not support source dataset with zero band.\n"); return NULL; } else if (nBands > 1) { if( bStrict ) { CPLError( CE_Failure, CPLE_NotSupported, "Unable to create copy, " "format only supports one raster band.\n" ); return NULL; } else CPLError( CE_Warning, CPLE_NotSupported, "Format only supports one " "raster band, first band will be copied.\n" ); } GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand( 1 ); if( !pfnProgress( 0.0, NULL, pProgressData ) ) { CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated\n" ); return NULL; } VSILFILE *fp = VSIFOpenL( pszFilename, "w+b" ); if( fp == NULL ) { CPLError( CE_Failure, CPLE_OpenFailed, "Attempt to create file '%s' failed.\n", pszFilename ); return NULL; } GInt32 nXSize = poSrcBand->GetXSize(); GInt32 nYSize = poSrcBand->GetYSize(); double adfGeoTransform[6]; poSrcDS->GetGeoTransform( adfGeoTransform ); double dfMinX = adfGeoTransform[0] + adfGeoTransform[1] / 2; double dfMaxX = adfGeoTransform[1] * (nXSize - 0.5) + adfGeoTransform[0]; double dfMinY = adfGeoTransform[5] * (nYSize - 0.5) + adfGeoTransform[3]; double dfMaxY = adfGeoTransform[3] + adfGeoTransform[5] / 2; CPLErr eErr = WriteHeader( fp, nXSize, nYSize, dfMinX, dfMaxX, dfMinY, dfMaxY, 0.0, 0.0 ); if( eErr != CE_None ) { VSIFCloseL( fp ); return NULL; } /* -------------------------------------------------------------------- */ /* Copy band data. */ /* -------------------------------------------------------------------- */ double *pfData = (double *)VSI_MALLOC2_VERBOSE( nXSize, sizeof( double ) ); if( pfData == NULL ) { VSIFCloseL( fp ); return NULL; } int bSrcHasNDValue; double dfSrcNoDataValue = poSrcBand->GetNoDataValue( &bSrcHasNDValue ); double dfMinZ = DBL_MAX; double dfMaxZ = -DBL_MAX; for( GInt32 iRow = nYSize - 1; iRow >= 0; iRow-- ) { eErr = poSrcBand->RasterIO( GF_Read, 0, iRow, nXSize, 1, pfData, nXSize, 1, GDT_Float64, 0, 0, NULL ); if( eErr != CE_None ) { VSIFCloseL( fp ); VSIFree( pfData ); return NULL; } for( int iCol=0; iCol<nXSize; iCol++ ) { if( bSrcHasNDValue && pfData[iCol] == dfSrcNoDataValue ) { pfData[iCol] = dfDefaultNoDataValue; } else { if( pfData[iCol] > dfMaxZ ) dfMaxZ = pfData[iCol]; if( pfData[iCol] < dfMinZ ) dfMinZ = pfData[iCol]; } CPL_LSBPTR64( pfData+iCol ); } if( VSIFWriteL( (void *)pfData, sizeof( double ), nXSize, fp ) != static_cast<unsigned>(nXSize) ) { VSIFCloseL( fp ); VSIFree( pfData ); CPLError( CE_Failure, CPLE_FileIO, "Unable to write grid row. Disk full?\n" ); return NULL; } if( !pfnProgress( static_cast<double>(nYSize - iRow)/nYSize, NULL, pProgressData ) ) { VSIFCloseL( fp ); VSIFree( pfData ); CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" ); return NULL; } } VSIFree( pfData ); /* write out the min and max values */ eErr = WriteHeader( fp, nXSize, nYSize, dfMinX, dfMaxX, dfMinY, dfMaxY, dfMinZ, dfMaxZ ); if( eErr != CE_None ) { VSIFCloseL( fp ); return NULL; } VSIFCloseL( fp ); GDALPamDataset *poDS = (GDALPamDataset *)GDALOpen( pszFilename, GA_Update ); if (poDS) { poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT ); } return poDS; }
GDALDataset * GIFDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS, int bStrict, char ** papszOptions, GDALProgressFunc pfnProgress, void * pProgressData ) { int nBands = poSrcDS->GetRasterCount(); int nXSize = poSrcDS->GetRasterXSize(); int nYSize = poSrcDS->GetRasterYSize(); int bInterlace = FALSE; /* -------------------------------------------------------------------- */ /* Check for interlaced option. */ /* -------------------------------------------------------------------- */ bInterlace = CSLFetchBoolean(papszOptions, "INTERLACING", FALSE); /* -------------------------------------------------------------------- */ /* Some some rudimentary checks */ /* -------------------------------------------------------------------- */ if( nBands != 1 ) { CPLError( CE_Failure, CPLE_NotSupported, "GIF driver only supports one band images.\n" ); return NULL; } if (nXSize > 65535 || nYSize > 65535) { CPLError( CE_Failure, CPLE_NotSupported, "GIF driver only supports datasets up to 65535x65535 size.\n" ); return NULL; } if( poSrcDS->GetRasterBand(1)->GetRasterDataType() != GDT_Byte && bStrict ) { CPLError( CE_Failure, CPLE_NotSupported, "GIF driver doesn't support data type %s. " "Only eight bit bands supported.\n", GDALGetDataTypeName( poSrcDS->GetRasterBand(1)->GetRasterDataType()) ); return NULL; } /* -------------------------------------------------------------------- */ /* Open the output file. */ /* -------------------------------------------------------------------- */ GifFileType *hGifFile; VSILFILE *fp; fp = VSIFOpenL( pszFilename, "wb" ); if( fp == NULL ) { CPLError( CE_Failure, CPLE_OpenFailed, "Failed to create %s:\n%s", pszFilename, VSIStrerror( errno ) ); return NULL; } #if defined(GIFLIB_MAJOR) && GIFLIB_MAJOR >= 5 int nError; hGifFile = EGifOpen( fp, VSIGIFWriteFunc, &nError ); #else hGifFile = EGifOpen( fp, VSIGIFWriteFunc ); #endif if( hGifFile == NULL ) { VSIFCloseL( fp ); CPLError( CE_Failure, CPLE_OpenFailed, "EGifOpenFilename(%s) failed. Does file already exist?", pszFilename ); return NULL; } /* -------------------------------------------------------------------- */ /* Prepare colortable. */ /* -------------------------------------------------------------------- */ GDALRasterBand *poBand = poSrcDS->GetRasterBand(1); ColorMapObject *psGifCT; int iColor; if( poBand->GetColorTable() == NULL ) { psGifCT = GifMakeMapObject( 256, NULL ); for( iColor = 0; iColor < 256; iColor++ ) { psGifCT->Colors[iColor].Red = (GifByteType) iColor; psGifCT->Colors[iColor].Green = (GifByteType) iColor; psGifCT->Colors[iColor].Blue = (GifByteType) iColor; } } else { GDALColorTable *poCT = poBand->GetColorTable(); int nFullCount = 1; while( nFullCount < poCT->GetColorEntryCount() ) nFullCount = nFullCount * 2; psGifCT = GifMakeMapObject( nFullCount, NULL ); for( iColor = 0; iColor < poCT->GetColorEntryCount(); iColor++ ) { GDALColorEntry sEntry; poCT->GetColorEntryAsRGB( iColor, &sEntry ); psGifCT->Colors[iColor].Red = (GifByteType) sEntry.c1; psGifCT->Colors[iColor].Green = (GifByteType) sEntry.c2; psGifCT->Colors[iColor].Blue = (GifByteType) sEntry.c3; } for( ; iColor < nFullCount; iColor++ ) { psGifCT->Colors[iColor].Red = 0; psGifCT->Colors[iColor].Green = 0; psGifCT->Colors[iColor].Blue = 0; } } /* -------------------------------------------------------------------- */ /* Setup parameters. */ /* -------------------------------------------------------------------- */ if (EGifPutScreenDesc(hGifFile, nXSize, nYSize, psGifCT->ColorCount, 255, psGifCT) == GIF_ERROR) { GifFreeMapObject(psGifCT); GDALPrintGifError(hGifFile, "Error writing gif file."); GIFAbstractDataset::myEGifCloseFile(hGifFile); VSIFCloseL( fp ); return NULL; } GifFreeMapObject(psGifCT); psGifCT = NULL; /* Support for transparency */ int bNoDataValue; double noDataValue = poBand->GetNoDataValue(&bNoDataValue); if (bNoDataValue && noDataValue >= 0 && noDataValue <= 255) { unsigned char extensionData[4]; extensionData[0] = 1; /* Transparent Color Flag */ extensionData[1] = 0; extensionData[2] = 0; extensionData[3] = (unsigned char)noDataValue; EGifPutExtension(hGifFile, 0xf9, 4, extensionData); } if (EGifPutImageDesc(hGifFile, 0, 0, nXSize, nYSize, bInterlace, NULL) == GIF_ERROR ) { GDALPrintGifError(hGifFile, "Error writing gif file."); GIFAbstractDataset::myEGifCloseFile(hGifFile); VSIFCloseL( fp ); return NULL; } /* -------------------------------------------------------------------- */ /* Loop over image, copying image data. */ /* -------------------------------------------------------------------- */ CPLErr eErr; GDALPamDataset *poDS; GByte *pabyScanline; pabyScanline = (GByte *) CPLMalloc( nXSize ); if( !pfnProgress( 0.0, NULL, pProgressData ) ) eErr = CE_Failure; if( !bInterlace ) { for( int iLine = 0; iLine < nYSize; iLine++ ) { eErr = poBand->RasterIO( GF_Read, 0, iLine, nXSize, 1, pabyScanline, nXSize, 1, GDT_Byte, nBands, nBands * nXSize ); if( eErr != CE_None || EGifPutLine( hGifFile, pabyScanline, nXSize ) == GIF_ERROR ) { CPLError( CE_Failure, CPLE_AppDefined, "Error writing gif file." ); goto error; } if( !pfnProgress( (iLine + 1) * 1.0 / nYSize, NULL, pProgressData ) ) { goto error; } } } else { int i, j; int nLinesRead = 0; int nLinesToRead = 0; for ( i = 0; i < 4; i++) { for (j = InterlacedOffset[i]; j < nYSize; j += InterlacedJumps[i]) { nLinesToRead ++; } } /* Need to perform 4 passes on the images: */ for ( i = 0; i < 4; i++) { for (j = InterlacedOffset[i]; j < nYSize; j += InterlacedJumps[i]) { eErr= poBand->RasterIO( GF_Read, 0, j, nXSize, 1, pabyScanline, nXSize, 1, GDT_Byte, 1, nXSize ); if (eErr != CE_None || EGifPutLine(hGifFile, pabyScanline, nXSize) == GIF_ERROR) { CPLError( CE_Failure, CPLE_AppDefined, "Error writing gif file." ); goto error; } nLinesRead ++; if( !pfnProgress( nLinesRead * 1.0 / nYSize, NULL, pProgressData ) ) { goto error; } } } } CPLFree( pabyScanline ); pabyScanline = NULL; /* -------------------------------------------------------------------- */ /* cleanup */ /* -------------------------------------------------------------------- */ if (GIFAbstractDataset::myEGifCloseFile(hGifFile) == GIF_ERROR) { CPLError( CE_Failure, CPLE_AppDefined, "EGifCloseFile() failed.\n" ); hGifFile = NULL; goto error; } hGifFile = NULL; VSIFCloseL( fp ); fp = NULL; /* -------------------------------------------------------------------- */ /* Do we need a world file? */ /* -------------------------------------------------------------------- */ if( CSLFetchBoolean( papszOptions, "WORLDFILE", FALSE ) ) { double adfGeoTransform[6]; if( poSrcDS->GetGeoTransform( adfGeoTransform ) == CE_None ) GDALWriteWorldFile( pszFilename, "wld", adfGeoTransform ); } /* -------------------------------------------------------------------- */ /* Re-open dataset, and copy any auxilary pam information. */ /* -------------------------------------------------------------------- */ /* If outputing to stdout, we can't reopen it, so we'll return */ /* a fake dataset to make the caller happy */ CPLPushErrorHandler(CPLQuietErrorHandler); poDS = (GDALPamDataset*) GDALOpen(pszFilename, GA_ReadOnly); CPLPopErrorHandler(); if (poDS) { poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT ); return poDS; } else { CPLErrorReset(); GIFDataset* poGIF_DS = new GIFDataset(); poGIF_DS->nRasterXSize = nXSize; poGIF_DS->nRasterYSize = nYSize; for(int i=0;i<nBands;i++) poGIF_DS->SetBand( i+1, new GIFRasterBand( poGIF_DS, i+1, NULL, 0 ) ); return poGIF_DS; } error: if (hGifFile) GIFAbstractDataset::myEGifCloseFile(hGifFile); if (fp) VSIFCloseL( fp ); if (pabyScanline) CPLFree( pabyScanline ); return NULL; }
GDALDataset * SRTMHGTDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS, int bStrict, char ** /* papszOptions*/, GDALProgressFunc pfnProgress, void * pProgressData ) { /* -------------------------------------------------------------------- */ /* Some some rudimentary checks */ /* -------------------------------------------------------------------- */ const int nBands = poSrcDS->GetRasterCount(); if (nBands == 0) { CPLError( CE_Failure, CPLE_NotSupported, "SRTMHGT driver does not support source dataset with zero band.\n"); return nullptr; } else if (nBands != 1) { CPLError( (bStrict) ? CE_Failure : CE_Warning, CPLE_NotSupported, "SRTMHGT driver only uses the first band of the dataset.\n"); if (bStrict) return nullptr; } /* -------------------------------------------------------------------- */ /* Checks the input SRS */ /* -------------------------------------------------------------------- */ OGRSpatialReference ogrsr_input; ogrsr_input.importFromWkt(poSrcDS->GetProjectionRef()); OGRSpatialReference ogrsr_wgs84; ogrsr_wgs84.SetWellKnownGeogCS( "WGS84" ); if ( ogrsr_input.IsSameGeogCS(&ogrsr_wgs84) == FALSE) { CPLError( CE_Warning, CPLE_AppDefined, "The source projection coordinate system is %s. Only WGS 84 " "is supported.\nThe SRTMHGT driver will generate a file as " "if the source was WGS 84 projection coordinate system.", poSrcDS->GetProjectionRef() ); } /* -------------------------------------------------------------------- */ /* Work out the LL origin. */ /* -------------------------------------------------------------------- */ double adfGeoTransform[6]; if (poSrcDS->GetGeoTransform( adfGeoTransform ) != CE_None) { CPLError( CE_Failure, CPLE_AppDefined, "Source image must have a geo transform matrix."); return nullptr; } const int nLLOriginLat = static_cast<int>( std::floor(adfGeoTransform[3] + poSrcDS->GetRasterYSize() * adfGeoTransform[5] + 0.5) ); int nLLOriginLong = static_cast<int>( std::floor(adfGeoTransform[0] + 0.5) ); if (std::abs(nLLOriginLat - ( adfGeoTransform[3] + (poSrcDS->GetRasterYSize() - 0.5 ) * adfGeoTransform[5] ) ) > 1e-10 || std::abs(nLLOriginLong - ( adfGeoTransform[0] + 0.5 * adfGeoTransform[1])) > 1e-10 ) { CPLError( CE_Warning, CPLE_AppDefined, "The corner coordinates of the source are not properly " "aligned on plain latitude/longitude boundaries."); } /* -------------------------------------------------------------------- */ /* Check image dimensions. */ /* -------------------------------------------------------------------- */ const int nXSize = poSrcDS->GetRasterXSize(); const int nYSize = poSrcDS->GetRasterYSize(); if (!((nXSize == 1201 && nYSize == 1201) || (nXSize == 3601 && nYSize == 3601) || (nXSize == 1801 && nYSize == 3601))) { CPLError( CE_Failure, CPLE_AppDefined, "Image dimensions should be 1201x1201, 3601x3601 or 1801x3601."); return nullptr; } /* -------------------------------------------------------------------- */ /* Check filename. */ /* -------------------------------------------------------------------- */ char expectedFileName[12]; CPLsnprintf(expectedFileName, sizeof(expectedFileName), "%c%02d%c%03d.HGT", (nLLOriginLat >= 0) ? 'N' : 'S', (nLLOriginLat >= 0) ? nLLOriginLat : -nLLOriginLat, (nLLOriginLong >= 0) ? 'E' : 'W', (nLLOriginLong >= 0) ? nLLOriginLong : -nLLOriginLong); if (!EQUAL(expectedFileName, CPLGetFilename(pszFilename))) { CPLError( CE_Warning, CPLE_AppDefined, "Expected output filename is %s.", expectedFileName); } /* -------------------------------------------------------------------- */ /* Write output file. */ /* -------------------------------------------------------------------- */ VSILFILE* fp = VSIFOpenL(pszFilename, "wb"); if (fp == nullptr) { CPLError( CE_Failure, CPLE_FileIO, "Cannot create file %s", pszFilename ); return nullptr; } GInt16* panData = reinterpret_cast<GInt16 *>( CPLMalloc(sizeof(GInt16) * nXSize) ); GDALRasterBand* poSrcBand = poSrcDS->GetRasterBand(1); int bSrcBandHasNoData; double srcBandNoData = poSrcBand->GetNoDataValue(&bSrcBandHasNoData); for( int iY = 0; iY < nYSize; iY++ ) { if( poSrcBand->RasterIO( GF_Read, 0, iY, nXSize, 1, reinterpret_cast<void *>( panData ), nXSize, 1, GDT_Int16, 0, 0, nullptr ) != CE_None ) { VSIFCloseL(fp); CPLFree( panData ); return nullptr; } /* Translate nodata values */ if (bSrcBandHasNoData && srcBandNoData != SRTMHG_NODATA_VALUE) { for( int iX = 0; iX < nXSize; iX++ ) { if (panData[iX] == srcBandNoData) panData[iX] = SRTMHG_NODATA_VALUE; } } #ifdef CPL_LSB GDALSwapWords(panData, 2, nXSize, 2); #endif if( VSIFWriteL( panData,sizeof(GInt16) * nXSize,1,fp ) != 1) { CPLError( CE_Failure, CPLE_FileIO, "Failed to write line %d in SRTMHGT dataset.\n", iY ); VSIFCloseL(fp); CPLFree( panData ); return nullptr; } if( pfnProgress && !pfnProgress( (iY+1) / static_cast<double>( nYSize ), nullptr, pProgressData ) ) { CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated CreateCopy()" ); VSIFCloseL(fp); CPLFree( panData ); return nullptr; } } CPLFree( panData ); VSIFCloseL(fp); /* -------------------------------------------------------------------- */ /* Reopen and copy missing information into a PAM file. */ /* -------------------------------------------------------------------- */ GDALPamDataset *poDS = reinterpret_cast<GDALPamDataset *>( GDALOpen( pszFilename, GA_ReadOnly ) ); if( poDS ) poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT); return poDS; }
static GDALDataset * XPMCreateCopy( const char * pszFilename, GDALDataset *poSrcDS, int bStrict, char ** papszOptions, GDALProgressFunc pfnProgress, void * pProgressData ) { int nBands = poSrcDS->GetRasterCount(); int nXSize = poSrcDS->GetRasterXSize(); int nYSize = poSrcDS->GetRasterYSize(); GDALColorTable *poCT; /* -------------------------------------------------------------------- */ /* Some some rudimentary checks */ /* -------------------------------------------------------------------- */ if( nBands != 1 ) { CPLError( CE_Failure, CPLE_NotSupported, "XPM driver only supports one band images.\n" ); return NULL; } if( poSrcDS->GetRasterBand(1)->GetRasterDataType() != GDT_Byte && bStrict ) { CPLError( CE_Failure, CPLE_NotSupported, "XPM driver doesn't support data type %s. " "Only eight bit bands supported.\n", GDALGetDataTypeName( poSrcDS->GetRasterBand(1)->GetRasterDataType()) ); return NULL; } /* -------------------------------------------------------------------- */ /* If there is no colortable on the source image, create a */ /* greyscale one with 64 levels of grey. */ /* -------------------------------------------------------------------- */ GDALRasterBand *poBand = poSrcDS->GetRasterBand(1); int i; GDALColorTable oGreyTable; poCT = poBand->GetColorTable(); if( poCT == NULL ) { poCT = &oGreyTable; for( i = 0; i < 256; i++ ) { GDALColorEntry sColor; sColor.c1 = (short) i; sColor.c2 = (short) i; sColor.c3 = (short) i; sColor.c4 = 255; poCT->SetColorEntry( i, &sColor ); } } /* -------------------------------------------------------------------- */ /* Build list of active colors, and the mapping from pixels to */ /* our active colormap. */ /* -------------------------------------------------------------------- */ const char *pszColorCodes = " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()-+=[]|:;,.<>?/"; int anPixelMapping[256]; GDALColorEntry asPixelColor[256]; int nActiveColors = MIN(poCT->GetColorEntryCount(),256); // Setup initial colortable and pixel value mapping. memset( anPixelMapping+0, 0, sizeof(int) * 256 ); for( i = 0; i < nActiveColors; i++ ) { poCT->GetColorEntryAsRGB( i, asPixelColor + i ); anPixelMapping[i] = i; } /* ==================================================================== */ /* Iterate merging colors until we are under our limit (about 85). */ /* ==================================================================== */ while( nActiveColors > (int) strlen(pszColorCodes) ) { int nClosestDistance = 768; int iClose1 = -1, iClose2 = -1; int iColor1, iColor2; // Find the closest pair of colors. for( iColor1 = 0; iColor1 < nActiveColors; iColor1++ ) { for( iColor2 = iColor1+1; iColor2 < nActiveColors; iColor2++ ) { int nDistance; if( asPixelColor[iColor1].c4 < 128 && asPixelColor[iColor2].c4 < 128 ) nDistance = 0; else nDistance = ABS(asPixelColor[iColor1].c1-asPixelColor[iColor2].c1) + ABS(asPixelColor[iColor1].c2-asPixelColor[iColor2].c2) + ABS(asPixelColor[iColor1].c3-asPixelColor[iColor2].c3); if( nDistance < nClosestDistance ) { nClosestDistance = nDistance; iClose1 = iColor1; iClose2 = iColor2; } } if( nClosestDistance < 8 ) break; } // This should never happen! if( iClose1 == -1 ) break; // Merge two selected colors - shift icolor2 into icolor1 and // move the last active color into icolor2's slot. for( i = 0; i < 256; i++ ) { if( anPixelMapping[i] == iClose2 ) anPixelMapping[i] = iClose1; else if( anPixelMapping[i] == nActiveColors-1 ) anPixelMapping[i] = iClose2; } asPixelColor[iClose2] = asPixelColor[nActiveColors-1]; nActiveColors--; } /* ==================================================================== */ /* Write the output image. */ /* ==================================================================== */ FILE *fpPBM; fpPBM = VSIFOpen( pszFilename, "wt+" ); if( fpPBM == NULL ) { CPLError( CE_Failure, CPLE_OpenFailed, "Unable to create file `%s'.", pszFilename ); return NULL; } /* -------------------------------------------------------------------- */ /* Write the header lines. */ /* -------------------------------------------------------------------- */ fprintf( fpPBM, "/* XPM */\n" ); fprintf( fpPBM, "static char *%s[] = {\n", CPLGetBasename( pszFilename ) ); fprintf( fpPBM, "/* width height num_colors chars_per_pixel */\n" ); fprintf( fpPBM, "\" %3d %3d %3d 1\",\n", nXSize, nYSize, nActiveColors ); fprintf( fpPBM, "/* colors */\n" ); /* -------------------------------------------------------------------- */ /* Write the color table. */ /* -------------------------------------------------------------------- */ for( i = 0; i < nActiveColors; i++ ) { if( asPixelColor[i].c4 < 128 ) fprintf( fpPBM, "\"%c c None\",\n", pszColorCodes[i] ); else fprintf( fpPBM, "\"%c c #%02x%02x%02x\",\n", pszColorCodes[i], asPixelColor[i].c1, asPixelColor[i].c2, asPixelColor[i].c3 ); } /* -------------------------------------------------------------------- */ /* Dump image. */ /* -------------------------------------------------------------------- */ int iLine; GByte *pabyScanline; pabyScanline = (GByte *) CPLMalloc( nXSize ); for( iLine = 0; iLine < nYSize; iLine++ ) { poBand->RasterIO( GF_Read, 0, iLine, nXSize, 1, (void *) pabyScanline, nXSize, 1, GDT_Byte, 0, 0 ); fputc( '"', fpPBM ); for( int iPixel = 0; iPixel < nXSize; iPixel++ ) fputc( pszColorCodes[anPixelMapping[pabyScanline[iPixel]]], fpPBM); fprintf( fpPBM, "\",\n" ); } CPLFree( pabyScanline ); /* -------------------------------------------------------------------- */ /* cleanup */ /* -------------------------------------------------------------------- */ fprintf( fpPBM, "};\n" ); VSIFClose( fpPBM ); /* -------------------------------------------------------------------- */ /* Re-open dataset, and copy any auxilary pam information. */ /* -------------------------------------------------------------------- */ GDALPamDataset *poDS = (GDALPamDataset *) GDALOpen( pszFilename, GA_ReadOnly ); if( poDS ) poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT ); return poDS; }
static GDALDataset *FITCreateCopy(const char * pszFilename, GDALDataset *poSrcDS, int bStrict, char ** papszOptions, GDALProgressFunc pfnProgress, void * pProgressData ) { CPLDebug("FIT", "CreateCopy %s - %i", pszFilename, bStrict); int nBands = poSrcDS->GetRasterCount(); if (nBands == 0) { CPLError( CE_Failure, CPLE_NotSupported, "FIT driver does not support source dataset with zero band.\n"); return nullptr; } /* -------------------------------------------------------------------- */ /* Create the dataset. */ /* -------------------------------------------------------------------- */ if( !pfnProgress( 0.0, nullptr, pProgressData ) ) { CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" ); return nullptr; } VSILFILE *fpImage = VSIFOpenL( pszFilename, "wb" ); if( fpImage == nullptr ) { CPLError( CE_Failure, CPLE_OpenFailed, "FIT - unable to create file %s.\n", pszFilename ); return nullptr; } /* -------------------------------------------------------------------- */ /* Generate header. */ /* -------------------------------------------------------------------- */ // XXX - should FIT_PAGE_SIZE be based on file page size ?? const size_t size = std::max(sizeof(FIThead02), FIT_PAGE_SIZE); FIThead02 *head = (FIThead02 *) malloc(size); FreeGuard<FIThead02> guardHead( head ); // clean header so padding (past real header) is all zeros memset( head, 0, size ); memcpy((char *) &head->magic, "IT", 2); memcpy((char *) &head->version, "02", 2); head->xSize = poSrcDS->GetRasterXSize(); gst_swapb(head->xSize); head->ySize = poSrcDS->GetRasterYSize(); gst_swapb(head->ySize); head->zSize = 1; gst_swapb(head->zSize); head->cSize = nBands; gst_swapb(head->cSize); GDALRasterBand *firstBand = poSrcDS->GetRasterBand(1); if (! firstBand) { CPL_IGNORE_RET_VAL(VSIFCloseL(fpImage)); return nullptr; } head->dtype = fitGetDataType(firstBand->GetRasterDataType()); if (! head->dtype) { CPL_IGNORE_RET_VAL(VSIFCloseL(fpImage)); return nullptr; } gst_swapb(head->dtype); head->order = 1; // interleaved - RGBRGB gst_swapb(head->order); head->space = 1; // upper left gst_swapb(head->space); // XXX - need to check all bands head->cm = fitGetColorModel(firstBand->GetColorInterpretation(), nBands); gst_swapb(head->cm); int blockX, blockY; firstBand->GetBlockSize(&blockX, &blockY); blockX = std::min(blockX, poSrcDS->GetRasterXSize()); blockY = std::min(blockY, poSrcDS->GetRasterYSize()); int nDTSize = GDALGetDataTypeSizeBytes(firstBand->GetRasterDataType()); try { CPL_IGNORE_RET_VAL( CPLSM(blockX) * CPLSM(blockY) * CPLSM(nDTSize) * CPLSM(nBands)); CPLDebug("FIT write", "inherited block size %ix%i", blockX, blockY); } catch( ... ) { blockX = std::min(256, poSrcDS->GetRasterXSize()); blockY = std::min(256, poSrcDS->GetRasterYSize()); } if( CSLFetchNameValue(papszOptions,"PAGESIZE") != nullptr ) { const char *str = CSLFetchNameValue(papszOptions,"PAGESIZE"); int newBlockX, newBlockY; sscanf(str, "%i,%i", &newBlockX, &newBlockY); if (newBlockX && newBlockY) { blockX = newBlockX; blockY = newBlockY; } else { CPLError(CE_Failure, CPLE_OpenFailed, "FIT - Unable to parse option PAGESIZE values [%s]", str); } } // XXX - need to do lots of checking of block size // * provide ability to override block size with options // * handle non-square block size (like scanline) // - probably default from non-tiled image - have default block size // * handle block size bigger than image size // * undesirable block size (non power of 2, others?) // * mismatched block sizes for different bands // * image that isn't even pages (i.e. partially empty pages at edge) CPLDebug("FIT write", "using block size %ix%i", blockX, blockY); head->xPageSize = blockX; gst_swapb(head->xPageSize); head->yPageSize = blockY; gst_swapb(head->yPageSize); head->zPageSize = 1; gst_swapb(head->zPageSize); head->cPageSize = nBands; gst_swapb(head->cPageSize); // XXX - need to check all bands head->minValue = firstBand->GetMinimum(); gst_swapb(head->minValue); // XXX - need to check all bands head->maxValue = firstBand->GetMaximum(); gst_swapb(head->maxValue); head->dataOffset = static_cast<unsigned int>(size); gst_swapb(head->dataOffset); CPL_IGNORE_RET_VAL(VSIFWriteL(head, size, 1, fpImage)); /* -------------------------------------------------------------------- */ /* Loop over image, copying image data. */ /* -------------------------------------------------------------------- */ unsigned long bytesPerPixel = nBands * nDTSize; size_t pageBytes = blockX * blockY * bytesPerPixel; char *output = (char *) malloc(pageBytes); if (! output) { CPLError(CE_Failure, CPLE_OutOfMemory, "FITRasterBand couldn't allocate %lu bytes", static_cast<unsigned long>(pageBytes)); CPL_IGNORE_RET_VAL(VSIFCloseL(fpImage)); return nullptr; } FreeGuard<char> guardOutput( output ); long maxx = (long) ceil(poSrcDS->GetRasterXSize() / (double) blockX); long maxy = (long) ceil(poSrcDS->GetRasterYSize() / (double) blockY); long maxx_full = (long) floor(poSrcDS->GetRasterXSize() / (double) blockX); long maxy_full = (long) floor(poSrcDS->GetRasterYSize() / (double) blockY); CPLDebug("FIT", "about to write %ld x %ld blocks", maxx, maxy); for(long y=0; y < maxy; y++) for(long x=0; x < maxx; x++) { long readX = blockX; long readY = blockY; int do_clean = FALSE; // handle cases where image size isn't an exact multiple // of page size if (x >= maxx_full) { readX = poSrcDS->GetRasterXSize() % blockX; do_clean = TRUE; } if (y >= maxy_full) { readY = poSrcDS->GetRasterYSize() % blockY; do_clean = TRUE; } // clean out image if only doing partial reads if (do_clean) memset( output, 0, pageBytes ); for( int iBand = 0; iBand < nBands; iBand++ ) { GDALRasterBand * poBand = poSrcDS->GetRasterBand( iBand+1 ); CPLErr eErr = poBand->RasterIO( GF_Read, // eRWFlag static_cast<int>(x * blockX), // nXOff static_cast<int>(y * blockY), // nYOff static_cast<int>(readX), // nXSize static_cast<int>(readY), // nYSize output + iBand * nDTSize, // pData blockX, // nBufXSize blockY, // nBufYSize firstBand->GetRasterDataType(), // eBufType bytesPerPixel, // nPixelSpace bytesPerPixel * blockX, nullptr); // nLineSpace if (eErr != CE_None) { CPLError(CE_Failure, CPLE_FileIO, "FIT write - CreateCopy got read error %i", eErr); CPL_IGNORE_RET_VAL(VSIFCloseL( fpImage )); VSIUnlink( pszFilename ); return nullptr; } } // for iBand #ifdef swapping char *p = output; unsigned long i; switch(nDTSize) { case 1: // do nothing break; case 2: for(i=0; i < pageBytes; i+= nDTSize) gst_swap16(p + i); break; case 4: for(i=0; i < pageBytes; i+= nDTSize) gst_swap32(p + i); break; case 8: for(i=0; i < pageBytes; i+= nDTSize) gst_swap64(p + i); break; default: CPLError(CE_Failure, CPLE_NotSupported, "FIT write - unsupported bytesPerPixel %d", nDTSize); } // switch #endif // swapping if( VSIFWriteL(output, 1, pageBytes, fpImage) != pageBytes ) { CPLError( CE_Failure, CPLE_FileIO, "Write failed" ); CPL_IGNORE_RET_VAL(VSIFCloseL( fpImage )); VSIUnlink( pszFilename ); return nullptr; } double perc = ((double) (y * maxx + x)) / (maxx * maxy); if( !pfnProgress( perc, nullptr, pProgressData ) ) { CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" ); //free(output); CPL_IGNORE_RET_VAL(VSIFCloseL( fpImage )); VSIUnlink( pszFilename ); return nullptr; } } // for x //free(output); CPL_IGNORE_RET_VAL(VSIFCloseL( fpImage )); pfnProgress( 1.0, nullptr, pProgressData ); /* -------------------------------------------------------------------- */ /* Re-open dataset, and copy any auxiliary pam information. */ /* -------------------------------------------------------------------- */ GDALPamDataset *poDS = (GDALPamDataset *) GDALOpen( pszFilename, GA_ReadOnly ); if( poDS ) poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT ); return poDS; }
GDALDataset *GSAGDataset::CreateCopy( const char *pszFilename, GDALDataset *poSrcDS, int bStrict, char **papszOptions, GDALProgressFunc pfnProgress, void *pProgressData ) { if( pfnProgress == NULL ) pfnProgress = GDALDummyProgress; int nBands = poSrcDS->GetRasterCount(); if (nBands == 0) { CPLError( CE_Failure, CPLE_NotSupported, "GSAG driver does not support source dataset with zero band.\n"); return NULL; } else if (nBands > 1) { if( bStrict ) { CPLError( CE_Failure, CPLE_NotSupported, "Unable to create copy, Golden Software ASCII Grid " "format only supports one raster band.\n" ); return NULL; } else CPLError( CE_Warning, CPLE_NotSupported, "Golden Software ASCII Grid format only supports one " "raster band, first band will be copied.\n" ); } if( !pfnProgress( 0.0, NULL, pProgressData ) ) { CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated\n" ); return NULL; } VSILFILE *fp = VSIFOpenL( pszFilename, "w+b" ); if( fp == NULL ) { CPLError( CE_Failure, CPLE_OpenFailed, "Attempt to create file '%s' failed.\n", pszFilename ); return NULL; } int nXSize = poSrcDS->GetRasterXSize(); int nYSize = poSrcDS->GetRasterYSize(); double adfGeoTransform[6]; poSrcDS->GetGeoTransform( adfGeoTransform ); std::ostringstream ssHeader; ssHeader.precision( nFIELD_PRECISION ); ssHeader.setf( std::ios::uppercase ); ssHeader << "DSAA\x0D\x0A"; ssHeader << nXSize << " " << nYSize << "\x0D\x0A"; ssHeader << adfGeoTransform[0] + adfGeoTransform[1] / 2 << " " << adfGeoTransform[1] * (nXSize - 0.5) + adfGeoTransform[0] << "\x0D\x0A"; ssHeader << adfGeoTransform[5] * (nYSize - 0.5) + adfGeoTransform[3] << " " << adfGeoTransform[3] + adfGeoTransform[5] / 2 << "\x0D\x0A"; if( VSIFWriteL( (void *)ssHeader.str().c_str(), 1, ssHeader.str().length(), fp ) != ssHeader.str().length() ) { VSIFCloseL( fp ); CPLError( CE_Failure, CPLE_FileIO, "Unable to create copy, writing header failed.\n" ); return NULL; } /* Save the location and write placeholders for the min/max Z value */ vsi_l_offset nRangeStart = VSIFTellL( fp ); const char *szDummyRange = "0.0000000000001 0.0000000000001\x0D\x0A"; size_t nDummyRangeLen = strlen( szDummyRange ); if( VSIFWriteL( (void *)szDummyRange, 1, nDummyRangeLen, fp ) != nDummyRangeLen ) { VSIFCloseL( fp ); CPLError( CE_Failure, CPLE_FileIO, "Unable to create copy, writing header failed.\n" ); return NULL; } /* -------------------------------------------------------------------- */ /* Copy band data. */ /* -------------------------------------------------------------------- */ double *pdfData = (double *)VSIMalloc2( nXSize, sizeof( double ) ); if( pdfData == NULL ) { VSIFCloseL( fp ); CPLError( CE_Failure, CPLE_OutOfMemory, "Unable to create copy, unable to allocate line buffer.\n" ); return NULL; } GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand(1); int bSrcHasNDValue; double dfSrcNoDataValue = poSrcBand->GetNoDataValue( &bSrcHasNDValue ); double dfMin = DBL_MAX; double dfMax = -DBL_MAX; for( int iRow=0; iRow<nYSize; iRow++ ) { CPLErr eErr = poSrcBand->RasterIO( GF_Read, 0, nYSize-iRow-1, nXSize, 1, pdfData, nXSize, 1, GDT_Float64, 0, 0 ); if( eErr != CE_None ) { VSIFCloseL( fp ); VSIFree( pdfData ); return NULL; } for( int iCol=0; iCol<nXSize; ) { for( int iCount=0; iCount<10 && iCol<nXSize; iCount++, iCol++ ) { double dfValue = pdfData[iCol]; if( bSrcHasNDValue && AlmostEqual( dfValue, dfSrcNoDataValue ) ) { dfValue = dfNODATA_VALUE; } else { if( dfValue > dfMax ) dfMax = dfValue; if( dfValue < dfMin ) dfMin = dfValue; } std::ostringstream ssOut; ssOut.precision(nFIELD_PRECISION); ssOut.setf( std::ios::uppercase ); ssOut << dfValue << " "; CPLString sOut = ssOut.str(); if( VSIFWriteL( sOut.c_str(), 1, sOut.length(), fp ) != sOut.length() ) { VSIFCloseL( fp ); VSIFree( pdfData ); CPLError( CE_Failure, CPLE_FileIO, "Unable to write grid cell. Disk full?\n" ); return NULL; } } if( VSIFWriteL( (void *)"\x0D\x0A", 1, 2, fp ) != 2 ) { VSIFCloseL( fp ); VSIFree( pdfData ); CPLError( CE_Failure, CPLE_FileIO, "Unable to finish write of grid line. Disk full?\n" ); return NULL; } } if( VSIFWriteL( (void *)"\x0D\x0A", 1, 2, fp ) != 2 ) { VSIFCloseL( fp ); VSIFree( pdfData ); CPLError( CE_Failure, CPLE_FileIO, "Unable to finish write of grid row. Disk full?\n" ); return NULL; } if( !pfnProgress( static_cast<double>(iRow + 1)/nYSize, NULL, pProgressData ) ) { VSIFCloseL( fp ); VSIFree( pdfData ); CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" ); return NULL; } } VSIFree( pdfData ); /* write out the min and max values */ std::ostringstream ssRange; ssRange.precision( nFIELD_PRECISION ); ssRange.setf( std::ios::uppercase ); ssRange << dfMin << " " << dfMax << "\x0D\x0A"; if( ssRange.str().length() != nDummyRangeLen ) { int nShiftSize = ssRange.str().length() - nDummyRangeLen; if( ShiftFileContents( fp, nRangeStart + nDummyRangeLen, nShiftSize, "\x0D\x0A" ) != CE_None ) { VSIFCloseL( fp ); CPLError( CE_Failure, CPLE_FileIO, "Unable to shift file contents.\n" ); return NULL; } } if( VSIFSeekL( fp, nRangeStart, SEEK_SET ) != 0 ) { VSIFCloseL( fp ); CPLError( CE_Failure, CPLE_FileIO, "Unable to seek to start of grid file copy.\n" ); return NULL; } if( VSIFWriteL( (void *)ssRange.str().c_str(), 1, ssRange.str().length(), fp ) != ssRange.str().length() ) { VSIFCloseL( fp ); CPLError( CE_Failure, CPLE_FileIO, "Unable to write range information.\n" ); return NULL; } VSIFCloseL( fp ); GDALPamDataset *poDS = (GDALPamDataset *)GDALOpen( pszFilename, GA_Update ); if (poDS) { poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT ); } return poDS; }
GDALDataset *GSBGDataset::CreateCopy( const char *pszFilename, GDALDataset *poSrcDS, int bStrict, char **papszOptions, GDALProgressFunc pfnProgress, void *pProgressData ) { if( pfnProgress == NULL ) pfnProgress = GDALDummyProgress; int nBands = poSrcDS->GetRasterCount(); if (nBands == 0) { CPLError( CE_Failure, CPLE_NotSupported, "GSBG driver does not support source dataset with zero band.\n"); return NULL; } else if (nBands > 1) { if( bStrict ) { CPLError( CE_Failure, CPLE_NotSupported, "Unable to create copy, Golden Software Binary Grid " "format only supports one raster band.\n" ); return NULL; } else CPLError( CE_Warning, CPLE_NotSupported, "Golden Software Binary Grid format only supports one " "raster band, first band will be copied.\n" ); } GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand( 1 ); if( poSrcBand->GetXSize() > SHRT_MAX || poSrcBand->GetYSize() > SHRT_MAX ) { CPLError( CE_Failure, CPLE_IllegalArg, "Unable to create grid, Golden Software Binary Grid format " "only supports sizes up to %dx%d. %dx%d not supported.\n", SHRT_MAX, SHRT_MAX, poSrcBand->GetXSize(), poSrcBand->GetYSize() ); return NULL; } if( !pfnProgress( 0.0, NULL, pProgressData ) ) { CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated\n" ); return NULL; } VSILFILE *fp = VSIFOpenL( pszFilename, "w+b" ); if( fp == NULL ) { CPLError( CE_Failure, CPLE_OpenFailed, "Attempt to create file '%s' failed.\n", pszFilename ); return NULL; } GInt16 nXSize = (GInt16) poSrcBand->GetXSize(); GInt16 nYSize = (GInt16) poSrcBand->GetYSize(); double adfGeoTransform[6]; poSrcDS->GetGeoTransform( adfGeoTransform ); double dfMinX = adfGeoTransform[0] + adfGeoTransform[1] / 2; double dfMaxX = adfGeoTransform[1] * (nXSize - 0.5) + adfGeoTransform[0]; double dfMinY = adfGeoTransform[5] * (nYSize - 0.5) + adfGeoTransform[3]; double dfMaxY = adfGeoTransform[3] + adfGeoTransform[5] / 2; CPLErr eErr = WriteHeader( fp, nXSize, nYSize, dfMinX, dfMaxX, dfMinY, dfMaxY, 0.0, 0.0 ); if( eErr != CE_None ) { VSIFCloseL( fp ); return NULL; } /* -------------------------------------------------------------------- */ /* Copy band data. */ /* -------------------------------------------------------------------- */ float *pfData = (float *)VSIMalloc2( nXSize, sizeof( float ) ); if( pfData == NULL ) { VSIFCloseL( fp ); CPLError( CE_Failure, CPLE_OutOfMemory, "Unable to create copy, unable to allocate line buffer.\n" ); return NULL; } int bSrcHasNDValue; float fSrcNoDataValue = (float) poSrcBand->GetNoDataValue( &bSrcHasNDValue ); double dfMinZ = DBL_MAX; double dfMaxZ = -DBL_MAX; for( GInt16 iRow = nYSize - 1; iRow >= 0; iRow-- ) { eErr = poSrcBand->RasterIO( GF_Read, 0, iRow, nXSize, 1, pfData, nXSize, 1, GDT_Float32, 0, 0 ); if( eErr != CE_None ) { VSIFCloseL( fp ); VSIFree( pfData ); return NULL; } for( int iCol=0; iCol<nXSize; iCol++ ) { if( bSrcHasNDValue && pfData[iCol] == fSrcNoDataValue ) { pfData[iCol] = fNODATA_VALUE; } else { if( pfData[iCol] > dfMaxZ ) dfMaxZ = pfData[iCol]; if( pfData[iCol] < dfMinZ ) dfMinZ = pfData[iCol]; } CPL_LSBPTR32( pfData+iCol ); } if( VSIFWriteL( (void *)pfData, 4, nXSize, fp ) != static_cast<unsigned>(nXSize) ) { VSIFCloseL( fp ); VSIFree( pfData ); CPLError( CE_Failure, CPLE_FileIO, "Unable to write grid row. Disk full?\n" ); return NULL; } if( !pfnProgress( static_cast<double>(nYSize - iRow)/nYSize, NULL, pProgressData ) ) { VSIFCloseL( fp ); VSIFree( pfData ); CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" ); return NULL; } } VSIFree( pfData ); /* write out the min and max values */ eErr = WriteHeader( fp, nXSize, nYSize, dfMinX, dfMaxX, dfMinY, dfMaxY, dfMinZ, dfMaxZ ); if( eErr != CE_None ) { VSIFCloseL( fp ); return NULL; } VSIFCloseL( fp ); GDALPamDataset *poDS = (GDALPamDataset *)GDALOpen( pszFilename, GA_Update ); if (poDS) { poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT ); } return poDS; }
GDALDataset *GSBGDataset::CreateCopy( const char *pszFilename, GDALDataset *poSrcDS, int bStrict, char **papszOptions, GDALProgressFunc pfnProgress, void *pProgressData ) { if( pfnProgress == NULL ) pfnProgress = GDALDummyProgress; int nBands = poSrcDS->GetRasterCount(); if (nBands == 0) { CPLError( CE_Failure, CPLE_NotSupported, "GSBG driver does not support source dataset with zero band.\n"); return NULL; } else if (nBands > 1) { if( bStrict ) { CPLError( CE_Failure, CPLE_NotSupported, "Unable to create copy, Golden Software Binary Grid " "format only supports one raster band.\n" ); return NULL; } else CPLError( CE_Warning, CPLE_NotSupported, "Golden Software Binary Grid format only supports one " "raster band, first band will be copied.\n" ); } GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand( 1 ); if( poSrcBand->GetXSize() > SHRT_MAX || poSrcBand->GetYSize() > SHRT_MAX ) { CPLError( CE_Failure, CPLE_IllegalArg, "Unable to create grid, Golden Software Binary Grid format " "only supports sizes up to %dx%d. %dx%d not supported.\n", SHRT_MAX, SHRT_MAX, poSrcBand->GetXSize(), poSrcBand->GetYSize() ); return NULL; } if( !pfnProgress( 0.0, NULL, pProgressData ) ) { CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated\n" ); return NULL; } VSILFILE *fp = VSIFOpenL( pszFilename, "w+b" ); if( fp == NULL ) { CPLError( CE_Failure, CPLE_OpenFailed, "Attempt to create file '%s' failed.\n", pszFilename ); return NULL; } GInt16 nXSize = poSrcBand->GetXSize(); GInt16 nYSize = poSrcBand->GetYSize(); double adfGeoTransform[6]; poSrcDS->GetGeoTransform( adfGeoTransform ); double dfMinX = adfGeoTransform[0] + adfGeoTransform[1] / 2; double dfMaxX = adfGeoTransform[1] * (nXSize - 0.5) + adfGeoTransform[0]; double dfMinY = adfGeoTransform[5] * (nYSize - 0.5) + adfGeoTransform[3]; double dfMaxY = adfGeoTransform[3] + adfGeoTransform[5] / 2; CPLErr eErr = WriteHeader( fp, nXSize, nYSize, dfMinX, dfMaxX, dfMinY, dfMaxY, 0.0, 0.0 ); if( eErr != CE_None ) { VSIFCloseL( fp ); return NULL; } /* -------------------------------------------------------------------- */ /* Copy band data. */ /* -------------------------------------------------------------------- */ float *pfData = (float *)VSIMalloc2( nXSize, sizeof( float ) ); if( pfData == NULL ) { VSIFCloseL( fp ); CPLError( CE_Failure, CPLE_OutOfMemory, "Unable to create copy, unable to allocate line buffer.\n" ); return NULL; } int bSrcHasNDValue; float fSrcNoDataValue = poSrcBand->GetNoDataValue( &bSrcHasNDValue ); double dfMinZ = DBL_MAX; double dfMaxZ = -DBL_MAX; for( GInt16 iRow = nYSize - 1; iRow >= 0; iRow-- ) { eErr = poSrcBand->RasterIO( GF_Read, 0, iRow, nXSize, 1, pfData, nXSize, 1, GDT_Float32, 0, 0 ); if( eErr != CE_None ) { VSIFCloseL( fp ); VSIFree( pfData ); return NULL; } for( int iCol=0; iCol<nXSize; iCol++ ) { if( bSrcHasNDValue && pfData[iCol] == fSrcNoDataValue ) { pfData[iCol] = fNODATA_VALUE; } else { if( pfData[iCol] > dfMaxZ ) dfMaxZ = pfData[iCol]; if( pfData[iCol] < dfMinZ ) dfMinZ = pfData[iCol]; } CPL_LSBPTR32( pfData+iCol ); } if( VSIFWriteL( (void *)pfData, 4, nXSize, fp ) != static_cast<unsigned>(nXSize) ) { VSIFCloseL( fp ); VSIFree( pfData ); CPLError( CE_Failure, CPLE_FileIO, "Unable to write grid row. Disk full?\n" ); return NULL; } if( !pfnProgress( static_cast<double>(iRow)/nYSize, NULL, pProgressData ) ) { VSIFCloseL( fp ); VSIFree( pfData ); CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" ); return NULL; } } VSIFree( pfData ); /* write out the min and max values */ eErr = WriteHeader( fp, nXSize, nYSize, dfMinX, dfMaxX, dfMinY, dfMaxY, dfMinZ, dfMaxZ ); if( eErr != CE_None ) { VSIFCloseL( fp ); return NULL; } VSIFCloseL( fp ); GDALPamDataset *poDstDS = (GDALPamDataset *)GDALOpen( pszFilename, GA_Update ); if( poDstDS == NULL ) { VSIUnlink( pszFilename ); CPLError( CE_Failure, CPLE_FileIO, "Unable to open copy of dataset.\n" ); return NULL; } else if( dynamic_cast<GSBGDataset *>(poDstDS) == NULL ) { VSIUnlink( pszFilename ); delete poDstDS; CPLError( CE_Failure, CPLE_FileIO, "Copy dataset not opened as Golden Surfer Binary Grid!?\n" ); return NULL; } GDALRasterBand *poDstBand = poSrcDS->GetRasterBand(1); if( poDstBand == NULL ) { VSIUnlink( pszFilename ); delete poDstDS; CPLError( CE_Failure, CPLE_FileIO, "Unable to open copy of raster band?\n" ); return NULL; } /* -------------------------------------------------------------------- */ /* Attempt to copy metadata. */ /* -------------------------------------------------------------------- */ if( !bStrict ) CPLPushErrorHandler( CPLQuietErrorHandler ); /* non-zero transform 2 or 4 or negative 1 or 5 not supported natively */ /*if( adfGeoTransform[2] != 0.0 || adfGeoTransform[4] != 0.0 || adfGeoTransform[1] < 0.0 || adfGeoTransform[5] < 0.0 ) poDstDS->GDALPamDataset::SetGeoTransform( adfGeoTransform );*/ const char *szProjectionRef = poSrcDS->GetProjectionRef(); if( *szProjectionRef != '\0' ) poDstDS->SetProjection( szProjectionRef ); char **pszMetadata = poSrcDS->GetMetadata(); if( pszMetadata != NULL ) poDstDS->SetMetadata( pszMetadata ); /* FIXME: Should the dataset description be copied as well, or is it * always the file name? */ poDstBand->SetDescription( poSrcBand->GetDescription() ); int bSuccess; double dfOffset = poSrcBand->GetOffset( &bSuccess ); if( bSuccess && dfOffset != 0.0 ) poDstBand->SetOffset( dfOffset ); double dfScale = poSrcBand->GetScale( &bSuccess ); if( bSuccess && dfScale != 1.0 ) poDstBand->SetScale( dfScale ); GDALColorInterp oColorInterp = poSrcBand->GetColorInterpretation(); if( oColorInterp != GCI_Undefined ) poDstBand->SetColorInterpretation( oColorInterp ); char **pszCatNames = poSrcBand->GetCategoryNames(); if( pszCatNames != NULL) poDstBand->SetCategoryNames( pszCatNames ); GDALColorTable *poColorTable = poSrcBand->GetColorTable(); if( poColorTable != NULL ) poDstBand->SetColorTable( poColorTable ); if( !bStrict ) CPLPopErrorHandler(); return poDstDS; }
/*! \warning The source raster must have only 1 band. Currently, the values in the source raster must be stored in one of the supported cell representations (CR_UINT1, CR_INT4, CR_REAL4, CR_REAL8). The meta data item PCRASTER_VALUESCALE will be checked to see what value scale to use. Otherwise a value scale is determined using GDALType2ValueScale(GDALDataType). This function always writes rasters using CR_UINT1, CR_INT4 or CR_REAL4 cell representations. */ GDALDataset* PCRasterDataset::createCopy( char const* filename, GDALDataset* source, CPL_UNUSED int strict, CPL_UNUSED char** options, GDALProgressFunc progress, void* progressData) { // Checks. int nrBands = source->GetRasterCount(); if(nrBands != 1) { CPLError(CE_Failure, CPLE_NotSupported, "PCRaster driver: Too many bands ('%d'): must be 1 band", nrBands); return 0; } GDALRasterBand* raster = source->GetRasterBand(1); // Create PCRaster raster. Determine properties of raster to create. size_t nrRows = raster->GetYSize(); size_t nrCols = raster->GetXSize(); std::string string; // The in-file type of the cells. CSF_CR fileCellRepresentation = GDALType2CellRepresentation( raster->GetRasterDataType(), false); if(fileCellRepresentation == CR_UNDEFINED) { CPLError(CE_Failure, CPLE_NotSupported, "PCRaster driver: Cannot determine a valid cell representation"); return 0; } // The value scale of the values. CSF_VS valueScale = VS_UNDEFINED; if(source->GetMetadataItem("PCRASTER_VALUESCALE")) { string = source->GetMetadataItem("PCRASTER_VALUESCALE"); } valueScale = !string.empty() ? string2ValueScale(string) : GDALType2ValueScale(raster->GetRasterDataType()); if(valueScale == VS_UNDEFINED) { CPLError(CE_Failure, CPLE_NotSupported, "PCRaster driver: Cannot determine a valid value scale"); return 0; } CSF_PT const projection = PT_YDECT2B; REAL8 const angle = 0.0; REAL8 west = 0.0; REAL8 north = 0.0; REAL8 cellSize = 1.0; double transform[6]; if(source->GetGeoTransform(transform) == CE_None) { if(transform[2] == 0.0 && transform[4] == 0.0) { west = static_cast<REAL8>(transform[0]); north = static_cast<REAL8>(transform[3]); cellSize = static_cast<REAL8>(transform[1]); } } // The in-memory type of the cells. CSF_CR appCellRepresentation = CR_UNDEFINED; appCellRepresentation = GDALType2CellRepresentation( raster->GetRasterDataType(), true); if(appCellRepresentation == CR_UNDEFINED) { CPLError(CE_Failure, CPLE_NotSupported, "PCRaster driver: Cannot determine a valid cell representation"); return 0; } // Check whether value scale fits the cell representation. Adjust when // needed. valueScale = fitValueScale(valueScale, appCellRepresentation); // Create a raster with the in file cell representation. MAP* map = Rcreate(filename, nrRows, nrCols, fileCellRepresentation, valueScale, projection, west, north, angle, cellSize); if(!map) { CPLError(CE_Failure, CPLE_OpenFailed, "PCRaster driver: Unable to create raster %s", filename); return 0; } // Try to convert in app cell representation to the cell representation // of the file. if(RuseAs(map, appCellRepresentation)) { CPLError(CE_Failure, CPLE_NotSupported, "PCRaster driver: Cannot convert cells: %s", MstrError()); Mclose(map); return 0; } int hasMissingValue; double missingValue = raster->GetNoDataValue(&hasMissingValue); // This is needed to get my (KDJ) unit tests running. // I am still uncertain why this is needed. If the input raster has float32 // values and the output int32, than the missing value in the dataset object // is not updated like the values are. if(missingValue == ::missingValue(CR_REAL4) && fileCellRepresentation == CR_INT4) { missingValue = ::missingValue(fileCellRepresentation); } // TODO conversie van INT2 naar INT4 ondersteunen. zie ruseas.c regel 503. // conversie op r 159. // Create buffer for one row of values. void* buffer = Rmalloc(map, nrCols); // Copy values from source to target. CPLErr errorCode = CE_None; for(size_t row = 0; errorCode == CE_None && row < nrRows; ++row) { // Get row from source. if(raster->RasterIO(GF_Read, 0, row, nrCols, 1, buffer, nrCols, 1, raster->GetRasterDataType(), 0, 0, NULL) != CE_None) { CPLError(CE_Failure, CPLE_FileIO, "PCRaster driver: Error reading from source raster"); errorCode = CE_Failure; break; } // Upon reading values are converted to the // right data type. This includes the missing value. If the source // value cannot be represented in the target data type it is set to a // missing value. if(hasMissingValue) { alterToStdMV(buffer, nrCols, appCellRepresentation, missingValue); } if(valueScale == VS_BOOLEAN) { castValuesToBooleanRange(buffer, nrCols, appCellRepresentation); } // Write row in target. RputRow(map, row, buffer); if(!progress((row + 1) / (static_cast<double>(nrRows)), 0, progressData)) { CPLError(CE_Failure, CPLE_UserInterrupt, "PCRaster driver: User terminated CreateCopy()"); errorCode = CE_Failure; break; } } Mclose(map); map = 0; free(buffer); buffer = 0; if( errorCode != CE_None ) return NULL; /* -------------------------------------------------------------------- */ /* Re-open dataset, and copy any auxiliary pam information. */ /* -------------------------------------------------------------------- */ GDALPamDataset *poDS = (GDALPamDataset *) GDALOpen( filename, GA_Update ); if( poDS ) poDS->CloneInfo( source, GCIF_PAM_DEFAULT ); return poDS; }
GDALDataset * RCreateCopy( const char * pszFilename, GDALDataset *poSrcDS, int bStrict, char ** papszOptions, GDALProgressFunc pfnProgress, void * pProgressData ) { int nBands = poSrcDS->GetRasterCount(); int nXSize = poSrcDS->GetRasterXSize(); int nYSize = poSrcDS->GetRasterYSize(); int bASCII = CSLFetchBoolean( papszOptions, "ASCII", FALSE ); int bCompressed = CSLFetchBoolean( papszOptions, "COMPRESS", !bASCII ); /* -------------------------------------------------------------------- */ /* Some some rudimentary checks */ /* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */ /* Setup the filename to actually use. We prefix with */ /* /vsigzip/ if we want compressed output. */ /* -------------------------------------------------------------------- */ CPLString osAdjustedFilename; if( bCompressed ) osAdjustedFilename = "/vsigzip/"; osAdjustedFilename += pszFilename; /* -------------------------------------------------------------------- */ /* Create the file. */ /* -------------------------------------------------------------------- */ FILE *fp; fp = VSIFOpenL( osAdjustedFilename, "wb" ); if( fp == NULL ) { CPLError( CE_Failure, CPLE_OpenFailed, "Unable to create file %s.\n", pszFilename ); return NULL; } /* -------------------------------------------------------------------- */ /* Write header with version, etc. */ /* -------------------------------------------------------------------- */ if( bASCII ) { const char *pszHeader = "RDA2\nA\n"; VSIFWriteL( pszHeader, 1, strlen(pszHeader), fp ); } else { const char *pszHeader = "RDX2\nX\n"; VSIFWriteL( pszHeader, 1, strlen(pszHeader), fp ); } RWriteInteger( fp, bASCII, 2 ); RWriteInteger( fp, bASCII, 133377 ); RWriteInteger( fp, bASCII, 131840 ); /* -------------------------------------------------------------------- */ /* Establish the primary pairlist with one component object. */ /* -------------------------------------------------------------------- */ RWriteInteger( fp, bASCII, 1026 ); RWriteInteger( fp, bASCII, 1 ); /* -------------------------------------------------------------------- */ /* Write the object name. Eventually we should derive this */ /* from the filename, possible with override by a creation */ /* option. */ /* -------------------------------------------------------------------- */ RWriteString( fp, bASCII, "gg" ); /* -------------------------------------------------------------------- */ /* For now we write the raster as a numeric array with */ /* attributes (526). */ /* -------------------------------------------------------------------- */ RWriteInteger( fp, bASCII, 526 ); RWriteInteger( fp, bASCII, nXSize * nYSize * nBands ); /* -------------------------------------------------------------------- */ /* Write the raster data. */ /* -------------------------------------------------------------------- */ double *padfScanline; CPLErr eErr = CE_None; int iLine; padfScanline = (double *) CPLMalloc( nXSize * sizeof(double) ); for( int iBand = 0; iBand < nBands; iBand++ ) { GDALRasterBand * poBand = poSrcDS->GetRasterBand( iBand+1 ); for( iLine = 0; iLine < nYSize && eErr == CE_None; iLine++ ) { int iValue; eErr = poBand->RasterIO( GF_Read, 0, iLine, nXSize, 1, padfScanline, nXSize, 1, GDT_Float64, sizeof(double), 0 ); if( bASCII ) { for( iValue = 0; iValue < nXSize; iValue++ ) { char szValue[128]; sprintf(szValue,"%.16g\n", padfScanline[iValue] ); VSIFWriteL( szValue, 1, strlen(szValue), fp ); } } else { for( iValue = 0; iValue < nXSize; iValue++ ) CPL_MSBPTR64( padfScanline + iValue ); VSIFWriteL( padfScanline, 8, nXSize, fp ); } if( eErr == CE_None && !pfnProgress( (iLine+1) / (double) nYSize, NULL, pProgressData ) ) { eErr = CE_Failure; CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated CreateCopy()" ); } } } CPLFree( padfScanline ); /* -------------------------------------------------------------------- */ /* Write out the dims attribute. */ /* -------------------------------------------------------------------- */ RWriteInteger( fp, bASCII, 1026 ); RWriteInteger( fp, bASCII, 1 ); RWriteString( fp, bASCII, "dim" ); RWriteInteger( fp, bASCII, 13 ); RWriteInteger( fp, bASCII, 3 ); RWriteInteger( fp, bASCII, nXSize ); RWriteInteger( fp, bASCII, nYSize ); RWriteInteger( fp, bASCII, nBands ); RWriteInteger( fp, bASCII, 254 ); /* -------------------------------------------------------------------- */ /* Terminate overall pairlist. */ /* -------------------------------------------------------------------- */ RWriteInteger( fp, bASCII, 254 ); /* -------------------------------------------------------------------- */ /* Cleanup. */ /* -------------------------------------------------------------------- */ VSIFCloseL( fp ); if( eErr != CE_None ) return NULL; /* -------------------------------------------------------------------- */ /* Re-open dataset, and copy any auxilary pam information. */ /* -------------------------------------------------------------------- */ GDALPamDataset *poDS = (GDALPamDataset *) GDALOpen( pszFilename, GA_ReadOnly ); if( poDS ) poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT ); return poDS; }