~ubuntu-branches/debian/sid/gdal/sid

« back to all changes in this revision

Viewing changes to gcore/rasterio.cpp

  • Committer: Package Import Robot
  • Author(s): Francesco Paolo Lovergine
  • Date: 2012-05-07 15:04:42 UTC
  • mfrom: (5.5.16 experimental)
  • Revision ID: package-import@ubuntu.com-20120507150442-2eks97loeh6rq005
Tags: 1.9.0-1
* Ready for sid, starting transition.
* All symfiles updated to latest builds.
* Added dh_numpy call in debian/rules to depend on numpy ABI.
* Policy bumped to 3.9.3, no changes required.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/******************************************************************************
2
 
 * $Id: rasterio.cpp 18744 2010-02-05 23:06:16Z pvachon $
 
2
 * $Id: rasterio.cpp 22420 2011-05-23 21:23:29Z rouault $
3
3
 *
4
4
 * Project:  GDAL Core
5
5
 * Purpose:  Contains default implementation of GDALRasterBand::IRasterIO()
30
30
 
31
31
#include "gdal_priv.h"
32
32
 
 
33
// Define a list of "C++" compilers that have broken template support or
 
34
// broken scoping so we can fall back on the legacy implementation of
 
35
// GDALCopyWords
 
36
#define NOT_BROKEN_COMPILER \
 
37
        (!(defined(_MSC_VER) && _MSC_VER <= 1200) && !defined(__BORLANDC__) && \
 
38
        !defined(__SUNPRO_CC))
33
39
 
34
 
#if !(defined(_MSC_VER) && _MSC_VER <= 1200)
 
40
#if NOT_BROKEN_COMPILER
35
41
#include <stdexcept>
36
42
#include <limits>
37
43
 
41
47
#endif
42
48
 
43
49
 
44
 
CPL_CVSID("$Id: rasterio.cpp 18744 2010-02-05 23:06:16Z pvachon $");
 
50
CPL_CVSID("$Id: rasterio.cpp 22420 2011-05-23 21:23:29Z rouault $");
45
51
 
46
52
/************************************************************************/
47
53
/*                             IRasterIO()                              */
64
70
    GDALRasterBlock *poBlock = NULL;
65
71
    int         nLBlockX=-1, nLBlockY=-1, iBufYOff, iBufXOff, iSrcY;
66
72
 
 
73
    if( eRWFlag == GF_Write && eFlushBlockErr != CE_None )
 
74
    {
 
75
        CPLError(eFlushBlockErr, CPLE_AppDefined,
 
76
                 "An error occured while writing a dirty block");
 
77
        CPLErr eErr = eFlushBlockErr;
 
78
        eFlushBlockErr = CE_None;
 
79
        return eErr;
 
80
    }
 
81
 
67
82
/* ==================================================================== */
68
83
/*      A common case is the data requested with the destination        */
69
84
/*      is packed, and the block width is the raster width.             */
161
176
    if( (nBufXSize < nXSize || nBufYSize < nYSize)
162
177
        && GetOverviewCount() > 0 && eRWFlag == GF_Read )
163
178
    {
164
 
        if( OverviewRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize, 
165
 
                              pData, nBufXSize, nBufYSize, 
166
 
                              eBufType, nPixelSpace, nLineSpace ) == CE_None )
167
 
            return CE_None;
 
179
        int         nOverview;
 
180
 
 
181
        nOverview =
 
182
            GDALBandGetBestOverviewLevel(this, nXOff, nYOff, nXSize, nYSize,
 
183
                                        nBufXSize, nBufYSize);
 
184
        if (nOverview >= 0)
 
185
        {
 
186
            GDALRasterBand* poOverviewBand = GetOverview(nOverview);
 
187
            if (poOverviewBand == NULL)
 
188
                return CE_Failure;
 
189
 
 
190
            return poOverviewBand->RasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
 
191
                                            pData, nBufXSize, nBufYSize, eBufType,
 
192
                                            nPixelSpace, nLineSpace );
 
193
        }
168
194
    }
169
195
 
170
196
/* ==================================================================== */
664
690
template <class Tin>
665
691
inline void CopyWord(const Tin tValueIn, float &fValueOut)
666
692
{
667
 
    fValueOut = tValueIn;
 
693
    fValueOut = (float) tValueIn;
668
694
}
669
695
 
