diff --git a/MIGRATION_GUIDE.TXT b/MIGRATION_GUIDE.TXT index a37f4d8c2c17..85870aba38d4 100644 --- a/MIGRATION_GUIDE.TXT +++ b/MIGRATION_GUIDE.TXT @@ -1,3 +1,9 @@ +MIGRATION GUIDE FROM GDAL 3.4 to GDAL 3.5 +----------------------------------------- + +- GDAL drivers may now return raster bands with the new data types GDT_Int64 or + GDT_UInt64. + MIGRATION GUIDE FROM GDAL 3.3 to GDAL 3.4 ----------------------------------------- diff --git a/alg/gdal_alg_priv.h b/alg/gdal_alg_priv.h index 3d97c3345ba2..1eee84f1ecbf 100644 --- a/alg/gdal_alg_priv.h +++ b/alg/gdal_alg_priv.h @@ -34,6 +34,8 @@ #ifndef DOXYGEN_SKIP +#include + #include "gdal_alg.h" #include "ogr_spatialref.h" @@ -146,10 +148,10 @@ template class GDALRasterPolygonEnumeratorT struct IntEqualityTest { - bool operator()(GInt32 a, GInt32 b) const { return a == b; } + bool operator()(std::int64_t a, std::int64_t b) const { return a == b; } }; -typedef GDALRasterPolygonEnumeratorT GDALRasterPolygonEnumerator; +typedef GDALRasterPolygonEnumeratorT GDALRasterPolygonEnumerator; typedef void* (*GDALTransformDeserializeFunc)( CPLXMLNode *psTree ); diff --git a/alg/gdalpansharpen.cpp b/alg/gdalpansharpen.cpp index cb30f895c87b..6029142e8556 100644 --- a/alg/gdalpansharpen.cpp +++ b/alg/gdalpansharpen.cpp @@ -267,8 +267,7 @@ GDALPansharpenOperation::Initialize( const GDALPansharpenOptions* psOptionsIn ) { if( psOptionsIn->nBitDepth < 0 || psOptionsIn->nBitDepth > 31 || (eWorkDataType == GDT_Byte && psOptionsIn->nBitDepth > 8) || - (eWorkDataType == GDT_UInt16 && psOptionsIn->nBitDepth > 16) || - (eWorkDataType == GDT_UInt32 && psOptionsIn->nBitDepth > 32) ) + (eWorkDataType == GDT_UInt16 && psOptionsIn->nBitDepth > 16) ) { CPLError(CE_Failure, CPLE_AppDefined, "Invalid value nBitDepth = %d for type %s", @@ -282,7 +281,7 @@ GDALPansharpenOperation::Initialize( const GDALPansharpenOptions* psOptionsIn ) psOptions->nBitDepth = 0; if( psOptions->nBitDepth && !(eWorkDataType == GDT_Byte || eWorkDataType == GDT_UInt16 || - eWorkDataType == GDT_UInt32) ) + eWorkDataType == GDT_UInt32 || eWorkDataType == GDT_UInt64) ) { CPLError(CE_Warning, CPLE_AppDefined, "Ignoring nBitDepth = %d for type %s", @@ -920,6 +919,18 @@ template CPLErr GDALPansharpenOperation::WeightedBrovey( nValues, nBandValues, nMaxValue); break; + case GDT_UInt64: + WeightedBrovey(pPanBuffer, pUpsampledSpectralBuffer, + static_cast(pDataBuf), + nValues, nBandValues, nMaxValue); + break; + + case GDT_Int64: + WeightedBrovey(pPanBuffer, pUpsampledSpectralBuffer, + static_cast(pDataBuf), + nValues, nBandValues, nMaxValue); + break; + case GDT_Float32: WeightedBrovey(pPanBuffer, pUpsampledSpectralBuffer, static_cast(pDataBuf), @@ -983,6 +994,18 @@ template CPLErr GDALPansharpenOperation::WeightedBrovey( static_cast(pDataBuf), nValues, nBandValues, 0); break; + case GDT_UInt64: + WeightedBrovey3( + pPanBuffer, pUpsampledSpectralBuffer, + static_cast(pDataBuf), nValues, nBandValues, 0); + break; + + case GDT_Int64: + WeightedBrovey3( + pPanBuffer, pUpsampledSpectralBuffer, + static_cast(pDataBuf), nValues, nBandValues, 0); + break; + case GDT_Float32: WeightedBrovey3( pPanBuffer, pUpsampledSpectralBuffer, @@ -1699,6 +1722,20 @@ GDALPansharpenOperation::PansharpenChunk( GDALDataType eWorkDataType, nValues, nBandValues); break; + case GDT_UInt64: + eErr = WeightedBrovey(static_cast(pPanBuffer), + static_cast(pUpsampledSpectralBuffer), + pDataBuf, eBufDataType, + nValues, nBandValues, nMaxValue); + break; + + case GDT_Int64: + eErr = WeightedBrovey(static_cast(pPanBuffer), + static_cast(pUpsampledSpectralBuffer), + pDataBuf, eBufDataType, + nValues, nBandValues); + break; + case GDT_Float32: eErr = WeightedBrovey(static_cast(pPanBuffer), static_cast(pUpsampledSpectralBuffer), diff --git a/alg/gdalrasterize.cpp b/alg/gdalrasterize.cpp index a5ee85033d94..8d3935475603 100644 --- a/alg/gdalrasterize.cpp +++ b/alg/gdalrasterize.cpp @@ -137,6 +137,12 @@ void gvBurnScanline( void *pCBData, int nY, int nXStart, int nXEnd, case GDT_UInt32: gvBurnScanlineBasic( psInfo, nY, nXStart, nXEnd, dfVariant ); break; + case GDT_Int64: + gvBurnScanlineBasic( psInfo, nY, nXStart, nXEnd, dfVariant ); + break; + case GDT_UInt64: + gvBurnScanlineBasic( psInfo, nY, nXStart, nXEnd, dfVariant ); + break; case GDT_Float32: gvBurnScanlineBasic( psInfo, nY, nXStart, nXEnd, dfVariant ); break; @@ -168,7 +174,8 @@ void gvBurnPointBasic( GDALRasterizeInfo *psInfo, + nY * psInfo->nLineSpace + nX * psInfo->nPixelSpace; T* pbyPixel = reinterpret_cast(pbyInsert); - burnValue += ( psInfo->eMergeAlg != GRMA_Add ) ? 0 : *pbyPixel; + if( psInfo->eMergeAlg == GRMA_Add ) + burnValue += static_cast(*pbyPixel); GDALCopyWord(burnValue, *pbyPixel); } } @@ -203,6 +210,12 @@ void gvBurnPoint( void *pCBData, int nY, int nX, double dfVariant ) case GDT_UInt32: gvBurnPointBasic( psInfo, nY, nX, dfVariant ); break; + case GDT_Int64: + gvBurnPointBasic( psInfo, nY, nX, dfVariant ); + break; + case GDT_UInt64: + gvBurnPointBasic( psInfo, nY, nX, dfVariant ); + break; case GDT_Float32: gvBurnPointBasic( psInfo, nY, nX, dfVariant ); break; diff --git a/alg/gdalrasterpolygonenumerator.cpp b/alg/gdalrasterpolygonenumerator.cpp index 4294d67c9cc8..a6fb42bca5a5 100644 --- a/alg/gdalrasterpolygonenumerator.cpp +++ b/alg/gdalrasterpolygonenumerator.cpp @@ -299,7 +299,7 @@ void GDALRasterPolygonEnumeratorT::ProcessLine( } } -template class GDALRasterPolygonEnumeratorT; +template class GDALRasterPolygonEnumeratorT; template class GDALRasterPolygonEnumeratorT; diff --git a/alg/gdalsievefilter.cpp b/alg/gdalsievefilter.cpp index 6ac4368e8d03..540e20b22161 100644 --- a/alg/gdalsievefilter.cpp +++ b/alg/gdalsievefilter.cpp @@ -77,7 +77,7 @@ CPL_CVSID("$Id$") static CPLErr GPMaskImageData( GDALRasterBandH hMaskBand, GByte *pabyMaskLine, int iY, int nXSize, - GInt32 *panImageLine ) + std::int64_t *panImageLine ) { const CPLErr eErr = @@ -113,7 +113,7 @@ GPMaskImageData( GDALRasterBandH hMaskBand, GByte *pabyMaskLine, static inline void CompareNeighbour( int nPolyId1, int nPolyId2, int *panPolyIdMap, - int * /* panPolyValue */, + std::int64_t * /* panPolyValue */, std::vector &anPolySizes, std::vector &anBigNeighbour ) @@ -215,16 +215,16 @@ GDALSieveFilter( GDALRasterBandH hSrcBand, GDALRasterBandH hMaskBand, /* -------------------------------------------------------------------- */ int nXSize = GDALGetRasterBandXSize( hSrcBand ); int nYSize = GDALGetRasterBandYSize( hSrcBand ); - GInt32 *panLastLineVal = static_cast( + auto *panLastLineVal = static_cast( + VSI_MALLOC2_VERBOSE(sizeof(std::int64_t), nXSize)); + auto *panThisLineVal = static_cast( + VSI_MALLOC2_VERBOSE(sizeof(std::int64_t), nXSize)); + auto *panLastLineId = static_cast( VSI_MALLOC2_VERBOSE(sizeof(GInt32), nXSize)); - GInt32 *panThisLineVal = static_cast( - VSI_MALLOC2_VERBOSE(sizeof(GInt32), nXSize)); - GInt32 *panLastLineId = static_cast( - VSI_MALLOC2_VERBOSE(sizeof(GInt32), nXSize)); - GInt32 *panThisLineId = static_cast( - VSI_MALLOC2_VERBOSE(sizeof(GInt32), nXSize)); - GInt32 *panThisLineWriteVal = static_cast( + auto *panThisLineId = static_cast( VSI_MALLOC2_VERBOSE(sizeof(GInt32), nXSize)); + auto *panThisLineWriteVal = static_cast( + VSI_MALLOC2_VERBOSE(sizeof(std::int64_t), nXSize)); GByte *pabyMaskLine = hMaskBand != nullptr ? static_cast(VSI_MALLOC_VERBOSE(nXSize)) @@ -257,7 +257,7 @@ GDALSieveFilter( GDALRasterBandH hSrcBand, GDALRasterBandH hMaskBand, eErr = GDALRasterIO( hSrcBand, GF_Read, 0, iY, nXSize, 1, - panThisLineVal, nXSize, 1, GDT_Int32, 0, 0 ); + panThisLineVal, nXSize, 1, GDT_Int64, 0, 0 ); if( eErr == CE_None && hMaskBand != nullptr ) eErr = GPMaskImageData(hMaskBand, pabyMaskLine, iY, nXSize, @@ -355,7 +355,7 @@ GDALSieveFilter( GDALRasterBandH hSrcBand, GDALRasterBandH hMaskBand, /* Read the image data. */ /* -------------------------------------------------------------------- */ eErr = GDALRasterIO( hSrcBand, GF_Read, 0, iY, nXSize, 1, - panThisLineVal, nXSize, 1, GDT_Int32, 0, 0 ); + panThisLineVal, nXSize, 1, GDT_Int64, 0, 0 ); if( eErr == CE_None && hMaskBand != nullptr ) eErr = GPMaskImageData( hMaskBand, pabyMaskLine, iY, nXSize, @@ -532,9 +532,9 @@ GDALSieveFilter( GDALRasterBandH hSrcBand, GDALRasterBandH hMaskBand, /* Read the image data. */ /* -------------------------------------------------------------------- */ eErr = GDALRasterIO( hSrcBand, GF_Read, 0, iY, nXSize, 1, - panThisLineVal, nXSize, 1, GDT_Int32, 0, 0 ); + panThisLineVal, nXSize, 1, GDT_Int64, 0, 0 ); - memcpy( panThisLineWriteVal, panThisLineVal, 4 * nXSize ); + memcpy( panThisLineWriteVal, panThisLineVal, sizeof(panThisLineVal[0]) * nXSize ); if( eErr == CE_None && hMaskBand != nullptr ) eErr = GPMaskImageData( hMaskBand, pabyMaskLine, iY, nXSize, @@ -580,7 +580,7 @@ GDALSieveFilter( GDALRasterBandH hSrcBand, GDALRasterBandH hMaskBand, /* Write the update data out. */ /* -------------------------------------------------------------------- */ eErr = GDALRasterIO( hDstBand, GF_Write, 0, iY, nXSize, 1, - panThisLineWriteVal, nXSize, 1, GDT_Int32, 0, 0 ); + panThisLineWriteVal, nXSize, 1, GDT_Int64, 0, 0 ); /* -------------------------------------------------------------------- */ /* Swap pixel value, and polygon id lines to be ready for the */ diff --git a/alg/gdalwarpkernel.cpp b/alg/gdalwarpkernel.cpp index 503092e90a92..bc0dd28dbe77 100644 --- a/alg/gdalwarpkernel.cpp +++ b/alg/gdalwarpkernel.cpp @@ -1591,6 +1591,16 @@ static bool GWKSetPixelValue( const GDALWarpKernel *poWK, int iBand, dfDstImag = 0.0; break; + case GDT_Int64: + dfDstReal = static_cast(reinterpret_cast(pabyDst)[iDstOffset]); + dfDstImag = 0.0; + break; + + case GDT_UInt64: + dfDstReal = static_cast(reinterpret_cast(pabyDst)[iDstOffset]); + dfDstImag = 0.0; + break; + case GDT_Float32: dfDstReal = reinterpret_cast(pabyDst)[iDstOffset]; dfDstImag = 0.0; @@ -1690,6 +1700,14 @@ static bool GWKSetPixelValue( const GDALWarpKernel *poWK, int iBand, CLAMP(GInt32); break; + case GDT_UInt64: + CLAMP(std::uint64_t); + break; + + case GDT_Int64: + CLAMP(std::int64_t); + break; + case GDT_Float32: reinterpret_cast(pabyDst)[iDstOffset] = static_cast(dfReal); break; @@ -1810,6 +1828,14 @@ static bool GWKSetPixelValueReal( const GDALWarpKernel *poWK, int iBand, dfDstReal = reinterpret_cast(pabyDst)[iDstOffset]; break; + case GDT_Int64: + dfDstReal = static_cast(reinterpret_cast(pabyDst)[iDstOffset]); + break; + + case GDT_UInt64: + dfDstReal = static_cast(reinterpret_cast(pabyDst)[iDstOffset]); + break; + case GDT_Float32: dfDstReal = reinterpret_cast(pabyDst)[iDstOffset]; break; @@ -1861,6 +1887,14 @@ static bool GWKSetPixelValueReal( const GDALWarpKernel *poWK, int iBand, CLAMP(GInt32); break; + case GDT_UInt64: + CLAMP(std::uint64_t); + break; + + case GDT_Int64: + CLAMP(std::int64_t); + break; + case GDT_Float32: reinterpret_cast(pabyDst)[iDstOffset] = static_cast(dfReal); break; @@ -1926,6 +1960,16 @@ static bool GWKGetPixelValue( const GDALWarpKernel *poWK, int iBand, *pdfImag = 0.0; break; + case GDT_Int64: + *pdfReal = static_cast(reinterpret_cast(pabySrc)[iSrcOffset]); + *pdfImag = 0.0; + break; + + case GDT_UInt64: + *pdfReal = static_cast(reinterpret_cast(pabySrc)[iSrcOffset]); + *pdfImag = 0.0; + break; + case GDT_Float32: *pdfReal = reinterpret_cast(pabySrc)[iSrcOffset]; *pdfImag = 0.0; @@ -2011,6 +2055,14 @@ static bool GWKGetPixelValueReal( const GDALWarpKernel *poWK, int iBand, *pdfReal = reinterpret_cast(pabySrc)[iSrcOffset]; break; + case GDT_Int64: + *pdfReal = static_cast(reinterpret_cast(pabySrc)[iSrcOffset]); + break; + + case GDT_UInt64: + *pdfReal = static_cast(reinterpret_cast(pabySrc)[iSrcOffset]); + break; + case GDT_Float32: *pdfReal = reinterpret_cast(pabySrc)[iSrcOffset]; break; @@ -2172,6 +2224,30 @@ static bool GWKGetPixelRow( const GDALWarpKernel *poWK, int iBand, break; } + case GDT_Int64: + { + auto pSrc = reinterpret_cast(poWK->papabySrcImage[iBand]); + pSrc += iSrcOffset; + for( int i = 0; i < nSrcLen; i += 2 ) + { + adfReal[i] = static_cast(pSrc[i]); + adfReal[i+1] = static_cast(pSrc[i+1]); + } + break; + } + + case GDT_UInt64: + { + auto pSrc = reinterpret_cast(poWK->papabySrcImage[iBand]); + pSrc += iSrcOffset; + for( int i = 0; i < nSrcLen; i += 2 ) + { + adfReal[i] = static_cast(pSrc[i]); + adfReal[i+1] = static_cast(pSrc[i+1]); + } + break; + } + case GDT_Float32: { float* pSrc = reinterpret_cast(poWK->papabySrcImage[iBand]); diff --git a/alg/polygonize.cpp b/alg/polygonize.cpp index fc6f2e07d57b..8ba5c53344c7 100644 --- a/alg/polygonize.cpp +++ b/alg/polygonize.cpp @@ -406,14 +406,16 @@ static void AddEdges( GInt32 *panThisLineId, GInt32 *panLastLineId, if( nThisId != -1 ) { if( papoPoly[nThisId] == nullptr ) - papoPoly[nThisId] = new RPolygon( panPolyValue[nThisId] ); + // FIXME loss of precision for [U]Int64 + papoPoly[nThisId] = new RPolygon( static_cast(panPolyValue[nThisId]) ); papoPoly[nThisId]->AddSegment( iXReal, iY, iXReal+1, iY, 1 ); } if( nPreviousId != -1 ) { if( papoPoly[nPreviousId] == nullptr ) - papoPoly[nPreviousId] = new RPolygon(panPolyValue[nPreviousId]); + // FIXME loss of precision for [U]Int64 + papoPoly[nPreviousId] = new RPolygon( static_cast(panPolyValue[nPreviousId]) ); papoPoly[nPreviousId]->AddSegment( iXReal, iY, iXReal+1, iY, 0 ); } @@ -424,7 +426,8 @@ static void AddEdges( GInt32 *panThisLineId, GInt32 *panLastLineId, if( nThisId != -1 ) { if( papoPoly[nThisId] == nullptr ) - papoPoly[nThisId] = new RPolygon(panPolyValue[nThisId]); + // FIXME loss of precision for [U]Int64 + papoPoly[nThisId] = new RPolygon( static_cast(panPolyValue[nThisId]) ); papoPoly[nThisId]->AddSegment( iXReal+1, iY, iXReal+1, iY+1, 1 ); } @@ -432,7 +435,8 @@ static void AddEdges( GInt32 *panThisLineId, GInt32 *panLastLineId, if( nRightId != -1 ) { if( papoPoly[nRightId] == nullptr ) - papoPoly[nRightId] = new RPolygon(panPolyValue[nRightId]); + // FIXME loss of precision for [U]Int64 + papoPoly[nRightId] = new RPolygon( static_cast(panPolyValue[nRightId]) ); papoPoly[nRightId]->AddSegment( iXReal+1, iY, iXReal+1, iY+1, 0 ); } @@ -899,7 +903,7 @@ GBool GDALFloatEquals( float A, float B ) * can be provided to determine which pixels are eligible for processing. * * Note that currently the source pixel band values are read into a - * signed 32bit integer buffer (Int32), so floating point or complex + * signed 64bit integer buffer (Int64), so floating point or complex * bands will be implicitly truncated before processing. If you want to use a * version using 32bit float buffers, see GDALFPolygonize(). * @@ -954,14 +958,14 @@ GDALPolygonize( GDALRasterBandH hSrcBand, void * pProgressArg ) { - return GDALPolygonizeT(hSrcBand, + return GDALPolygonizeT(hSrcBand, hMaskBand, hOutLayer, iPixValField, papszOptions, pfnProgress, pProgressArg, - GDT_Int32); + GDT_Int64); } /************************************************************************/ diff --git a/apps/gdal_create.cpp b/apps/gdal_create.cpp index 405785ace3d3..b55b78c3d49b 100644 --- a/apps/gdal_create.cpp +++ b/apps/gdal_create.cpp @@ -46,7 +46,7 @@ static void Usage() " [-outsize xsize ysize]\n" " [-bands count]\n" " [-burn value]*\n" - " [-ot {Byte/Int16/UInt16/UInt32/Int32/Float32/Float64/\n" + " [-ot {Byte/Int16/UInt16/UInt32/Int32/UInt64/Int64/Float32/Float64/\n" " CInt16/CInt32/CFloat32/CFloat64}] [-strict]\n" " [-a_srs srs_def] [-a_ullr ulx uly lrx lry] [-a_nodata value]\n" " [-mo \"META-TAG=VALUE\"]* [-q]\n" diff --git a/apps/gdal_rasterize_bin.cpp b/apps/gdal_rasterize_bin.cpp index 757849738a62..47351a52dbca 100644 --- a/apps/gdal_rasterize_bin.cpp +++ b/apps/gdal_rasterize_bin.cpp @@ -48,7 +48,7 @@ static void Usage(const char* pszErrorMsg = nullptr) " [-dialect dialect] [-of format] [-a_srs srs_def] [-to \"NAME=VALUE\"]*\n" " [-co \"NAME=VALUE\"]* [-a_nodata value] [-init value]*\n" " [-te xmin ymin xmax ymax] [-tr xres yres] [-tap] [-ts width height]\n" - " [-ot {Byte/Int16/UInt16/UInt32/Int32/Float32/Float64/\n" + " [-ot {Byte/Int16/UInt16/UInt32/Int32/UInt64/Int64/Float32/Float64/\n" " CInt16/CInt32/CFloat32/CFloat64}] [-optim {[AUTO]/VECTOR/RASTER}] [-q]\n" " \n" ); diff --git a/apps/gdal_translate_bin.cpp b/apps/gdal_translate_bin.cpp index 7868109350db..59b52d1170a1 100644 --- a/apps/gdal_translate_bin.cpp +++ b/apps/gdal_translate_bin.cpp @@ -46,7 +46,7 @@ static void Usage(const char* pszErrorMsg, int bShort) { printf( "Usage: gdal_translate [--help-general] [--long-usage]\n" - " [-ot {Byte/Int16/UInt16/UInt32/Int32/Float32/Float64/\n" + " [-ot {Byte/Int16/UInt16/UInt32/Int32/UInt64/Int64/Float32/Float64/\n" " CInt16/CInt32/CFloat32/CFloat64}] [-strict]\n" " [-if format]* [-of format]\n" " [-b band] [-mask band] [-expand {gray|rgb|rgba}]\n" diff --git a/apps/gdal_translate_lib.cpp b/apps/gdal_translate_lib.cpp index 0381d96c33ba..2f4e9986aeb4 100644 --- a/apps/gdal_translate_lib.cpp +++ b/apps/gdal_translate_lib.cpp @@ -1783,39 +1783,53 @@ GDALDatasetH GDALTranslate( const char *pszDest, GDALDatasetH hSrcDataset, !GDALDataTypeIsComplex(eBandType)); if( bSrcIsInteger && bDstIsInteger ) { - GInt32 nDstMin = 0; - GUInt32 nDstMax = 0; + std::int64_t nDstMin = 0; + std::uint64_t nDstMax = 0; switch( eBandType ) { case GDT_Byte: - nDstMin = 0; - nDstMax = 255; + nDstMin = std::numeric_limits::min(); + nDstMax = std::numeric_limits::max(); break; case GDT_UInt16: - nDstMin = 0; - nDstMax = 65535; + nDstMin = std::numeric_limits::min(); + nDstMax = std::numeric_limits::max(); break; case GDT_Int16: - nDstMin = -32768; - nDstMax = 32767; + nDstMin = std::numeric_limits::min(); + nDstMax = std::numeric_limits::max(); break; case GDT_UInt32: - nDstMin = 0; - nDstMax = 0xFFFFFFFFU; + nDstMin = std::numeric_limits::min(); + nDstMax = std::numeric_limits::max(); break; case GDT_Int32: - nDstMin = 0x80000000; - nDstMax = 0x7FFFFFFF; + nDstMin = std::numeric_limits::min(); + nDstMax = std::numeric_limits::max(); + break; + case GDT_UInt64: + nDstMin = std::numeric_limits::min(); + nDstMax = std::numeric_limits::max(); + break; + case GDT_Int64: + nDstMin = std::numeric_limits::min(); + nDstMax = std::numeric_limits::max(); break; default: CPLAssert(false); break; } - GInt32 nMin = atoi(pszMin); - GUInt32 nMax = static_cast(strtoul(pszMax, nullptr, 10)); - if( nMin < nDstMin || nMax > nDstMax ) - bFilterOutStatsMetadata = true; + try + { + const auto nMin = std::stoll(pszMin); + const auto nMax = std::stoull(pszMax); + if( nMin < nDstMin || nMax > nDstMax ) + bFilterOutStatsMetadata = true; + } + catch( const std::exception& ) + { + } } // Float64 is large enough to hold all integer <= 32 bit or float32 values // there might be other OK cases, but ere on safe side for now diff --git a/autotest/cpp/test_cpl.cpp b/autotest/cpp/test_cpl.cpp index c01324ab30fb..0b2c5c1b3eda 100644 --- a/autotest/cpp/test_cpl.cpp +++ b/autotest/cpp/test_cpl.cpp @@ -2714,12 +2714,12 @@ namespace tut } { CPLJSonStreamingWriter x(nullptr, nullptr); - x.Add(static_cast(-10000) * 1000000); + x.Add(static_cast(-10000) * 1000000); ensure_equals( x.GetString(), std::string("-10000000000") ); } { CPLJSonStreamingWriter x(nullptr, nullptr); - x.Add(static_cast(10000) * 1000000); + x.Add(static_cast(10000) * 1000000); ensure_equals( x.GetString(), std::string("10000000000") ); } { diff --git a/autotest/cpp/test_gdal.cpp b/autotest/cpp/test_gdal.cpp index 7e2dc4e985ae..d1bfb015f22e 100644 --- a/autotest/cpp/test_gdal.cpp +++ b/autotest/cpp/test_gdal.cpp @@ -160,8 +160,13 @@ namespace tut } ENSURE_EQUALS(GDALDataTypeUnion(GDT_Int16, GDT_UInt16), GDT_Int32); - ENSURE_EQUALS(GDALDataTypeUnion(GDT_Int16, GDT_UInt32), GDT_Float64); - ENSURE_EQUALS(GDALDataTypeUnion(GDT_UInt32, GDT_Int16), GDT_Float64); + ENSURE_EQUALS(GDALDataTypeUnion(GDT_Int16, GDT_UInt32), GDT_Int64); + ENSURE_EQUALS(GDALDataTypeUnion(GDT_UInt32, GDT_Int16), GDT_Int64); + ENSURE_EQUALS(GDALDataTypeUnion(GDT_Int64, GDT_UInt64), GDT_Float64); + ENSURE_EQUALS(GDALDataTypeUnion(GDT_Int64, GDT_Float32), GDT_Float64); + ENSURE_EQUALS(GDALDataTypeUnion(GDT_Int64, GDT_Float64), GDT_Float64); + ENSURE_EQUALS(GDALDataTypeUnion(GDT_UInt64, GDT_Float32), GDT_Float64); + ENSURE_EQUALS(GDALDataTypeUnion(GDT_UInt64, GDT_Float64), GDT_Float64); ENSURE_EQUALS(GDALDataTypeUnion(GDT_UInt32, GDT_CInt16), GDT_CFloat64); ENSURE_EQUALS(GDALDataTypeUnion(GDT_Float32, GDT_CInt32), GDT_CFloat64); ENSURE_EQUALS(GDALDataTypeUnion(GDT_CInt16, GDT_UInt32), GDT_CFloat64); @@ -204,6 +209,9 @@ namespace tut ENSURE_EQUALS(GDALFindDataType(64, false /* signed */, true /* floating */, false /* complex */), GDT_Float64); ENSURE_EQUALS(GDALFindDataType(64, false /* signed */, true /* floating */, true /* complex */), GDT_CFloat64); + ENSURE_EQUALS(GDALFindDataType(64, false /* signed */, false /* floating */, false /* complex */), GDT_UInt64); + ENSURE_EQUALS(GDALFindDataType(64, true /* signed */, false /* floating */, false /* complex */), GDT_Int64); + ENSURE_EQUALS(GDALDataTypeUnionWithValue(GDT_Byte, -32768, 0), GDT_Int16); ENSURE_EQUALS(GDALDataTypeUnionWithValue(GDT_Byte, -32769, 0), GDT_Int32); ENSURE_EQUALS(GDALDataTypeUnionWithValue(GDT_Float32, -99999, 0), GDT_Float32); @@ -243,6 +251,13 @@ namespace tut ensure( GDALAdjustValueToDataType(GDT_Int32,-10000000.0,&bClamped,&bRounded) == -10000000.0 && !bClamped && !bRounded); ensure( GDALAdjustValueToDataType(GDT_Int32,10000000.0,&bClamped,&bRounded) == 10000000.0 && !bClamped && !bRounded); + ensure( GDALAdjustValueToDataType(GDT_UInt64,10000000000.0,&bClamped,&bRounded) == 10000000000.0 && !bClamped && !bRounded); + ensure( GDALAdjustValueToDataType(GDT_UInt64,10000000000.4,&bClamped,&bRounded) == 10000000000.0 && !bClamped && bRounded); + ensure( GDALAdjustValueToDataType(GDT_UInt64,-1,&bClamped,&bRounded) == 0.0 && bClamped && !bRounded); + + ensure( GDALAdjustValueToDataType(GDT_Int64,-10000000000.0,&bClamped,&bRounded) == -10000000000.0 && !bClamped && !bRounded); + ensure( GDALAdjustValueToDataType(GDT_Int64,10000000000.0,&bClamped,&bRounded) == 10000000000.0 && !bClamped && !bRounded); + ensure( GDALAdjustValueToDataType(GDT_Float32, 0.0,&bClamped,&bRounded) == 0.0 && !bClamped && !bRounded); ensure( GDALAdjustValueToDataType(GDT_Float32, 1e-50,&bClamped,&bRounded) == 0.0 && !bClamped && !bRounded); ensure( GDALAdjustValueToDataType(GDT_Float32, 1.23,&bClamped,&bRounded) == static_cast(1.23f) && !bClamped && !bRounded); @@ -458,6 +473,8 @@ namespace tut ensure_equals( GDALDataTypeIsInteger(GDT_Int16), TRUE ); ensure_equals( GDALDataTypeIsInteger(GDT_UInt32), TRUE ); ensure_equals( GDALDataTypeIsInteger(GDT_Int32), TRUE ); + ensure_equals( GDALDataTypeIsInteger(GDT_UInt64), TRUE ); + ensure_equals( GDALDataTypeIsInteger(GDT_Int64), TRUE ); ensure( !GDALDataTypeIsInteger(GDT_Float32) ); ensure( !GDALDataTypeIsInteger(GDT_Float64) ); ensure_equals( GDALDataTypeIsInteger(GDT_CInt16), TRUE ); @@ -475,6 +492,8 @@ namespace tut ensure( !GDALDataTypeIsFloating(GDT_Int16) ); ensure( !GDALDataTypeIsFloating(GDT_UInt32) ); ensure( !GDALDataTypeIsFloating(GDT_Int32) ); + ensure( !GDALDataTypeIsFloating(GDT_UInt64) ); + ensure( !GDALDataTypeIsFloating(GDT_Int64) ); ensure_equals( GDALDataTypeIsFloating(GDT_Float32), TRUE ); ensure_equals( GDALDataTypeIsFloating(GDT_Float64), TRUE ); ensure( !GDALDataTypeIsFloating(GDT_CInt16) ); @@ -492,6 +511,8 @@ namespace tut ensure( !GDALDataTypeIsComplex(GDT_Int16) ); ensure( !GDALDataTypeIsComplex(GDT_UInt32) ); ensure( !GDALDataTypeIsComplex(GDT_Int32) ); + ensure( !GDALDataTypeIsComplex(GDT_UInt64) ); + ensure( !GDALDataTypeIsComplex(GDT_Int64) ); ensure( !GDALDataTypeIsComplex(GDT_Float32) ); ensure( !GDALDataTypeIsComplex(GDT_Float64) ); ensure_equals( GDALDataTypeIsComplex(GDT_CInt16), TRUE ); @@ -508,6 +529,8 @@ namespace tut ensure( !GDALDataTypeIsConversionLossy(GDT_Byte, GDT_Int16) ); ensure( !GDALDataTypeIsConversionLossy(GDT_Byte, GDT_UInt32) ); ensure( !GDALDataTypeIsConversionLossy(GDT_Byte, GDT_Int32) ); + ensure( !GDALDataTypeIsConversionLossy(GDT_Byte, GDT_UInt64) ); + ensure( !GDALDataTypeIsConversionLossy(GDT_Byte, GDT_Int64) ); ensure( !GDALDataTypeIsConversionLossy(GDT_Byte, GDT_Float32) ); ensure( !GDALDataTypeIsConversionLossy(GDT_Byte, GDT_Float64) ); ensure( !GDALDataTypeIsConversionLossy(GDT_Byte, GDT_CInt16) ); @@ -520,6 +543,8 @@ namespace tut ensure( GDALDataTypeIsConversionLossy(GDT_UInt16, GDT_Int16) ); ensure( !GDALDataTypeIsConversionLossy(GDT_UInt16, GDT_UInt32) ); ensure( !GDALDataTypeIsConversionLossy(GDT_UInt16, GDT_Int32) ); + ensure( !GDALDataTypeIsConversionLossy(GDT_UInt16, GDT_UInt64) ); + ensure( !GDALDataTypeIsConversionLossy(GDT_UInt16, GDT_Int64) ); ensure( !GDALDataTypeIsConversionLossy(GDT_UInt16, GDT_Float32) ); ensure( !GDALDataTypeIsConversionLossy(GDT_UInt16, GDT_Float64) ); ensure( GDALDataTypeIsConversionLossy(GDT_UInt16, GDT_CInt16) ); @@ -532,6 +557,8 @@ namespace tut ensure( !GDALDataTypeIsConversionLossy(GDT_Int16, GDT_Int16) ); ensure( GDALDataTypeIsConversionLossy(GDT_Int16, GDT_UInt32) ); ensure( !GDALDataTypeIsConversionLossy(GDT_Int16, GDT_Int32) ); + ensure( GDALDataTypeIsConversionLossy(GDT_Int16, GDT_UInt64) ); + ensure( !GDALDataTypeIsConversionLossy(GDT_Int16, GDT_Int64) ); ensure( !GDALDataTypeIsConversionLossy(GDT_Int16, GDT_Float32) ); ensure( !GDALDataTypeIsConversionLossy(GDT_Int16, GDT_Float64) ); ensure( !GDALDataTypeIsConversionLossy(GDT_Int16, GDT_CInt16) ); @@ -544,6 +571,8 @@ namespace tut ensure( GDALDataTypeIsConversionLossy(GDT_UInt32, GDT_Int16) ); ensure( !GDALDataTypeIsConversionLossy(GDT_UInt32, GDT_UInt32) ); ensure( GDALDataTypeIsConversionLossy(GDT_UInt32, GDT_Int32) ); + ensure( !GDALDataTypeIsConversionLossy(GDT_UInt32, GDT_UInt64) ); + ensure( !GDALDataTypeIsConversionLossy(GDT_UInt32, GDT_Int64) ); ensure( GDALDataTypeIsConversionLossy(GDT_UInt32, GDT_Float32) ); ensure( !GDALDataTypeIsConversionLossy(GDT_UInt32, GDT_Float64) ); ensure( GDALDataTypeIsConversionLossy(GDT_UInt32, GDT_CInt16) ); @@ -556,6 +585,8 @@ namespace tut ensure( GDALDataTypeIsConversionLossy(GDT_Int32, GDT_Int16) ); ensure( GDALDataTypeIsConversionLossy(GDT_Int32, GDT_UInt32) ); ensure( !GDALDataTypeIsConversionLossy(GDT_Int32, GDT_Int32) ); + ensure( GDALDataTypeIsConversionLossy(GDT_Int32, GDT_UInt64) ); + ensure( !GDALDataTypeIsConversionLossy(GDT_Int32, GDT_Int64) ); ensure( GDALDataTypeIsConversionLossy(GDT_Int32, GDT_Float32) ); ensure( !GDALDataTypeIsConversionLossy(GDT_Int32, GDT_Float64) ); ensure( GDALDataTypeIsConversionLossy(GDT_Int32, GDT_CInt16) ); @@ -563,11 +594,41 @@ namespace tut ensure( GDALDataTypeIsConversionLossy(GDT_Int32, GDT_CFloat32) ); ensure( !GDALDataTypeIsConversionLossy(GDT_Int32, GDT_CFloat64) ); + ensure( GDALDataTypeIsConversionLossy(GDT_UInt64, GDT_Byte) ); + ensure( GDALDataTypeIsConversionLossy(GDT_UInt64, GDT_UInt16) ); + ensure( GDALDataTypeIsConversionLossy(GDT_UInt64, GDT_Int16) ); + ensure( GDALDataTypeIsConversionLossy(GDT_UInt64, GDT_UInt32) ); + ensure( GDALDataTypeIsConversionLossy(GDT_UInt64, GDT_Int32) ); + ensure( !GDALDataTypeIsConversionLossy(GDT_UInt64, GDT_UInt64) ); + ensure( GDALDataTypeIsConversionLossy(GDT_UInt64, GDT_Int64) ); + ensure( GDALDataTypeIsConversionLossy(GDT_UInt64, GDT_Float32) ); + ensure( GDALDataTypeIsConversionLossy(GDT_UInt64, GDT_Float64) ); + ensure( GDALDataTypeIsConversionLossy(GDT_UInt64, GDT_CInt16) ); + ensure( GDALDataTypeIsConversionLossy(GDT_UInt64, GDT_CInt32) ); + ensure( GDALDataTypeIsConversionLossy(GDT_UInt64, GDT_CFloat32) ); + ensure( GDALDataTypeIsConversionLossy(GDT_UInt64, GDT_CFloat64) ); + + ensure( GDALDataTypeIsConversionLossy(GDT_Int64, GDT_Byte) ); + ensure( GDALDataTypeIsConversionLossy(GDT_Int64, GDT_UInt16) ); + ensure( GDALDataTypeIsConversionLossy(GDT_Int64, GDT_Int16) ); + ensure( GDALDataTypeIsConversionLossy(GDT_Int64, GDT_UInt32) ); + ensure( GDALDataTypeIsConversionLossy(GDT_Int64, GDT_Int32) ); + ensure( GDALDataTypeIsConversionLossy(GDT_Int64, GDT_UInt64) ); + ensure( !GDALDataTypeIsConversionLossy(GDT_Int64, GDT_Int64) ); + ensure( GDALDataTypeIsConversionLossy(GDT_Int64, GDT_Float32) ); + ensure( GDALDataTypeIsConversionLossy(GDT_Int64, GDT_Float64) ); + ensure( GDALDataTypeIsConversionLossy(GDT_Int64, GDT_CInt16) ); + ensure( GDALDataTypeIsConversionLossy(GDT_Int64, GDT_CInt32) ); + ensure( GDALDataTypeIsConversionLossy(GDT_Int64, GDT_CFloat32) ); + ensure( GDALDataTypeIsConversionLossy(GDT_Int64, GDT_CFloat64) ); + ensure( GDALDataTypeIsConversionLossy(GDT_Float32, GDT_Byte) ); ensure( GDALDataTypeIsConversionLossy(GDT_Float32, GDT_UInt16) ); ensure( GDALDataTypeIsConversionLossy(GDT_Float32, GDT_Int16) ); ensure( GDALDataTypeIsConversionLossy(GDT_Float32, GDT_UInt32) ); ensure( GDALDataTypeIsConversionLossy(GDT_Float32, GDT_Int32) ); + ensure( GDALDataTypeIsConversionLossy(GDT_Float32, GDT_UInt64) ); + ensure( GDALDataTypeIsConversionLossy(GDT_Float32, GDT_Int64) ); ensure( !GDALDataTypeIsConversionLossy(GDT_Float32, GDT_Float32) ); ensure( !GDALDataTypeIsConversionLossy(GDT_Float32, GDT_Float64) ); ensure( GDALDataTypeIsConversionLossy(GDT_Float32, GDT_CInt16) ); @@ -580,6 +641,8 @@ namespace tut ensure( GDALDataTypeIsConversionLossy(GDT_Float64, GDT_Int16) ); ensure( GDALDataTypeIsConversionLossy(GDT_Float64, GDT_UInt32) ); ensure( GDALDataTypeIsConversionLossy(GDT_Float64, GDT_Int32) ); + ensure( GDALDataTypeIsConversionLossy(GDT_Float64, GDT_UInt64) ); + ensure( GDALDataTypeIsConversionLossy(GDT_Float64, GDT_Int64) ); ensure( GDALDataTypeIsConversionLossy(GDT_Float64, GDT_Float32) ); ensure( !GDALDataTypeIsConversionLossy(GDT_Float64, GDT_Float64) ); ensure( GDALDataTypeIsConversionLossy(GDT_Float64, GDT_CInt16) ); @@ -592,6 +655,8 @@ namespace tut ensure( GDALDataTypeIsConversionLossy(GDT_CInt16, GDT_Int16) ); ensure( GDALDataTypeIsConversionLossy(GDT_CInt16, GDT_UInt32) ); ensure( GDALDataTypeIsConversionLossy(GDT_CInt16, GDT_Int32) ); + ensure( GDALDataTypeIsConversionLossy(GDT_CInt16, GDT_UInt64) ); + ensure( GDALDataTypeIsConversionLossy(GDT_CInt16, GDT_Int64) ); ensure( GDALDataTypeIsConversionLossy(GDT_CInt16, GDT_Float32) ); ensure( GDALDataTypeIsConversionLossy(GDT_CInt16, GDT_Float64) ); ensure( !GDALDataTypeIsConversionLossy(GDT_CInt16, GDT_CInt16) ); @@ -604,6 +669,8 @@ namespace tut ensure( GDALDataTypeIsConversionLossy(GDT_CInt32, GDT_Int16) ); ensure( GDALDataTypeIsConversionLossy(GDT_CInt32, GDT_UInt32) ); ensure( GDALDataTypeIsConversionLossy(GDT_CInt32, GDT_Int32) ); + ensure( GDALDataTypeIsConversionLossy(GDT_CInt32, GDT_UInt64) ); + ensure( GDALDataTypeIsConversionLossy(GDT_CInt32, GDT_Int64) ); ensure( GDALDataTypeIsConversionLossy(GDT_CInt32, GDT_Float32) ); ensure( GDALDataTypeIsConversionLossy(GDT_CInt32, GDT_Float64) ); ensure( GDALDataTypeIsConversionLossy(GDT_CInt32, GDT_CInt16) ); @@ -616,6 +683,8 @@ namespace tut ensure( GDALDataTypeIsConversionLossy(GDT_CFloat32, GDT_Int16) ); ensure( GDALDataTypeIsConversionLossy(GDT_CFloat32, GDT_UInt32) ); ensure( GDALDataTypeIsConversionLossy(GDT_CFloat32, GDT_Int32) ); + ensure( GDALDataTypeIsConversionLossy(GDT_CFloat32, GDT_UInt64) ); + ensure( GDALDataTypeIsConversionLossy(GDT_CFloat32, GDT_Int64) ); ensure( GDALDataTypeIsConversionLossy(GDT_CFloat32, GDT_Float32) ); ensure( GDALDataTypeIsConversionLossy(GDT_CFloat32, GDT_Float64) ); ensure( GDALDataTypeIsConversionLossy(GDT_CFloat32, GDT_CInt16) ); @@ -628,6 +697,8 @@ namespace tut ensure( GDALDataTypeIsConversionLossy(GDT_CFloat64, GDT_Int16) ); ensure( GDALDataTypeIsConversionLossy(GDT_CFloat64, GDT_UInt32) ); ensure( GDALDataTypeIsConversionLossy(GDT_CFloat64, GDT_Int32) ); + ensure( GDALDataTypeIsConversionLossy(GDT_CFloat64, GDT_UInt64) ); + ensure( GDALDataTypeIsConversionLossy(GDT_CFloat64, GDT_Int64) ); ensure( GDALDataTypeIsConversionLossy(GDT_CFloat64, GDT_Float32) ); ensure( GDALDataTypeIsConversionLossy(GDT_CFloat64, GDT_Float64) ); ensure( GDALDataTypeIsConversionLossy(GDT_CFloat64, GDT_CInt16) ); diff --git a/autotest/cpp/testcopywords.cpp b/autotest/cpp/testcopywords.cpp index 497f0aae5fd2..6ba6cd5133f1 100644 --- a/autotest/cpp/testcopywords.cpp +++ b/autotest/cpp/testcopywords.cpp @@ -125,6 +125,10 @@ template void FromR_2(GDALDataType intype, Co Test(intype, inval, invali, outtype, outval, outvali, numLine); else if (outtype == GDT_UInt32) Test(intype, inval, invali, outtype, outval, outvali, numLine); + else if (outtype == GDT_Int64) + Test(intype, inval, invali, outtype, outval, outvali, numLine); + else if (outtype == GDT_UInt64) + Test(intype, inval, invali, outtype, outval, outvali, numLine); else if (outtype == GDT_Float32) Test(intype, inval, invali, outtype, outval, outvali, numLine); else if (outtype == GDT_Float64) @@ -152,6 +156,10 @@ void FromR(GDALDataType intype, ConstantType inval, ConstantType invali, GDALDat FromR_2(intype, inval, invali, outtype, outval, outvali, numLine); else if (intype == GDT_UInt32) FromR_2(intype, inval, invali, outtype, outval, outvali, numLine); + else if (intype == GDT_Int64) + FromR_2(intype, inval, invali, outtype, outval, outvali, numLine); + else if (intype == GDT_UInt64) + FromR_2(intype, inval, invali, outtype, outval, outvali, numLine); else if (intype == GDT_Float32) FromR_2(intype, inval, invali, outtype, outval, outvali, numLine); else if (intype == GDT_Float64) @@ -173,7 +181,7 @@ void FromR(GDALDataType intype, ConstantType inval, ConstantType invali, GDALDat #define FROM_C(intype, inval, invali, outtype, outval, outvali) FromR(intype, inval, invali, outtype, outval, outvali, __LINE__) #define FROM_C_F(intype, inval, invali, outtype, outval, outvali) FromR(intype, inval, invali, outtype, outval, outvali, __LINE__) -#define IS_UNSIGNED(x) (x == GDT_Byte || x == GDT_UInt16 || x == GDT_UInt32) +#define IS_UNSIGNED(x) (x == GDT_Byte || x == GDT_UInt16 || x == GDT_UInt32 || x == GDT_UInt64) #define IS_FLOAT(x) (x == GDT_Float32 || x == GDT_Float64 || x == GDT_CFloat32 || x == GDT_CFloat64) #define CST_3000000000 (((GIntBig)3000) * 1000 * 1000) @@ -182,7 +190,7 @@ void FromR(GDALDataType intype, ConstantType inval, ConstantType invali, GDALDat static void check_GDT_Byte() { /* GDT_Byte */ - for(GDALDataType outtype=GDT_Byte; outtype<=GDT_CFloat64;outtype = (GDALDataType)(outtype + 1)) + for(GDALDataType outtype=GDT_Byte; outtype(3000000000) * 1000; + FROM_R(GDT_UInt64, nVal, GDT_Byte, 255); /* clamp */ + FROM_R(GDT_UInt64, nVal, GDT_Int16, 32767); /* clamp */ + FROM_R(GDT_UInt64, nVal, GDT_UInt16, 65535); /* clamp */ + FROM_R(GDT_UInt64, nVal, GDT_Int32, 2147483647); /* clamp */ + FROM_R(GDT_UInt64, nVal, GDT_UInt32, 4294967295U); /* clamp */ + FROM_R(GDT_UInt64, nVal, GDT_Int64, nVal); + FROM_R(GDT_UInt64, nVal, GDT_UInt64, nVal); + FROM_R(GDT_UInt64, nVal, GDT_Float32, static_cast(static_cast(nVal))); + FROM_R(GDT_UInt64, nVal, GDT_Float64, nVal); + FROM_R(GDT_UInt64, nVal, GDT_CInt16, 32767); /* clamp */ + FROM_R(GDT_UInt64, nVal, GDT_CInt32, 2147483647); /* clamp */ + FROM_R(GDT_UInt64, nVal, GDT_CFloat32, static_cast(static_cast(nVal))); + FROM_R(GDT_UInt64, nVal, GDT_CFloat64, nVal); +} + static void check_GDT_Float32and64() { /* GDT_Float32 and GDT_Float64 */ for(int i=0;i<2;i++) { GDALDataType intype = (i == 0) ? GDT_Float32 : GDT_Float64; - for(GDALDataType outtype=GDT_Byte; outtype<=GDT_CFloat64;outtype = (GDALDataType)(outtype + 1)) + for(GDALDataType outtype=GDT_Byte; outtype< GDT_TypeCount;outtype = (GDALDataType)(outtype + 1)) { if (IS_FLOAT(outtype)) { @@ -404,7 +485,7 @@ static void check_GDT_CInt16() FROM_C(GDT_CInt16, -32000, -32500, GDT_CInt32, -32000, -32500); FROM_C(GDT_CInt16, -32000, -32500, GDT_CFloat32, -32000, -32500); FROM_C(GDT_CInt16, -32000, -32500, GDT_CFloat64, -32000, -32500); - for(GDALDataType outtype=GDT_Byte; outtype<=GDT_CFloat64;outtype = (GDALDataType)(outtype + 1)) + for(GDALDataType outtype=GDT_Byte; outtype< GDT_TypeCount;outtype = (GDALDataType)(outtype + 1)) { FROM_C(GDT_CInt16, 127, 128, outtype, 127, 128); } @@ -436,7 +517,7 @@ static void check_GDT_CInt32() FROM_C(GDT_CInt32, -33000, -33500, GDT_CInt32, -33000, -33500); FROM_C(GDT_CInt32, -33000, -33500, GDT_CFloat32, -33000, -33500); FROM_C(GDT_CInt32, -33000, -33500, GDT_CFloat64, -33000, -33500); - for(GDALDataType outtype=GDT_Byte; outtype<=GDT_CFloat64;outtype = (GDALDataType)(outtype + 1)) + for(GDALDataType outtype=GDT_Byte; outtype< GDT_TypeCount;outtype = (GDALDataType)(outtype + 1)) { FROM_C(GDT_CInt32, 127, 128, outtype, 127, 128); } @@ -460,7 +541,7 @@ static void check_GDT_CFloat32and64() for(int i=0;i<2;i++) { GDALDataType intype = (i == 0) ? GDT_CFloat32 : GDT_CFloat64; - for(GDALDataType outtype=GDT_Byte; outtype<=GDT_CFloat64;outtype = (GDALDataType)(outtype + 1)) + for(GDALDataType outtype=GDT_Byte; outtype< GDT_TypeCount;outtype = (GDALDataType)(outtype + 1)) { if (IS_FLOAT(outtype)) { @@ -579,6 +660,8 @@ void CheckPacked(GDALDataType eIn, GDALDataType eOut) case GDT_Int16: CheckPacked(eIn, eOut); break; case GDT_UInt32: CheckPacked(eIn, eOut); break; case GDT_Int32: CheckPacked(eIn, eOut); break; + case GDT_UInt64: CheckPacked(eIn, eOut); break; + case GDT_Int64: CheckPacked(eIn, eOut); break; case GDT_Float32: CheckPacked(eIn, eOut); break; case GDT_Float64: CheckPacked(eIn, eOut); break; default: @@ -597,6 +680,8 @@ static void CheckPacked(GDALDataType eIn, GDALDataType eOut) case GDT_Int16: CheckPacked(eIn, eOut); break; case GDT_UInt32: CheckPacked(eIn, eOut); break; case GDT_Int32: CheckPacked(eIn, eOut); break; + case GDT_UInt64: CheckPacked(eIn, eOut); break; + case GDT_Int64: CheckPacked(eIn, eOut); break; case GDT_Float32: CheckPacked(eIn, eOut); break; case GDT_Float64: CheckPacked(eIn, eOut); break; default: @@ -615,6 +700,8 @@ int main(int /* argc */, char* /* argv */ []) check_GDT_UInt16(); check_GDT_Int32(); check_GDT_UInt32(); + check_GDT_Int64(); + check_GDT_UInt64(); check_GDT_Float32and64(); check_GDT_CInt16(); check_GDT_CInt32(); @@ -704,10 +791,12 @@ int main(int /* argc */, char* /* argv */ []) free(pIn); free(pOut); - for( GDALDataType eIn = GDT_Byte; eIn <= GDT_Float64; eIn = static_cast(eIn + 1) ) + for( GDALDataType eIn = GDT_Byte; eIn < GDT_TypeCount; eIn = static_cast(eIn + 1) ) { - for( GDALDataType eOut = GDT_Byte; eOut <= GDT_Float64; eOut = static_cast(eOut + 1) ) + if( GDALDataTypeIsComplex(eIn) ) continue; + for( GDALDataType eOut = GDT_Byte; eOut < GDT_TypeCount; eOut = static_cast(eOut + 1) ) { + if( GDALDataTypeIsComplex(eOut) ) continue; CheckPacked(eIn, eOut); } } diff --git a/autotest/cpp/testperfcopywords.cpp b/autotest/cpp/testperfcopywords.cpp index b564be4a6a0d..431bb2109156 100644 --- a/autotest/cpp/testperfcopywords.cpp +++ b/autotest/cpp/testperfcopywords.cpp @@ -44,9 +44,9 @@ int main(int /* argc */, char* /* argv */ []) clock_t start, end; - for(intype=GDT_Byte; intype<=GDT_CFloat64;intype++) + for(intype=GDT_Byte; intypei2", 'h', gdal.GDT_Int16, None, None], ["i4", 'i', gdal.GDT_Int32, None, None], - ["i8", 'q', gdal.GDT_Float64, None, None], + ["i8", 'q', gdal.GDT_Int64, None, None], ["u2", 'H', gdal.GDT_UInt16, None, None], ["u4", 'I', gdal.GDT_UInt32, None, None], ["u8", 'Q', gdal.GDT_Float64, None, None], + ["u8", 'Q', gdal.GDT_UInt64, None, None], ["f4", 'f', gdal.GDT_Float32, None, None], [" + + diff --git a/doc/source/programs/gdal_create.rst b/doc/source/programs/gdal_create.rst index 7fea7775f3cf..61570c7225ee 100644 --- a/doc/source/programs/gdal_create.rst +++ b/doc/source/programs/gdal_create.rst @@ -23,7 +23,7 @@ Synopsis [-outsize xsize ysize] [-bands count] [-burn value]* - [-ot {Byte/Int16/UInt16/UInt32/Int32/Float32/Float64/ + [-ot {Byte/Int16/UInt16/UInt32/Int32/UInt64/Int64/Float32/Float64/ CInt16/CInt32/CFloat32/CFloat64}] [-strict] [-a_srs srs_def] [-a_ullr ulx uly lrx lry] [-a_nodata value] [-mo "META-TAG=VALUE"]* [-q] diff --git a/doc/source/programs/gdal_rasterize.rst b/doc/source/programs/gdal_rasterize.rst index f870f5356fe0..3deac86b3fa4 100644 --- a/doc/source/programs/gdal_rasterize.rst +++ b/doc/source/programs/gdal_rasterize.rst @@ -21,7 +21,7 @@ Synopsis [-dialect dialect] [-of format] [-a_srs srs_def] [-to NAME=VALUE]* [-co "NAME=VALUE"]* [-a_nodata value] [-init value]* [-te xmin ymin xmax ymax] [-tr xres yres] [-tap] [-ts width height] - [-ot {Byte/Int16/UInt16/UInt32/Int32/Float32/Float64/ + [-ot {Byte/Int16/UInt16/UInt32/Int32/UInt64/Int64/Float32/Float64/ CInt16/CInt32/CFloat32/CFloat64}] [-optim {[AUTO]/VECTOR/RASTER}] [-q] diff --git a/doc/source/programs/gdal_translate.rst b/doc/source/programs/gdal_translate.rst index 0f4cda32b453..f833fc72d110 100644 --- a/doc/source/programs/gdal_translate.rst +++ b/doc/source/programs/gdal_translate.rst @@ -17,7 +17,7 @@ Synopsis gdal_translate [--help-general] - [-ot {Byte/Int16/UInt16/UInt32/Int32/Float32/Float64/ + [-ot {Byte/Int16/UInt16/UInt32/Int32/UInt64/Int64/Float32/Float64/ CInt16/CInt32/CFloat32/CFloat64}] [-strict] [-if format]* [-of format] [-b band]* [-mask band] [-expand {gray|rgb|rgba}] diff --git a/doc/source/user/raster_data_model.rst b/doc/source/user/raster_data_model.rst index bb49df212321..c448d25e9093 100644 --- a/doc/source/user/raster_data_model.rst +++ b/doc/source/user/raster_data_model.rst @@ -196,7 +196,10 @@ A raster band is represented in GDAL with the :cpp:class:`GDALRasterBand` class. A raster band has the following properties: - A width and height in pixels and lines. This is the same as that defined for the dataset, if this is a full resolution band. -- A datatype (GDALDataType). One of Byte, UInt16, Int16, UInt32, Int32, Float32, Float64, and the complex types CInt16, CInt32, CFloat32, and CFloat64. +- A datatype (GDALDataType). One of Byte, UInt16, Int16, UInt32, Int32, UInt64, Int64, Float32, Float64, and the complex types CInt16, CInt32, CFloat32, and CFloat64. + + UInt64 and Int64 data types have been added in GDAL 3.5. Beyond reading and write pixel values, their support is limited. Some algorithms might use 64-bit floating-point internally (warping), as well as some methods like GetNoDataValue(), or even 32-bit floating point (overview, RasterIO resampling). Hence the range where exact values are preserved can be [0, 2^53] (or less if 32-bit floating-point is used). + - A block size. This is a preferred (efficient) access chunk size. For tiled images this will be one tile. For scanline oriented images this will normally be one scanline. - A list of name/value pair metadata in the same format as the dataset, but of information that is potentially specific to this band. - An optional description string. diff --git a/frmts/gtiff/cogdriver.cpp b/frmts/gtiff/cogdriver.cpp index c40b8e04431e..8e565a185de5 100644 --- a/frmts/gtiff/cogdriver.cpp +++ b/frmts/gtiff/cogdriver.cpp @@ -1358,7 +1358,7 @@ void GDALRegister_COG() poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drivers/raster/cog.html" ); poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, - "Byte UInt16 Int16 UInt32 Int32 Float32 " + "Byte UInt16 Int16 UInt32 Int32 UInt64 Int64 Float32 " "Float64 CInt16 CInt32 CFloat32 CFloat64" ); poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" ); diff --git a/frmts/gtiff/geotiff.cpp b/frmts/gtiff/geotiff.cpp index eb5f7b4021ca..29d2be091a5d 100644 --- a/frmts/gtiff/geotiff.cpp +++ b/frmts/gtiff/geotiff.cpp @@ -1431,6 +1431,10 @@ GTiffRasterBand::GTiffRasterBand( GTiffDataset *poDSIn, int nBandIn ): eDataType = GDT_CFloat32; else if( nSampleFormat == SAMPLEFORMAT_COMPLEXINT ) eDataType = GDT_CInt32; + else if( nSampleFormat == SAMPLEFORMAT_INT ) + eDataType = GDT_Int64; + else + eDataType = GDT_UInt64; } else if( nBitsPerSample == 128 ) { @@ -8527,6 +8531,18 @@ inline bool GTiffDataset::IsFirstPixelEqualToNoData( const void* pBuffer ) *(static_cast(pBuffer)) == static_cast(dfEffectiveNoData); } + if( m_nBitsPerSample == 64 && eDT == GDT_UInt64 ) + { + return GDALIsValueInRange(dfEffectiveNoData) && + *(static_cast(pBuffer)) == + static_cast(dfEffectiveNoData); + } + if( m_nBitsPerSample == 64 && eDT == GDT_Int64 ) + { + return GDALIsValueInRange(dfEffectiveNoData) && + *(static_cast(pBuffer)) == + static_cast(dfEffectiveNoData); + } if( m_nBitsPerSample == 32 && eDT == GDT_Float32 ) { if( CPLIsNan(m_dfNoDataValue) ) @@ -9434,6 +9450,16 @@ template<> uint32_t AdjustValue(uint32_t value, uint64_t nRoundUpBitTe return AdjustValueInt(value, nRoundUpBitTest); } +template<> int64_t AdjustValue(int64_t value, uint64_t nRoundUpBitTest) +{ + return AdjustValueInt(value, nRoundUpBitTest); +} + +template<> uint64_t AdjustValue(uint64_t value, uint64_t nRoundUpBitTest) +{ + return AdjustValueInt(value, nRoundUpBitTest); +} + template<> float AdjustValue(float value, uint64_t) { return std::nextafter(value, std::numeric_limits::max()); @@ -9490,6 +9516,12 @@ template<> uint32_t RoundValueDiscardLsb(const void* ptr, return RoundValueDiscardLsbUnsigned(ptr, nMask, nRoundUpBitTest); } +template<> uint64_t RoundValueDiscardLsb(const void* ptr, + uint64_t nMask, + uint64_t nRoundUpBitTest) +{ + return RoundValueDiscardLsbUnsigned(ptr, nMask, nRoundUpBitTest); +} template<> int8_t RoundValueDiscardLsb(const void* ptr, uint64_t nMask, uint64_t nRoundUpBitTest) @@ -9511,6 +9543,13 @@ template<> int32_t RoundValueDiscardLsb(const void* ptr, return RoundValueDiscardLsbSigned(ptr, nMask, nRoundUpBitTest); } +template<> int64_t RoundValueDiscardLsb(const void* ptr, + uint64_t nMask, + uint64_t nRoundUpBitTest) +{ + return RoundValueDiscardLsbSigned(ptr, nMask, nRoundUpBitTest); +} + template<> uint32_t RoundValueDiscardLsb(const void* ptr, uint64_t nMask, uint64_t nRoundUpBitTest) @@ -9784,6 +9823,44 @@ static void DiscardLsb( GByte* pabyBuffer, GPtrDiff_t nBytes, int iBand, pabyBuffer, nBytes, iBand, nBands, nPlanarConfig, panMaskOffsetLsb, bHasNoData, nNoDataValue); } + else if( nBitsPerSample == 64 && nSampleFormat == SAMPLEFORMAT_INT ) + { + // FIXME: we should not rely on dfNoDataValue when we support native data type for nodata + int64_t nNoDataValue = 0; + if( bHasNoData && + dfNoDataValue >= static_cast(std::numeric_limits::min()) && + dfNoDataValue <= static_cast(std::numeric_limits::max()) && + dfNoDataValue == static_cast(static_cast(dfNoDataValue)) ) + { + nNoDataValue = static_cast(dfNoDataValue); + } + else + { + bHasNoData = false; + } + DiscardLsbT( + pabyBuffer, nBytes, iBand, nBands, nPlanarConfig, + panMaskOffsetLsb, bHasNoData, nNoDataValue); + } + else if( nBitsPerSample == 64 && nSampleFormat == SAMPLEFORMAT_UINT ) + { + // FIXME: we should not rely on dfNoDataValue when we support native data type for nodata + uint64_t nNoDataValue = 0; + if( bHasNoData && + dfNoDataValue >= static_cast(std::numeric_limits::min()) && + dfNoDataValue <= static_cast(std::numeric_limits::max()) && + dfNoDataValue == static_cast(static_cast(dfNoDataValue)) ) + { + nNoDataValue = static_cast(dfNoDataValue); + } + else + { + bHasNoData = false; + } + DiscardLsbT( + pabyBuffer, nBytes, iBand, nBands, nPlanarConfig, + panMaskOffsetLsb, bHasNoData, nNoDataValue); + } else if( nBitsPerSample == 32 && nSampleFormat == SAMPLEFORMAT_IEEEFP ) { float fNoDataValue = static_cast(dfNoDataValue); @@ -16545,7 +16622,7 @@ TIFF *GTiffDataset::CreateLL( const char * pszFilename, uint16_t l_nSampleFormat = 0; if( (eType == GDT_Byte && EQUAL(pszPixelType,"SIGNEDBYTE")) - || eType == GDT_Int16 || eType == GDT_Int32 ) + || eType == GDT_Int16 || eType == GDT_Int32 || eType == GDT_Int64 ) l_nSampleFormat = SAMPLEFORMAT_INT; else if( eType == GDT_CInt16 || eType == GDT_CInt32 ) l_nSampleFormat = SAMPLEFORMAT_COMPLEXINT; diff --git a/frmts/gtiff/gt_overview.cpp b/frmts/gtiff/gt_overview.cpp index 1ee1f7a4bb42..86fc4d08aa5e 100644 --- a/frmts/gtiff/gt_overview.cpp +++ b/frmts/gtiff/gt_overview.cpp @@ -378,6 +378,16 @@ GTIFFBuildOverviewsEx( const char * pszFilename, nBandFormat = SAMPLEFORMAT_INT; break; + case GDT_UInt64: + nBandBits = 64; + nBandFormat = SAMPLEFORMAT_UINT; + break; + + case GDT_Int64: + nBandBits = 64; + nBandFormat = SAMPLEFORMAT_INT; + break; + case GDT_Float32: nBandBits = 32; nBandFormat = SAMPLEFORMAT_IEEEFP; diff --git a/frmts/hdf4/hdf4dataset.cpp b/frmts/hdf4/hdf4dataset.cpp index 8ec7c153c5db..e1f34e19920f 100644 --- a/frmts/hdf4/hdf4dataset.cpp +++ b/frmts/hdf4/hdf4dataset.cpp @@ -205,9 +205,9 @@ GDALDataType HDF4Dataset::GetDataType( int32 iNumType ) case DFNT_UINT32: return GDT_UInt32; case DFNT_INT64: - return GDT_Unknown; + return GDT_Int64; case DFNT_UINT64: - return GDT_Unknown; + return GDT_UInt64; case DFNT_FLOAT32: return GDT_Float32; case DFNT_FLOAT64: diff --git a/frmts/hdf4/hdf4imagedataset.cpp b/frmts/hdf4/hdf4imagedataset.cpp index 11321b05191b..90034e3c4656 100644 --- a/frmts/hdf4/hdf4imagedataset.cpp +++ b/frmts/hdf4/hdf4imagedataset.cpp @@ -3949,6 +3949,38 @@ GDALDataset *HDF4ImageDataset::Create( const char * pszFilename, aiDimSizes[poDS->iYDim] = nYSize; aiDimSizes[poDS->iBandDim] = nBands; + const auto GetHDFType = [](GDALDataType eTypeIn) + { + switch ( eTypeIn ) + { + case GDT_Float64: + return DFNT_FLOAT64; + case GDT_Float32: + return DFNT_FLOAT32; + case GDT_UInt64: + // SDCreate() doens't like it + return DFNT_UINT64; + case GDT_UInt32: + return DFNT_UINT32; + case GDT_UInt16: + return DFNT_UINT16; + case GDT_Int64: + // SDCreate() doens't like it + return DFNT_INT64; + case GDT_Int32: + return DFNT_INT32; + case GDT_Int16: + return DFNT_INT16; + case GDT_Byte: + return DFNT_UINT8; + default: + CPLError(CE_Warning, CPLE_NotSupported, + "Datatype %s not supported. Defauting to Byte", + GDALGetDataTypeName(eTypeIn)); + return DFNT_UINT8; + } + }; + const char *pszSDSName = nullptr; int32 iSDS = -1; @@ -3957,38 +3989,10 @@ GDALDataset *HDF4ImageDataset::Create( const char * pszFilename, for( int iBand = 0; iBand < nBands; iBand++ ) { pszSDSName = CPLSPrintf( "Band%d", iBand ); - switch ( eType ) - { - case GDT_Float64: - iSDS = SDcreate( poDS->hSD, pszSDSName, DFNT_FLOAT64, - poDS->iRank, aiDimSizes ); - break; - case GDT_Float32: - iSDS = SDcreate( poDS-> hSD, pszSDSName, DFNT_FLOAT32, - poDS->iRank, aiDimSizes ); - break; - case GDT_UInt32: - iSDS = SDcreate( poDS->hSD, pszSDSName, DFNT_UINT32, - poDS->iRank, aiDimSizes ); - break; - case GDT_UInt16: - iSDS = SDcreate( poDS->hSD, pszSDSName, DFNT_UINT16, - poDS->iRank, aiDimSizes ); - break; - case GDT_Int32: - iSDS = SDcreate( poDS->hSD, pszSDSName, DFNT_INT32, - poDS->iRank, aiDimSizes ); - break; - case GDT_Int16: - iSDS = SDcreate( poDS->hSD, pszSDSName, DFNT_INT16, - poDS->iRank, aiDimSizes ); - break; - case GDT_Byte: - default: - iSDS = SDcreate( poDS->hSD, pszSDSName, DFNT_UINT8, - poDS->iRank, aiDimSizes ); - break; - } + iSDS = SDcreate( poDS->hSD, pszSDSName, GetHDFType(eType), + poDS->iRank, aiDimSizes ); + if( iSDS < 0 ) + break; SDendaccess( iSDS ); } } @@ -3996,38 +4000,8 @@ GDALDataset *HDF4ImageDataset::Create( const char * pszFilename, { pszSDSName = "3-dimensional Scientific Dataset"; poDS->iDataset = 0; - switch ( eType ) - { - case GDT_Float64: - iSDS = SDcreate( poDS->hSD, pszSDSName, DFNT_FLOAT64, - poDS->iRank, aiDimSizes ); - break; - case GDT_Float32: - iSDS = SDcreate( poDS->hSD, pszSDSName, DFNT_FLOAT32, - poDS->iRank, aiDimSizes ); - break; - case GDT_UInt32: - iSDS = SDcreate( poDS->hSD, pszSDSName, DFNT_UINT32, - poDS->iRank, aiDimSizes ); - break; - case GDT_UInt16: - iSDS = SDcreate( poDS->hSD, pszSDSName, DFNT_UINT16, - poDS->iRank, aiDimSizes ); - break; - case GDT_Int32: - iSDS = SDcreate( poDS->hSD, pszSDSName, DFNT_INT32, - poDS->iRank, aiDimSizes ); - break; - case GDT_Int16: - iSDS = SDcreate( poDS->hSD, pszSDSName, DFNT_INT16, - poDS->iRank, aiDimSizes ); - break; - case GDT_Byte: - default: - iSDS = SDcreate( poDS->hSD, pszSDSName, DFNT_UINT8, - poDS->iRank, aiDimSizes ); - break; - } + iSDS = SDcreate( poDS->hSD, pszSDSName, GetHDFType(eType), + poDS->iRank, aiDimSizes ); } else { @@ -4089,6 +4063,7 @@ void GDALRegister_HDF4Image() poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drivers/raster/hdf4.html" ); poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, "Byte Int16 UInt16 Int32 UInt32 " + // "Int64 UInt64 " "Float32 Float64" ); poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST, diff --git a/frmts/hdf5/hdf5dataset.cpp b/frmts/hdf5/hdf5dataset.cpp index 22afe724d82a..493758f1c212 100644 --- a/frmts/hdf5/hdf5dataset.cpp +++ b/frmts/hdf5/hdf5dataset.cpp @@ -180,6 +180,10 @@ GDALDataType HDF5Dataset::GetDataType(hid_t TypeID) return GDT_Int32; else if( H5Tequal(H5T_NATIVE_UINT, TypeID) ) return GDT_UInt32; + else if( H5Tequal(H5T_NATIVE_INT64, TypeID) ) + return GDT_Int64; + else if( H5Tequal(H5T_NATIVE_UINT64, TypeID) ) + return GDT_UInt64; else if( H5Tequal(H5T_NATIVE_LONG, TypeID) ) { #if SIZEOF_UNSIGNED_LONG == 4 diff --git a/frmts/hdf5/hdf5multidim.cpp b/frmts/hdf5/hdf5multidim.cpp index a6f67bcb8c69..2bbe6116b5b7 100644 --- a/frmts/hdf5/hdf5multidim.cpp +++ b/frmts/hdf5/hdf5multidim.cpp @@ -131,16 +131,6 @@ static GDALExtendedDataType BuildDataType(hid_t hDataType, bool& bHasVLen, bool& bNonNativeDataType = true; return GDALExtendedDataType::Create(GDT_Int16); } - else if( H5Tequal(H5T_NATIVE_LLONG, hDataType) ) - { - bNonNativeDataType = true; - return GDALExtendedDataType::Create(GDT_Float64); - } - else if( H5Tequal(H5T_NATIVE_ULLONG, hDataType) ) - { - bNonNativeDataType = true; - return GDALExtendedDataType::Create(GDT_Float64); - } else if( eDT != GDT_Unknown ) return GDALExtendedDataType::Create(eDT); else if (klass == H5T_STRING ) @@ -1433,6 +1423,8 @@ static hid_t GetHDF5DataTypeFromGDALDataType(const GDALExtendedDataType& dt, case GDT_Int16: hBufferType = H5Tcopy(H5T_NATIVE_SHORT); break; case GDT_UInt32: hBufferType = H5Tcopy(H5T_NATIVE_UINT); break; case GDT_Int32: hBufferType = H5Tcopy(H5T_NATIVE_INT); break; + case GDT_UInt64: hBufferType = H5Tcopy(H5T_NATIVE_UINT64); break; + case GDT_Int64: hBufferType = H5Tcopy(H5T_NATIVE_INT64); break; case GDT_Float32: hBufferType = H5Tcopy(H5T_NATIVE_FLOAT); break; case GDT_Float64: hBufferType = H5Tcopy(H5T_NATIVE_DOUBLE); break; case GDT_CInt16: @@ -1592,22 +1584,6 @@ static void CopyValue(const GByte* pabySrcBuffer, hid_t hSrcDataType, &nVal, GDALExtendedDataType::Create(GDT_Int16), pabyDstBuffer, dstDataType); } - else if( H5Tequal(H5T_NATIVE_LLONG, hSrcDataType) ) - { - const double dfVal = static_cast( - *reinterpret_cast(pabySrcBuffer)); - GDALExtendedDataType::CopyValue( - &dfVal, GDALExtendedDataType::Create(GDT_Float64), - pabyDstBuffer, dstDataType); - } - else if( H5Tequal(H5T_NATIVE_ULLONG, hSrcDataType) ) - { - const double dfVal = static_cast( - *reinterpret_cast(pabySrcBuffer)); - GDALExtendedDataType::CopyValue( - &dfVal, GDALExtendedDataType::Create(GDT_Float64), - pabyDstBuffer, dstDataType); - } else { GDALDataType eDT = ::HDF5Dataset::GetDataType(hSrcDataType); @@ -1744,7 +1720,9 @@ bool HDF5Array::IRead(const GUInt64* arrayStartIdx, H5Tequal(hParent, H5T_NATIVE_USHORT) || H5Tequal(hParent, H5T_NATIVE_SHORT) || H5Tequal(hParent, H5T_NATIVE_UINT) || - H5Tequal(hParent, H5T_NATIVE_INT) ) + H5Tequal(hParent, H5T_NATIVE_INT) || + H5Tequal(hParent, H5T_NATIVE_UINT64) || + H5Tequal(hParent, H5T_NATIVE_INT64) ) { hBufferType = H5Tcopy(m_hNativeDT); if( m_dt != bufferDataType ) @@ -2025,7 +2003,9 @@ bool HDF5Attribute::IRead(const GUInt64* arrayStartIdx, H5Tequal(hParent, H5T_NATIVE_USHORT) || H5Tequal(hParent, H5T_NATIVE_SHORT) || H5Tequal(hParent, H5T_NATIVE_UINT) || - H5Tequal(hParent, H5T_NATIVE_INT) ) + H5Tequal(hParent, H5T_NATIVE_INT) || + H5Tequal(hParent, H5T_NATIVE_UINT64) || + H5Tequal(hParent, H5T_NATIVE_INT64)) { hBufferType = H5Tcopy(m_hNativeDT); } diff --git a/frmts/mem/memdataset.cpp b/frmts/mem/memdataset.cpp index c08c10eaccdc..48bc657e36d1 100644 --- a/frmts/mem/memdataset.cpp +++ b/frmts/mem/memdataset.cpp @@ -2471,7 +2471,7 @@ void GDALRegister_MEM() poDriver->SetMetadataItem( GDAL_DCAP_MULTIDIM_RASTER, "YES" ); poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "In Memory Raster" ); poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, - "Byte Int16 UInt16 Int32 UInt32 Float32 Float64 " + "Byte Int16 UInt16 Int32 UInt32 Int64 UInt64 Float32 Float64 " "CInt16 CInt32 CFloat32 CFloat64" ); poDriver->SetMetadataItem( GDAL_DCAP_COORDINATE_EPOCH, "YES" ); diff --git a/frmts/netcdf/netcdfdataset.cpp b/frmts/netcdf/netcdfdataset.cpp index 340d72e9e988..27ee6451664e 100644 --- a/frmts/netcdf/netcdfdataset.cpp +++ b/frmts/netcdf/netcdfdataset.cpp @@ -391,6 +391,10 @@ netCDFRasterBand::netCDFRasterBand( const netCDFRasterBand::CONSTRUCTOR_OPEN&, eDataType = GDT_UInt16; else if( nc_datatype == NC_UINT ) eDataType = GDT_UInt32; + else if( nc_datatype == NC_INT64 ) + eDataType = GDT_Int64; + else if( nc_datatype == NC_UINT64 ) + eDataType = GDT_UInt64; #endif else { @@ -589,7 +593,8 @@ netCDFRasterBand::netCDFRasterBand( const netCDFRasterBand::CONSTRUCTOR_OPEN&, #ifdef NETCDF_HAS_NC4 if( nc_datatype == NC_UBYTE || nc_datatype == NC_USHORT || - nc_datatype == NC_UINT ) + nc_datatype == NC_UINT || + nc_datatype == NC_UINT64 ) bSignedData = false; #endif @@ -779,6 +784,34 @@ netCDFRasterBand::netCDFRasterBand( const netCDFRasterBand::CONSTRUCTOR_CREATE&, nc_datatype = NC_DOUBLE; break; #ifdef NETCDF_HAS_NC4 + case GDT_Int64: + if( poNCDFDS->eFormat == NCDF_FORMAT_NC4 ) + { + nc_datatype = NC_INT64; + } + else + { + if( nBand == 1 ) + CPLError(CE_Warning, CPLE_AppDefined, + "Unsupported GDAL datatype %s, treat as NC_DOUBLE.", "Int64"); + nc_datatype = NC_DOUBLE; + eDataType = GDT_Float64; + } + break; + case GDT_UInt64: + if( poNCDFDS->eFormat == NCDF_FORMAT_NC4 ) + { + nc_datatype = NC_UINT64; + } + else + { + if( nBand == 1 ) + CPLError(CE_Warning, CPLE_AppDefined, + "Unsupported GDAL datatype %s, treat as NC_DOUBLE.", "UInt64"); + nc_datatype = NC_DOUBLE; + eDataType = GDT_Float64; + } + break; case GDT_UInt16: if( poNCDFDS->eFormat == NCDF_FORMAT_NC4 ) { @@ -2004,6 +2037,22 @@ bool netCDFRasterBand::FetchNetcdfChunk( size_t xstart, CheckData(pImage, pImageNC, edge[nBandXPos], nYChunkSize, false); } + else if( eDataType == GDT_Int64 ) + { + status = nc_get_vara_longlong(cdfid, nZId, start, edge, + static_cast(pImageNC)); + if( status == NC_NOERR ) + CheckData(pImage, pImageNC, edge[nBandXPos], + nYChunkSize, false); + } + else if( eDataType == GDT_UInt64 ) + { + status = nc_get_vara_ulonglong(cdfid, nZId, start, edge, + static_cast(pImageNC)); + if( status == NC_NOERR ) + CheckData(pImage, pImageNC, edge[nBandXPos], + nYChunkSize, false); + } else if ( eDataType == GDT_CInt16 ) { status = nc_get_vara(cdfid, nZId, start, edge, @@ -2306,6 +2355,18 @@ CPLErr netCDFRasterBand::IWriteBlock( CPL_UNUSED int nBlockXOff, status = nc_put_vara_uint(cdfid, nZId, start, edge, static_cast(pImage)); } + else if( eDataType == GDT_UInt64 && + static_cast(poDS)->eFormat == NCDF_FORMAT_NC4 ) + { + status = nc_put_vara_ulonglong(cdfid, nZId, start, edge, + static_cast(pImage)); + } + else if( eDataType == GDT_Int64 && + static_cast(poDS)->eFormat == NCDF_FORMAT_NC4 ) + { + status = nc_put_vara_longlong(cdfid, nZId, start, edge, + static_cast(pImage)); + } #endif else { @@ -8948,9 +9009,19 @@ netCDFDataset::Create( const char *pszFilename, CPLMutexHolderD(&hNCMutex); + CPLStringList aosOptions(CSLDuplicate(papszOptions)); +#ifdef NETCDF_HAS_NC4 + if( aosOptions.FetchNameValue("FORMAT") == nullptr && + (eType == GDT_UInt16 || eType == GDT_UInt32 || + eType == GDT_UInt64 || eType == GDT_Int64) ) + { + CPLDebug("netCDF", "Selecting FORMAT=NC4 due to data type"); + aosOptions.SetNameValue("FORMAT", "NC4"); + } +#endif netCDFDataset *poDS = netCDFDataset::CreateLL(pszFilename, nXSize, nYSize, nBands, - papszOptions); + aosOptions.List()); if( !poDS ) return nullptr; @@ -9088,7 +9159,7 @@ netCDFDataset::CreateCopy( const char *pszFilename, GDALDataset *poSrcDS, return nullptr; } - GDALDataType eDT; + GDALDataType eDT = GDT_Unknown; GDALRasterBand *poSrcBand = nullptr; for( int iBand = 1; iBand <= nBands; iBand++ ) { @@ -9107,9 +9178,19 @@ netCDFDataset::CreateCopy( const char *pszFilename, GDALDataset *poSrcDS, return nullptr; // Same as in Create(). + CPLStringList aosOptions(CSLDuplicate(papszOptions)); +#ifdef NETCDF_HAS_NC4 + if( aosOptions.FetchNameValue("FORMAT") == nullptr && + (eDT == GDT_UInt16 || eDT == GDT_UInt32 || + eDT == GDT_UInt64 || eDT == GDT_Int64) ) + { + CPLDebug("netCDF", "Selecting FORMAT=NC4 due to data type"); + aosOptions.SetNameValue("FORMAT", "NC4"); + } +#endif netCDFDataset *poDS = netCDFDataset::CreateLL(pszFilename, nXSize, nYSize, nBands, - papszOptions); + aosOptions.List()); if( !poDS ) return nullptr; @@ -9399,17 +9480,41 @@ netCDFDataset::CreateCopy( const char *pszFilename, GDALDataset *poSrcDS, eErr = NCDFCopyBand(poSrcBand, poDstBand, nXSize, nYSize, GDALScaledProgress, pScaledProgress); } - else if( (eDT == GDT_UInt16) || (eDT == GDT_Int16) ) + else if( eDT == GDT_UInt16 ) { - CPLDebug("GDAL_netCDF", "GInt16 Band#%d", iBand); + CPLDebug("GDAL_netCDF", "GUInt16 Band#%d", iBand); eErr = NCDFCopyBand(poSrcBand, poDstBand, nXSize, nYSize, GDALScaledProgress, pScaledProgress); } - else if( (eDT == GDT_UInt32) || (eDT == GDT_Int32) ) + else if( eDT == GDT_Int16 ) { CPLDebug("GDAL_netCDF", "GInt16 Band#%d", iBand); + eErr = NCDFCopyBand(poSrcBand, poDstBand, nXSize, nYSize, + GDALScaledProgress, pScaledProgress); + } + else if( eDT == GDT_UInt32 ) + { + CPLDebug("GDAL_netCDF", "GUInt32 Band#%d", iBand); + eErr = NCDFCopyBand(poSrcBand, poDstBand, nXSize, nYSize, + GDALScaledProgress, pScaledProgress); + } + else if( eDT == GDT_Int32 ) + { + CPLDebug("GDAL_netCDF", "GInt32 Band#%d", iBand); eErr = NCDFCopyBand(poSrcBand, poDstBand, nXSize, nYSize, - GDALScaledProgress, pScaledProgress); + GDALScaledProgress, pScaledProgress); + } + else if( eDT == GDT_UInt64 ) + { + CPLDebug("GDAL_netCDF", "GUInt64 Band#%d", iBand); + eErr = NCDFCopyBand(poSrcBand, poDstBand, nXSize, nYSize, + GDALScaledProgress, pScaledProgress); + } + else if( eDT == GDT_Int64 ) + { + CPLDebug("GDAL_netCDF", "GInt64 Band#%d", iBand); + eErr = NCDFCopyBand(poSrcBand, poDstBand, nXSize, nYSize, + GDALScaledProgress, pScaledProgress); } else if( eDT == GDT_Float32 ) { @@ -9728,6 +9833,14 @@ void GDALRegister_netCDF() poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "Network Common Data Format"); poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/netcdf.html"); poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "nc"); + poDriver->SetMetadataItem(GDAL_DMD_CREATIONDATATYPES, +#ifdef NETCDF_HAS_NC4 + "Byte UInt16 Int16 UInt32 Int32 Int64 UInt64 " +#else + "Byte Int16 Int32 " +#endif + "Float32 Float64 " + "CInt16 CInt32 CFloat32 CFloat64" ); poDriver->SetMetadataItem(GDAL_DMD_CREATIONOPTIONLIST, "" "