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 :
|