670
696
template <class Tin>
1066
1092
        {
1067
1093
            if (nDstPixelOffset == 1)
1068
1094
            {
1069
 
                memset(pabyDstWord, *(GByte*)pDstData, nWordCount - 1);
 
1095
                if (nWordCount > 0)
 
1096
                    memset(pabyDstWord, *(GByte*)pDstData, nWordCount);
1070
1097
            }
1071
1098
            else
1072
1099
            {
2088
2115
    for( int iOverview = 0; iOverview < nOverviewCount; iOverview++ )
2089
2116
    {
2090
2117
        GDALRasterBand  *poOverview = poBand->GetOverview( iOverview );
 
2118
        if (poOverview == NULL)
 
2119
            continue;
 
2120
 
2091
2121
        double          dfResolution;
2092
2122
 
2093
2123
        // What resolution is this?
2182
2212
/*      Recast the call in terms of the new raster layer.               */
2183
2213
/* -------------------------------------------------------------------- */
2184
2214
    GDALRasterBand* poOverviewBand = GetOverview(nOverview);
 
2215
    if (poOverviewBand == NULL)
 
2216
        return CE_Failure;
 
2217
 
2185
2218
    return poOverviewBand->RasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
2186
2219
                                     pData, nBufXSize, nBufYSize, eBufType,
2187
2220
                                     nPixelSpace, nLineSpace );
2236
2269
                    poBand->GetOverview(iOverview);
2237
2270
                GDALRasterBand* poOvrFirstBand =
2238
2271
                    poFirstBand->GetOverview(iOverview);
 
2272
                if ( poOvrBand == NULL || poOvrFirstBand == NULL)
 
2273
                    continue;
 
2274
 
2239
2275
                if ( poOvrFirstBand->GetXSize() != poOvrBand->GetXSize() ||
2240
2276
                     poOvrFirstBand->GetYSize() != poOvrBand->GetYSize() )
2241
2277
                {
2588
2624
}
2589
2625
 
2590
2626
/************************************************************************/
 
2627
/*                  GDALCopyWholeRasterGetSwathSize()                   */
 
2628
/************************************************************************/
 
2629
 
 
2630
static void GDALCopyWholeRasterGetSwathSize(GDALRasterBand *poSrcPrototypeBand,
 
2631
                                            GDALRasterBand *poDstPrototypeBand,
 
2632
                                            int nBandCount,
 
2633
                                            int bDstIsCompressed, int bInterleave,
 
2634
                                            int* pnSwathCols, int *pnSwathLines)
 
2635
{
 
2636
    GDALDataType eDT = poDstPrototypeBand->GetRasterDataType();
 
2637
    int nSrcBlockXSize, nSrcBlockYSize;
 
2638
    int nBlockXSize, nBlockYSize;
 
2639
 
 
2640
    int nXSize = poSrcPrototypeBand->GetXSize();
 
2641
    int nYSize = poSrcPrototypeBand->GetYSize();
 
2642
 
 
2643
    poSrcPrototypeBand->GetBlockSize( &nSrcBlockXSize, &nSrcBlockYSize );
 
2644
    poDstPrototypeBand->GetBlockSize( &nBlockXSize, &nBlockYSize );
 
2645
 
 
2646
    int nMaxBlockXSize = MAX(nBlockXSize, nSrcBlockXSize);
 
2647
    int nMaxBlockYSize = MAX(nBlockYSize, nSrcBlockYSize);
 
2648
    
 
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;
 
2659
 
 
2660
    /* But let's check that  */
 
2661
    if (bDstIsCompressed && bInterleave && nTargetSwathSize > GDALGetCacheMax64())
 
2662
    {
 
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);
 
2666
    }
 
2667
 
 
2668
    int nPixelSize = (GDALGetDataTypeSize(eDT) / 8);
 
2669
    if( bInterleave)
 
2670
        nPixelSize *= nBandCount;
 
2671
 
 
2672
    // aim for one row of blocks.  Do not settle for less.
 
2673
    int nSwathCols  = nXSize;
 
2674
    int nSwathLines = nBlockYSize;
 
2675
 
 
2676
#define IS_MULTIPLE_OF(x,y) ((y)%(x) == 0)
 
2677
#define ROUND_TO(x,y) (((x)/(y))*(y))
 
2678
 
 
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))
 
2687
    {
 
2688
        if (((GIntBig)nMaxBlockXSize) * nMaxBlockYSize * nPixelSize <=
 
2689
                                                    (GIntBig)nTargetSwathSize)
 
2690
        {
 
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;
 
2698
 
 
2699
            if (((GIntBig)nSwathCols) * nSwathLines * nPixelSize >
 
2700
                                                    (GIntBig)nTargetSwathSize)
 
2701
            {
 
2702
                nSwathCols  = nXSize;
 
2703
                nSwathLines = nBlockYSize;
 
2704
            }
 
2705
        }
 
2706
    }
 
