LCOV - code coverage report
Current view: directory - frmts/vrt - vrtwarped.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 380 299 78.7 %
Date: 2011-12-18 Functions: 34 24 70.6 %

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

Generated by: LCOV version 1.7