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. */ /* ==================================================================== */ VSILFILE *fpPBM; fpPBM = VSIFOpenL( pszFilename, "wb+" ); if( fpPBM == NULL ) { CPLError( CE_Failure, CPLE_OpenFailed, "Unable to create file `%s'.", pszFilename ); return NULL; } /* -------------------------------------------------------------------- */ /* Write the header lines. */ /* -------------------------------------------------------------------- */ VSIFPrintfL( fpPBM, "/* XPM */\n" ); VSIFPrintfL( fpPBM, "static char *%s[] = {\n", CPLGetBasename( pszFilename ) ); VSIFPrintfL( fpPBM, "/* width height num_colors chars_per_pixel */\n" ); VSIFPrintfL( fpPBM, "\" %3d %3d %3d 1\",\n", nXSize, nYSize, nActiveColors ); VSIFPrintfL( fpPBM, "/* colors */\n" ); /* -------------------------------------------------------------------- */ /* Write the color table. */ /* -------------------------------------------------------------------- */ for( i = 0; i < nActiveColors; i++ ) { if( asPixelColor[i].c4 < 128 ) VSIFPrintfL( fpPBM, "\"%c c None\",\n", pszColorCodes[i] ); else VSIFPrintfL( 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 ); VSIFPutcL( '"', fpPBM ); for( int iPixel = 0; iPixel < nXSize; iPixel++ ) VSIFPutcL( pszColorCodes[anPixelMapping[pabyScanline[iPixel]]], fpPBM); VSIFPrintfL( fpPBM, "\",\n" ); } CPLFree( pabyScanline ); /* -------------------------------------------------------------------- */ /* cleanup */ /* -------------------------------------------------------------------- */ VSIFPrintfL( fpPBM, "};\n" ); VSIFCloseL( 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; }
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 *)VSIMalloc2( nXSize, sizeof( double ) ); if( pfData == NULL ) { VSIFCloseL( fp ); CPLError( CE_Failure, CPLE_OutOfMemory, "Unable to create copy, unable to allocate line buffer.\n" ); 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] = dfNoData_Value; } else { if( pfData[iCol] > dfMaxZ ) dfMaxZ = pfData[iCol]; if( pfData[iCol] < dfMinZ ) dfMinZ = pfData[iCol]; } CPL_LSBPTR32( 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 * SRTMHGTDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS, int bStrict, CPL_UNUSED char ** papszOptions, GDALProgressFunc pfnProgress, void * pProgressData ) { if( pfnProgress && !pfnProgress( 0.0, NULL, pProgressData ) ) return NULL; /* -------------------------------------------------------------------- */ /* 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 NULL; } 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 NULL; } /* -------------------------------------------------------------------- */ /* Checks the input SRS */ /* -------------------------------------------------------------------- */ OGRSpatialReference ogrsr_input; char* c = const_cast<char *>( poSrcDS->GetProjectionRef() ); ogrsr_input.importFromWkt(&c); 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 NULL; } 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))) { CPLError( CE_Failure, CPLE_AppDefined, "Image dimensions should be 1201x1201 or 3601x3601."); return NULL; } /* -------------------------------------------------------------------- */ /* Check filename. */ /* -------------------------------------------------------------------- */ char expectedFileName[12]; snprintf(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 == NULL) { CPLError( CE_Failure, CPLE_FileIO, "Cannot create file %s", pszFilename ); return NULL; } 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, NULL ) != CE_None ) { VSIFCloseL(fp); CPLFree( panData ); return NULL; } /* 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 NULL; } if( pfnProgress && !pfnProgress( (iY+1) / static_cast<double>( nYSize ), NULL, pProgressData ) ) { CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated CreateCopy()" ); VSIFCloseL(fp); CPLFree( panData ); return NULL; } } 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; }
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; }
static GDALDataset * DTEDCreateCopy( 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, "DTED driver does not support source dataset with zero band.\n"); return nullptr; } 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 nullptr; } if( pfnProgress && !pfnProgress( 0.0, nullptr, pProgressData ) ) return nullptr; /* -------------------------------------------------------------------- */ /* 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; 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.\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. */ /* -------------------------------------------------------------------- */ double adfGeoTransform[6]; poSrcDS->GetGeoTransform( adfGeoTransform ); int nLLOriginLat = (int) floor(adfGeoTransform[3] + poSrcDS->GetRasterYSize() * adfGeoTransform[5] + 0.5); int 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; int nReferenceLat = nLLOriginLat < 0 ? - (nLLOriginLat + 1) : nLLOriginLat; if( nReferenceLat >= 80 ) expectedXSize = (poSrcDS->GetRasterYSize() - 1) / 6 + 1; else if( nReferenceLat >= 75 ) expectedXSize = (poSrcDS->GetRasterYSize() - 1) / 4 + 1; else if( nReferenceLat >= 70 ) expectedXSize = (poSrcDS->GetRasterYSize() - 1) / 3 + 1; else if( nReferenceLat >= 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 = DTEDCreate( pszFilename, nLevel, nLLOriginLat, nLLOriginLong ); if( pszError != nullptr ) { CPLError( CE_Failure, CPLE_AppDefined, "%s", pszError ); return nullptr; } /* -------------------------------------------------------------------- */ /* Open the DTED file so we can output the data to it. */ /* -------------------------------------------------------------------- */ DTEDInfo *psDTED = DTEDOpen( pszFilename, "rb+", FALSE ); if( psDTED == nullptr ) return nullptr; /* -------------------------------------------------------------------- */ /* Read all the data in a single buffer. */ /* -------------------------------------------------------------------- */ GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand( 1 ); GInt16 *panData = (GInt16 *) VSI_MALLOC_VERBOSE(sizeof(GInt16) * psDTED->nXSize * psDTED->nYSize); if (panData == nullptr) { DTEDClose(psDTED); return nullptr; } for( int iY = 0; iY < psDTED->nYSize; iY++ ) { if( poSrcBand->RasterIO( GF_Read, 0, iY, psDTED->nXSize, 1, (void *) (panData + iY * psDTED->nXSize), psDTED->nXSize, 1, GDT_Int16, 0, 0, nullptr ) != CE_None ) { DTEDClose( psDTED ); CPLFree( panData ); return nullptr; } if( pfnProgress && !pfnProgress(0.5 * (iY+1) / (double) psDTED->nYSize, nullptr, pProgressData ) ) { CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated CreateCopy()" ); DTEDClose( psDTED ); CPLFree( panData ); return nullptr; } } 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, nullptr, pProgressData ) ) { CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated CreateCopy()" ); DTEDClose( psDTED ); CPLFree( panData ); return nullptr; } } 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; } CPLsnprintf( szPartialCell, sizeof(szPartialCell), "%02d",iPartialCell); DTEDSetMetadata(psDTED, DTEDMD_PARTIALCELL_DSI, szPartialCell); /* -------------------------------------------------------------------- */ /* Try to copy any matching available metadata. */ /* -------------------------------------------------------------------- */ if( poSrcDS->GetMetadataItem( "DTED_VerticalAccuracy_UHL" ) != nullptr ) DTEDSetMetadata( psDTED, DTEDMD_VERTACCURACY_UHL, poSrcDS->GetMetadataItem( "DTED_VerticalAccuracy_UHL" ) ); if( poSrcDS->GetMetadataItem( "DTED_VerticalAccuracy_ACC" ) != nullptr ) DTEDSetMetadata( psDTED, DTEDMD_VERTACCURACY_ACC, poSrcDS->GetMetadataItem( "DTED_VerticalAccuracy_ACC" ) ); if( poSrcDS->GetMetadataItem( "DTED_SecurityCode_UHL" ) != nullptr ) DTEDSetMetadata( psDTED, DTEDMD_SECURITYCODE_UHL, poSrcDS->GetMetadataItem( "DTED_SecurityCode_UHL" ) ); if( poSrcDS->GetMetadataItem( "DTED_SecurityCode_DSI" ) != nullptr ) DTEDSetMetadata( psDTED, DTEDMD_SECURITYCODE_DSI, poSrcDS->GetMetadataItem( "DTED_SecurityCode_DSI" ) ); if( poSrcDS->GetMetadataItem( "DTED_UniqueRef_UHL" ) != nullptr ) DTEDSetMetadata( psDTED, DTEDMD_UNIQUEREF_UHL, poSrcDS->GetMetadataItem( "DTED_UniqueRef_UHL" ) ); if( poSrcDS->GetMetadataItem( "DTED_UniqueRef_DSI" ) != nullptr ) DTEDSetMetadata( psDTED, DTEDMD_UNIQUEREF_DSI, poSrcDS->GetMetadataItem( "DTED_UniqueRef_DSI" ) ); if( poSrcDS->GetMetadataItem( "DTED_DataEdition" ) != nullptr ) DTEDSetMetadata( psDTED, DTEDMD_DATA_EDITION, poSrcDS->GetMetadataItem( "DTED_DataEdition" ) ); if( poSrcDS->GetMetadataItem( "DTED_MatchMergeVersion" ) != nullptr ) DTEDSetMetadata( psDTED, DTEDMD_MATCHMERGE_VERSION, poSrcDS->GetMetadataItem( "DTED_MatchMergeVersion" ) ); if( poSrcDS->GetMetadataItem( "DTED_MaintenanceDate" ) != nullptr ) DTEDSetMetadata( psDTED, DTEDMD_MAINT_DATE, poSrcDS->GetMetadataItem( "DTED_MaintenanceDate" ) ); if( poSrcDS->GetMetadataItem( "DTED_MatchMergeDate" ) != nullptr ) DTEDSetMetadata( psDTED, DTEDMD_MATCHMERGE_DATE, poSrcDS->GetMetadataItem( "DTED_MatchMergeDate" ) ); if( poSrcDS->GetMetadataItem( "DTED_MaintenanceDescription" ) != nullptr ) DTEDSetMetadata( psDTED, DTEDMD_MAINT_DESCRIPTION, poSrcDS->GetMetadataItem( "DTED_MaintenanceDescription" ) ); if( poSrcDS->GetMetadataItem( "DTED_Producer" ) != nullptr ) DTEDSetMetadata( psDTED, DTEDMD_PRODUCER, poSrcDS->GetMetadataItem( "DTED_Producer" ) ); if( poSrcDS->GetMetadataItem( "DTED_VerticalDatum" ) != nullptr ) DTEDSetMetadata( psDTED, DTEDMD_VERTDATUM, poSrcDS->GetMetadataItem( "DTED_VerticalDatum" ) ); if( poSrcDS->GetMetadataItem( "DTED_HorizontalDatum" ) != nullptr ) DTEDSetMetadata( psDTED, DTEDMD_HORIZDATUM, poSrcDS->GetMetadataItem( "DTED_HorizontalDatum" ) ); if( poSrcDS->GetMetadataItem( "DTED_DigitizingSystem" ) != nullptr ) DTEDSetMetadata( psDTED, DTEDMD_DIGITIZING_SYS, poSrcDS->GetMetadataItem( "DTED_DigitizingSystem" ) ); if( poSrcDS->GetMetadataItem( "DTED_CompilationDate" ) != nullptr ) DTEDSetMetadata( psDTED, DTEDMD_COMPILATION_DATE, poSrcDS->GetMetadataItem( "DTED_CompilationDate" ) ); if( poSrcDS->GetMetadataItem( "DTED_HorizontalAccuracy" ) != nullptr ) DTEDSetMetadata( psDTED, DTEDMD_HORIZACCURACY, poSrcDS->GetMetadataItem( "DTED_HorizontalAccuracy" ) ); if( poSrcDS->GetMetadataItem( "DTED_RelHorizontalAccuracy" ) != nullptr ) DTEDSetMetadata( psDTED, DTEDMD_REL_HORIZACCURACY, poSrcDS->GetMetadataItem( "DTED_RelHorizontalAccuracy" ) ); if( poSrcDS->GetMetadataItem( "DTED_RelVerticalAccuracy" ) != nullptr ) 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; }
/*! \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. const int nrBands = source->GetRasterCount(); if(nrBands != 1) { CPLError(CE_Failure, CPLE_NotSupported, "PCRaster driver: Too many bands ('%d'): must be 1 band", nrBands); return NULL; } GDALRasterBand* raster = source->GetRasterBand(1); // Create PCRaster raster. Determine properties of raster to create. // 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 NULL; } // The value scale of the values. CSF_VS valueScale = VS_UNDEFINED; std::string osString; if(source->GetMetadataItem("PCRASTER_VALUESCALE")) { osString = source->GetMetadataItem("PCRASTER_VALUESCALE"); } valueScale = !osString.empty() ? string2ValueScale(osString) : GDALType2ValueScale(raster->GetRasterDataType()); if(valueScale == VS_UNDEFINED) { CPLError(CE_Failure, CPLE_NotSupported, "PCRaster driver: Cannot determine a valid value scale"); return NULL; } CSF_PT const projection = PT_YDECT2B; const REAL8 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 NULL; } // Check whether value scale fits the cell representation. Adjust when // needed. valueScale = fitValueScale(valueScale, appCellRepresentation); // Create a raster with the in file cell representation. const size_t nrRows = raster->GetYSize(); const size_t nrCols = raster->GetXSize(); 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 NULL; } // 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 NULL; } 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: Proper translation of TODO. // TODO: Support conversion to INT2 (?) INT4. ruseas.c see line 503. // Conversion 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, static_cast<int>(row), static_cast<int>(nrCols), 1, buffer, static_cast<int>(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)), NULL, progressData)) { CPLError(CE_Failure, CPLE_UserInterrupt, "PCRaster driver: User terminated CreateCopy()"); errorCode = CE_Failure; break; } } Mclose(map); map = NULL; free(buffer); buffer = NULL; if( errorCode != CE_None ) return NULL; /* -------------------------------------------------------------------- */ /* Re-open dataset, and copy any auxiliary pam information. */ /* -------------------------------------------------------------------- */ GDALPamDataset *poDS = reinterpret_cast<GDALPamDataset *>( GDALOpen( filename, GA_Update ) ); if( poDS ) poDS->CloneInfo( source, GCIF_PAM_DEFAULT ); return poDS; }