2707
 
 
2708
    int nMemoryPerCol = nSwathCols * nPixelSize;
 
2709
 
 
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)
 
2714
    {
 
2715
        nSwathLines = nTargetSwathSize / nMemoryPerCol;
 
2716
        if (nSwathLines == 0)
 
2717
            nSwathLines = 1;
 
2718
 
 
2719
        CPLDebug( "GDAL",
 
2720
              "GDALCopyWholeRasterGetSwathSize(): adjusting to %d line swath "
 
2721
              "since requirement (%d * %d bytes) exceed target swath size (%d bytes) ",
 
2722
              nSwathLines, nBlockYSize, nMemoryPerCol, nTargetSwathSize);
 
2723
    }
 
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 )
 
2729
    {
 
2730
        nSwathLines = MIN(nYSize,MAX(1,nTargetSwathSize/nMemoryPerCol));
 
2731
 
 
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);
 
2737
    }
 
2738
 
 
2739
 
 
2740
    if (bDstIsCompressed)
 
2741
    {
 
2742
        if (nSwathLines < nBlockYSize)
 
2743
        {
 
2744
            nSwathLines = nBlockYSize;
 
2745
 
 
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;
 
2753
 
 
2754
            CPLDebug( "GDAL",
 
2755
              "GDALCopyWholeRasterGetSwathSize(): because of compression and too high block,\n"
 
2756
              "use partial width at one time");
 
2757
        }
 
2758
        else if ((nSwathLines % nBlockYSize) != 0)
 
2759
        {
 
2760
            /* Round on a multiple of nBlockYSize */
 
2761
            nSwathLines = ROUND_TO(nSwathLines, nBlockYSize);
 
2762
            CPLDebug( "GDAL",
 
2763
              "GDALCopyWholeRasterGetSwathSize(): because of compression, \n"
 
2764
              "round nSwathLines to block height : %d", nSwathLines);
 
2765
        }
 
2766
    }
 
2767
 
 
2768
    *pnSwathCols = nSwathCols;
 
2769
    *pnSwathLines = nSwathLines;
 
2770
}
 
2771
 
 
2772
/************************************************************************/
2591
2773
/*                     GDALDatasetCopyWholeRaster()                     */
2592
2774
/************************************************************************/
2593
2775
 
2604
2786
 * in particular "chunking" the copy in substantial blocks and, if appropriate,
2605
2787
 * performing the transfer in a pixel interleaved fashion.
2606
2788
 *
2607
 
 * Currently the only papszOptions value supported is "INTERLEAVE=PIXEL"
2608
 
 * to force pixel interleaved operation.  More options may be supported in
 
2789
 * Currently the only papszOptions value supported are : "INTERLEAVE=PIXEL"
 
2790
 * to force pixel interleaved operation and "COMPRESSED=YES" to force alignment
 
2791
 * on target dataset block sizes to achieve best compression.  More options may be supported in
2609
2792
 * the future.  
2610
2793
 *
2611
2794
 * @param hSrcDS the source dataset
2665
2848
/* -------------------------------------------------------------------- */
2666
2849
    if( nBandCount == 0 )
2667
2850
        return CE_None;
2668
 
    
2669
 
    GDALRasterBand *poPrototypeBand = poDstDS->GetRasterBand(1);
2670
 
    GDALDataType eDT = poPrototypeBand->GetRasterDataType();
2671
 
    int nBlockXSize, nBlockYSize;
2672
2851
 
2673
 
    poPrototypeBand->GetBlockSize( &nBlockXSize, &nBlockYSize );
 
2852
    GDALRasterBand *poSrcPrototypeBand = poSrcDS->GetRasterBand(1);
 
2853
    GDALRasterBand *poDstPrototypeBand = poDstDS->GetRasterBand(1);
 
2854
    GDALDataType eDT = poDstPrototypeBand->GetRasterDataType();
2674
2855
 
2675
2856
/* -------------------------------------------------------------------- */
2676
2857
/*      Do we want to try and do the operation in a pixel               */
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;
2714
 
 
2715
 
    /* But let's check that  */
2716
 
    if (bDstIsCompressed && bInterleave && nTargetSwathSize > GDALGetCacheMax())
2717
 
    {
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);
2721
 
    }
2722
 
 
2723
 
    void *pSwathBuf;
 
2888
 
 
2889
    int nSwathCols, nSwathLines;
 
2890
    GDALCopyWholeRasterGetSwathSize(poSrcPrototypeBand,
 
2891
                                    poDstPrototypeBand,
 
2892
                                    nBandCount,
 
2893
                                    bDstIsCompressed, bInterleave,
 
2894
                                    &nSwathCols, &nSwathLines);
