LCOV - code coverage report
Current view: directory - frmts/vrt - vrtwarped.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 318 269 84.6 %
Date: 2010-01-09 Functions: 25 24 96.0 %

       1                 : /******************************************************************************
       2                 :  * $Id: vrtwarped.cpp 17852 2009-10-18 11:15:09Z rouault $
       3                 :  *
       4                 :  * Project:  Virtual GDAL Datasets
       5                 :  * Purpose:  Implementation of VRTWarpedRasterBand *and VRTWarpedDataset.
       6                 :  * Author:   Frank Warmerdam <warmerdam@pobox.com>
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2004, Frank Warmerdam <warmerdam@pobox.com>
      10                 :  *
      11                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      12                 :  * copy of this software and associated documentation files (the "Software"),
      13                 :  * to deal in the Software without restriction, including without limitation
      14                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15                 :  * and/or sell copies of the Software, and to permit persons to whom the
      16                 :  * Software is furnished to do so, subject to the following conditions:
      17                 :  *
      18                 :  * The above copyright notice and this permission notice shall be included
      19                 :  * in all copies or substantial portions of the Software.
      20                 :  *
      21                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27                 :  * DEALINGS IN THE SOFTWARE.
      28                 :  ****************************************************************************/
      29                 : 
      30                 : #include "vrtdataset.h"
      31                 : #include "cpl_minixml.h"
      32                 : #include "cpl_string.h"
      33                 : #include "gdalwarper.h"
      34                 : #include <cassert>
      35                 : 
      36                 : CPL_CVSID("$Id: vrtwarped.cpp 17852 2009-10-18 11:15:09Z rouault $");
      37                 : 
      38                 : /************************************************************************/
      39                 : /*                      GDALAutoCreateWarpedVRT()                       */
      40                 : /************************************************************************/
      41                 : 
      42                 : /**
      43                 :  * Create virtual warped dataset automatically.
      44                 :  *
      45                 :  * This function will create a warped virtual file representing the 
      46                 :  * input image warped into the target coordinate system.  A GenImgProj
      47                 :  * transformation is created to accomplish any required GCP/Geotransform
      48                 :  * warp and reprojection to the target coordinate system.  The output virtual
      49                 :  * dataset will be "northup" in the target coordinate system.   The
      50                 :  * GDALSuggestedWarpOutput() function is used to determine the bounds and
      51                 :  * resolution of the output virtual file which should be large enough to 
      52                 :  * include all the input image 
      53                 :  *
      54                 :  * Note that the constructed GDALDatasetH will acquire one or more references 
      55                 :  * to the passed in hSrcDS.  Reference counting semantics on the source 
      56                 :  * dataset should be honoured.  That is, don't just GDALClose() it unless it 
      57                 :  * was opened with GDALOpenShared(). 
      58                 :  *
      59                 :  * The returned dataset will have no associated filename for itself.  If you
      60                 :  * want to write the virtual dataset description to a file, use the
      61                 :  * GDALSetDescription() function (or SetDescription() method) on the dataset
      62                 :  * to assign a filename before it is closed.  
      63                 :  *
      64                 :  * @param hSrcDS The source dataset. 
      65                 :  *
      66                 :  * @param pszSrcWKT The coordinate system of the source image.  If NULL, it 
      67                 :  * will be read from the source image. 
      68                 :  *
      69                 :  * @param pszDstWKT The coordinate system to convert to.  If NULL no change 
      70                 :  * of coordinate system will take place.  
      71                 :  *
      72                 :  * @param eResampleAlg One of GRA_NearestNeighbour, GRA_Bilinear, GRA_Cubic or 
      73                 :  * GRA_CubicSpline.  Controls the sampling method used. 
      74                 :  *
      75                 :  * @param dfMaxError Maximum error measured in input pixels that is allowed in 
      76                 :  * approximating the transformation (0.0 for exact calculations).
      77                 :  *
      78                 :  * @param psOptions Additional warp options, normally NULL.
      79                 :  *
      80                 :  * @return NULL on failure, or a new virtual dataset handle on success.
      81                 :  */
      82                 : 
      83                 : GDALDatasetH CPL_STDCALL 
      84               1 : GDALAutoCreateWarpedVRT( GDALDatasetH hSrcDS, 
      85                 :                          const char *pszSrcWKT,
      86                 :                          const char *pszDstWKT,
      87                 :                          GDALResampleAlg eResampleAlg, 
      88                 :                          double dfMaxError, 
      89                 :                          const GDALWarpOptions *psOptionsIn )
      90                 :     
      91                 : {
      92                 :     GDALWarpOptions *psWO;
      93                 :     int i;
      94                 : 
      95               1 :     VALIDATE_POINTER1( hSrcDS, "GDALAutoCreateWarpedVRT", NULL );
      96                 : 
      97                 : /* -------------------------------------------------------------------- */
      98                 : /*      Populate the warp options.                                      */
      99                 : /* -------------------------------------------------------------------- */
     100               1 :     if( psOptionsIn != NULL )
     101               0 :         psWO = GDALCloneWarpOptions( psOptionsIn );
     102                 :     else
     103               1 :         psWO = GDALCreateWarpOptions();
     104                 : 
     105               1 :     psWO->eResampleAlg = eResampleAlg;
     106                 : 
     107               1 :     psWO->hSrcDS = hSrcDS;
     108                 : 
     109               1 :     psWO->nBandCount = GDALGetRasterCount( hSrcDS );
     110               1 :     psWO->panSrcBands = (int *) CPLMalloc(sizeof(int) * psWO->nBandCount);
     111               1 :     psWO->panDstBands = (int *) CPLMalloc(sizeof(int) * psWO->nBandCount);
     112                 : 
     113               4 :     for( i = 0; i < psWO->nBandCount; i++ )
     114                 :     {
     115               3 :         psWO->panSrcBands[i] = i+1;
     116               3 :         psWO->panDstBands[i] = i+1;
     117                 :     }
     118                 : 
     119                 :     /* TODO: should fill in no data where available */
     120                 : 
     121                 : /* -------------------------------------------------------------------- */
     122                 : /*      Create the transformer.                                         */
     123                 : /* -------------------------------------------------------------------- */
     124               1 :     psWO->pfnTransformer = GDALGenImgProjTransform;
     125                 :     psWO->pTransformerArg = 
     126                 :         GDALCreateGenImgProjTransformer( psWO->hSrcDS, pszSrcWKT, 
     127                 :                                          NULL, pszDstWKT,
     128               1 :                                          TRUE, 1.0, 0 );
     129                 : 
     130               1 :     if( psWO->pTransformerArg == NULL )
     131                 :     {
     132               0 :         GDALDestroyWarpOptions( psWO );
     133               0 :         return NULL;
     134                 :     }
     135                 : 
     136                 : /* -------------------------------------------------------------------- */
     137                 : /*      Figure out the desired output bounds and resolution.            */
     138                 : /* -------------------------------------------------------------------- */
     139                 :     double adfDstGeoTransform[6];
     140                 :     int    nDstPixels, nDstLines;
     141                 :     CPLErr eErr;
     142                 : 
     143                 :     eErr = 
     144                 :         GDALSuggestedWarpOutput( hSrcDS, psWO->pfnTransformer, 
     145                 :                                  psWO->pTransformerArg, 
     146               1 :                                  adfDstGeoTransform, &nDstPixels, &nDstLines );
     147                 : 
     148                 : /* -------------------------------------------------------------------- */
     149                 : /*      Update the transformer to include an output geotransform        */
     150                 : /*      back to pixel/line coordinates.                                 */
     151                 : /*                                                                      */
     152                 : /* -------------------------------------------------------------------- */
     153                 :     GDALSetGenImgProjTransformerDstGeoTransform( 
     154               1 :         psWO->pTransformerArg, adfDstGeoTransform );
     155                 : 
     156                 : /* -------------------------------------------------------------------- */
     157                 : /*      Do we want to apply an approximating transformation?            */
     158                 : /* -------------------------------------------------------------------- */
     159               1 :     if( dfMaxError > 0.0 )
     160                 :     {
     161                 :         psWO->pTransformerArg = 
     162                 :             GDALCreateApproxTransformer( psWO->pfnTransformer, 
     163                 :                                          psWO->pTransformerArg, 
     164               0 :                                          dfMaxError );
     165               0 :         psWO->pfnTransformer = GDALApproxTransform;
     166                 :     }
     167                 : 
     168                 : /* -------------------------------------------------------------------- */
     169                 : /*      Create the VRT file.                                            */
     170                 : /* -------------------------------------------------------------------- */
     171                 :     GDALDatasetH hDstDS;
     172                 : 
     173                 :     hDstDS = GDALCreateWarpedVRT( hSrcDS, nDstPixels, nDstLines, 
     174               1 :                                   adfDstGeoTransform, psWO );
     175                 : 
     176               1 :     GDALDestroyWarpOptions( psWO );
     177                 : 
     178               1 :     if( pszDstWKT != NULL )
     179               0 :         GDALSetProjection( hDstDS, pszDstWKT );
     180               1 :     else if( pszSrcWKT != NULL )
     181               0 :         GDALSetProjection( hDstDS, pszDstWKT );
     182               1 :     else if( GDALGetGCPCount( hSrcDS ) > 0 )
     183               1 :         GDALSetProjection( hDstDS, GDALGetGCPProjection( hSrcDS ) );
     184                 :     else 
     185               0 :         GDALSetProjection( hDstDS, GDALGetProjectionRef( hSrcDS ) );
     186                 : 
     187               1 :     return hDstDS;
     188                 : }
     189                 : 
     190                 : /************************************************************************/
     191                 : /*                        GDALCreateWarpedVRT()                         */
     192                 : /************************************************************************/
     193                 : 
     194                 : /**
     195                 :  * Create virtual warped dataset.
     196                 :  *
     197                 :  * This function will create a warped virtual file representing the 
     198                 :  * input image warped based on a provided transformation.  Output bounds
     199                 :  * and resolution are provided explicitly.
     200                 :  *
     201                 :  * Note that the constructed GDALDatasetH will acquire one or more references 
     202                 :  * to the passed in hSrcDS.  Reference counting semantics on the source 
     203                 :  * dataset should be honoured.  That is, don't just GDALClose() it unless it 
     204                 :  * was opened with GDALOpenShared(). 
     205                 :  *
     206                 :  * @param hSrcDS The source dataset. 
     207                 :  *
     208                 :  * @param nPixels Width of the virtual warped dataset to create
     209                 :  *
     210                 :  * @param nLines Height of the virtual warped dataset to create
     211                 :  *
     212                 :  * @param padfGeoTransform Geotransform matrix of the virtual warped dataset to create
     213                 :  *
     214                 :  * @param psOptions Warp options. Must be different from NULL.
     215                 :  *
     216                 :  * @return NULL on failure, or a new virtual dataset handle on success.
     217                 :  */
     218                 : 
     219                 : GDALDatasetH CPL_STDCALL
     220               1 : GDALCreateWarpedVRT( GDALDatasetH hSrcDS, 
     221                 :                      int nPixels, int nLines, double *padfGeoTransform,
     222                 :                      GDALWarpOptions *psOptions )
     223                 :     
     224                 : {
     225               1 :     VALIDATE_POINTER1( hSrcDS, "GDALCreateWarpedVRT", NULL );
     226                 : 
     227                 : /* -------------------------------------------------------------------- */
     228                 : /*      Create the VRTDataset and populate it with bands.               */
     229                 : /* -------------------------------------------------------------------- */
     230               1 :     VRTWarpedDataset *poDS = new VRTWarpedDataset( nPixels, nLines );
     231                 :     int i;
     232                 : 
     233               1 :     psOptions->hDstDS = (GDALDatasetH) poDS;
     234                 : 
     235               1 :     poDS->SetGeoTransform( padfGeoTransform );
     236                 : 
     237               4 :     for( i = 0; i < psOptions->nBandCount; i++ )
     238                 :     {
     239                 :         VRTWarpedRasterBand *poBand;
     240                 :         GDALRasterBand *poSrcBand = (GDALRasterBand *) 
     241               3 :             GDALGetRasterBand( hSrcDS, i+1 );
     242                 : 
     243               3 :         poDS->AddBand( poSrcBand->GetRasterDataType(), NULL );
     244                 : 
     245               3 :         poBand = (VRTWarpedRasterBand *) poDS->GetRasterBand( i+1 );
     246               3 :         poBand->CopyCommonInfoFrom( poSrcBand );
     247                 :     }
     248                 : 
     249                 : /* -------------------------------------------------------------------- */
     250                 : /*      Initialize the warp on the VRTWarpedDataset.                    */
     251                 : /* -------------------------------------------------------------------- */
     252               1 :     poDS->Initialize( psOptions );
     253                 :     
     254               1 :     return (GDALDatasetH) poDS;
     255                 : }
     256                 : 
     257                 : /************************************************************************/
     258                 : /* ==================================================================== */
     259                 : /*                          VRTWarpedDataset                            */
     260                 : /* ==================================================================== */
     261                 : /************************************************************************/
     262                 : 
     263                 : /************************************************************************/
     264                 : /*                          VRTWarpedDataset()                          */
     265                 : /************************************************************************/
     266                 : 
     267              39 : VRTWarpedDataset::VRTWarpedDataset( int nXSize, int nYSize )
     268              39 :         : VRTDataset( nXSize, nYSize )
     269                 : 
     270                 : {
     271              39 :     poWarper = NULL;
     272              39 :     nBlockXSize = 512;
     273              39 :     nBlockYSize = 128;
     274              39 :     eAccess = GA_Update;
     275                 : 
     276              39 :     nOverviewCount = 0;
     277              39 :     papoOverviews = NULL;
     278              39 : }
     279                 : 
     280                 : /************************************************************************/
     281                 : /*                         ~VRTWarpedDataset()                          */
     282                 : /************************************************************************/
     283                 : 
     284              78 : VRTWarpedDataset::~VRTWarpedDataset()
     285                 : 
     286                 : {
     287              39 :     FlushCache();
     288                 : 
     289                 : /* -------------------------------------------------------------------- */
     290                 : /*      Cleanup overviews.                                              */
     291                 : /* -------------------------------------------------------------------- */
     292                 :     int iOverview;
     293                 : 
     294              41 :     for( iOverview = 0; iOverview < nOverviewCount; iOverview++ )
     295                 :     {
     296               2 :         GDALDatasetH hDS = (GDALDatasetH) papoOverviews[iOverview];
     297                 : 
     298               2 :         if( GDALDereferenceDataset( hDS ) < 1 )
     299                 :         {
     300               2 :             GDALReferenceDataset( hDS );
     301               2 :             GDALClose( hDS );
     302                 :         }
     303                 :     }
     304                 : 
     305              39 :     CPLFree( papoOverviews );
     306                 : 
     307                 : /* -------------------------------------------------------------------- */
     308                 : /*      Cleanup warper if one is in effect.                             */
     309                 : /* -------------------------------------------------------------------- */
     310              39 :     if( poWarper != NULL )
     311                 :     {
     312              39 :         const GDALWarpOptions *psWO = poWarper->GetOptions();
     313                 : 
     314                 : /* -------------------------------------------------------------------- */
     315                 : /*      We take care to only call GDALClose() on psWO->hSrcDS if the    */
     316                 : /*      reference count drops to zero.  This is makes it so that we     */
     317                 : /*      can operate reference counting semantics more-or-less           */
     318                 : /*      properly even if the dataset isn't open in shared mode,         */
     319                 : /*      though we require that the caller also honour the reference     */
     320                 : /*      counting semantics even though it isn't a shared dataset.       */
     321                 : /* -------------------------------------------------------------------- */
     322              39 :         if( psWO->hSrcDS != NULL )
     323                 :         {
     324              39 :             if( GDALDereferenceDataset( psWO->hSrcDS ) < 1 )
     325                 :             {
     326              35 :                 GDALReferenceDataset( psWO->hSrcDS );
     327              35 :                 GDALClose( psWO->hSrcDS );
     328                 :             }
     329                 :         }
     330                 : 
     331                 : /* -------------------------------------------------------------------- */
     332                 : /*      We are responsible for cleaning up the transformer outselves.   */
     333                 : /* -------------------------------------------------------------------- */
     334              39 :         if( psWO->pTransformerArg != NULL )
     335              39 :             GDALDestroyTransformer( psWO->pTransformerArg );
     336                 : 
     337              39 :         delete poWarper;
     338                 :     }
     339              78 : }
     340                 : 
     341                 : /************************************************************************/
     342                 : /*                             Initialize()                             */
     343                 : /*                                                                      */
     344                 : /*      Initialize a dataset from passed in warp options.               */
     345                 : /************************************************************************/
     346                 : 
     347               5 : CPLErr VRTWarpedDataset::Initialize( void *psWO )
     348                 : 
     349                 : {
     350               5 :     if( poWarper != NULL )
     351               0 :         delete poWarper;
     352                 : 
     353               5 :     poWarper = new GDALWarpOperation();
     354                 : 
     355                 :     // The act of initializing this warped dataset with this warp options
     356                 :     // will result in our assuming ownership of a reference to the
     357                 :     // hSrcDS.
     358                 : 
     359               5 :     if( ((GDALWarpOptions *) psWO)->hSrcDS != NULL )
     360               5 :         GDALReferenceDataset( ((GDALWarpOptions *) psWO)->hSrcDS );
     361                 : 
     362               5 :     return poWarper->Initialize( (GDALWarpOptions *) psWO );
     363                 : }
     364                 : 
     365                 : /************************************************************************/
     366                 : /*                            GetFileList()                             */
     367                 : /************************************************************************/
     368                 : 
     369               0 : char** VRTWarpedDataset::GetFileList()
     370                 : {
     371               0 :     char** papszFileList = GDALDataset::GetFileList();
     372                 :     
     373               0 :     if( poWarper != NULL )
     374                 :     {
     375               0 :         const GDALWarpOptions *psWO = poWarper->GetOptions();
     376                 :         const char* pszFilename;
     377                 :         
     378               0 :         if( psWO->hSrcDS != NULL &&
     379                 :             (pszFilename =
     380               0 :                     ((GDALDataset*)psWO->hSrcDS)->GetDescription()) != NULL )
     381                 :         {
     382                 :             VSIStatBufL  sStat;
     383               0 :             if( VSIStatL( pszFilename, &sStat ) == 0 )
     384                 :             {
     385               0 :                 papszFileList = CSLAddString(papszFileList, pszFilename);
     386                 :             }
     387                 :         }
     388                 :     }
     389                 :     
     390               0 :     return papszFileList;
     391                 : }
     392                 : 
     393                 : /************************************************************************/
     394                 : /*                     VRTWarpedOverviewTransform()                     */
     395                 : /************************************************************************/
     396                 : 
     397                 : typedef struct {
     398                 :     GDALTransformerInfo sTI;
     399                 : 
     400                 :     GDALTransformerFunc pfnBaseTransformer;
     401                 :     void              *pBaseTransformerArg;
     402                 : 
     403                 :     double            dfXOverviewFactor;
     404                 :     double            dfYOverviewFactor;
     405                 : } VWOTInfo;
     406                 : 
     407                 : static
     408             258 : int VRTWarpedOverviewTransform( void *pTransformArg, int bDstToSrc, 
     409                 :                                 int nPointCount, 
     410                 :                                 double *padfX, double *padfY, double *padfZ,
     411                 :                                 int *panSuccess )
     412                 : 
     413                 : {
     414             258 :     VWOTInfo *psInfo = (VWOTInfo *) pTransformArg;
     415                 :     int i, bSuccess;
     416                 : 
     417             258 :     if( bDstToSrc )
     418                 :     {
     419          131498 :         for( i = 0; i < nPointCount; i++ )
     420                 :         {
     421          131240 :             padfX[i] *= psInfo->dfXOverviewFactor;
     422          131240 :             padfY[i] *= psInfo->dfYOverviewFactor;
     423                 :         }
     424                 :     }
     425                 : 
     426                 :     bSuccess = psInfo->pfnBaseTransformer( psInfo->pBaseTransformerArg, 
     427                 :                                            bDstToSrc,
     428                 :                                            nPointCount, padfX, padfY, padfZ, 
     429             258 :                                            panSuccess );
     430                 : 
     431             258 :     if( !bDstToSrc )
     432                 :     {
     433               0 :         for( i = 0; i < nPointCount; i++ )
     434                 :         {
     435               0 :             padfX[i] /= psInfo->dfXOverviewFactor;
     436               0 :             padfY[i] /= psInfo->dfYOverviewFactor;
     437                 :         }
     438                 :     }
     439                 : 
     440             258 :     return bSuccess;
     441                 : }
     442                 : 
     443               2 : static void VRTWarpedOverviewCleanup(void* pTransformArg)
     444                 : {
     445               2 :     VWOTInfo *psInfo = (VWOTInfo *) pTransformArg;
     446                 : 
     447               2 :     CPLFree( psInfo );
     448               2 : }
     449                 : 
     450                 : /************************************************************************/
     451                 : /*                           BuildOverviews()                           */
     452                 : /*                                                                      */
     453                 : /*      For overviews, we actually just build a whole new dataset       */
     454                 : /*      with an extra layer of transformation on the warper used to     */
     455                 : /*      accomplish downsampling by the desired factor.                  */
     456                 : /************************************************************************/
     457                 : 
     458                 : CPLErr 
     459               2 : VRTWarpedDataset::IBuildOverviews( const char *pszResampling, 
     460                 :                                    int nOverviews, int *panOverviewList, 
     461                 :                                    int nListBands, int *panBandList,
     462                 :                                    GDALProgressFunc pfnProgress, 
     463                 :                                    void * pProgressData )
     464                 :     
     465                 : {
     466                 : /* -------------------------------------------------------------------- */
     467                 : /*      Initial progress result.                                        */
     468                 : /* -------------------------------------------------------------------- */
     469               2 :     if( !pfnProgress( 0.0, NULL, pProgressData ) )
     470                 :     {
     471               0 :         CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
     472               0 :         return CE_Failure;
     473                 :     }
     474                 : 
     475                 : /* -------------------------------------------------------------------- */
     476                 : /*      Establish which of the overview levels we already have, and     */
     477                 : /*      which are new.                                                  */
     478                 : /* -------------------------------------------------------------------- */
     479               2 :     int   i, nNewOverviews, *panNewOverviewList = NULL;
     480                 : 
     481               2 :     nNewOverviews = 0;
     482               2 :     panNewOverviewList = (int *) CPLCalloc(sizeof(int),nOverviews);
     483               4 :     for( i = 0; i < nOverviews; i++ )
     484                 :     {
     485                 :         int   j;
     486                 : 
     487               2 :         for( j = 0; j < nOverviewCount; j++ )
     488                 :         {
     489                 :             int    nOvFactor;
     490               0 :             VRTWarpedDataset *poOverview = papoOverviews[j];
     491                 :             
     492                 :             nOvFactor = (int) 
     493               0 :                 (0.5+GetRasterXSize() / (double) poOverview->GetRasterXSize());
     494                 : 
     495               0 :             if( nOvFactor == panOverviewList[i] 
     496                 :                 || nOvFactor == GDALOvLevelAdjust( panOverviewList[i], 
     497                 :                                                    GetRasterXSize() ) )
     498               0 :                 panOverviewList[i] *= -1;
     499                 :         }
     500                 : 
     501               2 :         if( panOverviewList[i] > 0 )
     502               2 :             panNewOverviewList[nNewOverviews++] = panOverviewList[i];
     503                 :     }
     504                 : 
     505                 : /* -------------------------------------------------------------------- */
     506                 : /*      Create each missing overview (we don't need to do anything      */
     507                 : /*      to update existing overviews).                                  */
     508                 : /* -------------------------------------------------------------------- */
     509               4 :     for( i = 0; i < nNewOverviews; i++ )
     510                 :     {
     511                 :         int    nOXSize, nOYSize, iBand;
     512                 :         VWOTInfo *psInfo;
     513                 :         VRTWarpedDataset *poOverviewDS;
     514                 :         
     515                 : /* -------------------------------------------------------------------- */
     516                 : /*      What size should this overview be.                              */
     517                 : /* -------------------------------------------------------------------- */
     518               2 :         nOXSize = (GetRasterXSize() + panNewOverviewList[i] - 1) 
     519               4 :             / panNewOverviewList[i];
     520                 :                                  
     521               2 :         nOYSize = (GetRasterYSize() + panNewOverviewList[i] - 1) 
     522               4 :             / panNewOverviewList[i];
     523                 : 
     524                 : /* -------------------------------------------------------------------- */
     525                 : /*      Create the overview dataset.                                    */
     526                 : /* -------------------------------------------------------------------- */
     527               2 :         poOverviewDS = new VRTWarpedDataset( nOXSize, nOYSize );
     528                 :         
     529               8 :         for( iBand = 0; iBand < GetRasterCount(); iBand++ )
     530                 :         {
     531               2 :             GDALRasterBand *poOldBand = GetRasterBand(iBand+1);
     532                 :             VRTWarpedRasterBand *poNewBand = 
     533                 :                 new VRTWarpedRasterBand( poOverviewDS, iBand+1, 
     534               2 :                                          poOldBand->GetRasterDataType() );
     535                 :             
     536               2 :             poNewBand->CopyCommonInfoFrom( poOldBand );
     537               2 :             poOverviewDS->SetBand( iBand+1, poNewBand );
     538                 :         }
     539                 : 
     540               2 :         nOverviewCount++;
     541                 :         papoOverviews = (VRTWarpedDataset **)
     542               2 :             CPLRealloc( papoOverviews, sizeof(void*) * nOverviewCount );
     543                 : 
     544               2 :         papoOverviews[nOverviewCount-1] = poOverviewDS;
     545                 :         
     546                 : /* -------------------------------------------------------------------- */
     547                 : /*      Prepare update transformation information that will apply       */
     548                 : /*      the overview decimation.                                        */
     549                 : /* -------------------------------------------------------------------- */
     550               2 :         GDALWarpOptions *psWO = (GDALWarpOptions *) poWarper->GetOptions();
     551               2 :         psInfo = (VWOTInfo *) CPLCalloc(sizeof(VWOTInfo),1);
     552                 : 
     553               2 :         strcpy( psInfo->sTI.szSignature, "GTI" );
     554               2 :         psInfo->sTI.pszClassName = "VRTWarpedOverviewTransform";
     555               2 :         psInfo->sTI.pfnTransform = VRTWarpedOverviewTransform;
     556               2 :         psInfo->sTI.pfnCleanup = VRTWarpedOverviewCleanup;
     557               2 :         psInfo->sTI.pfnSerialize = NULL;
     558                 : 
     559               2 :         psInfo->pfnBaseTransformer = psWO->pfnTransformer;
     560               2 :         psInfo->pBaseTransformerArg = psWO->pTransformerArg;
     561                 : 
     562               2 :         psInfo->dfXOverviewFactor = GetRasterXSize() / (double) nOXSize;
     563               2 :         psInfo->dfYOverviewFactor = GetRasterYSize() / (double) nOYSize;
     564                 : 
     565                 : /* -------------------------------------------------------------------- */
     566                 : /*      Initialize the new dataset with adjusted warp options, and      */
     567                 : /*      then restore to original condition.                             */
     568                 : /* -------------------------------------------------------------------- */
     569               2 :         psWO->pfnTransformer = VRTWarpedOverviewTransform;
     570               2 :         psWO->pTransformerArg = psInfo;
     571                 : 
     572               2 :         poOverviewDS->Initialize( psWO );
     573                 : 
     574               2 :         psWO->pfnTransformer = psInfo->pfnBaseTransformer;
     575               2 :         psWO->pTransformerArg = psInfo->pBaseTransformerArg;
     576                 :     }
     577                 : 
     578               2 :     CPLFree( panNewOverviewList );
     579                 : 
     580                 : /* -------------------------------------------------------------------- */
     581                 : /*      Progress finished.                                              */
     582                 : /* -------------------------------------------------------------------- */
     583               2 :     pfnProgress( 1.0, NULL, pProgressData );
     584                 : 
     585               2 :     SetNeedsFlush();
     586                 : 
     587               2 :     return CE_None;
     588                 : }
     589                 : 
     590                 : /************************************************************************/
     591                 : /*                      GDALInitializeWarpedVRT()                       */
     592                 : /************************************************************************/
     593                 : 
     594                 : /**
     595                 :  * Set warp info on virtual warped dataset.
     596                 :  *
     597                 :  * Initializes all the warping information for a virtual warped dataset.
     598                 :  *
     599                 :  * This method is the same as the C++ method VRTWarpedDataset::Initialize().
     600                 :  *
     601                 :  * @param hDS dataset previously created with the VRT driver, and a 
     602                 :  * SUBCLASS of "VRTWarpedDataset".
     603                 :  * 
     604                 :  * @param psWO the warp options to apply.  Note that ownership of the
     605                 :  * transformation information is taken over by the function though everything
     606                 :  * else remains the property of the caller. 
     607                 :  *
     608                 :  * @return CE_None on success or CE_Failure if an error occurs. 
     609                 :  */
     610                 : 
     611                 : CPLErr CPL_STDCALL 
     612               2 : GDALInitializeWarpedVRT( GDALDatasetH hDS, GDALWarpOptions *psWO )
     613                 : 
     614                 : {
     615               2 :     VALIDATE_POINTER1( hDS, "GDALInitializeWarpedVRT", CE_Failure );
     616                 : 
     617               2 :     return ((VRTWarpedDataset *) hDS)->Initialize( psWO );
     618                 : }
     619                 : 
     620                 : /************************************************************************/
     621                 : /*                              XMLInit()                               */
     622                 : /************************************************************************/
     623                 : 
     624              34 : CPLErr VRTWarpedDataset::XMLInit( CPLXMLNode *psTree, const char *pszVRTPath )
     625                 : 
     626                 : {
     627                 :     CPLErr eErr;
     628                 : 
     629                 : /* -------------------------------------------------------------------- */
     630                 : /*      Initialize blocksize before calling sub-init so that the        */
     631                 : /*      band initializers can get it from the dataset object when       */
     632                 : /*      they are created.                                               */
     633                 : /* -------------------------------------------------------------------- */
     634              34 :     nBlockXSize = atoi(CPLGetXMLValue(psTree,"BlockXSize","512"));
     635              34 :     nBlockYSize = atoi(CPLGetXMLValue(psTree,"BlockYSize","128"));
     636                 : 
     637                 : /* -------------------------------------------------------------------- */
     638                 : /*      Initialize all the general VRT stuff.  This will even           */
     639                 : /*      create the VRTWarpedRasterBands and initialize them.            */
     640                 : /* -------------------------------------------------------------------- */
     641              34 :     eErr = VRTDataset::XMLInit( psTree, pszVRTPath );
     642                 : 
     643              34 :     if( eErr != CE_None )
     644               0 :         return eErr;
     645                 : 
     646                 : /* -------------------------------------------------------------------- */
     647                 : /*      Find the GDALWarpOptions XML tree.                              */
     648                 : /* -------------------------------------------------------------------- */
     649                 :     CPLXMLNode *psOptionsTree;
     650              34 :     psOptionsTree = CPLGetXMLNode( psTree, "GDALWarpOptions" );
     651              34 :     if( psOptionsTree == NULL )
     652                 :     {
     653                 :         CPLError( CE_Failure, CPLE_AppDefined,
     654               0 :                   "Count not find required GDALWarpOptions in XML." );
     655               0 :         return CE_Failure;
     656                 :     }
     657                 : 
     658                 : /* -------------------------------------------------------------------- */
     659                 : /*      Adjust the SourceDataset in the warp options to take into       */
     660                 : /*      account that it is relative to the VRT if appropriate.          */
     661                 : /* -------------------------------------------------------------------- */
     662                 :     int bRelativeToVRT = 
     663                 :         atoi(CPLGetXMLValue(psOptionsTree,
     664              34 :                             "SourceDataset.relativeToVRT", "0" ));
     665                 : 
     666                 :     const char *pszRelativePath = CPLGetXMLValue(psOptionsTree,
     667              34 :                                                  "SourceDataset", "" );
     668                 :     char *pszAbsolutePath;
     669                 : 
     670              34 :     if( bRelativeToVRT )
     671                 :         pszAbsolutePath = 
     672                 :             CPLStrdup(CPLProjectRelativeFilename( pszVRTPath, 
     673              32 :                                                   pszRelativePath ) );
     674                 :     else
     675               2 :         pszAbsolutePath = CPLStrdup(pszRelativePath);
     676                 : 
     677              34 :     CPLSetXMLValue( psOptionsTree, "SourceDataset", pszAbsolutePath );
     678              34 :     CPLFree( pszAbsolutePath );
     679                 : 
     680                 : /* -------------------------------------------------------------------- */
     681                 : /*      And instantiate the warp options, and corresponding warp        */
     682                 : /*      operation.                                                      */
     683                 : /* -------------------------------------------------------------------- */
     684                 :     GDALWarpOptions *psWO;
     685                 : 
     686              34 :     psWO = GDALDeserializeWarpOptions( psOptionsTree );
     687              34 :     if( psWO == NULL )
     688               0 :         return CE_Failure;
     689                 : 
     690              34 :     this->eAccess = GA_Update;
     691              34 :     psWO->hDstDS = this;
     692                 : 
     693                 : /* -------------------------------------------------------------------- */
     694                 : /*      Instantiate the warp operation.                                 */
     695                 : /* -------------------------------------------------------------------- */
     696              34 :     poWarper = new GDALWarpOperation();
     697                 : 
     698              34 :     eErr = poWarper->Initialize( psWO );
     699              34 :     if( eErr != CE_None)
     700                 :     {
     701                 : /* -------------------------------------------------------------------- */
     702                 : /*      We are responsible for cleaning up the transformer outselves.   */
     703                 : /* -------------------------------------------------------------------- */
     704               0 :         if( psWO->pTransformerArg != NULL )
     705               0 :             GDALDestroyTransformer( psWO->pTransformerArg );
     706                 :     }
     707                 : 
     708              34 :     GDALDestroyWarpOptions( psWO );
     709              34 :     if( eErr != CE_None )
     710                 :     {
     711               0 :         delete poWarper;
     712               0 :         poWarper = NULL;
     713                 :     }
     714                 : 
     715                 : /* -------------------------------------------------------------------- */
     716                 : /*      Generate overviews, if appropriate.                             */
     717                 : /* -------------------------------------------------------------------- */
     718                 :     char **papszTokens = CSLTokenizeString( 
     719              34 :         CPLGetXMLValue( psTree, "OverviewList", "" ));
     720                 :     int iOverview;
     721                 : 
     722              70 :     for( iOverview = 0; 
     723              35 :          papszTokens != NULL && papszTokens[iOverview] != NULL;
     724                 :          iOverview++ )
     725                 :     {
     726               1 :         int nOvFactor = atoi(papszTokens[iOverview]);
     727                 : 
     728               1 :         if (nOvFactor > 0)
     729               1 :             BuildOverviews( "NEAREST", 1, &nOvFactor, 0, NULL, NULL, NULL );
     730                 :         else
     731                 :             CPLError(CE_Failure, CPLE_AppDefined,
     732               0 :                      "Bad value for overview factor : %s", papszTokens[iOverview]);
     733                 :     }
     734                 : 
     735              34 :     CSLDestroy( papszTokens );
     736                 : 
     737              34 :     return eErr;
     738                 : }
     739                 : 
     740                 : /************************************************************************/
     741                 : /*                           SerializeToXML()                           */
     742                 : /************************************************************************/
     743                 : 
     744               4 : CPLXMLNode *VRTWarpedDataset::SerializeToXML( const char *pszVRTPath )
     745                 : 
     746                 : {
     747                 :     CPLXMLNode *psTree;
     748                 : 
     749               4 :     psTree = VRTDataset::SerializeToXML( pszVRTPath );
     750                 : 
     751               4 :     if( psTree == NULL )
     752               0 :         return psTree;
     753                 : 
     754                 : /* -------------------------------------------------------------------- */
     755                 : /*      Set subclass.                                                   */
     756                 : /* -------------------------------------------------------------------- */
     757                 :     CPLCreateXMLNode( 
     758                 :         CPLCreateXMLNode( psTree, CXT_Attribute, "subClass" ), 
     759               4 :         CXT_Text, "VRTWarpedDataset" );
     760                 : 
     761                 : /* -------------------------------------------------------------------- */
     762                 : /*      Serialize the block size.                                       */
     763                 : /* -------------------------------------------------------------------- */
     764                 :     CPLCreateXMLElementAndValue( psTree, "BlockXSize",
     765               4 :                                  CPLSPrintf( "%d", nBlockXSize ) );
     766                 :     CPLCreateXMLElementAndValue( psTree, "BlockYSize",
     767               4 :                                  CPLSPrintf( "%d", nBlockYSize ) );
     768                 : 
     769                 : /* -------------------------------------------------------------------- */
     770                 : /*      Serialize the overview list.                                    */
     771                 : /* -------------------------------------------------------------------- */
     772               4 :     if( nOverviewCount > 0 )
     773                 :     {
     774                 :         char *pszOverviewList;
     775                 :         int iOverview;
     776                 :         
     777               1 :         pszOverviewList = (char *) CPLMalloc(nOverviewCount*8 + 10);
     778               1 :         pszOverviewList[0] = '\0';
     779               2 :         for( iOverview = 0; iOverview < nOverviewCount; iOverview++ )
     780                 :         {
     781                 :             int nOvFactor;
     782                 : 
     783                 :             nOvFactor = (int) 
     784                 :                 (0.5+GetRasterXSize() 
     785               1 :                  / (double) papoOverviews[iOverview]->GetRasterXSize());
     786                 : 
     787                 :             sprintf( pszOverviewList + strlen(pszOverviewList), 
     788               1 :                      "%d ", nOvFactor );
     789                 :         }
     790                 : 
     791               1 :         CPLCreateXMLElementAndValue( psTree, "OverviewList", pszOverviewList );
     792                 : 
     793               1 :         CPLFree( pszOverviewList );
     794                 :     }
     795                 : 
     796                 : /* ==================================================================== */
     797                 : /*      Serialize the warp options.                                     */
     798                 : /* ==================================================================== */
     799                 :     CPLXMLNode *psWOTree;
     800                 : 
     801               4 :     if( poWarper != NULL )
     802                 :     {
     803                 : /* -------------------------------------------------------------------- */
     804                 : /*      We reset the destination dataset name so it doesn't get         */
     805                 : /*      written out in the serialize warp options.                      */
     806                 : /* -------------------------------------------------------------------- */
     807               4 :         char *pszSavedName = CPLStrdup(GetDescription());
     808               4 :         SetDescription("");
     809                 : 
     810               4 :         psWOTree = GDALSerializeWarpOptions( poWarper->GetOptions() );
     811               4 :         CPLAddXMLChild( psTree, psWOTree );
     812                 : 
     813               4 :         SetDescription( pszSavedName );
     814               4 :         CPLFree( pszSavedName );
     815                 : 
     816                 : /* -------------------------------------------------------------------- */
     817                 : /*      We need to consider making the source dataset relative to       */
     818                 : /*      the VRT file if possible.  Adjust accordingly.                  */
     819                 : /* -------------------------------------------------------------------- */
     820               4 :         CPLXMLNode *psSDS = CPLGetXMLNode( psWOTree, "SourceDataset" );
     821                 :         int bRelativeToVRT;
     822                 :         char *pszRelativePath;
     823                 : 
     824                 :         pszRelativePath = 
     825                 :             CPLStrdup(
     826                 :                 CPLExtractRelativePath( pszVRTPath, psSDS->psChild->pszValue, 
     827               4 :                                         &bRelativeToVRT ) );
     828                 : 
     829               4 :         CPLFree( psSDS->psChild->pszValue );
     830               4 :         psSDS->psChild->pszValue = pszRelativePath;
     831                 : 
     832                 :         CPLCreateXMLNode( 
     833                 :             CPLCreateXMLNode( psSDS, CXT_Attribute, "relativeToVRT" ), 
     834               4 :             CXT_Text, bRelativeToVRT ? "1" : "0" );
     835                 :     }
     836                 : 
     837               4 :     return psTree;
     838                 : }
     839                 : 
     840                 : /************************************************************************/
     841                 : /*                            GetBlockSize()                            */
     842                 : /************************************************************************/
     843                 : 
     844              69 : void VRTWarpedDataset::GetBlockSize( int *pnBlockXSize, int *pnBlockYSize )
     845                 : 
     846                 : {
     847              69 :     assert( NULL != pnBlockXSize );
     848              69 :     assert( NULL != pnBlockYSize );
     849                 : 
     850              69 :     *pnBlockXSize = nBlockXSize;
     851              69 :     *pnBlockYSize = nBlockYSize;
     852              69 : }
     853                 : 
     854                 : /************************************************************************/
     855                 : /*                            ProcessBlock()                            */
     856                 : /*                                                                      */
     857                 : /*      Warp a single requested block, and then push each band of       */
     858                 : /*      the result into the block cache.                                */
     859                 : /************************************************************************/
     860                 : 
     861              65 : CPLErr VRTWarpedDataset::ProcessBlock( int iBlockX, int iBlockY )
     862                 : 
     863                 : {
     864              65 :     if( poWarper == NULL )
     865               0 :         return CE_Failure;
     866                 : 
     867              65 :     const GDALWarpOptions *psWO = poWarper->GetOptions();
     868                 : 
     869                 : /* -------------------------------------------------------------------- */
     870                 : /*      Allocate block of memory large enough to hold all the bands     */
     871                 : /*      for this block.                                                 */
     872                 : /* -------------------------------------------------------------------- */
     873                 :     int iBand;
     874                 :     GByte *pabyDstBuffer;
     875                 :     int   nDstBufferSize;
     876              65 :     int   nWordSize = (GDALGetDataTypeSize(psWO->eWorkingDataType) / 8);
     877                 : 
     878                 :     // FIXME? : risk of overflow in multiplication if nBlockXSize or nBlockYSize are very large
     879              65 :     nDstBufferSize = nBlockXSize * nBlockYSize * psWO->nBandCount * nWordSize;
     880                 : 
     881              65 :     pabyDstBuffer = (GByte *) VSIMalloc(nDstBufferSize);
     882                 : 
     883              65 :     if( pabyDstBuffer == NULL )
     884                 :     {
     885                 :         CPLError( CE_Failure, CPLE_OutOfMemory,
     886                 :                   "Out of memory allocating %d byte buffer in VRTWarpedDataset::ProcessBlock()",
     887               0 :                   nDstBufferSize );
     888               0 :         return CE_Failure;
     889                 :     }       
     890                 : 
     891              65 :     memset( pabyDstBuffer, 0, nDstBufferSize );
     892                 : 
     893                 : /* -------------------------------------------------------------------- */
     894                 : /*      Process INIT_DEST option to initialize the buffer prior to      */
     895                 : /*      warping into it.                                                */
     896                 : /* NOTE:The following code is 99% similar in gdalwarpoperation.cpp and  */
     897                 : /*      vrtwarped.cpp. Be careful to keep it in sync !                  */
     898                 : /* -------------------------------------------------------------------- */
     899                 :     const char *pszInitDest = CSLFetchNameValue( psWO->papszWarpOptions,
     900              65 :                                                  "INIT_DEST" );
     901                 : 
     902              65 :     if( pszInitDest != NULL && !EQUAL(pszInitDest, "") )
     903                 :     {
     904                 :         char **papszInitValues = 
     905              15 :             CSLTokenizeStringComplex( pszInitDest, ",", FALSE, FALSE );
     906              15 :         int nInitCount = CSLCount(papszInitValues);
     907                 :                                                            
     908              46 :         for( iBand = 0; iBand < psWO->nBandCount; iBand++ )
     909                 :         {
     910                 :             double adfInitRealImag[2];
     911                 :             GByte *pBandData;
     912              31 :             int nBandSize = nBlockXSize * nBlockYSize * nWordSize;
     913              31 :             const char *pszBandInit = papszInitValues[MIN(iBand,nInitCount-1)];
     914                 : 
     915              32 :             if( EQUAL(pszBandInit,"NO_DATA")
     916                 :                 && psWO->padfDstNoDataReal != NULL )
     917                 :             {
     918               1 :                 adfInitRealImag[0] = psWO->padfDstNoDataReal[iBand];
     919               1 :                 adfInitRealImag[1] = psWO->padfDstNoDataImag[iBand];
     920                 :             }
     921                 :             else
     922                 :             {
     923                 :                 CPLStringToComplex( pszBandInit,
     924              30 :                                     adfInitRealImag + 0, adfInitRealImag + 1);
     925                 :             }
     926                 : 
     927              31 :             pBandData = ((GByte *) pabyDstBuffer) + iBand * nBandSize;
     928                 :             
     929              31 :             if( psWO->eWorkingDataType == GDT_Byte )
     930                 :                 memset( pBandData, 
     931              37 :                         MAX(0,MIN(255,(int)adfInitRealImag[0])), 
     932              55 :                         nBandSize);
     933              26 :             else if( adfInitRealImag[0] == 0.0 && adfInitRealImag[1] == 0 )
     934                 :             {
     935              13 :                 memset( pBandData, 0, nBandSize );
     936                 :             }
     937               0 :             else if( adfInitRealImag[1] == 0.0 )
     938                 :             {
     939                 :                 GDALCopyWords( &adfInitRealImag, GDT_Float64, 0, 
     940                 :                                pBandData,psWO->eWorkingDataType,nWordSize,
     941               0 :                                nBlockXSize * nBlockYSize );
     942                 :             }
     943                 :             else
     944                 :             {
     945                 :                 GDALCopyWords( &adfInitRealImag, GDT_CFloat64, 0, 
     946                 :                                pBandData,psWO->eWorkingDataType,nWordSize,
     947               0 :                                nBlockXSize * nBlockYSize );
     948                 :             }
     949                 :         }
     950                 : 
     951              15 :         CSLDestroy( papszInitValues );
     952                 :     }
     953                 : 
     954                 : /* -------------------------------------------------------------------- */
     955                 : /*      Warp into this buffer.                                          */
     956                 : /* -------------------------------------------------------------------- */
     957                 :     CPLErr eErr;
     958                 : 
     959                 :     eErr = 
     960                 :         poWarper->WarpRegionToBuffer( 
     961                 :             iBlockX * nBlockXSize, iBlockY * nBlockYSize, 
     962                 :             nBlockXSize, nBlockYSize,
     963              65 :             pabyDstBuffer, psWO->eWorkingDataType );
     964                 : 
     965              65 :     if( eErr != CE_None )
     966                 :     {
     967               0 :         VSIFree( pabyDstBuffer );
     968               0 :         return eErr;
     969                 :     }
     970                 :                         
     971                 : /* -------------------------------------------------------------------- */
     972                 : /*      Copy out into cache blocks for each band.                       */
     973                 : /* -------------------------------------------------------------------- */
     974             152 :     for( iBand = 0; iBand < psWO->nBandCount; iBand++ )
     975                 :     {
     976                 :         GDALRasterBand *poBand;
     977                 :         GDALRasterBlock *poBlock;
     978                 : 
     979              87 :         poBand = GetRasterBand(iBand+1);
     980              87 :         poBlock = poBand->GetLockedBlockRef( iBlockX, iBlockY, TRUE );
     981                 : 
     982                 :         CPLAssert( poBlock != NULL && poBlock->GetDataRef() != NULL );
     983                 : 
     984                 :         GDALCopyWords( pabyDstBuffer + iBand*nBlockXSize*nBlockYSize*nWordSize,
     985                 :                        psWO->eWorkingDataType, nWordSize, 
     986                 :                        poBlock->GetDataRef(), 
     987                 :                        poBlock->GetDataType(), 
     988                 :                        GDALGetDataTypeSize(poBlock->GetDataType())/8,
     989              87 :                        nBlockXSize * nBlockYSize );
     990                 : 
     991              87 :         poBlock->DropLock();
     992                 :     }
     993                 : 
     994              65 :     VSIFree( pabyDstBuffer );
     995                 :     
     996              65 :     return CE_None;
     997                 : }
     998                 : 
     999                 : /************************************************************************/
    1000                 : /*                              AddBand()                               */
    1001                 : /************************************************************************/
    1002                 : 
    1003               5 : CPLErr VRTWarpedDataset::AddBand( GDALDataType eType, char **papszOptions )
    1004                 : 
    1005                 : {
    1006                 :     UNREFERENCED_PARAM( papszOptions );
    1007                 : 
    1008                 :     SetBand( GetRasterCount() + 1,
    1009               5 :              new VRTWarpedRasterBand( this, GetRasterCount() + 1, eType ) );
    1010                 : 
    1011               5 :     return CE_None;
    1012                 : }
    1013                 : 
    1014                 : /************************************************************************/
    1015                 : /* ==================================================================== */
    1016                 : /*                        VRTWarpedRasterBand                           */
    1017                 : /* ==================================================================== */
    1018                 : /************************************************************************/
    1019                 : 
    1020                 : /************************************************************************/
    1021                 : /*                        VRTWarpedRasterBand()                         */
    1022                 : /************************************************************************/
    1023                 : 
    1024              69 : VRTWarpedRasterBand::VRTWarpedRasterBand( GDALDataset *poDS, int nBand,
    1025              69 :                                           GDALDataType eType )
    1026                 : 
    1027                 : {
    1028              69 :     Initialize( poDS->GetRasterXSize(), poDS->GetRasterYSize() );
    1029                 : 
    1030              69 :     this->poDS = poDS;
    1031              69 :     this->nBand = nBand;
    1032              69 :     this->eAccess = GA_Update;
    1033                 : 
    1034                 :     ((VRTWarpedDataset *) poDS)->GetBlockSize( &nBlockXSize, 
    1035              69 :                                                &nBlockYSize );
    1036                 : 
    1037              69 :     if( eType != GDT_Unknown )
    1038               7 :         this->eDataType = eType;
    1039              69 : }
    1040                 : 
    1041                 : /************************************************************************/
    1042                 : /*                        ~VRTWarpedRasterBand()                        */
    1043                 : /************************************************************************/
    1044                 : 
    1045             138 : VRTWarpedRasterBand::~VRTWarpedRasterBand()
    1046                 : 
    1047                 : {
    1048              69 :     FlushCache();
    1049             138 : }
    1050                 : 
    1051                 : /************************************************************************/
    1052                 : /*                             IReadBlock()                             */
    1053                 : /************************************************************************/
    1054                 : 
    1055              65 : CPLErr VRTWarpedRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
    1056                 :                                      void * pImage )
    1057                 : 
    1058                 : {
    1059                 :     CPLErr eErr;
    1060              65 :     VRTWarpedDataset *poWDS = (VRTWarpedDataset *) poDS;
    1061                 :     GDALRasterBlock *poBlock;
    1062                 : 
    1063              65 :     poBlock = GetLockedBlockRef( nBlockXOff, nBlockYOff, TRUE );
    1064                 : 
    1065              65 :     eErr = poWDS->ProcessBlock( nBlockXOff, nBlockYOff );
    1066                 : 
    1067              65 :     if( eErr == CE_None && pImage != poBlock->GetDataRef() )
    1068                 :     {
    1069                 :         int nDataBytes;
    1070                 :         nDataBytes = (GDALGetDataTypeSize(poBlock->GetDataType()) / 8)
    1071               0 :             * poBlock->GetXSize() * poBlock->GetYSize();
    1072               0 :         memcpy( pImage, poBlock->GetDataRef(), nDataBytes );
    1073                 :     }
    1074                 : 
    1075              65 :     poBlock->DropLock();
    1076                 : 
    1077              65 :     return eErr;
    1078                 : }
    1079                 : 
    1080                 : /************************************************************************/
    1081                 : /*                            IWriteBlock()                             */
    1082                 : /************************************************************************/
    1083                 : 
    1084               8 : CPLErr VRTWarpedRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
    1085                 :                                      void * pImage )
    1086                 : 
    1087                 : {
    1088                 :     CPLErr eErr;
    1089               8 :     VRTWarpedDataset *poWDS = (VRTWarpedDataset *) poDS;
    1090                 : 
    1091                 :     /* This is a bit tricky. In the case we are warping a VRTWarpedDataset */
    1092                 :     /* with a destination alpha band, IWriteBlock can be called on that alpha */
    1093                 :     /* band by GDALWarpDstAlphaMasker */
    1094                 :     /* We don't need to do anything since the data will be kept in the block */
    1095                 :     /* cache by VRTWarpedRasterBand::IReadBlock */
    1096               8 :     if (poWDS->poWarper->GetOptions()->nDstAlphaBand == nBand)
    1097                 :     {
    1098               8 :         eErr = CE_None;
    1099                 :     }
    1100                 :     else
    1101                 :     {
    1102                 :         /* Otherwise, call the superclass method, that will fail of course */
    1103               0 :         eErr = VRTRasterBand::IWriteBlock(nBlockXOff, nBlockYOff, pImage);
    1104                 :     }
    1105                 : 
    1106               8 :     return eErr;
    1107                 : }
    1108                 : 
    1109                 : /************************************************************************/
    1110                 : /*                              XMLInit()                               */
    1111                 : /************************************************************************/
    1112                 : 
    1113              62 : CPLErr VRTWarpedRasterBand::XMLInit( CPLXMLNode * psTree, 
    1114                 :                                   const char *pszVRTPath )
    1115                 : 
    1116                 : {
    1117              62 :     return VRTRasterBand::XMLInit( psTree, pszVRTPath );
    1118                 : }
    1119                 : 
    1120                 : /************************************************************************/
    1121                 : /*                           SerializeToXML()                           */
    1122                 : /************************************************************************/
    1123                 : 
    1124               6 : CPLXMLNode *VRTWarpedRasterBand::SerializeToXML( const char *pszVRTPath )
    1125                 : 
    1126                 : {
    1127               6 :     CPLXMLNode *psTree = VRTRasterBand::SerializeToXML( pszVRTPath );
    1128                 : 
    1129                 : /* -------------------------------------------------------------------- */
    1130                 : /*      Set subclass.                                                   */
    1131                 : /* -------------------------------------------------------------------- */
    1132                 :     CPLCreateXMLNode( 
    1133                 :         CPLCreateXMLNode( psTree, CXT_Attribute, "subClass" ), 
    1134               6 :         CXT_Text, "VRTWarpedRasterBand" );
    1135                 : 
    1136               6 :     return psTree;
    1137                 : }
    1138                 : 
    1139                 : /************************************************************************/
    1140                 : /*                          GetOverviewCount()                          */
    1141                 : /************************************************************************/
    1142                 : 
    1143               1 : int VRTWarpedRasterBand::GetOverviewCount()
    1144                 : 
    1145                 : {
    1146               1 :     VRTWarpedDataset *poWDS = (VRTWarpedDataset *) poDS;
    1147                 : 
    1148               1 :     return poWDS->nOverviewCount;
    1149                 : }
    1150                 : 
    1151                 : /************************************************************************/
    1152                 : /*                            GetOverview()                             */
    1153                 : /************************************************************************/
    1154                 : 
    1155               1 : GDALRasterBand *VRTWarpedRasterBand::GetOverview( int iOverview )
    1156                 : 
    1157                 : {
    1158               1 :     VRTWarpedDataset *poWDS = (VRTWarpedDataset *) poDS;
    1159                 : 
    1160               1 :     if( iOverview < 0 || iOverview >= poWDS->nOverviewCount )
    1161               0 :         return NULL;
    1162                 :     else
    1163               1 :         return poWDS->papoOverviews[iOverview]->GetRasterBand( nBand );
    1164                 : }
    1165                 : 

Generated by: LCOV version 1.7