161
176
if( (nBufXSize < nXSize || nBufYSize < nYSize)
162
177
&& GetOverviewCount() > 0 && eRWFlag == GF_Read )
164
if( OverviewRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
165
pData, nBufXSize, nBufYSize,
166
eBufType, nPixelSpace, nLineSpace ) == CE_None )
182
GDALBandGetBestOverviewLevel(this, nXOff, nYOff, nXSize, nYSize,
183
nBufXSize, nBufYSize);
186
GDALRasterBand* poOverviewBand = GetOverview(nOverview);
187
if (poOverviewBand == NULL)
190
return poOverviewBand->RasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
191
pData, nBufXSize, nBufYSize, eBufType,
192
nPixelSpace, nLineSpace );
170
196
/* ==================================================================== */
2590
2626
/************************************************************************/
2627
/* GDALCopyWholeRasterGetSwathSize() */
2628
/************************************************************************/
2630
static void GDALCopyWholeRasterGetSwathSize(GDALRasterBand *poSrcPrototypeBand,
2631
GDALRasterBand *poDstPrototypeBand,
2633
int bDstIsCompressed, int bInterleave,
2634
int* pnSwathCols, int *pnSwathLines)
2636
GDALDataType eDT = poDstPrototypeBand->GetRasterDataType();
2637
int nSrcBlockXSize, nSrcBlockYSize;
2638
int nBlockXSize, nBlockYSize;
2640
int nXSize = poSrcPrototypeBand->GetXSize();
2641
int nYSize = poSrcPrototypeBand->GetYSize();
2643
poSrcPrototypeBand->GetBlockSize( &nSrcBlockXSize, &nSrcBlockYSize );
2644
poDstPrototypeBand->GetBlockSize( &nBlockXSize, &nBlockYSize );
2646
int nMaxBlockXSize = MAX(nBlockXSize, nSrcBlockXSize);
2647
int nMaxBlockYSize = MAX(nBlockYSize, nSrcBlockYSize);
2649
/* -------------------------------------------------------------------- */
2650
/* What will our swath size be? */
2651
/* -------------------------------------------------------------------- */
2652
/* When writing interleaved data in a compressed format, we want to be sure */
2653
/* that each block will only be written once, so the swath size must not be */
2654
/* greater than the block cache. */
2655
/* So as the default cache size is 40 MB, 10 MB is a safe value */
2656
int nTargetSwathSize = atoi(CPLGetConfigOption("GDAL_SWATH_SIZE", "10000000"));
2657
if (nTargetSwathSize < 1000000)
2658
nTargetSwathSize = 1000000;
2660
/* But let's check that */
2661
if (bDstIsCompressed && bInterleave && nTargetSwathSize > GDALGetCacheMax64())
2663
CPLError(CE_Warning, CPLE_AppDefined,
2664
"When translating into a compressed interleave format, the block cache size (" CPL_FRMT_GIB ") "
2665
"should be at least the size of the swath (%d)", GDALGetCacheMax64(), nTargetSwathSize);
2668
int nPixelSize = (GDALGetDataTypeSize(eDT) / 8);
2670
nPixelSize *= nBandCount;
2672
// aim for one row of blocks. Do not settle for less.
2673
int nSwathCols = nXSize;
2674
int nSwathLines = nBlockYSize;
2676
#define IS_MULTIPLE_OF(x,y) ((y)%(x) == 0)
2677
#define ROUND_TO(x,y) (((x)/(y))*(y))
2679
/* if both input and output datasets are tiled, that the tile dimensions */
2680
/* are "compatible", try to stick to a swath dimension that is a multiple */
2681
/* of input and output block dimensions */
2682
if (nBlockXSize != nXSize && nSrcBlockXSize != nXSize &&
2683
IS_MULTIPLE_OF(nBlockXSize, nMaxBlockXSize) &&
2684
IS_MULTIPLE_OF(nSrcBlockXSize, nMaxBlockXSize) &&
2685
IS_MULTIPLE_OF(nBlockYSize, nMaxBlockYSize) &&
2686
IS_MULTIPLE_OF(nSrcBlockYSize, nMaxBlockYSize))
2688
if (((GIntBig)nMaxBlockXSize) * nMaxBlockYSize * nPixelSize <=
2689
(GIntBig)nTargetSwathSize)
2691
nSwathCols = nTargetSwathSize / (nMaxBlockYSize * nPixelSize);
2692
nSwathCols = ROUND_TO(nSwathCols, nMaxBlockXSize);
2693
if (nSwathCols == 0)
2694
nSwathCols = nMaxBlockXSize;
2695
if (nSwathCols > nXSize)
2696
nSwathCols = nXSize;
2697
nSwathLines = nMaxBlockYSize;
2699
if (((GIntBig)nSwathCols) * nSwathLines * nPixelSize >
2700
(GIntBig)nTargetSwathSize)
2702
nSwathCols = nXSize;
2703
nSwathLines = nBlockYSize;
2708
int nMemoryPerCol = nSwathCols * nPixelSize;
2710
/* Do the computation on a big int since for example when translating */
2711
/* the JPL WMS layer, we overflow 32 bits*/
2712
GIntBig nSwathBufSize = (GIntBig)nMemoryPerCol * nSwathLines;
2713
if (nSwathBufSize > (GIntBig)nTargetSwathSize)
2715
nSwathLines = nTargetSwathSize / nMemoryPerCol;
2716
if (nSwathLines == 0)
2720
"GDALCopyWholeRasterGetSwathSize(): adjusting to %d line swath "
2721
"since requirement (%d * %d bytes) exceed target swath size (%d bytes) ",
2722
nSwathLines, nBlockYSize, nMemoryPerCol, nTargetSwathSize);
2724
// If we are processing single scans, try to handle several at once.
2725
// If we are handling swaths already, only grow the swath if a row
2726
// of blocks is substantially less than our target buffer size.
2727
else if( nSwathLines == 1
2728
|| nMemoryPerCol * nSwathLines < nTargetSwathSize / 10 )
2730
nSwathLines = MIN(nYSize,MAX(1,nTargetSwathSize/nMemoryPerCol));
2732
/* If possible try to align to source and target block height */
2733
if ((nSwathLines % nMaxBlockYSize) != 0 && nSwathLines > nMaxBlockYSize &&
2734
IS_MULTIPLE_OF(nBlockYSize, nMaxBlockYSize) &&
2735
IS_MULTIPLE_OF(nSrcBlockYSize, nMaxBlockYSize))
2736
nSwathLines = ROUND_TO(nSwathLines, nMaxBlockYSize);
2740
if (bDstIsCompressed)
2742
if (nSwathLines < nBlockYSize)
2744
nSwathLines = nBlockYSize;
2746
/* Number of pixels that can be read/write simultaneously */
2747
nSwathCols = nTargetSwathSize / (nSwathLines * nPixelSize);
2748
nSwathCols = ROUND_TO(nSwathCols, nBlockXSize);
2749
if (nSwathCols == 0)
2750
nSwathCols = nBlockXSize;
2751
if (nSwathCols > nXSize)
2752
nSwathCols = nXSize;
2755
"GDALCopyWholeRasterGetSwathSize(): because of compression and too high block,\n"
2756
"use partial width at one time");
2758
else if ((nSwathLines % nBlockYSize) != 0)
2760
/* Round on a multiple of nBlockYSize */
2761
nSwathLines = ROUND_TO(nSwathLines, nBlockYSize);
2763
"GDALCopyWholeRasterGetSwathSize(): because of compression, \n"
2764
"round nSwathLines to block height : %d", nSwathLines);
2768
*pnSwathCols = nSwathCols;
2769
*pnSwathLines = nSwathLines;
2772
/************************************************************************/
2591
2773
/* GDALDatasetCopyWholeRaster() */
2592
2774
/************************************************************************/
2704
2885
/* -------------------------------------------------------------------- */
2705
2886
/* What will our swath size be? */
2706
2887
/* -------------------------------------------------------------------- */
2707
/* When writing interleaved data in a compressed format, we want to be sure */
2708
/* that each block will only be written once, so the swath size must not be */
2709
/* greater than the block cache. */
2710
/* So as the default cache size is 40 MB, 10 MB is a safe value */
2711
int nTargetSwathSize = atoi(CPLGetConfigOption("GDAL_SWATH_SIZE", "10000000"));
2712
if (nTargetSwathSize < 1000000)
2713
nTargetSwathSize = 1000000;
2715
/* But let's check that */
2716
if (bDstIsCompressed && bInterleave && nTargetSwathSize > GDALGetCacheMax())
2718
CPLError(CE_Warning, CPLE_AppDefined,
2719
"When translating into a compressed interleave format, the block cache size (%d) "
2720
"should be at least the size of the swath (%d)", GDALGetCacheMax(), nTargetSwathSize);
2889
int nSwathCols, nSwathLines;
2890
GDALCopyWholeRasterGetSwathSize(poSrcPrototypeBand,
2893
bDstIsCompressed, bInterleave,
2894
&nSwathCols, &nSwathLines);
2725
2896
int nPixelSize = (GDALGetDataTypeSize(eDT) / 8);
2726
2897
if( bInterleave)
2727
2898
nPixelSize *= nBandCount;
2729
// aim for one row of blocks. Do not settle for less.
2730
int nSwathCols = nXSize;
2731
int nSwathLines = nBlockYSize;
2733
int nMemoryPerLine = nXSize * nPixelSize;
2735
/* Do the computation on a big int since for example when translating */
2736
/* the JPL WMS layer, we overflow 32 bits*/
2737
GIntBig nSwathBufSize = (GIntBig)nMemoryPerLine * nSwathLines;
2738
if (nSwathBufSize > (GIntBig)nTargetSwathSize)
2740
nSwathLines = nTargetSwathSize / nMemoryPerLine;
2741
if (nSwathLines == 0)
2744
"GDALDatasetCopyWholeRaster(): adjusting to %d line swath "
2745
"since requirement (%d * %d bytes) exceed target swath size (%d bytes) ",
2746
nSwathLines, nBlockYSize, nMemoryPerLine, nTargetSwathSize);
2748
// If we are processing single scans, try to handle several at once.
2749
// If we are handling swaths already, only grow the swath if a row
2750
// of blocks is substantially less than our target buffer size.
2751
else if( nSwathLines == 1
2752
|| nMemoryPerLine * nSwathLines < nTargetSwathSize / 10 )
2753
nSwathLines = MIN(nYSize,MAX(1,nTargetSwathSize/nMemoryPerLine));
2756
if (bDstIsCompressed)
2758
if (nSwathLines < nBlockYSize)
2760
nSwathLines = nBlockYSize;
2762
/* Number of pixels that can be read/write simultaneously */
2763
nSwathCols = nTargetSwathSize / (nSwathLines * nPixelSize);
2764
nSwathCols = (nSwathCols / nBlockXSize) * nBlockXSize;
2765
if (nSwathCols == 0)
2766
nSwathCols = nBlockXSize;
2767
if (nSwathCols > nXSize)
2768
nSwathCols = nXSize;
2771
"GDALDatasetCopyWholeRaster(): because of compression and too high block,\n"
2772
"use partial width at one time");
2776
/* Round on a multiple of nBlockYSize */
2777
nSwathLines = (nSwathLines / nBlockYSize) * nBlockYSize;
2779
"GDALDatasetCopyWholeRaster(): because of compression, \n"
2780
"round nSwathLines to block height : %d", nSwathLines);
2784
pSwathBuf = VSIMalloc3(nSwathCols, nSwathLines, nPixelSize );
2900
void *pSwathBuf = VSIMalloc3(nSwathCols, nSwathLines, nPixelSize );
2785
2901
if( pSwathBuf == NULL )
2787
2903
CPLError( CE_Failure, CPLE_OutOfMemory,
3022
/************************************************************************/
3023
/* GDALRasterBandCopyWholeRaster() */
3024
/************************************************************************/
3027
* \brief Copy all raster band raster data.
3029
* This function copies the complete raster contents of one band to
3030
* another similarly configured band. The source and destination
3031
* bands must have the same width and height. The bands do not have
3032
* to have the same data type.
3034
* It implements efficient copying, in particular "chunking" the copy in
3035
* substantial blocks.
3037
* Currently the only papszOptions value supported is : "COMPRESSED=YES" to
3038
* force alignment on target dataset block sizes to achieve best compression.
3039
* More options may be supported in the future.
3041
* @param hSrcBand the source band
3042
* @param hDstBand the destination band
3043
* @param papszOptions transfer hints in "StringList" Name=Value format.
3044
* @param pfnProgress progress reporting function.
3045
* @param pProgressData callback data for progress function.
3047
* @return CE_None on success, or CE_Failure on failure.
3050
CPLErr CPL_STDCALL GDALRasterBandCopyWholeRaster(
3051
GDALRasterBandH hSrcBand, GDALRasterBandH hDstBand, char **papszOptions,
3052
GDALProgressFunc pfnProgress, void *pProgressData )
3055
VALIDATE_POINTER1( hSrcBand, "GDALRasterBandCopyWholeRaster", CE_Failure );
3056
VALIDATE_POINTER1( hDstBand, "GDALRasterBandCopyWholeRaster", CE_Failure );
3058
GDALRasterBand *poSrcBand = (GDALRasterBand *) hSrcBand;
3059
GDALRasterBand *poDstBand = (GDALRasterBand *) hDstBand;
3060
CPLErr eErr = CE_None;
3062
if( pfnProgress == NULL )
3063
pfnProgress = GDALDummyProgress;
3065
/* -------------------------------------------------------------------- */
3066
/* Confirm the datasets match in size and band counts. */
3067
/* -------------------------------------------------------------------- */
3068
int nXSize = poSrcBand->GetXSize(),
3069
nYSize = poSrcBand->GetYSize();
3071
if( poDstBand->GetXSize() != nXSize
3072
|| poDstBand->GetYSize() != nYSize )
3074
CPLError( CE_Failure, CPLE_AppDefined,
3075
"Input and output band sizes do not\n"
3076
"match in GDALRasterBandCopyWholeRaster()" );
3080
/* -------------------------------------------------------------------- */
3081
/* Report preliminary (0) progress. */
3082
/* -------------------------------------------------------------------- */
3083
if( !pfnProgress( 0.0, NULL, pProgressData ) )
3085
CPLError( CE_Failure, CPLE_UserInterrupt,
3086
"User terminated CreateCopy()" );
3090
GDALDataType eDT = poDstBand->GetRasterDataType();
3092
/* If the destination is compressed, we must try to write blocks just once, to save */
3093
/* disk space (GTiff case for example), and to avoid data loss (JPEG compression for example) */
3094
int bDstIsCompressed = FALSE;
3095
const char* pszDstCompressed= CSLFetchNameValue( papszOptions, "COMPRESSED" );
3096
if (pszDstCompressed != NULL && CSLTestBoolean(pszDstCompressed))
3097
bDstIsCompressed = TRUE;
3099
/* -------------------------------------------------------------------- */
3100
/* What will our swath size be? */
3101
/* -------------------------------------------------------------------- */
3103
int nSwathCols, nSwathLines;
3104
GDALCopyWholeRasterGetSwathSize(poSrcBand,
3107
bDstIsCompressed, FALSE,
3108
&nSwathCols, &nSwathLines);
3110
int nPixelSize = (GDALGetDataTypeSize(eDT) / 8);
3112
void *pSwathBuf = VSIMalloc3(nSwathCols, nSwathLines, nPixelSize );
3113
if( pSwathBuf == NULL )
3115
CPLError( CE_Failure, CPLE_OutOfMemory,
3116
"Failed to allocate %d*%d*%d byte swath buffer in\n"
3117
"GDALRasterBandCopyWholeRaster()",
3118
nSwathCols, nSwathLines, nPixelSize );
3123
"GDALRasterBandCopyWholeRaster(): %d*%d swaths",
3124
nSwathCols, nSwathLines );
3126
/* ==================================================================== */
3127
/* Band oriented (uninterleaved) case. */
3128
/* ==================================================================== */
3132
for( iY = 0; iY < nYSize && eErr == CE_None; iY += nSwathLines )
3134
int nThisLines = nSwathLines;
3136
if( iY + nThisLines > nYSize )
3137
nThisLines = nYSize - iY;
3139
for( iX = 0; iX < nXSize && eErr == CE_None; iX += nSwathCols )
3141
int nThisCols = nSwathCols;
3143
if( iX + nThisCols > nXSize )
3144
nThisCols = nXSize - iX;
3146
eErr = poSrcBand->RasterIO( GF_Read,
3147
iX, iY, nThisCols, nThisLines,
3148
pSwathBuf, nThisCols, nThisLines,
3151
if( eErr == CE_None )
3152
eErr = poDstBand->RasterIO( GF_Write,
3153
iX, iY, nThisCols, nThisLines,
3154
pSwathBuf, nThisCols, nThisLines,
3159
(iY+nThisLines) / (float) (nYSize),
3160
NULL, pProgressData ) )
3163
CPLError( CE_Failure, CPLE_UserInterrupt,
3164
"User terminated CreateCopy()" );
3169
/* -------------------------------------------------------------------- */
3171
/* -------------------------------------------------------------------- */
3172
CPLFree( pSwathBuf );