2724
2895
 
2725
2896
    int nPixelSize = (GDALGetDataTypeSize(eDT) / 8);
2726
2897
    if( bInterleave)
2727
2898
        nPixelSize *= nBandCount;
2728
2899
 
2729
 
    // aim for one row of blocks.  Do not settle for less.
2730
 
    int nSwathCols  = nXSize;
2731
 
    int nSwathLines = nBlockYSize;
2732
 
 
2733
 
    int nMemoryPerLine = nXSize * nPixelSize;
2734
 
 
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)
2739
 
    {
2740
 
        nSwathLines = nTargetSwathSize / nMemoryPerLine;
2741
 
        if (nSwathLines == 0)
2742
 
            nSwathLines = 1;
2743
 
        CPLDebug( "GDAL", 
2744
 
              "GDALDatasetCopyWholeRaster(): adjusting to %d line swath "
2745
 
              "since requirement (%d * %d bytes) exceed target swath size (%d bytes) ",
2746
 
              nSwathLines, nBlockYSize, nMemoryPerLine, nTargetSwathSize);
2747
 
    }
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));
2754
 
 
2755
 
 
2756
 
    if (bDstIsCompressed)
2757
 
    {
2758
 
        if (nSwathLines < nBlockYSize)
2759
 
        {
2760
 
            nSwathLines = nBlockYSize;
2761
 
 
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;
2769
 
 
2770
 
            CPLDebug( "GDAL", 
2771
 
              "GDALDatasetCopyWholeRaster(): because of compression and too high block,\n"
2772
 
              "use partial width at one time");
2773
 
        }
2774
 
        else
2775
 
        {
2776
 
            /* Round on a multiple of nBlockYSize */
2777
 
            nSwathLines = (nSwathLines / nBlockYSize) * nBlockYSize;
2778
 
            CPLDebug( "GDAL", 
2779
 
              "GDALDatasetCopyWholeRaster(): because of compression, \n"
2780
 
              "round nSwathLines to block height : %d", nSwathLines);
2781
 
        }
2782
 
    }
2783
 
 
2784
 
    pSwathBuf = VSIMalloc3(nSwathCols, nSwathLines, nPixelSize );
 
2900
    void *pSwathBuf = VSIMalloc3(nSwathCols, nSwathLines, nPixelSize );
2785
2901
    if( pSwathBuf == NULL )
2786
2902
    {
2787
2903
        CPLError( CE_Failure, CPLE_OutOfMemory,
2901
3017
 
2902
3018
    return eErr;
2903
3019
}
 
3020
 
 
3021
 
 
3022
/************************************************************************/
 
3023
/*                     GDALRasterBandCopyWholeRaster()                  */
 
3024
/************************************************************************/
 
3025
 
 
3026
/**
 
3027
 * \brief Copy all raster band raster data.
 
3028
 *
 
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.
 
3033
 *
 
3034
 * It implements efficient copying, in particular "chunking" the copy in
 
3035
 * substantial blocks.
 
3036
 *
 
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.
 
3040
 *
 
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.
 
3046
 *
 
3047
 * @return CE_None on success, or CE_Failure on failure.
 
3048
 */
 
3049
 
 
3050
CPLErr CPL_STDCALL GDALRasterBandCopyWholeRaster(
 
3051
    GDALRasterBandH hSrcBand, GDALRasterBandH hDstBand, char **papszOptions,
 
3052
    GDALProgressFunc pfnProgress, void *pProgressData )
 
3053
 
 
3054
{
 
3055
    VALIDATE_POINTER1( hSrcBand, "GDALRasterBandCopyWholeRaster", CE_Failure );
 
3056
    VALIDATE_POINTER1( hDstBand, "GDALRasterBandCopyWholeRaster", CE_Failure );
 
3057
 
 
3058
    GDALRasterBand *poSrcBand = (GDALRasterBand *) hSrcBand;
 
3059
    GDALRasterBand *poDstBand = (GDALRasterBand *) hDstBand;
 
3060
    CPLErr eErr = CE_None;
 
3061
 
 
3062
    if( pfnProgress == NULL )
 
3063
        pfnProgress = GDALDummyProgress;
 
3064
 
 
3065
/* -------------------------------------------------------------------- */
 
3066
/*      Confirm the datasets match in size and band counts.             */
 
3067
/* -------------------------------------------------------------------- */
 
3068
    int nXSize = poSrcBand->GetXSize(),
 
3069
        nYSize = poSrcBand->GetYSize();
 
3070
 
 
3071
    if( poDstBand->GetXSize() != nXSize
 
3072
        || poDstBand->GetYSize() != nYSize )
 
3073
    {
 
3074
        CPLError( CE_Failure, CPLE_AppDefined,
 
3075
                  "Input and output band sizes do not\n"
 
3076
                  "match in GDALRasterBandCopyWholeRaster()" );
 
3077
        return CE_Failure;
 
3078
    }
 
3079
 
 
3080
/* -------------------------------------------------------------------- */
 
3081
/*      Report preliminary (0) progress.                                */
 
3082
/* -------------------------------------------------------------------- */
 
3083
    if( !pfnProgress( 0.0, NULL, pProgressData ) )
 
3084
    {
 
3085
        CPLError( CE_Failure, CPLE_UserInterrupt,
 
3086
                  "User terminated CreateCopy()" );
 
3087
        return CE_Failure;
 
3088
    }
 
3089
 
 
3090
    GDALDataType eDT = poDstBand->GetRasterDataType();
 
3091
 
 
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;
 
3098
 
 
3099
/* -------------------------------------------------------------------- */
 
3100
/*      What will our swath size be?                                    */
 
3101
/* -------------------------------------------------------------------- */
 
3102
 
 
3103
    int nSwathCols, nSwathLines;
 
3104
    GDALCopyWholeRasterGetSwathSize(poSrcBand,
 
3105
                                    poDstBand,
 
3106
                                    1,
 
3107
                                    bDstIsCompressed, FALSE,
 
3108
                                    &nSwathCols, &nSwathLines);
 
3109
 
 
3110
    int nPixelSize = (GDALGetDataTypeSize(eDT) / 8);
 
3111
 
 
3112
    void *pSwathBuf = VSIMalloc3(nSwathCols, nSwathLines, nPixelSize );
 
3113
    if( pSwathBuf == NULL )
 
3114
    {
 
3115
        CPLError( CE_Failure, CPLE_OutOfMemory,
 
3116
                "Failed to allocate %d*%d*%d byte swath buffer in\n"
 
3117
                "GDALRasterBandCopyWholeRaster()",
 
3118
                nSwathCols, nSwathLines, nPixelSize );
 
3119
        return CE_Failure;
 
3120
    }
 
3121
 
 
3122
    CPLDebug( "GDAL",
 
3123
            "GDALRasterBandCopyWholeRaster(): %d*%d swaths",
 
3124
            nSwathCols, nSwathLines );
 
3125
 
 
3126
/* ==================================================================== */
 
3127
/*      Band oriented (uninterleaved) case.                             */
 
3128
/* ==================================================================== */
 
3129
 
 
3130
    int iX, iY;
 
3131
 
 
3132
    for( iY = 0; iY < nYSize && eErr == CE_None; iY += nSwathLines )
 
3133
    {
 
3134
        int nThisLines = nSwathLines;
 
3135
 
 
3136
        if( iY + nThisLines > nYSize )
 
3137
            nThisLines = nYSize - iY;
 
3138
 
 
3139
        for( iX = 0; iX < nXSize && eErr == CE_None; iX += nSwathCols )
 
3140
        {
 
3141
            int nThisCols = nSwathCols;
 
3142
 
 
3143
            if( iX + nThisCols > nXSize )
 
3144
                nThisCols = nXSize - iX;
 
3145
 
 
3146
            eErr = poSrcBand->RasterIO( GF_Read,
 
3147
                                    iX, iY, nThisCols, nThisLines,
 
3148
                                    pSwathBuf, nThisCols, nThisLines,
 
3149
                                    eDT, 0, 0 );
 
3150
 
 
3151
            if( eErr == CE_None )
 
3152
                eErr = poDstBand->RasterIO( GF_Write,
 
3153
                                        iX, iY, nThisCols, nThisLines,
 
3154
                                        pSwathBuf, nThisCols, nThisLines,
 
3155
                                        eDT, 0, 0 );
 
3156
 
 
3157
            if( eErr == CE_None
 
3158
                && !pfnProgress(
 
3159
                    (iY+nThisLines) / (float) (nYSize),
 
3160
                    NULL, pProgressData ) )
 
3161
            {
 
3162
                eErr = CE_Failure;
 
3163
                CPLError( CE_Failure, CPLE_UserInterrupt,
 
3164
                        "User terminated CreateCopy()" );
 
3165
            }
 
3166
        }
 
3167
    }
 
3168
 
 
3169
/* -------------------------------------------------------------------- */
 
3170
/*      Cleanup                                                         */
 
3171
/* -------------------------------------------------------------------- */
 
3172
    CPLFree( pSwathBuf );
 
3173
 
 
3174
    return eErr;
 
3175
}